From aae4b466ca81076024dd63c86f2f65069870856f Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Sat, 7 Nov 2026 13:22:54 -0700 Subject: [PATCH 1/4] pbkdf2: 16-byte PBES2 default salt; callers accept the v7 short-salt indicator --- tests/api.c | 54 +++++++++++++++++++++++++++----------- tests/api/test_asn.c | 30 +++++++++++++++++++++ tests/api/test_pwdbased.c | 23 ++++++++++++++++ wolfcrypt/src/asn.c | 9 +++++-- wolfcrypt/src/evp.c | 14 ++++++++++ wolfcrypt/src/wc_encrypt.c | 11 ++++++++ wolfcrypt/test/test.c | 10 +++++++ 7 files changed, 134 insertions(+), 17 deletions(-) diff --git a/tests/api.c b/tests/api.c index 0e2747575fa..990d8bc4015 100644 --- a/tests/api.c +++ b/tests/api.c @@ -13585,6 +13585,7 @@ static int test_wolfSSL_PKCS5(void) const char *passwd = "pass1234"; #endif const unsigned char *salt = (unsigned char *)"salt1234"; + const unsigned char *salt16 = (unsigned char *)"salt1234salt5678"; unsigned char *out = (unsigned char *)XMALLOC(WC_SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); int ret = 0; @@ -13593,11 +13594,16 @@ static int test_wolfSSL_PKCS5(void) ExpectIntEQ(ret = PKCS5_PBKDF2_HMAC_SHA1(passwd,(int)XSTRLEN(passwd), salt, (int)XSTRLEN((const char *) salt), 10, WC_SHA_DIGEST_SIZE,out), WOLFSSL_SUCCESS); + /* A 16-byte salt gets no FIPS v7 indicator, so none may be cleared. */ + ExpectIntEQ(PKCS5_PBKDF2_HMAC_SHA1(passwd, (int)XSTRLEN(passwd), salt16, + 16, 10, WC_SHA_DIGEST_SIZE, out), WOLFSSL_SUCCESS); #ifdef WOLFSSL_SHA512 ExpectIntEQ(ret = PKCS5_PBKDF2_HMAC(passwd,(int)XSTRLEN(passwd), salt, (int)XSTRLEN((const char *) salt), 10, wolfSSL_EVP_sha512(), WC_SHA_DIGEST_SIZE, out), SSL_SUCCESS); + ExpectIntEQ(PKCS5_PBKDF2_HMAC(passwd, (int)XSTRLEN(passwd), salt16, 16, + 10, wolfSSL_EVP_sha512(), WC_SHA_DIGEST_SIZE, out), SSL_SUCCESS); #endif XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -21812,7 +21818,7 @@ static int test_wolfSSL_PKCS8_d2i(void) #if !defined(NO_DES3) && !defined(NO_SHA) && defined(HAVE_PBKDF2) ExpectNotNull(bio = BIO_new(BIO_s_mem())); /* Write Encrypted PKCS#8 PEM to BIO. */ - bytes = 1834; + bytes = 1846; ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_des_ede3_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_des_ede3_cbc(), @@ -21895,8 +21901,8 @@ static int test_wolfSSL_PKCS8_d2i(void) bio = NULL; #ifdef HAVE_PBKDF2 ExpectNotNull(bio = BIO_new(BIO_s_mem())); - /* Write Encrypted PKCS#8 PEM to BIO (test write 0 then 379) */ - bytes = 379; + /* Write Encrypted PKCS#8 PEM to BIO (test write 0 then 391) */ + bytes = 391; ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(), NULL, 0, NoPasswordCallBack, (void*)"yassl123"), 0); ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(), @@ -28153,13 +28159,14 @@ static int test_wolfSSL_CRYPTO_memcmp(void) | wolfCrypt ASN *----------------------------------------------------------------------------*/ -static int test_wc_CreateEncryptedPKCS8Key(void) -{ - EXPECT_DECLS; #if defined(HAVE_PKCS8) && !defined(NO_PWDBASED) && defined(WOLFSSL_AES_256) \ && !defined(NO_AES_CBC) && !defined(NO_RSA) && !defined(NO_SHA) && \ !defined(NO_ASN_CRYPT) && defined(HAVE_PBKDF2) - WC_RNG rng; +/* Encrypt server_key_der_2048 with salt (NULL for the default), decrypt it + * and compare with the original. */ +static int create_enc_pkcs8_check(WC_RNG* rng, byte* salt, word32 saltSz) +{ + EXPECT_DECLS; byte* encKey = NULL; word32 encKeySz = 0; word32 decKeySz = 0; @@ -28167,21 +28174,18 @@ static int test_wc_CreateEncryptedPKCS8Key(void) word32 passwordSz = (word32)XSTRLEN(password); word32 tradIdx = 0; - XMEMSET(&rng, 0, sizeof(WC_RNG)); - ExpectIntEQ(wc_InitRng(&rng), 0); - PRIVATE_KEY_UNLOCK(); /* Call with NULL for out buffer to get necessary length. */ ExpectIntEQ(wc_CreateEncryptedPKCS8Key((byte*)server_key_der_2048, sizeof_server_key_der_2048, NULL, &encKeySz, password, (int)passwordSz, - PKCS5, PBES2, AES256CBCb, NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL), - WC_NO_ERR_TRACE(LENGTH_ONLY_E)); + PKCS5, PBES2, AES256CBCb, salt, saltSz, WC_PKCS12_ITT_DEFAULT, rng, + NULL), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectNotNull(encKey = (byte*)XMALLOC(encKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); /* Call with the allocated out buffer. */ ExpectIntGT(wc_CreateEncryptedPKCS8Key((byte*)server_key_der_2048, sizeof_server_key_der_2048, encKey, &encKeySz, password, (int)passwordSz, - PKCS5, PBES2, AES256CBCb, NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL), - 0); + PKCS5, PBES2, AES256CBCb, salt, saltSz, WC_PKCS12_ITT_DEFAULT, rng, + NULL), 0); /* Decrypt the encrypted PKCS8 key we just made. */ ExpectIntGT((decKeySz = (word32)wc_DecryptPKCS8Key(encKey, encKeySz, password, (int)passwordSz)), 0); @@ -28190,9 +28194,29 @@ static int test_wc_CreateEncryptedPKCS8Key(void) /* Check that the decrypted key matches the key prior to encryption. */ ExpectIntEQ(XMEMCMP(encKey + tradIdx, server_key_der_2048, sizeof_server_key_der_2048), 0); - PRIVATE_KEY_LOCK(); XFREE(encKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return EXPECT_RESULT(); +} +#endif + +static int test_wc_CreateEncryptedPKCS8Key(void) +{ + EXPECT_DECLS; +#if defined(HAVE_PKCS8) && !defined(NO_PWDBASED) && defined(WOLFSSL_AES_256) \ + && !defined(NO_AES_CBC) && !defined(NO_RSA) && !defined(NO_SHA) && \ + !defined(NO_ASN_CRYPT) && defined(HAVE_PBKDF2) + WC_RNG rng; + byte salt8[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + XMEMSET(&rng, 0, sizeof(WC_RNG)); + ExpectIntEQ(wc_InitRng(&rng), 0); + PRIVATE_KEY_UNLOCK(); + EXPECT_TEST(create_enc_pkcs8_check(&rng, NULL, 0)); + /* An 8-byte salt: FIPS v7 flags it, and the key must still round-trip. */ + EXPECT_TEST(create_enc_pkcs8_check(&rng, salt8, sizeof(salt8))); + PRIVATE_KEY_LOCK(); + wc_FreeRng(&rng); #endif return EXPECT_RESULT(); diff --git a/tests/api/test_asn.c b/tests/api/test_asn.c index ca8f344a1da..d955cc0a827 100644 --- a/tests/api/test_asn.c +++ b/tests/api/test_asn.c @@ -6923,8 +6923,10 @@ int test_wc_Pkcs8EncryptDecisionCoverage(void) WC_RNG rng; byte key[32]; byte out[512]; + byte fill[512]; byte salt[8]; word32 outSz; + word32 need = 0; XMEMSET(key, 3, sizeof(key)); XMEMSET(salt, 4, sizeof(salt)); @@ -6949,6 +6951,34 @@ int test_wc_Pkcs8EncryptDecisionCoverage(void) "pw", 2, PKCS5, PBES2, AES128CBCb, salt, sizeof(salt), 1000, 0x7FFFFFFF, &rng, HEAP_HINT), WC_NO_ERR_TRACE(ALGO_ID_E)); + /* Zero and one byte short return BUFFER_E and leave the buffer + * untouched; the queried size succeeds. */ + outSz = 0; + ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), NULL, &outSz, + "pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng, + HEAP_HINT), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); + need = outSz; + ExpectIntGT(need, 1); + ExpectIntLE(need, sizeof(out)); + XMEMSET(out, 0xA5, sizeof(out)); + XMEMSET(fill, 0xA5, sizeof(fill)); + outSz = 0; + ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), out, &outSz, + "pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng, + HEAP_HINT), WC_NO_ERR_TRACE(BUFFER_E)); + outSz = need - 1; + ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), out, &outSz, + "pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng, + HEAP_HINT), WC_NO_ERR_TRACE(BUFFER_E)); + ExpectBufEQ(out, fill, sizeof(out)); +#if defined(HAVE_PBKDF2) && !defined(NO_HMAC) && !defined(NO_SHA) + outSz = need; + ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), out, &outSz, + "pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng, + HEAP_HINT), (int)need); + ExpectBufEQ(out + need, fill + need, sizeof(out) - need); +#endif + ExpectIntEQ(wc_FreeRng(&rng), 0); #endif /* HAVE_AES_CBC && !NO_AES && WOLFSSL_AES_128 && !FIPS */ return EXPECT_RESULT(); diff --git a/tests/api/test_pwdbased.c b/tests/api/test_pwdbased.c index 6009a1f08f3..5cec58f0fb7 100644 --- a/tests/api/test_pwdbased.c +++ b/tests/api/test_pwdbased.c @@ -159,6 +159,12 @@ int test_wc_PBKDF2DecisionCoverage(void) 0x5d, 0x63, 0xcb, 0x06 }; byte derived[24] = {0}; int prevMax; +#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + static const byte salt16[16] = { 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, + 0xcb, 0x06, 0x78, 0x57, 0x8E, 0x5a, + 0x5d, 0x63, 0xcb, 0x06 }; +#endif /* output==NULL || pLen<0 || sLen<0 || kLen<0 -- vary each operand alone. */ ExpectIntEQ(wc_PBKDF2_ex(NULL, passwd, (int)sizeof(passwd), @@ -200,9 +206,26 @@ int test_wc_PBKDF2DecisionCoverage(void) WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* valid derivation */ +#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* The 8-byte salt is below the SP 800-132 Section 5.1 minimum of 128 + * bits, so the v7 module derives the key and flags it not approved. */ ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd), salt, (int)sizeof(salt), 2, (int)sizeof(derived), + WC_SHA256, HEAP_HINT, INVALID_DEVID), WC_FIPS_NOT_APPROVED); + /* wc_CryptKey and the EVP PBKDF2 calls clear the indicator only under + * 16 bytes, so the module must flag 15 and not 16. */ + ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd), + salt16, (int)sizeof(salt16) - 1, 2, (int)sizeof(derived), + WC_SHA256, HEAP_HINT, INVALID_DEVID), WC_FIPS_NOT_APPROVED); + ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd), + salt16, (int)sizeof(salt16), 2, (int)sizeof(derived), WC_SHA256, HEAP_HINT, INVALID_DEVID), 0); +#else + ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), 2, (int)sizeof(derived), + WC_SHA256, HEAP_HINT, INVALID_DEVID), 0); +#endif #endif return EXPECT_RESULT(); } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 4b9eeaaec70..dcfed9b50db 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -11213,6 +11213,7 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz, word32 pbeLen = 0; word32 kdfLen = 0; word32 encLen = 0; + word32 outerLen = 0; byte cbcIv[MAX_IV_SIZE]; word32 idx = 0; word32 encIdx = 0; @@ -11234,7 +11235,7 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz, } if (ret == 0 && (salt == NULL || saltSz == 0)) { genSalt = 1; - saltSz = 8; + saltSz = (version == PKCS5v2) ? PKCS5V2_SALT_SZ : PKCS5_SALT_SZ; } if (ret == 0 && version == PKCS5v2) { ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &pbeId, &blockSz); @@ -11296,7 +11297,7 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz, if (ret == 0) { /* outerLen = length of PBE encoding + octet string data */ /* Plus 2 for tag and length for pbe */ - word32 outerLen = 2 + pbeLen; + outerLen = 2 + pbeLen; /* Octet string tag, length */ outerLen += 1 + SetLength(keySz + padSz, NULL); /* Octet string bytes */ @@ -11306,6 +11307,10 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz, *outSz = 1 + SetLength(outerLen, NULL) + outerLen; return WC_NO_ERR_TRACE(LENGTH_ONLY_E); } + if (*outSz < 1 + SetLength(outerLen, NULL) + outerLen) + ret = BUFFER_E; + } + if (ret == 0) { SetOctetString(keySz + padSz, out); idx += SetSequence(outerLen, out + idx); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index f60e4d59517..e0cb25261b7 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -5537,6 +5537,13 @@ int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen, iter, keylen, WC_SHA); +#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* Key is derived; a salt under 128 bits is the expected indicator + * (SP 800-132 sec 5.1). Any other one fails below. */ + if (ret == WC_FIPS_NOT_APPROVED && saltlen < 16) + ret = 0; +#endif if (ret == 0) return WOLFSSL_SUCCESS; else @@ -5566,6 +5573,13 @@ int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen, iter, keylen, pbkdf2HashType); +#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* Key is derived; a salt under 128 bits is the expected indicator + * (SP 800-132 sec 5.1). Any other one fails below. */ + if (ret == WC_FIPS_NOT_APPROVED && saltlen < 16) + ret = 0; +#endif if (ret == 0) return WOLFSSL_SUCCESS; else diff --git a/wolfcrypt/src/wc_encrypt.c b/wolfcrypt/src/wc_encrypt.c index a79535d0e2f..a0fa99bfda3 100644 --- a/wolfcrypt/src/wc_encrypt.c +++ b/wolfcrypt/src/wc_encrypt.c @@ -480,6 +480,17 @@ int wc_CryptKey(const char* password, int passwordSz, const byte* salt, ret = wc_PBKDF2(key, (const byte*)password, passwordSz, salt, saltSz, iterations, (int)derivedLen, typeH); PRIVATE_KEY_LOCK(); + #if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* Key is derived; a salt under 128 bits is the expected + * indicator (SP 800-132 sec 5.1). Any other one fails. */ + if (ret == WC_FIPS_NOT_APPROVED && saltSz < 16) + ret = 0; + else if (ret == WC_FIPS_NOT_APPROVED) { + ret = FIPS_UNAPPROVED_E; + WOLFSSL_ERROR_VERBOSE(ret); + } + #endif break; #endif #ifndef NO_SHA diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9fabf2da026..911460c4766 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -49611,6 +49611,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void) salt, (int)sizeof(salt), iterations, kLen, WC_SHA256, HEAP_HINT, devId); PRIVATE_KEY_LOCK(); +#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* 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); From 92b85e5c6ed04822750a746cf8192724f3b639a5 Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Fri, 6 Nov 2026 17:40:36 -0700 Subject: [PATCH 2/4] tests: expect the FIPS v7 ECDH curve refusal (from wolfssl#11359) --- tests/api/test_ecc.c | 8 ++++++-- wolfcrypt/test/test.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/tests/api/test_ecc.c b/tests/api/test_ecc.c index b3936ec0545..11101ba0aba 100644 --- a/tests/api/test_ecc.c +++ b/tests/api/test_ecc.c @@ -808,9 +808,13 @@ int test_wc_ecc_shared_secret_at_infinity(void) EXPECT_DECLS; #ifdef TEST_ECC_SHARED_SECRET_AT_INFINITY #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && \ - (ECC_MIN_KEY_SZ <= 224) && !defined(WOLFSSL_SP_MATH) + (ECC_MIN_KEY_SZ <= 224) && !defined(WOLFSSL_SP_MATH) && \ + !(FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS)) /* secp224r1 is not single precision accelerated, so this drives the - * software ECDH path even in SP builds that offload P-256. */ + * software ECDH path even in SP builds that offload P-256. The v7 + * module refuses ECDH on P-224 (outside its KAS-ECC-SSC curve set), so + * there the P-256 case below carries the identity check. */ ExpectIntEQ(ecc_shared_secret_inf_case( "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 911460c4766..3a2468ef0eb 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -54685,6 +54685,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif WC_DECLARE_VAR(sharedA, byte, ECC_SHARED_SIZE, HEAP_HINT); WC_DECLARE_VAR(sharedB, byte, ECC_SHARED_SIZE, HEAP_HINT); word32 y; + int doEcdh = 1; #endif #ifndef WC_NO_RNG #ifdef HAVE_ECC_KEY_EXPORT @@ -54854,7 +54855,27 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #endif +#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* v7 refuses ECDH outside P-256, P-384 and P-521: expect the refusal and + * skip only the shared secret steps for this curve. */ + if (userA->dp != NULL && + userA->dp->id != ECC_SECP256R1 && + userA->dp->id != ECC_SECP384R1 && + userA->dp->id != ECC_SECP521R1) { + x = ECC_SHARED_SIZE; + PRIVATE_KEY_UNLOCK(); + ret = wc_ecc_shared_secret(userA, userB, sharedA, &x); + PRIVATE_KEY_LOCK(); + if (ret != WC_NO_ERR_TRACE(ECC_CURVE_OID_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + ret = 0; + doEcdh = 0; + } +#endif + if (doEcdh) + { x = ECC_SHARED_SIZE; PRIVATE_KEY_UNLOCK(); do { @@ -54932,6 +54953,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif wc_ecc_set_flags(userA, 0); wc_ecc_set_flags(userB, 0); #endif /* HAVE_ECC_CDH */ + } #endif /* HAVE_ECC_DHE */ #endif /* !WOLFSSL_ATECC508A && WOLFSSL_ATECC608A */ @@ -54962,6 +54984,8 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ !defined(WOLFSSL_MICROCHIP_TA100) #ifdef HAVE_ECC_DHE + if (doEcdh) + { y = ECC_SHARED_SIZE; PRIVATE_KEY_UNLOCK(); do { @@ -54978,6 +55002,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (XMEMCMP(sharedA, sharedB, y)) ERROR_OUT(WC_TEST_RET_ENC_NC, done); TEST_SLEEP(); + } #endif /* HAVE_ECC_DHE */ #ifdef HAVE_COMP_KEY @@ -55015,6 +55040,8 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #ifdef HAVE_ECC_DHE + if (doEcdh) + { y = ECC_SHARED_SIZE; PRIVATE_KEY_UNLOCK(); do { @@ -55031,6 +55058,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (XMEMCMP(sharedA, sharedB, y)) ERROR_OUT(WC_TEST_RET_ENC_NC, done); TEST_SLEEP(); + } #endif /* HAVE_ECC_DHE */ } #endif /* HAVE_COMP_KEY */ From 5faeaaf5df274c81da7b019311b89efdf2a26a92 Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Fri, 6 Nov 2026 17:48:43 -0700 Subject: [PATCH 3/4] tests: expect the FIPS v7 indicator for a caller-set ECDSA k (wolfssl#11359) --- wolfcrypt/test/test.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 3a2468ef0eb..4ee2687fe03 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -54028,6 +54028,16 @@ 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) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* 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); @@ -54039,6 +54049,17 @@ 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) && defined(WC_HAVE_FIPS_INDICATOR) && \ + !defined(FIPS_NO_WRAPPERS) + /* 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(); @@ -54060,6 +54081,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(); From 036087d2a1fafea8c6adc65c01cf367009704db3 Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Fri, 6 Nov 2026 17:48:43 -0700 Subject: [PATCH 4/4] tests: expect BAD_FUNC_ARG from wc_HmacSizeByType on FIPS v7 --- wolfcrypt/test/test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4ee2687fe03..69af7d949a0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -12592,7 +12592,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha256_test(void) #if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(6,0,0) if ((ret = wc_HmacSizeByType(WC_SHA256)) != WC_SHA256_DIGEST_SIZE) return WC_TEST_RET_ENC_EC(ret); -#if FIPS_VERSION3_GE(6,0,0) && !defined(WOLFSSL_FIPS_DEV_NO_POST) +#if FIPS_VERSION3_GE(6,0,0) && \ + !(FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR)) && \ + !defined(WOLFSSL_FIPS_DEV_NO_POST) if ((ret = wc_HmacSizeByType(21)) != WC_NO_ERR_TRACE(HMAC_KAT_FIPS_E)) #else if ((ret = wc_HmacSizeByType(21)) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))