diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b7ca4492d..503f94946a 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.c b/tests/api.c index ecbcc4eed3..7b5034eb57 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 cbe2e10a8a..fcfa85b0ce 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 80f23e76b7..8b9e4863e1 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 0000000000..7facfd2005 --- /dev/null +++ b/tests/api/test_pwdbased.c @@ -0,0 +1,72 @@ +/* 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_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 }; + 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_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, + 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 0000000000..d3dd361baf --- /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/evp.c b/wolfcrypt/src/evp.c index 8b01a071f0..0c718d71f9 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) diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 9f59568b57..86ced62fc4 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) {