Skip to content

Commit 1ffb2e8

Browse files
Merge pull request #12057 from kaleb-himes/PQ-FS-2026-Part4-Fenrir-v7-indicator
Pq fs 2026 part4 fenrir v7 indicator
2 parents 73956d0 + 036087d commit 1ffb2e8

8 files changed

Lines changed: 195 additions & 20 deletions

File tree

‎tests/api.c‎

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13585,6 +13585,7 @@ static int test_wolfSSL_PKCS5(void)
1358513585
const char *passwd = "pass1234";
1358613586
#endif
1358713587
const unsigned char *salt = (unsigned char *)"salt1234";
13588+
const unsigned char *salt16 = (unsigned char *)"salt1234salt5678";
1358813589
unsigned char *out = (unsigned char *)XMALLOC(WC_SHA_DIGEST_SIZE, NULL,
1358913590
DYNAMIC_TYPE_TMP_BUFFER);
1359013591
int ret = 0;
@@ -13593,11 +13594,16 @@ static int test_wolfSSL_PKCS5(void)
1359313594
ExpectIntEQ(ret = PKCS5_PBKDF2_HMAC_SHA1(passwd,(int)XSTRLEN(passwd), salt,
1359413595
(int)XSTRLEN((const char *) salt), 10, WC_SHA_DIGEST_SIZE,out),
1359513596
WOLFSSL_SUCCESS);
13597+
/* A 16-byte salt gets no FIPS v7 indicator, so none may be cleared. */
13598+
ExpectIntEQ(PKCS5_PBKDF2_HMAC_SHA1(passwd, (int)XSTRLEN(passwd), salt16,
13599+
16, 10, WC_SHA_DIGEST_SIZE, out), WOLFSSL_SUCCESS);
1359613600

1359713601
#ifdef WOLFSSL_SHA512
1359813602
ExpectIntEQ(ret = PKCS5_PBKDF2_HMAC(passwd,(int)XSTRLEN(passwd), salt,
1359913603
(int)XSTRLEN((const char *) salt), 10, wolfSSL_EVP_sha512(),
1360013604
WC_SHA_DIGEST_SIZE, out), SSL_SUCCESS);
13605+
ExpectIntEQ(PKCS5_PBKDF2_HMAC(passwd, (int)XSTRLEN(passwd), salt16, 16,
13606+
10, wolfSSL_EVP_sha512(), WC_SHA_DIGEST_SIZE, out), SSL_SUCCESS);
1360113607
#endif
1360213608

1360313609
XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -21893,7 +21899,7 @@ static int test_wolfSSL_PKCS8_d2i(void)
2189321899
#if !defined(NO_DES3) && !defined(NO_SHA) && defined(HAVE_PBKDF2)
2189421900
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
2189521901
/* Write Encrypted PKCS#8 PEM to BIO. */
21896-
bytes = 1834;
21902+
bytes = 1846;
2189721903
ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_des_ede3_cbc(),
2189821904
NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes);
2189921905
ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_des_ede3_cbc(),
@@ -21976,8 +21982,8 @@ static int test_wolfSSL_PKCS8_d2i(void)
2197621982
bio = NULL;
2197721983
#ifdef HAVE_PBKDF2
2197821984
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
21979-
/* Write Encrypted PKCS#8 PEM to BIO (test write 0 then 379) */
21980-
bytes = 379;
21985+
/* Write Encrypted PKCS#8 PEM to BIO (test write 0 then 391) */
21986+
bytes = 391;
2198121987
ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(),
2198221988
NULL, 0, NoPasswordCallBack, (void*)"yassl123"), 0);
2198321989
ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(),
@@ -28254,35 +28260,33 @@ static int test_wolfSSL_CRYPTO_memcmp(void)
2825428260
| wolfCrypt ASN
2825528261
*----------------------------------------------------------------------------*/
2825628262

