From f95f0bd20f399b990936b2e57719487549b0ae7d Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Mon, 23 Mar 2026 15:49:24 -0400 Subject: [PATCH 1/9] Add upper limit to PBKDF iteration count Add WC_PBKDF_MAX_ITERATIONS (default 100000) to cap the iteration count in wc_PBKDF1_ex(), wc_PBKDF2_ex(), and wc_PKCS12_PBKDF_ex(). --- wolfcrypt/src/pwdbased.c | 15 +++++ wolfcrypt/test/test.c | 124 +++++++++++++++++++++++++++++++++++ wolfssl/wolfcrypt/pwdbased.h | 9 +++ 3 files changed, 148 insertions(+) diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index c2ed5c042f5..7135c098bfe 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -79,6 +79,11 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, if (iterations <= 0) iterations = 1; + if (iterations > WC_PBKDF_MAX_ITERATIONS) { + WOLFSSL_MSG("PBKDF1 iteration count exceeds WC_PBKDF_MAX_ITERATIONS"); + return BAD_FUNC_ARG; + } + hashT = wc_HashTypeConvert(hashType); err = wc_HashGetDigestSize(hashT); if (err < 0) @@ -215,6 +220,11 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt, if (iterations <= 0) iterations = 1; + if (iterations > WC_PBKDF_MAX_ITERATIONS) { + WOLFSSL_MSG("PBKDF2 iteration count exceeds WC_PBKDF_MAX_ITERATIONS"); + return BAD_FUNC_ARG; + } + hashT = wc_HashTypeConvert(hashType); hLen = wc_HashGetDigestSize(hashT); if (hLen < 0) @@ -403,6 +413,11 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, if (iterations <= 0) iterations = 1; + if (iterations > WC_PBKDF_MAX_ITERATIONS) { + WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds WC_PBKDF_MAX_ITERATIONS"); + return BAD_FUNC_ARG; + } + hashT = wc_HashTypeConvert(hashType); ret = wc_HashGetDigestSize(hashT); if (ret < 0) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5499ec89471..e4b72e2c064 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -30758,6 +30758,20 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_pbkdf_test(void) if (XMEMCMP(derived, verify2, 24) != 0) return WC_TEST_RET_ENC_NC; + /* Test iteration cap: iterations above WC_PBKDF_MAX_ITERATIONS must be + * rejected to prevent CPU exhaustion DoS via crafted PKCS#12 files. */ + ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, + WC_PBKDF_MAX_ITERATIONS + 1, kLen, WC_SHA256, + id, HEAP_HINT); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_NC; + + ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, + WC_PBKDF_MAX_ITERATIONS, kLen, WC_SHA256, + id, HEAP_HINT); + if (ret < 0) + return WC_TEST_RET_ENC_EC(ret); + return 0; } #endif /* HAVE_PKCS12 && !NO_SHA256 */ @@ -30789,6 +30803,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void) if (XMEMCMP(derived, verify, sizeof(verify)) != 0) return WC_TEST_RET_ENC_NC; + /* Test iteration cap */ + ret = wc_PBKDF2_ex(derived, (byte*)passwd, (int)XSTRLEN(passwd), + salt, (int)sizeof(salt), WC_PBKDF_MAX_ITERATIONS + 1, + kLen, WC_SHA256, HEAP_HINT, devId); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_NC; + return 0; } @@ -30820,6 +30841,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf1_test(void) if (XMEMCMP(derived, verify, sizeof(verify)) != 0) return WC_TEST_RET_ENC_NC; + /* Test iteration cap */ + ret = wc_PBKDF1_ex(derived, kLen, NULL, 0, (byte*)passwd, + (int)XSTRLEN(passwd), salt, (int)sizeof(salt), + WC_PBKDF_MAX_ITERATIONS + 1, WC_SHA, HEAP_HINT); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_NC; + return 0; } #endif /* HAVE_PBKDF2 && !NO_SHA */ @@ -30844,6 +30872,52 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void) if (ret != 0) return ret; #endif +#ifdef HAVE_PKCS12 + /* Test that a crafted PKCS#12 with INT_MAX MAC iterations is rejected + * immediately rather than hanging in DoPKCS12Hash(). */ + { + static const byte evil_p12[] = { + 0x30, 0x58, 0x02, 0x01, 0x03, 0x30, 0x1e, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x11, 0x04, 0x0f, 0x30, 0x0d, + 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x33, 0x30, + 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x08, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x02, 0x04, 0x7f, 0xff, + 0xff, 0xff + }; + WC_PKCS12* evilPkcs12 = wc_PKCS12_new_ex(HEAP_HINT); + if (evilPkcs12 == NULL) + return WC_TEST_RET_ENC_EC(MEMORY_E); + + ret = wc_d2i_PKCS12(evil_p12, (word32)sizeof(evil_p12), evilPkcs12); + if (ret == 0) { + byte* evilKey = NULL; + byte* evilCert = NULL; + word32 evilKeySz = 0, evilCertSz = 0; + WC_DerCertList* evilCa = NULL; + + ret = wc_PKCS12_parse(evilPkcs12, "test", &evilKey, &evilKeySz, + &evilCert, &evilCertSz, &evilCa); + XFREE(evilKey, HEAP_HINT, DYNAMIC_TYPE_PKCS); + XFREE(evilCert, HEAP_HINT, DYNAMIC_TYPE_PKCS); + if (evilCa) + wc_FreeCertList(evilCa, HEAP_HINT); + wc_PKCS12_free(evilPkcs12); + /* Parse must fail (iteration cap), not succeed or hang */ + if (ret == 0) + return WC_TEST_RET_ENC_NC; + } + else { + wc_PKCS12_free(evilPkcs12); + } + ret = 0; + } +#endif /* HAVE_PKCS12 */ #ifdef HAVE_SCRYPT ret = scrypt_test(); if (ret != 0) @@ -30943,6 +31017,56 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_test(void) goto out; } + /* Test that a crafted PKCS#12 with INT_MAX MAC iterations is rejected + * immediately rather than hanging in DoPKCS12Hash(). This is a 90-byte + * minimal PKCS#12 with mac->itt = 0x7FFFFFFF (2,147,483,647). */ + { + static const byte evil_p12[] = { + 0x30, 0x58, 0x02, 0x01, 0x03, 0x30, 0x1e, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x11, 0x04, 0x0f, 0x30, 0x0d, + 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x33, 0x30, + 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x08, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x02, 0x04, 0x7f, 0xff, + 0xff, 0xff + }; + WC_PKCS12* evilPkcs12 = wc_PKCS12_new_ex(HEAP_HINT); + if (evilPkcs12 == NULL) { + ret = WC_TEST_RET_ENC_EC(MEMORY_E); + goto out; + } + ret = wc_d2i_PKCS12(evil_p12, (word32)sizeof(evil_p12), evilPkcs12); + if (ret != 0) { + wc_PKCS12_free(evilPkcs12); + ret = WC_TEST_RET_ENC_EC(ret); + goto out; + } + { + byte* evilKey = NULL; + byte* evilCert = NULL; + word32 evilKeySz = 0, evilCertSz = 0; + WC_DerCertList* evilCa = NULL; + ret = wc_PKCS12_parse(evilPkcs12, "test", &evilKey, &evilKeySz, + &evilCert, &evilCertSz, &evilCa); + XFREE(evilKey, HEAP_HINT, DYNAMIC_TYPE_PKCS); + XFREE(evilCert, HEAP_HINT, DYNAMIC_TYPE_PKCS); + if (evilCa) + wc_FreeCertList(evilCa, HEAP_HINT); + } + wc_PKCS12_free(evilPkcs12); + /* Must have been rejected (not hung) */ + if (ret == 0) { + ret = WC_TEST_RET_ENC_NC; + goto out; + } + ret = 0; /* rejection is the expected outcome */ + } + out: if (derCaListOut) diff --git a/wolfssl/wolfcrypt/pwdbased.h b/wolfssl/wolfcrypt/pwdbased.h index fc2eddfd8dd..fb56df627f4 100644 --- a/wolfssl/wolfcrypt/pwdbased.h +++ b/wolfssl/wolfcrypt/pwdbased.h @@ -35,6 +35,15 @@ extern "C" { #endif +/* Maximum allowed PBKDF iteration count to prevent CPU exhaustion DoS. + * Attacker-controlled PKCS#12 files can specify iterations up to INT_MAX + * (2,147,483,647) in the MAC data, causing hours of CPU time. + * Override by defining WC_PBKDF_MAX_ITERATIONS before including this header. + * Normal PKCS#12 files use 1,000–10,000 iterations. */ +#ifndef WC_PBKDF_MAX_ITERATIONS + #define WC_PBKDF_MAX_ITERATIONS 100000 +#endif + #if FIPS_VERSION3_GE(6,0,0) extern const unsigned int wolfCrypt_FIPS_pbkdf_ro_sanity[2]; WOLFSSL_LOCAL int wolfCrypt_FIPS_PBKDF_sanity(void); From 6174e0e8628e91aa6cec50c6d082acfae4a739a5 Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Thu, 26 Mar 2026 23:34:14 -0400 Subject: [PATCH 2/9] simplify the tests. --- wolfcrypt/test/test.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e4b72e2c064..8fc1912c1df 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -30758,20 +30758,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_pbkdf_test(void) if (XMEMCMP(derived, verify2, 24) != 0) return WC_TEST_RET_ENC_NC; - /* Test iteration cap: iterations above WC_PBKDF_MAX_ITERATIONS must be - * rejected to prevent CPU exhaustion DoS via crafted PKCS#12 files. */ - ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, - WC_PBKDF_MAX_ITERATIONS + 1, kLen, WC_SHA256, - id, HEAP_HINT); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) - return WC_TEST_RET_ENC_NC; - - ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, - WC_PBKDF_MAX_ITERATIONS, kLen, WC_SHA256, - id, HEAP_HINT); - if (ret < 0) - return WC_TEST_RET_ENC_EC(ret); - return 0; } #endif /* HAVE_PKCS12 && !NO_SHA256 */ @@ -30803,13 +30789,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void) if (XMEMCMP(derived, verify, sizeof(verify)) != 0) return WC_TEST_RET_ENC_NC; - /* Test iteration cap */ - ret = wc_PBKDF2_ex(derived, (byte*)passwd, (int)XSTRLEN(passwd), - salt, (int)sizeof(salt), WC_PBKDF_MAX_ITERATIONS + 1, - kLen, WC_SHA256, HEAP_HINT, devId); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) - return WC_TEST_RET_ENC_NC; - return 0; } @@ -30841,13 +30820,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf1_test(void) if (XMEMCMP(derived, verify, sizeof(verify)) != 0) return WC_TEST_RET_ENC_NC; - /* Test iteration cap */ - ret = wc_PBKDF1_ex(derived, kLen, NULL, 0, (byte*)passwd, - (int)XSTRLEN(passwd), salt, (int)sizeof(salt), - WC_PBKDF_MAX_ITERATIONS + 1, WC_SHA, HEAP_HINT); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) - return WC_TEST_RET_ENC_NC; - return 0; } #endif /* HAVE_PBKDF2 && !NO_SHA */ From 2801482476efe1527199c2e2b007976120fafc48 Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Fri, 27 Mar 2026 00:32:40 -0400 Subject: [PATCH 3/9] better macro gating in tests --- wolfcrypt/test/test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 8fc1912c1df..014cd8a345f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -30844,7 +30844,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void) if (ret != 0) return ret; #endif -#ifdef HAVE_PKCS12 +#if defined(HAVE_PKCS12) && !defined(NO_ASN) && !defined(NO_PWDBASED) && \ + !defined(NO_HMAC) && !defined(NO_CERTS) /* Test that a crafted PKCS#12 with INT_MAX MAC iterations is rejected * immediately rather than hanging in DoPKCS12Hash(). */ { @@ -30889,7 +30890,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void) } ret = 0; } -#endif /* HAVE_PKCS12 */ +#endif /* HAVE_PKCS12 && !NO_ASN && !NO_PWDBASED && !NO_HMAC && !NO_CERTS */ #ifdef HAVE_SCRYPT ret = scrypt_test(); if (ret != 0) From b336fc984f4b3d2a820b9f0b534d8ff43dab7fdd Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Wed, 1 Apr 2026 17:24:59 -0400 Subject: [PATCH 4/9] get rid of bad tests --- wolfcrypt/test/test.c | 97 ------------------------------------------- 1 file changed, 97 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 014cd8a345f..5499ec89471 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -30844,53 +30844,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void) if (ret != 0) return ret; #endif -#if defined(HAVE_PKCS12) && !defined(NO_ASN) && !defined(NO_PWDBASED) && \ - !defined(NO_HMAC) && !defined(NO_CERTS) - /* Test that a crafted PKCS#12 with INT_MAX MAC iterations is rejected - * immediately rather than hanging in DoPKCS12Hash(). */ - { - static const byte evil_p12[] = { - 0x30, 0x58, 0x02, 0x01, 0x03, 0x30, 0x1e, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01, 0xa0, 0x11, 0x04, 0x0f, 0x30, 0x0d, - 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x33, 0x30, - 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, - 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x08, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x02, 0x04, 0x7f, 0xff, - 0xff, 0xff - }; - WC_PKCS12* evilPkcs12 = wc_PKCS12_new_ex(HEAP_HINT); - if (evilPkcs12 == NULL) - return WC_TEST_RET_ENC_EC(MEMORY_E); - - ret = wc_d2i_PKCS12(evil_p12, (word32)sizeof(evil_p12), evilPkcs12); - if (ret == 0) { - byte* evilKey = NULL; - byte* evilCert = NULL; - word32 evilKeySz = 0, evilCertSz = 0; - WC_DerCertList* evilCa = NULL; - - ret = wc_PKCS12_parse(evilPkcs12, "test", &evilKey, &evilKeySz, - &evilCert, &evilCertSz, &evilCa); - XFREE(evilKey, HEAP_HINT, DYNAMIC_TYPE_PKCS); - XFREE(evilCert, HEAP_HINT, DYNAMIC_TYPE_PKCS); - if (evilCa) - wc_FreeCertList(evilCa, HEAP_HINT); - wc_PKCS12_free(evilPkcs12); - /* Parse must fail (iteration cap), not succeed or hang */ - if (ret == 0) - return WC_TEST_RET_ENC_NC; - } - else { - wc_PKCS12_free(evilPkcs12); - } - ret = 0; - } -#endif /* HAVE_PKCS12 && !NO_ASN && !NO_PWDBASED && !NO_HMAC && !NO_CERTS */ #ifdef HAVE_SCRYPT ret = scrypt_test(); if (ret != 0) @@ -30990,56 +30943,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_test(void) goto out; } - /* Test that a crafted PKCS#12 with INT_MAX MAC iterations is rejected - * immediately rather than hanging in DoPKCS12Hash(). This is a 90-byte - * minimal PKCS#12 with mac->itt = 0x7FFFFFFF (2,147,483,647). */ - { - static const byte evil_p12[] = { - 0x30, 0x58, 0x02, 0x01, 0x03, 0x30, 0x1e, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01, 0xa0, 0x11, 0x04, 0x0f, 0x30, 0x0d, - 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x33, 0x30, - 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, - 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x08, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x02, 0x04, 0x7f, 0xff, - 0xff, 0xff - }; - WC_PKCS12* evilPkcs12 = wc_PKCS12_new_ex(HEAP_HINT); - if (evilPkcs12 == NULL) { - ret = WC_TEST_RET_ENC_EC(MEMORY_E); - goto out; - } - ret = wc_d2i_PKCS12(evil_p12, (word32)sizeof(evil_p12), evilPkcs12); - if (ret != 0) { - wc_PKCS12_free(evilPkcs12); - ret = WC_TEST_RET_ENC_EC(ret); - goto out; - } - { - byte* evilKey = NULL; - byte* evilCert = NULL; - word32 evilKeySz = 0, evilCertSz = 0; - WC_DerCertList* evilCa = NULL; - ret = wc_PKCS12_parse(evilPkcs12, "test", &evilKey, &evilKeySz, - &evilCert, &evilCertSz, &evilCa); - XFREE(evilKey, HEAP_HINT, DYNAMIC_TYPE_PKCS); - XFREE(evilCert, HEAP_HINT, DYNAMIC_TYPE_PKCS); - if (evilCa) - wc_FreeCertList(evilCa, HEAP_HINT); - } - wc_PKCS12_free(evilPkcs12); - /* Must have been rejected (not hung) */ - if (ret == 0) { - ret = WC_TEST_RET_ENC_NC; - goto out; - } - ret = 0; /* rejection is the expected outcome */ - } - out: if (derCaListOut) From 446309d08fca619fa705de801303f974703b0475 Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Wed, 8 Apr 2026 17:55:53 -0400 Subject: [PATCH 5/9] Limit was too low --- wolfssl/wolfcrypt/pwdbased.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfssl/wolfcrypt/pwdbased.h b/wolfssl/wolfcrypt/pwdbased.h index fb56df627f4..dbb084358d0 100644 --- a/wolfssl/wolfcrypt/pwdbased.h +++ b/wolfssl/wolfcrypt/pwdbased.h @@ -41,7 +41,7 @@ * Override by defining WC_PBKDF_MAX_ITERATIONS before including this header. * Normal PKCS#12 files use 1,000–10,000 iterations. */ #ifndef WC_PBKDF_MAX_ITERATIONS - #define WC_PBKDF_MAX_ITERATIONS 100000 + #define WC_PBKDF_MAX_ITERATIONS 2000000 #endif #if FIPS_VERSION3_GE(6,0,0) From 8ea014a7fd6fd3abba0c8ffa4252a3e57172fabe Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Fri, 10 Apr 2026 10:45:15 -0400 Subject: [PATCH 6/9] Comment fixup. --- wolfssl/wolfcrypt/pwdbased.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfssl/wolfcrypt/pwdbased.h b/wolfssl/wolfcrypt/pwdbased.h index dbb084358d0..8a59f30e86c 100644 --- a/wolfssl/wolfcrypt/pwdbased.h +++ b/wolfssl/wolfcrypt/pwdbased.h @@ -39,7 +39,7 @@ * Attacker-controlled PKCS#12 files can specify iterations up to INT_MAX * (2,147,483,647) in the MAC data, causing hours of CPU time. * Override by defining WC_PBKDF_MAX_ITERATIONS before including this header. - * Normal PKCS#12 files use 1,000–10,000 iterations. */ + * Normal p12 files use 1k to 10k iterations. */ #ifndef WC_PBKDF_MAX_ITERATIONS #define WC_PBKDF_MAX_ITERATIONS 2000000 #endif From 45de230b425c70f343fd924c5619e3d9fd26adf7 Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Fri, 10 Apr 2026 12:58:40 -0400 Subject: [PATCH 7/9] Line length fixup and repro in second impl. --- wolfcrypt/src/pwdbased.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 7135c098bfe..77011bd6014 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -414,7 +414,8 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, iterations = 1; if (iterations > WC_PBKDF_MAX_ITERATIONS) { - WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds WC_PBKDF_MAX_ITERATIONS"); + WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds " + "WC_PBKDF_MAX_ITERATIONS"); return BAD_FUNC_ARG; } @@ -626,6 +627,12 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, iterations = 1; } + if (iterations > WC_PBKDF_MAX_ITERATIONS) { + WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds " + "WC_PBKDF_MAX_ITERATIONS"); + return BAD_FUNC_ARG; + } + /* u = hash output size. */ hashT = wc_HashTypeConvert(hashType); ret = wc_HashGetDigestSize(hashT); From 47a95f8eaab6e45c49f350e572ae8e2bf95e29d1 Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Wed, 15 Apr 2026 17:36:33 -0400 Subject: [PATCH 8/9] Known macros --- .wolfssl_known_macro_extras | 1 + 1 file changed, 1 insertion(+) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index ba5e47ef67e..85b10adbfec 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -646,6 +646,7 @@ WC_NO_ASYNC_SLEEP WC_NO_RNG_SIMPLE WC_NO_STATIC_ASSERT WC_NO_VERBOSE_RNG +WC_PBKDF_MAX_ITERATIONS WC_PKCS11_FIND_WITH_ID_ONLY WC_PKCS12_PBKDF_USING_MP_API WC_PROTECT_ENCRYPTED_MEM From 536911bfcb2f93f0a416296789ff5403d23d023c Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Tue, 28 Apr 2026 11:19:50 -0400 Subject: [PATCH 9/9] API Docs --- doc/dox_comments/header_files/pwdbased.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/dox_comments/header_files/pwdbased.h b/doc/dox_comments/header_files/pwdbased.h index 25870b835bf..d2418b96b5c 100644 --- a/doc/dox_comments/header_files/pwdbased.h +++ b/doc/dox_comments/header_files/pwdbased.h @@ -174,7 +174,8 @@ int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen, \brief Extended version of PBKDF1 with heap hint. \return 0 on success - \return BAD_FUNC_ARG on invalid arguments + \return BAD_FUNC_ARG on invalid arguments or iterations is greater than + WC_PBKDF_MAX_ITERATIONS \return MEMORY_E on memory allocation error \param key Output key buffer @@ -209,7 +210,8 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, \brief Extended version of PBKDF2 with heap hint and device ID. \return 0 on success - \return BAD_FUNC_ARG on invalid arguments + \return BAD_FUNC_ARG on invalid arguments or iterations is greater than + WC_PBKDF_MAX_ITERATIONS \return MEMORY_E on memory allocation error \param output Output key buffer @@ -244,7 +246,8 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, \brief Extended version of PKCS12_PBKDF with heap hint. \return 0 on success - \return BAD_FUNC_ARG on invalid arguments + \return BAD_FUNC_ARG on invalid arguments or iterations is greater than + WC_PBKDF_MAX_ITERATIONS \return MEMORY_E on memory allocation error \param output Output key buffer