diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 30b3ba8b2ff..b4c0b0ecbc2 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4779,6 +4779,30 @@ static void wc_ecc_free_async(ecc_key* key) #ifdef HAVE_ECC_DHE +#if FIPS_VERSION3_GE(7,0,0) +/* The module's KAS-ECC-SSC validation covers only P-256, P-384 and P-521, + * and FIPS 140-3 IG C.B does not permit an algorithm implementation that + * has not been CAVP tested to be used in an approved mode; SP 800-131A + * Rev. 2 Section 5 (Table 4) additionally disallows EC key agreement + * providing fewer than 112 bits of security strength (len(n) < 224). The + * curve is resolved from key->dp, never from ecc_sets[key->idx], so a + * custom-curve key (idx == ECC_CUSTOM_IDX) cannot index out of range. */ +static int ecc_fips_kas_curve_allowed(const ecc_key* key) +{ + if (key->dp == NULL) { + return ECC_BAD_ARG_E; + } + switch (key->dp->id) { + case ECC_SECP256R1: + case ECC_SECP384R1: + case ECC_SECP521R1: + return 0; + default: + return ECC_CURVE_OID_E; + } +} +#endif /* FIPS_VERSION3_GE(7,0,0) */ + /** Create an ECC shared secret between two keys private_key The private ECC key (heap hint based off of private key) @@ -4808,7 +4832,27 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, return BAD_FUNC_ARG; } -#ifdef WOLF_CRYPTO_CB +#if FIPS_VERSION3_GE(7,0,0) + /* Gate ahead of the crypto callback and the hardware dispatch below so no + * backend computes a shared secret on a curve outside the validated + * KAS-ECC-SSC set (FIPS 140-3 IG C.B). */ + err = ecc_fips_kas_curve_allowed(private_key); + if (err == 0) { + err = ecc_fips_kas_curve_allowed(public_key); + } + if (err != 0) { + return err; + } +#endif + +#if defined(WOLF_CRYPTO_CB) && !FIPS_VERSION3_GE(7,0,0) + /* The ECDH crypto-callback dispatch is compiled out of v7 FIPS builds: + * the module is validated as a software module, FIPS 140-3 IG C.B bars + * using an algorithm implementation in the approved mode without CAVP + * testing, and an offload to a callback or hardware executes outside + * the validated module. A hybrid software-plus-hardware module + * configuration would reintroduce the dispatch under its own build + * option. */ #ifndef WOLF_CRYPTO_CB_FIND if (private_key->devId != INVALID_DEVID) #endif @@ -5296,6 +5340,15 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, return ECC_BAD_ARG_E; } +#if FIPS_VERSION3_GE(7,0,0) + /* Direct callers of this entry point (and the async path) get the same + * KAS-ECC-SSC validated-curve gate as wc_ecc_shared_secret(). */ + err = ecc_fips_kas_curve_allowed(private_key); + if (err != 0) { + return err; + } +#endif + switch (private_key->state) { case ECC_STATE_NONE: case ECC_STATE_SHARED_SEC_GEN: @@ -6306,6 +6359,26 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id, { int err; +#if FIPS_VERSION3_GE(7,0,0) + /* SP 800-131A Rev. 2 Table 2 disallows ECDSA key pair generation + * providing fewer than 112 bits of security strength (len(n) < 224), and + * SP 800-186 Section 3.2.1.1 retains P-192 for legacy use only, so + * refuse to generate on any curve smaller than 224 bits. The bound + * mirrors wc_ecc_set_curve(): an explicit curve_id selects the curve + * directly, otherwise keysize selects the smallest compiled curve that + * fits, so keysize 0 would land on the smallest compiled curve and is + * rejected too. Signature verification with the small curves stays + * available (legacy use per SP 800-131A Rev. 2 Table 2). */ + if (curve_id > ECC_CURVE_DEF) { + if (wc_ecc_get_curve_size_from_id(curve_id) < WC_ECC_FIPS_GEN_MIN) { + return ECC_CURVE_OID_E; + } + } + else if (keysize < WC_ECC_FIPS_GEN_MIN) { + return ECC_CURVE_OID_E; + } +#endif + err = _ecc_make_key_ex(rng, keysize, key, curve_id, flags); #if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \ @@ -7670,6 +7743,17 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return ECC_BAD_ARG_E; } +#if FIPS_VERSION3_GE(7,0,0) + /* SP 800-131A Rev. 2 Table 2: ECDSA digital signature generation with + * len(n) < 224 is disallowed, while signature verification with those + * curves remains legacy use, so only the signing path is gated. The + * curve is resolved from key->dp, never from ecc_sets[key->idx], so a + * custom-curve key (idx == ECC_CUSTOM_IDX) cannot index out of range. */ + if (key->dp->size < WC_ECC_FIPS_GEN_MIN) { + return SIG_TYPE_E; + } +#endif + #if defined(WOLFSSL_SP_MATH) if (key->idx == ECC_CUSTOM_IDX || (1 #ifndef WOLFSSL_SP_NO_256 diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 60d29f30e03..2d9c8bf32ad 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -622,6 +622,19 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, WOLFSSL_ERROR_VERBOSE(HMAC_MIN_KEYLEN_E); return HMAC_MIN_KEYLEN_E; } +#if FIPS_VERSION3_GE(7,0,0) + /* FIPS 198-1 Section 4 (step 2) sets K0 = H(K) when the key is + * longer than the block size, so any length computes correctly, but + * the module's CAVP HMAC testing covers key lengths only up to + * 1024 bits and FIPS 140-3 IG C.B does not permit an algorithm + * implementation to be used in the approved mode outside its tested + * scope, so reject longer keys unless the caller explicitly opts out + * of the approved-mode limits with allowFlag. */ + if (length > HMAC_FIPS_MAX_KEY) { + WOLFSSL_ERROR_VERBOSE(BAD_LENGTH_E); + return BAD_LENGTH_E; + } +#endif } #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 2e396516740..828d930004d 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -695,6 +695,77 @@ static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz * and array_add_one (shared utility) which both must * remain available to SHA-512-only builds */ +#if FIPS_VERSION3_GE(7,0,0) +/* SP 800-90A Rev. 1 Section 9.2 requires the reseed function to obtain its + * entropy input from "a randomness source ... that supports the security + * strength of the DRBG" and lists entropy_input among the information "not + * provided by the consuming application": "it shall not be provided by the + * consuming application as an input parameter during the reseed request" + * (reseed process step 4: Get_entropy_input). Section 9.2 does permit + * additional_input from the consuming application, and its length may be + * zero, so the caller's bytes are mixed as the additional_input argument of + * the Section 10.1.1.3 reseed algorithm while fresh entropy is drawn from + * the module's seed source exactly as the end-of-seedlife reseed in + * PollAndReSeed() draws it. */ +static int Rng_ReseedFromSeedSource(WC_RNG* rng, const byte* addIn, + word32 addInSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap, + DYNAMIC_TYPE_SEED); + if (newSeed == NULL) { + return MEMORY_E; + } +#else + byte newSeed[SEED_SZ + SEED_BLOCK_SZ]; +#endif + +#ifdef WC_RNG_SEED_CB + if (seedCb == NULL) { + ret = DRBG_NO_SEED_CB; + } + else { + ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ); + if (ret != 0) { + ret = DRBG_FAILURE; + } + } +#else + ret = wc_GenerateSeed(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ); + if (ret != 0) { + ret = DRBG_FAILURE; + } +#endif + if (ret == DRBG_SUCCESS) { + ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ); + } + if (ret == DRBG_SUCCESS) { +#ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) { + ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, + newSeed + SEED_BLOCK_SZ, SEED_SZ, + addIn, addInSz); + } +#endif +#ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbgType == WC_DRBG_SHA512) { + ret = Hash512_DRBG_Reseed((DRBG_SHA512_internal *)rng->drbg512, + newSeed + SEED_BLOCK_SZ, SEED_SZ, + addIn, addInSz); + } +#endif + } + /* SP 800-90A Rev. 1 Section 8.6.6: the entropy input is a critical + * security parameter, so it does not outlive the reseed. */ + ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ); +#ifdef WOLFSSL_SMALL_STACK + XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED); +#endif + return ret; +} +#endif /* FIPS_VERSION3_GE(7,0,0) */ + /* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */ int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) { @@ -713,8 +784,14 @@ int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) #endif return BAD_FUNC_ARG; } +#if FIPS_VERSION3_GE(7,0,0) + /* Caller bytes become additional_input; entropy comes from the + * module's seed source (SP 800-90A Rev. 1 Section 9.2). */ + return Rng_ReseedFromSeedSource(rng, seed, seedSz); +#else return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz, NULL, 0); +#endif } #endif #ifdef WOLFSSL_DRBG_SHA512 @@ -728,8 +805,14 @@ int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) #endif return BAD_FUNC_ARG; } +#if FIPS_VERSION3_GE(7,0,0) + /* Caller bytes become additional_input; entropy comes from the + * module's seed source (SP 800-90A Rev. 1 Section 9.2). */ + return Rng_ReseedFromSeedSource(rng, seed, seedSz); +#else return Hash512_DRBG_Reseed((DRBG_SHA512_internal *)rng->drbg512, seed, seedSz, NULL, 0); +#endif } #endif diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index f70bec33932..22507f1f49d 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -9890,6 +9890,31 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha_test(void) #endif } +#if FIPS_VERSION3_GE(7,0,0) + /* Keys above HMAC_FIPS_MAX_KEY (1024 bits) are outside the module's + * CAVP-tested key range: wc_HmacSetKey must reject them, a key at the + * maximum must pass, and the wc_HmacSetKey_ex allowFlag escape must + * still accept the longer key as a non-approved use. */ + { + byte maxKey[HMAC_FIPS_MAX_KEY + 1]; + XMEMSET(maxKey, 0x0b, sizeof(maxKey)); + if ((ret = wc_HmacInit(&hmac, HEAP_HINT, devId)) != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey(&hmac, WC_SHA, maxKey, (word32)sizeof(maxKey)); + if (ret != WC_NO_ERR_TRACE(BAD_LENGTH_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey(&hmac, WC_SHA, maxKey, + (word32)sizeof(maxKey) - 1); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey_ex(&hmac, WC_SHA, maxKey, (word32)sizeof(maxKey), + allowShortKeyWithFips); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + wc_HmacFree(&hmac); + } +#endif + out: wc_HmacFree(&hmac); @@ -9994,6 +10019,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha224_test(void) ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)keys[i], (word32)XSTRLEN(keys[i])); +#if FIPS_VERSION3_GE(7,0,0) + /* Keys above HMAC_FIPS_MAX_KEY (1024 bits) are outside the module's + * CAVP-tested key range and are rejected in approved mode; the long + * RFC 4231 style vectors stay covered through the wc_HmacSetKey_ex + * allowFlag escape. */ + if (XSTRLEN(keys[i]) > HMAC_FIPS_MAX_KEY) { + if (ret != WC_NO_ERR_TRACE(BAD_LENGTH_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey_ex(&hmac, WC_SHA224, (byte*)keys[i], + (word32)XSTRLEN(keys[i]), 1); + } +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -10155,6 +10192,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha256_test(void) ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)keys[i], (word32)XSTRLEN(keys[i])); +#if FIPS_VERSION3_GE(7,0,0) + /* Keys above HMAC_FIPS_MAX_KEY (1024 bits) are outside the module's + * CAVP-tested key range and are rejected in approved mode; the long + * RFC 4231 style vectors stay covered through the wc_HmacSetKey_ex + * allowFlag escape. */ + if (XSTRLEN(keys[i]) > HMAC_FIPS_MAX_KEY) { + if (ret != WC_NO_ERR_TRACE(BAD_LENGTH_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey_ex(&hmac, WC_SHA256, (byte*)keys[i], + (word32)XSTRLEN(keys[i]), 1); + } +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_I(i), out); @@ -10317,6 +10366,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha384_test(void) ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)keys[i], (word32)XSTRLEN(keys[i])); +#if FIPS_VERSION3_GE(7,0,0) + /* Keys above HMAC_FIPS_MAX_KEY (1024 bits) are outside the module's + * CAVP-tested key range and are rejected in approved mode; the long + * RFC 4231 style vectors stay covered through the wc_HmacSetKey_ex + * allowFlag escape. */ + if (XSTRLEN(keys[i]) > HMAC_FIPS_MAX_KEY) { + if (ret != WC_NO_ERR_TRACE(BAD_LENGTH_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey_ex(&hmac, WC_SHA384, (byte*)keys[i], + (word32)XSTRLEN(keys[i]), 1); + } +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -10472,6 +10533,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha512_test(void) ret = wc_HmacSetKey(&hmac, WC_SHA512, (byte*)keys[i], (word32)XSTRLEN(keys[i])); +#if FIPS_VERSION3_GE(7,0,0) + /* Keys above HMAC_FIPS_MAX_KEY (1024 bits) are outside the module's + * CAVP-tested key range and are rejected in approved mode; the long + * RFC 4231 style vectors stay covered through the wc_HmacSetKey_ex + * allowFlag escape. */ + if (XSTRLEN(keys[i]) > HMAC_FIPS_MAX_KEY) { + if (ret != WC_NO_ERR_TRACE(BAD_LENGTH_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey_ex(&hmac, WC_SHA512, (byte*)keys[i], + (word32)XSTRLEN(keys[i]), 1); + } +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -10685,6 +10758,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha3_test(void) ret = wc_HmacSetKey(&hmac, hashType[j], (byte*)key[i], (word32)XSTRLEN(key[i])); +#if FIPS_VERSION3_GE(7,0,0) + /* Keys above HMAC_FIPS_MAX_KEY (1024 bits) are outside the + * module's CAVP-tested key range and are rejected in approved + * mode; the big-key vector stays covered through the + * wc_HmacSetKey_ex allowFlag escape. */ + if (XSTRLEN(key[i]) > HMAC_FIPS_MAX_KEY) { + if (ret != WC_NO_ERR_TRACE(BAD_LENGTH_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_HmacSetKey_ex(&hmac, hashType[j], (byte*)key[i], + (word32)XSTRLEN(key[i]), 1); + } +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -30932,7 +31017,13 @@ static wc_test_ret_t rsa_even_mod_test(WC_RNG* rng, RsaKey* key) #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) ret = wc_RsaPublicEncrypt(tmp, inLen, out, (int)outSz, key, rng); if (ret != WC_NO_ERR_TRACE(MP_VAL) && - ret != WC_NO_ERR_TRACE(MP_EXPTMOD_E)) + ret != WC_NO_ERR_TRACE(MP_EXPTMOD_E) +#if FIPS_VERSION3_GE(7,0,0) + /* v7 refuses PKCS#1 v1.5 key transport before touching the key + * (SP 800-131A Rev. 2 Section 6 Table 5). */ + && ret != WC_NO_ERR_TRACE(FIPS_WRONG_API_E) +#endif + ) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_even_mod); } @@ -30942,7 +31033,11 @@ static wc_test_ret_t rsa_even_mod_test(WC_RNG* rng, RsaKey* key) ret = wc_RsaPrivateDecrypt(out, outSz, plain, (int)plainSz, key); if (ret != WC_NO_ERR_TRACE(MP_VAL) && ret != WC_NO_ERR_TRACE(MP_EXPTMOD_E) && - ret != WC_NO_ERR_TRACE(MP_INVMOD_E)) + ret != WC_NO_ERR_TRACE(MP_INVMOD_E) +#if FIPS_VERSION3_GE(7,0,0) + && ret != WC_NO_ERR_TRACE(FIPS_WRONG_API_E) +#endif + ) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_even_mod); } @@ -31987,6 +32082,23 @@ static wc_test_ret_t rsa_oaep_padding_test(RsaKey* key, WC_RNG* rng) /* check using pkcsv15 padding with _ex API */ XMEMSET(plain, 0, plainSz); +#if FIPS_VERSION3_GE(7,0,0) + /* SP 800-131A Rev. 2 Section 6 (Table 5): WC_RSA_PKCSV15_PAD key + * transport is refused by the extended wrappers under v7. */ + WC_TEST_RSA_ASYNC_DO(&key->asyncDev, + wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, key, rng, + WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0)); + if (ret != WC_NO_ERR_TRACE(FIPS_WRONG_API_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa); +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + WC_TEST_RSA_ASYNC_DO(&key->asyncDev, + wc_RsaPrivateDecrypt_ex(out, (word32)outSz, plain, plainSz, key, + WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0)); + if (ret != WC_NO_ERR_TRACE(FIPS_WRONG_API_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + ret = 0; +#else WC_TEST_RSA_ASYNC_DO(&key->asyncDev, wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, key, rng, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0)); @@ -32007,6 +32119,7 @@ static wc_test_ret_t rsa_oaep_padding_test(RsaKey* key, WC_RNG* rng) } TEST_SLEEP(); #endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* FIPS_VERSION3_GE(7,0,0) */ exit_rsa: WC_FREE_VAR(in, HEAP_HINT); @@ -32051,6 +32164,7 @@ static wc_test_ret_t rsa_pkcs1_test(RsaKey* key, WC_RNG* rng, if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_pkcs1); #endif +#if FIPS_VERSION3_LT(7,0,0) #ifndef WOLFSSL_MICROCHIP_TA100 WC_TEST_RSA_ASYNC_DO(&key->asyncDev, wc_RsaPublicEncrypt(in, inLen, out, outSz, key, rng)); @@ -32091,6 +32205,25 @@ static wc_test_ret_t rsa_pkcs1_test(RsaKey* key, WC_RNG* rng, ERROR_OUT(WC_TEST_RET_ENC_NC, exit_rsa_pkcs1); } TEST_SLEEP(); +#else /* FIPS_VERSION3_GE(7,0,0) */ + /* SP 800-131A Rev. 2 Section 6 (Table 5): RSAES-PKCS1-v1_5 key transport + * is disallowed after December 31, 2023; the v7 module refuses the fixed + * PKCS#1 v1.5 services with FIPS_WRONG_API_E. */ + WC_TEST_RSA_ASYNC_DO(&key->asyncDev, + wc_RsaPublicEncrypt(in, inLen, out, outSz, key, rng)); + if (ret != WC_NO_ERR_TRACE(FIPS_WRONG_API_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_pkcs1); + idx = (word32)outSz; + WC_TEST_RSA_ASYNC_DO(&key->asyncDev, + wc_RsaPrivateDecrypt(out, idx, plain, plainSz, key)); + if (ret != WC_NO_ERR_TRACE(FIPS_WRONG_API_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_pkcs1); + WC_TEST_RSA_ASYNC_DO(&key->asyncDev, + wc_RsaPrivateDecryptInline(out, idx, &res, key)); + if (ret != WC_NO_ERR_TRACE(FIPS_WRONG_API_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_pkcs1); + ret = 0; +#endif /* FIPS_VERSION3_LT(7,0,0) */ WC_TEST_RSA_ASYNC_DO(&key->asyncDev, wc_RsaSSL_Sign(in, inLen, out, outSz, key, rng)); @@ -38106,6 +38239,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void) ret = wc_PBKDF2_ex(derived, (byte*)passwd, (int)XSTRLEN(passwd), salt, (int)sizeof(salt), iterations, kLen, WC_SHA256, HEAP_HINT, devId); +#if FIPS_VERSION3_GE(7,0,0) + /* 8-byte salt: computed, but the module must deliver the + * WC_FIPS_NOT_APPROVED indicator to the caller per SP 800-132 + * Section 5.1 ("shall be at least 128 bits") and FIPS 140-3 IG 2.4.C; + * the test fails if the indicator is missing. */ + if (ret != WC_FIPS_NOT_APPROVED) + return WC_TEST_RET_ENC_EC(ret); + ret = 0; +#endif if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -38533,6 +38675,21 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #endif /* !NO_SHA256 */ #ifndef NO_SHA +#if FIPS_VERSION3_GE(7,0,0) + /* SP 800-56C Rev. 2 Section 4 approves the HKDF auxiliary function only + * with an approved hash and the module's key-derivation coverage is + * SHA-256/384/512, so the generic wrappers refuse SHA-1 (see + * HkdfDigestAllowed in fips.c). */ + ret = wc_HKDF_Extract_ex(WC_SHA, NULL, 0, ikm1, (word32)sizeof(ikm1), + prk, HEAP_HINT, devId); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_EC(ret); + ret = wc_HKDF_Expand_ex(WC_SHA, prk, WC_SHA_DIGEST_SIZE, NULL, 0, + okm1, (word32)L, HEAP_HINT, devId); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_EC(ret); + ret = 0; +#else #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ret = wc_HKDF_Extract_ex(WC_SHA, NULL, 0, ikm1, (word32)sizeof(ikm1), prk, HEAP_HINT, devId); @@ -38554,6 +38711,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) if (XMEMCMP(okm1, res1, (unsigned long)L) != 0) return WC_TEST_RET_ENC_NC; +#endif /* FIPS_VERSION3_GE(7,0,0) */ #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ @@ -42460,6 +42618,15 @@ static wc_test_ret_t ecc_test_sign_vectors(WC_RNG* rng) #endif ret = wc_ecc_sign_set_k(k, sizeof(k), key); +#if FIPS_VERSION3_GE(7,0,0) + /* FIPS 186-5 Section 6.3: a caller-supplied per-message secret is a + * non-approved use, so the module must deliver the WC_FIPS_NOT_APPROVED + * indicator to the caller (FIPS 140-3 IG 2.4.C); the test fails if the + * indicator is missing. */ + if (ret != WC_FIPS_NOT_APPROVED) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + ret = 0; +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -42471,6 +42638,16 @@ static wc_test_ret_t ecc_test_sign_vectors(WC_RNG* rng) if (ret == 0) ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigSz, rng, key); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); +#if FIPS_VERSION3_GE(7,0,0) + /* The signature consuming the staged k must deliver the + * WC_FIPS_NOT_APPROVED indicator to the caller (FIPS 186-5 + * Section 6.3, FIPS 140-3 IG 2.4.C); the test fails if the indicator + * is missing, and the signature bytes are still verified against the + * expected vector below. */ + if (ret != WC_FIPS_NOT_APPROVED) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + ret = 0; +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); TEST_SLEEP(); @@ -42492,6 +42669,9 @@ static wc_test_ret_t ecc_test_sign_vectors(WC_RNG* rng) if (ret == 0) ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigSz, rng, key); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + /* The staged k was consumed by the first signature, so this second + * signature uses a fresh random k and must succeed without the + * WC_FIPS_NOT_APPROVED indicator. */ if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); TEST_SLEEP(); @@ -43258,6 +43438,24 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif WARNING_OUT(ECC_CURVE_OID_E, done); #ifdef HAVE_ECC_DHE +#if FIPS_VERSION3_GE(7,0,0) + /* The module's KAS-ECC-SSC validation covers P-256, P-384 and P-521 + * only, so under v7 wc_ecc_shared_secret refuses every other curve with + * ECC_CURVE_OID_E (FIPS 140-3 IG C.B; SP 800-131A Rev. 2 Section 5 + * Table 4 for len(n) < 224). Assert the refusal once, then skip the + * composite flow for that curve the same way the key-size mismatch above + * does; P-224 signing coverage remains in the ECDSA vector tests. */ + if (userA->dp != NULL && + userA->dp->id != ECC_SECP256R1 && + userA->dp->id != ECC_SECP384R1 && + userA->dp->id != ECC_SECP521R1) { + x = ECC_SHARED_SIZE; + ret = wc_ecc_shared_secret(userA, userB, sharedA, &x); + if (ret != WC_NO_ERR_TRACE(ECC_CURVE_OID_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + WARNING_OUT(ECC_CURVE_OID_E, done); + } +#endif #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ !defined(HAVE_SELFTEST) diff --git a/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index 1dd946f3d40..089b4147c38 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/wolfssl/wolfcrypt/hmac.h @@ -69,6 +69,14 @@ enum { HMAC_FIPS_MIN_KEY = 14, /* 112 bit key length minimum. Note that this * minimum also applies to the salt length for * HKDF. */ +#if FIPS_VERSION3_GE(7,0,0) + HMAC_FIPS_MAX_KEY = 128, /* 1024 bit key length maximum for the approved + * mode. FIPS 198-1 Section 4 (step 2) reduces + * a key longer than the block size to + * K0 = H(K), so longer keys compute correctly, + * but key lengths above 1024 bits are outside + * the module's CAVP-tested HMAC key range. */ +#endif IPAD = 0x36, OPAD = 0x5C,