28257-
static int test_wc_CreateEncryptedPKCS8Key(void)
28258-
{
28259-
EXPECT_DECLS;
2826028263
#if defined(HAVE_PKCS8) && !defined(NO_PWDBASED) && defined(WOLFSSL_AES_256) \
2826128264
&& !defined(NO_AES_CBC) && !defined(NO_RSA) && !defined(NO_SHA) && \
2826228265
!defined(NO_ASN_CRYPT) && defined(HAVE_PBKDF2)
28263-
WC_RNG rng;
28266+
/* Encrypt server_key_der_2048 with salt (NULL for the default), decrypt it
28267+
* and compare with the original. */
28268+
static int create_enc_pkcs8_check(WC_RNG* rng, byte* salt, word32 saltSz)
28269+
{
28270+
EXPECT_DECLS;
2826428271
byte* encKey = NULL;
2826528272
word32 encKeySz = 0;
2826628273
word32 decKeySz = 0;
2826728274
const char password[] = "Lorem ipsum dolor sit amet";
2826828275
word32 passwordSz = (word32)XSTRLEN(password);
2826928276
word32 tradIdx = 0;
2827028277

28271-
XMEMSET(&rng, 0, sizeof(WC_RNG));
28272-
ExpectIntEQ(wc_InitRng(&rng), 0);
28273-
PRIVATE_KEY_UNLOCK();
2827428278
/* Call with NULL for out buffer to get necessary length. */
2827528279
ExpectIntEQ(wc_CreateEncryptedPKCS8Key((byte*)server_key_der_2048,
2827628280
sizeof_server_key_der_2048, NULL, &encKeySz, password, (int)passwordSz,
28277-
PKCS5, PBES2, AES256CBCb, NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL),
28278-
WC_NO_ERR_TRACE(LENGTH_ONLY_E));
28281+
PKCS5, PBES2, AES256CBCb, salt, saltSz, WC_PKCS12_ITT_DEFAULT, rng,
28282+
NULL), WC_NO_ERR_TRACE(LENGTH_ONLY_E));
2827928283
ExpectNotNull(encKey = (byte*)XMALLOC(encKeySz, HEAP_HINT,
2828028284
DYNAMIC_TYPE_TMP_BUFFER));
2828128285
/* Call with the allocated out buffer. */
2828228286
ExpectIntGT(wc_CreateEncryptedPKCS8Key((byte*)server_key_der_2048,
2828328287
sizeof_server_key_der_2048, encKey, &encKeySz, password, (int)passwordSz,
28284-
PKCS5, PBES2, AES256CBCb, NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL),
28285-
0);
28288+
PKCS5, PBES2, AES256CBCb, salt, saltSz, WC_PKCS12_ITT_DEFAULT, rng,
28289+
NULL), 0);
2828628290
/* Decrypt the encrypted PKCS8 key we just made. */
2828728291
ExpectIntGT((decKeySz = (word32)wc_DecryptPKCS8Key(encKey, encKeySz, password,
2828828292
(int)passwordSz)), 0);
@@ -28291,9 +28295,29 @@ static int test_wc_CreateEncryptedPKCS8Key(void)
2829128295
/* Check that the decrypted key matches the key prior to encryption. */
2829228296
ExpectIntEQ(XMEMCMP(encKey + tradIdx, server_key_der_2048,
2829328297
sizeof_server_key_der_2048), 0);
28294-
PRIVATE_KEY_LOCK();
2829528298

2829628299
XFREE(encKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
28300+
return EXPECT_RESULT();
28301+
}
28302+
#endif
28303+
28304+
static int test_wc_CreateEncryptedPKCS8Key(void)
28305+
{
28306+
EXPECT_DECLS;
28307+
#if defined(HAVE_PKCS8) && !defined(NO_PWDBASED) && defined(WOLFSSL_AES_256) \
28308+
&& !defined(NO_AES_CBC) && !defined(NO_RSA) && !defined(NO_SHA) && \
28309+
!defined(NO_ASN_CRYPT) && defined(HAVE_PBKDF2)
28310+
WC_RNG rng;
28311+
byte salt8[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
28312+
28313+
XMEMSET(&rng, 0, sizeof(WC_RNG));
28314+
ExpectIntEQ(wc_InitRng(&rng), 0);
28315+
PRIVATE_KEY_UNLOCK();
28316+
EXPECT_TEST(create_enc_pkcs8_check(&rng, NULL, 0));
28317+
/* An 8-byte salt: FIPS v7 flags it, and the key must still round-trip. */
28318+
EXPECT_TEST(create_enc_pkcs8_check(&rng, salt8, sizeof(salt8)));
28319+
PRIVATE_KEY_LOCK();
28320+
2829728321
wc_FreeRng(&rng);
2829828322
#endif
2829928323
return EXPECT_RESULT();

‎tests/api/test_asn.c‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6923,8 +6923,10 @@ int test_wc_Pkcs8EncryptDecisionCoverage(void)
69236923
WC_RNG rng;
69246924
byte key[32];
69256925
byte out[512];
6926+
byte fill[512];
69266927
byte salt[8];
69276928
word32 outSz;
6929+
word32 need = 0;
69286930

69296931
XMEMSET(key, 3, sizeof(key));
69306932
XMEMSET(salt, 4, sizeof(salt));
@@ -6949,6 +6951,34 @@ int test_wc_Pkcs8EncryptDecisionCoverage(void)
69496951
"pw", 2, PKCS5, PBES2, AES128CBCb, salt, sizeof(salt), 1000,
69506952
0x7FFFFFFF, &rng, HEAP_HINT), WC_NO_ERR_TRACE(ALGO_ID_E));
69516953

