OSSL_PROVIDER-FIPS(7SSL)
π OSSL_PROVIDER-FIPS π
okay bestie, welcome to the OSSL_PROVIDER-FIPS page β that's section 7SSL of the OpenSSL manual, and it's literally about the certified glow-up module of OpenSSL. this is part 1, so don't go anywhere. π
β¨ NAME β¨
OSSL_PROVIDER-FIPS β the OpenSSL FIPS provider. periodt.
π¦ DESCRIPTION π¦
so the OpenSSL FIPS provider is a special provider that conforms to the Federal Information Processing Standards (FIPS) laid out in FIPS 140-3. this module ships an approved set of cryptographic algorithms that some accredited testing laboratory has actually validated. no cap. π
πΈ Properties πΈ
the implementations in this provider have these properties set, specifically for the approved algorithms:
"provider=fips""fips=yes"
you can drop these into a property query string with fetching functions like EVP_MD_fetch(3) or EVP_CIPHER_fetch(3), and also with any other function that takes a property query string, like EVP_PKEY_CTX_new_from_name(3).
to be FIPS compliant, it is mandatory to include "fips=yes" as part of all property queries. that's what guarantees only FIPS approved implementations get used for cryptographic operations. and lowkey the "fips=yes" query may also pull in other non-crypto support operations that aren't even in the FIPS provider β like asymmetric key encoders, see "Asymmetric Key Management" in OSSL_PROVIDER-default(7).
it is not mandatory to include "provider=fips" in your property query. but including "provider=fips" guarantees that the OpenSSL FIPS provider is used for cryptographic operations rather than some other FIPS capable provider. it's giving "be specific, girl". π
π Approved algorithms π
algorithms fetched with "fips=yes" may still be unapproved if certain conditions aren't met. see "FIPS indicators" in fips_module(7) for the extra info. every "fips=yes" algorithm implementation supplied by this provider exposes a gettable "fips-indicator" context parameter and returns 1 when the operation is approved. π«Ά
β οΈ applications must not treat a missing indicator as an assertion of FIPS approval. that's a big no no. π
π Provider parameters π
see "Provider parameters" in provider-base(7) for a list of base parameters. the OpenSSL FIPS provider also handles FIPS indicator related parameters, exactly as specified by "FIPS indicator options" in fips_config(5).
π OPERATIONS AND ALGORITHMS π
the OpenSSL FIPS provider supports these operations and algorithms:
β Hashing Algorithms / Message Digests β
- SHA1, see
EVP_MD-SHA1(7) - SHA2, see
EVP_MD-SHA2(7) - SHA3, see
EVP_MD-SHA3(7) - SHAKE, see
EVP_MD-SHAKE(7) - CSHAKE, see
EVP_MD-CSHAKE(7) - CSHAKE-KECCAK, see
EVP_MD-CSHAKE-KECCAK(7)- it is used internally as a sub algorithm of CSHAKE. iykyk.
- ML-DSA-MU, see
EVP_MD-ML-DSA-MU(7)
π Symmetric Ciphers π
- AES, see
EVP_CIPHER-AES(7) - 3DES, see
EVP_CIPHER-DES(7)
π§ Message Authentication Code (MAC) π§
- CMAC, see
EVP_MAC-CMAC(7) - GMAC, see
EVP_MAC-GMAC(7) - HMAC, see
EVP_MAC-HMAC(7) - KMAC, see
EVP_MAC-KMAC(7)
π Key Derivation Function (KDF) π
- HKDF, see
EVP_KDF-HKDF(7) - HKDF-SHA256, see
EVP_KDF-HKDF(7) - HKDF-SHA384, see
EVP_KDF-HKDF(7) - HKDF-SHA512, see
EVP_KDF-HKDF(7) - TLS13-KDF, see
EVP_KDF-TLS13_KDF(7) - SSKDF, see
EVP_KDF-SS(7) - PBKDF2, see
EVP_KDF-PBKDF2(7) - SNMPKDF, see
EVP_KDF-SNMPKDF(7) - SRTPKDF, see
EVP_KDF-SRTPKDF(7) - SSHKDF, see
EVP_KDF-SSHKDF(7) - TLS1-PRF, see
EVP_KDF-TLS1_PRF(7) - KBKDF, see
EVP_KDF-KB(7) - X942KDF-ASN1, see
EVP_KDF-X942-ASN1(7) - X942KDF-CONCAT, see
EVP_KDF-X942-CONCAT(7) - X963KDF, see
EVP_KDF-X963(7)
π¦ Key Exchange π¦
- DH, see
EVP_KEYEXCH-DH(7) - ECDH, see
EVP_KEYEXCH-ECDH(7) - X25519, see
EVP_KEYEXCH-X25519(7) - X448, see
EVP_KEYEXCH-X448(7) - ML-KEM, see
EVP_KEM-ML-KEM(7) - TLS1-PRF
- HKDF
π Asymmetric Signature π
- RSA, see
EVP_SIGNATURE-RSA(7)- the X931 padding mode
"OSSL_PKEY_RSA_PAD_MODE_X931"is no longer supported for signature generation, but may be used for verification for legacy use cases. (this is a FIPS 140-3 requirement, so don't @ me.)
- the X931 padding mode
- DSA, see
EVP_SIGNATURE-DSA(7) - ED25519, see
EVP_SIGNATURE-ED25519(7) - ED448, see
EVP_SIGNATURE-ED448(7) - ECDSA, see
EVP_SIGNATURE-ECDSA(7) - ML-DSA-44, see
EVP_SIGNATURE-ML-DSA(7) - ML-DSA-65, see
EVP_SIGNATURE-ML-DSA(7) - ML-DSA-87, see
EVP_SIGNATURE-ML-DSA(7) - SLH-DSA, see
EVP_SIGNATURE-SLH-DSA(7) - HMAC, see
EVP_SIGNATURE-HMAC(7) - CMAC, see
EVP_SIGNATURE-CMAC(7) - LMS, see
EVP_SIGNATURE-LMS(7)
πΈ Asymmetric Cipher πΈ
- RSA, see
EVP_ASYM_CIPHER-RSA(7)
β Asymmetric Key Encapsulation β
- RSA, see
EVP_KEM-RSA(7)
π Asymmetric Key Management π
- DH, see
EVP_KEYMGMT-DH(7) - DHX, see
EVP_KEYMGMT-DHX(7) - DSA, see
EVP_KEYMGMT-DSA(7) - RSA, see
EVP_KEYMGMT-RSA(7) - RSA-PSS
- EC, see
EVP_KEYMGMT-EC(7) - ED25519, see
EVP_KEYMGMT-ED25519(7) - ED448, see
EVP_KEYMGMT-ED448(7) - X25519, see
EVP_KEYMGMT-X25519(7)- this is an unapproved algorithm. the FIPS 140-3 IG states that "Curves that are included in SP 800-186 but not included in SP 800-56Arev3 are not approved for key agreement".
- X448, see
EVP_KEYMGMT-X448(7)- this is an unapproved algorithm. the FIPS 140-3 IG states that "Curves that are included in SP 800-186 but not" included in SP 800-56Arev3 are not approved for key agreement".
- TLS1-PRF
- HKDF
- HMAC, see
EVP_KEYMGMT-HMAC(7) - CMAC, see
EVP_KEYMGMT-CMAC(7) - ML-DSA-44, see
EVP_KEYMGMT-ML-DSA(7) - ML-DSA-65, see
EVP_KEYMGMT-ML-DSA(7) - ML-DSA-87, see
EVP_KEYMGMT-ML-DSA(7) - SLH-DSA-SHA2-128s, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHA2-128f, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHA2-192s, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHA2-192f, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHA2-256s, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHA2-256f, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHAKE-128s, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHAKE-128f, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHAKE-192s, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHAKE-192f, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHAKE-256s, see
EVP_KEYMGMT-SLH-DSA(7) - SLH-DSA-SHAKE-256f, see
EVP_KEYMGMT-SLH-DSA(7)
π Random Number Generation π
- CRNG-TEST, see
EVP_RAND-CRNG-TEST(7) - CTR-DRBG, see
EVP_RAND-CTR-DRBG(7) - HASH-DRBG, see
EVP_RAND-HASH-DRBG(7) - HMAC-DRBG, see
EVP_RAND-HMAC-DRBG(7) - TEST-RAND, see
EVP_RAND-TEST-RAND(7)- TEST-RAND is an unapproved algorithm. π
π₯ STATUS INDICATOR π₯
FIPS 140-3 requires that services provide an indicator when the service uses an approved cryptographic algorithm in an approved manner. in most cases the status can be determined implicitly by just observing the return code from an approved security service call β but the FIPS provider module may permit the use of approved cryptographic algorithms in a non-approved manner in some cases. π
for this, the Ubuntu FIPS provider module provides an explicit status indicator, implemented as a gettable provider module parameter, and you can access it using OSSL_PROVIDER_get_params(3) on the OSSL_PROVIDER associated with the FIPS provider module.
see OSSL_PARAM(3) for info about passing parameters.
the following OSSL_PARAM key is used for accessing the status indicator:
"ubuntu.fips-unapproved-usage"- (
UBUNTU_OSSL_PROV_FIPS_PARAM_UNAPPROVED_USAGE) <integer> β gets1if theOSSL_LIB_CTX(3)associated with theOSSL_PROVIDERhas been used to execute a security service call that used an approved cryptographic algorithm in a non-approved manner inside the FIPS provider module. querying this parameter resets it to 0. note that this only applies to services inside of the FIPS provider module boundary β it cannot indicate whether theOSSL_LIB_CTXhas been used to execute security service calls in other provider modules. π
- (
okay that's the lore so far... π more parts coming, don't touch that dial π
π§ͺ SELF TESTING π§ͺ
Okay bestie, so here's the thing about FIPS modules β they're required to run cryptographic algorithm self tests. That's just the vibe. FIPS 140-3 says you need known answer tests running on startup, plus conditional tests that run while cryptographic operations are happening. Both. Always. No skipping. π
There's an optional callback mechanism you can use to get info back out to the user β that's what OSSL_SELF_TEST_set_callback(3) is for. π«Ά
The parameters passed to that callback are described over in OSSL_SELF_TEST_new(3).
The OpenSSL FIPS module uses the mechanism below to spill all the tea about the self tests as they run. Super useful for debugging if a self test is failing. The callback also lets you force any self test to fail, so you can check that it behaves correctly when things go wrong. And heads up: all self tests run even if a self test failure occurs. It doesn't just stop and cry, it keeps going. π
The types the FIPS module passes to OSSL_SELF_TEST_onbegin()
"Module_Integrity"(OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY) β uses HMAC SHA256 on the module file to validate that the module has not been modified. The integrity value gets compared to a value written to a configuration file during installation. π"KAT_Mac"(OSSL_SELF_TEST_TYPE_KAT_MAC) β used during the Module Integrity test to perform a known answer test on HMAC SHA256 before using it. In pre-4.0 versions,OSSL_SELF_TEST_TYPE_KAT_INTEGRITY("KAT_Integrity") was used for this instead."KAT_Cipher"(OSSL_SELF_TEST_TYPE_KAT_CIPHER) β known answer test for a symmetric cipher."KAT_AsymmetricCipher"(OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER) β known answer test for a asymmetric cipher."KAT_Digest"(OSSL_SELF_TEST_TYPE_KAT_DIGEST) β known answer test for a digest."KAT_AsymmetricKeyGeneration"(OSSL_SELF_TEST_TYPE_KAT_ASYM_KEYGEN) β known answer test for asymmetric key generation."KAT_Signature"(OSSL_SELF_TEST_TYPE_KAT_SIGNATURE) β known answer test for a signature."PCT_Signature"(OSSL_SELF_TEST_TYPE_PCT_SIGNATURE) β pairwise consistency check for a signature."KAT_KDF"(OSSL_SELF_TEST_TYPE_KAT_KDF) β known answer test for a key derivation function."KAT_KA"(OSSL_SELF_TEST_TYPE_KAT_KA) β known answer test for key agreement."KAT_KEM"(OSSL_SELF_TEST_TYPE_KAT_KEM) β known answer test for key encapsulation."DRBG"(OSSL_SELF_TEST_TYPE_DRBG) β known answer test for a deterministic random bit generator."Conditional_PCT"(OSSL_SELF_TEST_TYPE_PCT) β conditional test that is run during the generation of key pairs."Import_PCT"(OSSL_SELF_TEST_TYPE_PCT_IMPORT) β conditional test that is run during the import of key pairs."Conditional_KAT"(OSSL_SELF_TEST_TYPE_PCT_KAT) β conditional test run during generation that derive the public key from the private key and checks that the public key matches. This is a SP 800-56A requirement, btw."Continuous_RNG_Test"(OSSL_SELF_TEST_TYPE_CRNG) β continuous random number generator test."Install_Integrity"(OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY) β this is deprecated. The option is no longer used since FIPS 140-3 requires self tests to always run on startup. Previous FIPS 140-2 validations allowed the self tests to be run just once. Rip old behavior, you will not be missed πͺ¦
The descriptions the FIPS module passes to OSSL_SELF_TEST_onbegin()
"HMAC"(OSSL_SELF_TEST_DESC_INTEGRITY_HMAC) β"Module_Integrity"uses this one."RSA"(OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1)"RSA"(OSSL_SELF_TEST_DESC_PCT_RSA)"ECDSA"(OSSL_SELF_TEST_DESC_PCT_ECDSA)"EDDSA"(OSSL_SELF_TEST_DESC_PCT_EDDSA)"DSA"(OSSL_SELF_TEST_DESC_PCT_DSA)"ML-DSA"(OSSL_SELF_TEST_DESC_PCT_ML_DSA)"ML-KEM"(OSSL_SELF_TEST_DESC_PCT_ML_KEM)"SLH-DSA"(OSSL_SELF_TEST_DESC_PCT_SLH_DSA)
Key generation tests used with the "Pairwise_Consistency_Test" type.
"RSA_Encrypt"(OSSL_SELF_TEST_DESC_ASYM_RSA_ENC)"RSA_Decrypt"(OSSL_SELF_TEST_DESC_ASYM_RSA_DEC)
"KAT_AsymmetricCipher" uses this to indicate an encrypt or decrypt KAT.
"ML-DSA"(OSSL_SELF_TEST_DESC_KEYGEN_ML_DSA)"ML-KEM"(OSSL_SELF_TEST_DESC_KEYGEN_ML_KEM)"SLH-DSA"(OSSL_SELF_TEST_DESC_KEYGEN_SLH_DSA)
"KAT_AsymmetricKeyGeneration" uses this to indicate a key generation KAT.
"AES_GCM"(OSSL_SELF_TEST_DESC_CIPHER_AES_GCM)"AES_ECB_Decrypt"(OSSL_SELF_TEST_DESC_CIPHER_AES_ECB)"TDES"(OSSL_SELF_TEST_DESC_CIPHER_TDES)
Symmetric cipher tests used with the "KAT_Cipher" type.
"SHA1"(OSSL_SELF_TEST_DESC_MD_SHA1)"SHA2"(OSSL_SELF_TEST_DESC_MD_SHA2)"SHA3"(OSSL_SELF_TEST_DESC_MD_SHA3)
Digest tests used with the "KAT_Digest" type.
"DSA"(OSSL_SELF_TEST_DESC_SIGN_DSA)"RSA"(OSSL_SELF_TEST_DESC_SIGN_RSA)"ECDSA"(OSSL_SELF_TEST_DESC_SIGN_ECDSA)"DetECDSA"(OSSL_SELF_TEST_DESC_SIGN_DetECDSA)"EDDSA"(OSSL_SELF_TEST_DESC_SIGN_EDDSA)"LMS"(OSSL_SELF_TEST_DESC_SIGN_LMS)"ML-DSA"(OSSL_SELF_TEST_DESC_SIGN_ML_DSA)"SLH-DSA"(OSSL_SELF_TEST_DESC_SIGN_SLH_DSA)
Signature tests used with the "KAT_Signature" type.
"ECDH"(OSSL_SELF_TEST_DESC_KA_ECDH)"DH"(OSSL_SELF_TEST_DESC_KA_DH)
Key agreement tests used with the "KAT_KA" type.
"HKDF"(OSSL_SELF_TEST_DESC_KDF_HKDF)"TLS13_KDF_EXTRACT"(OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT)"TLS13_KDF_EXPAND"(OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND)"SSKDF"(OSSL_SELF_TEST_DESC_KDF_SSKDF)"X963KDF"(OSSL_SELF_TEST_DESC_KDF_X963KDF)"X942KDF"(OSSL_SELF_TEST_DESC_KDF_X942KDF)"PBKDF2"(OSSL_SELF_TEST_DESC_KDF_PBKDF2)"SNMPKDF"(OSSL_SELF_TEST_DESC_KDF_SNMPKDF)"SRTPKDF"(OSSL_SELF_TEST_DESC_KDF_SRTPKDF)"SSHKDF"(OSSL_SELF_TEST_DESC_KDF_SSHKDF)"TLS12_PRF"(OSSL_SELF_TEST_DESC_KDF_TLS12_PRF)"KBKDF"(OSSL_SELF_TEST_DESC_KDF_KBKDF)
Key Encapsulation Function tests used with the "KAT_KEM" type.
"KEM_Encap"(OSSL_SELF_TEST_DESC_ENCAP_KEM)"KEM_Decap"(OSSL_SELF_TEST_DESC_DECAP_KEM)"KEM_Decap_Reject"(OSSL_SELF_TEST_DESC_DECAP_REJ_KEM)
Key Derivation Function tests used with the "KAT_KDF" type.
"CTR"(OSSL_SELF_TEST_DESC_DRBG_CTR)"HASH"(OSSL_SELF_TEST_DESC_DRBG_HASH)"HMAC"(OSSL_SELF_TEST_DESC_DRBG_HMAC)
DRBG tests used with the "DRBG" type.
"RNG"(OSSL_SELF_TEST_DESC_RNG)
"Continuous_RNG_Test" uses this.
β¨ EXAMPLES β¨
Here's a cute lil self test callback, shown below for illustrative purposes. It's giving "hello world but make it FIPS." π
#include <openssl/self_test.h>
static OSSL_CALLBACK self_test_cb;
static int self_test_cb(const OSSL_PARAM params[], void *arg)
{
int ret = 0;
const OSSL_PARAM *p = NULL;
const char *phase = NULL, *type = NULL, *desc = NULL;
p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
phase = (const char *)p->data;
p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
desc = (const char *)p->data;
p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
type = (const char *)p->data;
/* Do some logging */
if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
BIO_printf(bio_out, "%s : (%s) : ", desc, type);
if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
|| strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
BIO_printf(bio_out, "%s\n", phase);
/* Corrupt the SHA1 self test during the 'corrupt' phase by returning 0 */
if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
&& strcmp(desc, OSSL_SELF_TEST_DESC_MD_SHA1) == 0) {
BIO_printf(bio_out, "%s %s", phase, desc);
return 0;
}
ret = 1;
err:
return ret;
}
π NOTES π
Okay so, some released versions of OpenSSL do not include a validated FIPS provider. To figure out which versions actually went through the validation process, go check the OpenSSL Downloads page <https://www.openssl.org/source/>. If you need FIPS-approved functionality, it is essential to build your FIPS provider using one of the validated versions listed there. Don't freestyle it bestie, this is the whole point. π
But here's the slay part β normally you can use a FIPS provider built from one of those validated versions alongside libcrypto and libssl compiled from any release within the same major release series. That flexibility is how you get bug fixes and CVEs patched when they fall outside the FIPS boundary. π
You can load the FIPS provider into multiple library contexts like any other provider. However, the following restriction applies: the FIPS provider cannot be used by multiple copies of OpenSSL libcrypto in a single process.
Here's why, and it's lowkey cursed: the provider saves core callbacks to the libcrypto it got in the OSSL_provider_init() call into global data. So if subsequent invocations of its OSSL_provider_init() function hand it different addresses for those callbacks than the initial call did, it will fail. π
When does that happen? When different copies of libcrypto are hanging out in the process memory and both try to load the same FIPS provider. Awkward. π¬
A workaround: load a different copy of the FIPS provider for each of the libcrypto instances in the process. Iconic problem-solving, honestly. π
π SEE ALSO π
openssl-fipsinstall(1), fips_config(5), OSSL_SELF_TEST_set_callback(3), OSSL_SELF_TEST_new(3), OSSL_PARAM(3), openssl-core.h(7), openssl-core_dispatch.h(7), provider(7), <https://www.openssl.org/source/>
π°οΈ HISTORY π°οΈ
- The
HKDF-SHA256,HKDF-SHA384andHKDF-SHA512algorithms were added in OpenSSL 3.6. β¨ - The
CSHAKE-128andCSHAKE-256algorithms were added in OpenSSL 4.0. π¦ - All other functionality was added in OpenSSL 3.0. The origin story, fr fr.
Β©οΈ COPYRIGHT Β©οΈ
Copyright 2019-2026 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.
And that's a wrap on part 2, bestie!! π«Ά This whole thing came from OpenSSL 4.0.3, dated 2026-09-29, and it's filed under OSSL_PROVIDER-FIPS(7SSL). Go forth and self-test responsibly. πβ¨π
π¦ where this page comes from
- ubuntu stonking: openssl 4.0.3-1ubuntu1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms