From 319f1d699d61675df3f5ff20a80781e85192c0c6 Mon Sep 17 00:00:00 2001 From: HIDEKI MIYAZAKI Date: Wed, 20 May 2026 07:25:35 -0700 Subject: [PATCH 1/3] fix clamp iterations <= 0 to 1 instead of returning an error --- tests/api.c | 4 +++ tests/api/include.am | 3 ++ tests/api/test_pkcs12.c | 15 +++++++-- tests/api/test_pwdbased.c | 71 +++++++++++++++++++++++++++++++++++++++ tests/api/test_pwdbased.h | 34 +++++++++++++++++++ wolfcrypt/src/pwdbased.c | 8 ++--- 6 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 tests/api/test_pwdbased.c create mode 100644 tests/api/test_pwdbased.h diff --git a/tests/api.c b/tests/api.c index ecbcc4eed3e..7b5034eb571 100644 --- a/tests/api.c +++ b/tests/api.c @@ -242,6 +242,7 @@ #include #include #include +#include #include #include #include @@ -40101,6 +40102,9 @@ TEST_CASE testCases[] = { /* wolfCrypt PKCS#12 */ TEST_PKCS12_DECLS, + /* wolfCrypt pwdbased (PBKDF1/PBKDF2) */ + TEST_PWDBASED_DECLS, + /* * test_wolfCrypt_Cleanup needs to come after the above wolfCrypt tests to * avoid memory leaks. diff --git a/tests/api/include.am b/tests/api/include.am index cbe2e10a8ae..fcfa85b0cef 100644 --- a/tests/api/include.am +++ b/tests/api/include.am @@ -65,6 +65,8 @@ tests_unit_test_SOURCES += tests/api/test_asn.c tests_unit_test_SOURCES += tests/api/test_pkcs7.c # PKCS#12 tests_unit_test_SOURCES += tests/api/test_pkcs12.c +# pwdbased (PBKDF1/PBKDF2) +tests_unit_test_SOURCES += tests/api/test_pwdbased.c # OpenSSL ASN.1 tests_unit_test_SOURCES += tests/api/test_ossl_asn1.c # OpenSSL BN @@ -165,6 +167,7 @@ EXTRA_DIST += tests/api/test_x509.h EXTRA_DIST += tests/api/test_asn.h EXTRA_DIST += tests/api/test_pkcs7.h EXTRA_DIST += tests/api/test_pkcs12.h +EXTRA_DIST += tests/api/test_pwdbased.h EXTRA_DIST += tests/api/test_ossl_asn1.h EXTRA_DIST += tests/api/test_ossl_bn.h EXTRA_DIST += tests/api/test_ossl_bio.h diff --git a/tests/api/test_pkcs12.c b/tests/api/test_pkcs12.c index 80f23e76b73..8b9e4863e16 100644 --- a/tests/api/test_pkcs12.c +++ b/tests/api/test_pkcs12.c @@ -647,10 +647,11 @@ int test_wc_PKCS12_PBKDF(void) salt2, (int)sizeof(salt2), 1000, 24, WC_SHA256, 1), 0); ExpectIntEQ(XMEMCMP(derived, verify2, 24), 0); - /* iterations <= 0 treated as 1 */ + /* iterations <= 0 must be rejected */ ExpectIntEQ(wc_PKCS12_PBKDF(derived, passwd, (int)sizeof(passwd), - salt, (int)sizeof(salt), 0, 24, WC_SHA256, 1), 0); - ExpectIntEQ(XMEMCMP(derived, verify, 24), 0); + salt, (int)sizeof(salt), 0, 24, WC_SHA256, 1), BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS12_PBKDF(derived, passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), -1, 24, WC_SHA256, 1), BAD_FUNC_ARG); #endif return EXPECT_RESULT(); } @@ -714,6 +715,14 @@ int test_wc_PKCS12_PBKDF_ex(void) salt, (int)sizeof(salt), 1, 24, WC_SHA256, 2, NULL), 0); ExpectIntEQ(wc_PKCS12_PBKDF_ex(derived, passwd, (int)sizeof(passwd), salt, (int)sizeof(salt), 1, 24, WC_SHA256, 3, NULL), 0); + + /* iterations <= 0 must be rejected */ + ExpectIntEQ(wc_PKCS12_PBKDF_ex(derived, passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), 0, 24, WC_SHA256, 1, NULL), + BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS12_PBKDF_ex(derived, passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), -1, 24, WC_SHA256, 1, NULL), + BAD_FUNC_ARG); #endif return EXPECT_RESULT(); } diff --git a/tests/api/test_pwdbased.c b/tests/api/test_pwdbased.c new file mode 100644 index 00000000000..cdd561b1547 --- /dev/null +++ b/tests/api/test_pwdbased.c @@ -0,0 +1,71 @@ +/* test_pwdbased.c + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include +#include + +/* test that wc_PBKDF1_ex rejects iterations <= 0 */ +int test_wc_PBKDF1_ex_iterations(void) +{ + EXPECT_DECLS; +#if defined(HAVE_PBKDF1) && !defined(NO_SHA) && !defined(HAVE_SELFTEST) + static const byte passwd[] = { 'p', 'a', 's', 's' }; + static const byte salt[] = { 0x78, 0x57, 0x8E, 0x5a, + 0x5d, 0x63, 0xcb, 0x06 }; + byte derived[16]; + + ExpectIntEQ(wc_PBKDF1_ex(derived, (int)sizeof(derived), NULL, 0, + passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), 0, WC_SHA, HEAP_HINT), + BAD_FUNC_ARG); + ExpectIntEQ(wc_PBKDF1_ex(derived, (int)sizeof(derived), NULL, 0, + passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), -1, WC_SHA, HEAP_HINT), + BAD_FUNC_ARG); +#endif + return EXPECT_RESULT(); +} + +/* test that wc_PBKDF2_ex rejects iterations <= 0 */ +int test_wc_PBKDF2_ex_iterations(void) +{ + EXPECT_DECLS; +#if defined(HAVE_PBKDF2) && !defined(NO_HMAC) && !defined(NO_SHA256) && \ + !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + static const byte passwd[] = { 'p', 'a', 's', 's' }; + static const byte salt[] = { 0x78, 0x57, 0x8E, 0x5a, + 0x5d, 0x63, 0xcb, 0x06 }; + byte derived[24]; + + ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), 0, + (int)sizeof(derived), WC_SHA256, HEAP_HINT, INVALID_DEVID), + BAD_FUNC_ARG); + ExpectIntEQ(wc_PBKDF2_ex(derived, passwd, (int)sizeof(passwd), + salt, (int)sizeof(salt), -1, + (int)sizeof(derived), WC_SHA256, HEAP_HINT, INVALID_DEVID), + BAD_FUNC_ARG); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_pwdbased.h b/tests/api/test_pwdbased.h new file mode 100644 index 00000000000..d3dd361baf4 --- /dev/null +++ b/tests/api/test_pwdbased.h @@ -0,0 +1,34 @@ +/* test_pwdbased.h + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef WOLFCRYPT_TEST_PWDBASED_H +#define WOLFCRYPT_TEST_PWDBASED_H + +#include + +int test_wc_PBKDF1_ex_iterations(void); +int test_wc_PBKDF2_ex_iterations(void); + +#define TEST_PWDBASED_DECLS \ + TEST_DECL_GROUP("pwdbased", test_wc_PBKDF1_ex_iterations), \ + TEST_DECL_GROUP("pwdbased", test_wc_PBKDF2_ex_iterations) + +#endif /* WOLFCRYPT_TEST_PWDBASED_H */ diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 9f59568b575..86ced62fc44 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -98,7 +98,7 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, return BAD_FUNC_ARG; if (iterations <= 0) - iterations = 1; + return BAD_FUNC_ARG; if (iterations > current_wc_pbkdf_max_iterations) { WOLFSSL_MSG("PBKDF1 iteration count exceeds current_wc_pbkdf_max_iterations"); @@ -239,7 +239,7 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt, } #endif if (iterations <= 0) - iterations = 1; + return BAD_FUNC_ARG; if (iterations > current_wc_pbkdf_max_iterations) { WOLFSSL_MSG("PBKDF2 iteration count exceeds current_wc_pbkdf_max_iterations"); @@ -432,7 +432,7 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, } if (iterations <= 0) - iterations = 1; + return BAD_FUNC_ARG; if (iterations > current_wc_pbkdf_max_iterations) { WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds " @@ -660,7 +660,7 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, } if (iterations <= 0) { - iterations = 1; + return BAD_FUNC_ARG; } if (iterations > current_wc_pbkdf_max_iterations) { From 03eb38e89786114f7f3472be6b5f3fa4a6877bad Mon Sep 17 00:00:00 2001 From: HIDEKI MIYAZAKI Date: Wed, 20 May 2026 11:04:07 -0700 Subject: [PATCH 2/3] fix EVP_BytesToKey --- wolfcrypt/src/evp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 8b01a071f09..0c718d71f94 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6757,6 +6757,10 @@ void wolfSSL_EVP_init(void) if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) goto end; + /* OpenSSL treats count <= 0 as 1 iteration */ + if (count <= 0) + count = 1; + ret = wc_PBKDF1_ex(key, (int)info->keySz, iv, (int)info->ivSz, data, sz, salt, EVP_SALT_SIZE, count, hashType, NULL); if (ret == 0) From afb3ca4b772f058a6d5b9e9fb42020e6c684d2dd Mon Sep 17 00:00:00 2001 From: HIDEKI MIYAZAKI Date: Wed, 20 May 2026 17:31:08 -0700 Subject: [PATCH 3/3] fix prb failures --- CMakeLists.txt | 1 + tests/api/test_pwdbased.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b7ca4492d2..503f94946a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2950,6 +2950,7 @@ if(WOLFSSL_EXAMPLES) tests/api/test_asn.c tests/api/test_pkcs7.c tests/api/test_pkcs12.c + tests/api/test_pwdbased.c tests/api/test_ossl_asn1.c tests/api/test_ossl_bio.c tests/api/test_ossl_bn.c diff --git a/tests/api/test_pwdbased.c b/tests/api/test_pwdbased.c index cdd561b1547..7facfd20058 100644 --- a/tests/api/test_pwdbased.c +++ b/tests/api/test_pwdbased.c @@ -28,7 +28,8 @@ int test_wc_PBKDF1_ex_iterations(void) { EXPECT_DECLS; -#if defined(HAVE_PBKDF1) && !defined(NO_SHA) && !defined(HAVE_SELFTEST) +#if defined(HAVE_PBKDF1) && !defined(NO_PWDBASED) && !defined(NO_SHA) && \ + !defined(HAVE_SELFTEST) static const byte passwd[] = { 'p', 'a', 's', 's' }; static const byte salt[] = { 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06 }; @@ -50,8 +51,8 @@ int test_wc_PBKDF1_ex_iterations(void) int test_wc_PBKDF2_ex_iterations(void) { EXPECT_DECLS; -#if defined(HAVE_PBKDF2) && !defined(NO_HMAC) && !defined(NO_SHA256) && \ - !defined(HAVE_SELFTEST) && \ +#if defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) && !defined(NO_HMAC) && \ + !defined(NO_SHA256) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) static const byte passwd[] = { 'p', 'a', 's', 's' }; static const byte salt[] = { 0x78, 0x57, 0x8E, 0x5a,