6954+
/* Zero and one byte short return BUFFER_E and leave the buffer
6955+
* untouched; the queried size succeeds. */
6956+
outSz = 0;
6957+
ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), NULL, &outSz,
6958+
"pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng,
6959+
HEAP_HINT), WC_NO_ERR_TRACE(LENGTH_ONLY_E));
6960+
need = outSz;
6961+
ExpectIntGT(need, 1);
6962+
ExpectIntLE(need, sizeof(out));
6963+
XMEMSET(out, 0xA5, sizeof(out));
6964+
XMEMSET(fill, 0xA5, sizeof(fill));
6965+
outSz = 0;
6966+
ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), out, &outSz,
6967+
"pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng,
6968+
HEAP_HINT), WC_NO_ERR_TRACE(BUFFER_E));
6969+
outSz = need - 1;
6970+
ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), out, &outSz,
6971+
"pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng,
6972+
HEAP_HINT), WC_NO_ERR_TRACE(BUFFER_E));
6973+
ExpectBufEQ(out, fill, sizeof(out));
6974+
#if defined(HAVE_PBKDF2) && !defined(NO_HMAC) && !defined(NO_SHA)
6975+
outSz = need;
6976+
ExpectIntEQ(wc_EncryptPKCS8Key_ex(key, sizeof(key), out, &outSz,
6977+
"pw", 2, PKCS5, PBES2, AES128CBCb, NULL, 0, 1000, 0, &rng,
6978+
HEAP_HINT), (int)need);
6979+
ExpectBufEQ(out + need, fill + need, sizeof(out) - need);
6980+
#endif
6981+
69526982
ExpectIntEQ(wc_FreeRng(&rng), 0);
69536983
#endif /* HAVE_AES_CBC && !NO_AES && WOLFSSL_AES_128 && !FIPS */
69546984
return EXPECT_RESULT();

‎tests/api/test_ecc.c‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,9 +1003,13 @@ int test_wc_ecc_shared_secret_at_infinity(void)
10031003
EXPECT_DECLS;
10041004
#ifdef TEST_ECC_SHARED_SECRET_AT_INFINITY
10051005
#if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && \
1006-
(ECC_MIN_KEY_SZ <= 224) && !defined(WOLFSSL_SP_MATH)
1006+
(ECC_MIN_KEY_SZ <= 224) && !defined(WOLFSSL_SP_MATH) && \
1007+
!(FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \
1008+
!defined(FIPS_NO_WRAPPERS))
10071009
/* secp224r1 is not single precision accelerated, so this drives the
1008-
* software ECDH path even in SP builds that offload P-256. */
1010+
* software ECDH path even in SP builds that offload P-256. The v7
1011+
* module refuses ECDH on P-224 (outside its KAS-ECC-SSC curve set), so
1012+
* there the P-256 case below carries the identity check. */
10091013
ExpectIntEQ(ecc_shared_secret_inf_case(
10101014
"b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
10111015
"bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",

‎tests/api/test_pwdbased.c‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ int test_wc_PBKDF2DecisionCoverage(void)
167167
0x5d, 0x63, 0xcb, 0x06 };
168168
byte derived[24] = {0};
169169
int prevMax;
170+
#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \
171+
!defined(FIPS_NO_WRAPPERS)
172+
static const byte salt16[16] = { 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63,
173+
0xcb, 0x06, 0x78, 0x57, 0x8E, 0x5a,
174+
0x5d, 0x63, 0xcb, 0x06 };
175+
#endif
170176

171177
/* output==NULL || pLen<0 || sLen<0 || kLen<0 -- vary each operand alone. */
172178
ExpectIntEQ(wc_PBKDF2_ex(NULL, passwd, (int)sizeof(passwd),
@@ -208,9 +214,26 @@ int test_wc_PBKDF2DecisionCoverage(void)
208214
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
209215

210216
/* valid derivation */
217+
#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \
218+
!defined(FIPS_NO_WRAPPERS)
219+
/* The 8-byte salt is below the SP 800-132 Section 5.1 minimum of 128
220+
* bits, so the v7 module derives the key and flags it not approved. */
211221
ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd),
212222
salt, (int)sizeof(salt), 2, (int)sizeof(derived),
223+
WC_SHA256, HEAP_HINT, INVALID_DEVID), WC_FIPS_NOT_APPROVED);
224+
/* wc_CryptKey and the EVP PBKDF2 calls clear the indicator only under
225+
* 16 bytes, so the module must flag 15 and not 16. */
226+
ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd),
227+
salt16, (int)sizeof(salt16) - 1, 2, (int)sizeof(derived),
228+
WC_SHA256, HEAP_HINT, INVALID_DEVID), WC_FIPS_NOT_APPROVED);
229+
ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd),
230+
salt16, (int)sizeof(salt16), 2, (int)sizeof(derived),
213231
WC_SHA256, HEAP_HINT, INVALID_DEVID), 0);
232+
#else
233+
ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd),
234+
salt, (int)sizeof(salt), 2, (int)sizeof(derived),
235+
WC_SHA256, HEAP_HINT, INVALID_DEVID), 0);
236+
#endif
214237
#endif
215238
return EXPECT_RESULT();
216239
}

‎wolfcrypt/src/asn.c‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11213,6 +11213,7 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz,
1121311213
word32 pbeLen = 0;
1121411214
word32 kdfLen = 0;
1121511215
word32 encLen = 0;
11216+
word32 outerLen = 0;
1121611217
byte cbcIv[MAX_IV_SIZE];
1121711218
word32 idx = 0;
1121811219
word32 encIdx = 0;
@@ -11234,7 +11235,7 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz,
1123411235
}
1123511236
if (ret == 0 && (salt == NULL || saltSz == 0)) {
1123611237
genSalt = 1;
11237-
saltSz = 8;
11238+
saltSz = (version == PKCS5v2) ? PKCS5V2_SALT_SZ : PKCS5_SALT_SZ;
1123811239
}
1123911240
if (ret == 0 && version == PKCS5v2) {
1124011241
ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &pbeId, &blockSz);
@@ -11296,7 +11297,7 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz,
1129611297
if (ret == 0) {
1129711298
/* outerLen = length of PBE encoding + octet string data */
1129811299
/* Plus 2 for tag and length for pbe */
11299-
word32 outerLen = 2 + pbeLen;
11300+
outerLen = 2 + pbeLen;
1130011301
/* Octet string tag, length */
1130111302
outerLen += 1 + SetLength(keySz + padSz, NULL);
1130211303
/* Octet string bytes */
@@ -11306,6 +11307,10 @@ int wc_EncryptPKCS8Key_ex(byte* key, word32 keySz, byte* out, word32* outSz,
1130611307
*outSz = 1 + SetLength(outerLen, NULL) + outerLen;
1130711308
return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
1130811309
}
11310+
if (*outSz < 1 + SetLength(outerLen, NULL) + outerLen)
11311+
ret = BUFFER_E;
11312+
}
11313+
if (ret == 0) {
1130911314
SetOctetString(keySz + padSz, out);
1131011315

1131111316
idx += SetSequence(outerLen, out + idx);

‎wolfcrypt/src/evp.c‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5537,6 +5537,13 @@ int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
55375537

55385538
ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen,
55395539
iter, keylen, WC_SHA);
5540+
#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \
5541+
!defined(FIPS_NO_WRAPPERS)
5542+
/* Key is derived; a salt under 128 bits is the expected indicator
5543+
* (SP 800-132 sec 5.1). Any other one fails below. */
5544+
if (ret == WC_FIPS_NOT_APPROVED && saltlen < 16)
5545+
ret = 0;
5546+
#endif
55405547
if (ret == 0)
55415548
return WOLFSSL_SUCCESS;
55425549
else
@@ -5566,6 +5573,13 @@ int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
55665573

55675574
ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen,
55685575
iter, keylen, pbkdf2HashType);
5576+
#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \
5577+
!defined(FIPS_NO_WRAPPERS)
5578+
/* Key is derived; a salt under 128 bits is the expected indicator
5579+
* (SP 800-132 sec 5.1). Any other one fails below. */
5580+
if (ret == WC_FIPS_NOT_APPROVED && saltlen < 16)
5581+
ret = 0;
5582+
#endif
55695583
if (ret == 0)
55705584
return WOLFSSL_SUCCESS;
55715585
else

‎wolfcrypt/src/wc_encrypt.c‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,17 @@ int wc_CryptKey(const char* password, int passwordSz, const byte* salt,
480480
ret = wc_PBKDF2(key, (const byte*)password, passwordSz,
481481
salt, saltSz, iterations, (int)derivedLen, typeH);
482482
PRIVATE_KEY_LOCK();
483+
#if FIPS_VERSION3_GE(7,0,0) && defined(WC_HAVE_FIPS_INDICATOR) && \
484+
!defined(FIPS_NO_WRAPPERS)
485+
/* Key is derived; a salt under 128 bits is the expected
486+
* indicator (SP 800-132 sec 5.1). Any other one fails. */
487+
if (ret == WC_FIPS_NOT_APPROVED && saltSz < 16)
488+
ret = 0;
489+
else if (ret == WC_FIPS_NOT_APPROVED) {
490+
ret = FIPS_UNAPPROVED_E;
491+
WOLFSSL_ERROR_VERBOSE(ret);
492+
}
493+
#endif
483494
break;
484495
#endif
485496
#ifndef NO_SHA

0 commit comments

Comments
 (0)