mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 10:50:53 +02:00
Merge pull request #10050 from anhu/pbkdf_max
Add upper limit to PBKDF iteration count
This commit is contained in:
@@ -30,8 +30,8 @@ ARDUINO_UNOR4_WIFI
|
||||
ASN_DUMP_OID
|
||||
ASN_TEMPLATE_SKIP_ISCA_CHECK
|
||||
ATCAPRINTF
|
||||
ATCA_HAL_I2C
|
||||
ATCA_ENABLE_DEPRECATED
|
||||
ATCA_HAL_I2C
|
||||
ATCA_TFLEX_SUPPORT
|
||||
ATECC_DEV_TYPE
|
||||
AVR
|
||||
@@ -471,7 +471,6 @@ NO_WOLFSSL_RENESAS_FSPSM_AES
|
||||
NO_WOLFSSL_RENESAS_FSPSM_HASH
|
||||
NO_WOLFSSL_RENESAS_TSIP_CRYPT_AES
|
||||
NO_WOLFSSL_SHA256
|
||||
NO_WOLFSSL_SHA256_INTERLEAVE
|
||||
NO_WOLFSSL_SHA512_INTERLEAVE
|
||||
NO_WOLFSSL_SKIP_TRAILING_PAD
|
||||
NO_WOLFSSL_SMALL_STACK_STATIC
|
||||
@@ -628,7 +627,6 @@ USS_API
|
||||
WC_AESXTS_STREAM_NO_REQUEST_ACCOUNTING
|
||||
WC_AES_BS_WORD_SIZE
|
||||
WC_AES_GCM_DEC_AUTH_EARLY
|
||||
WC_ALLOW_ECC_ZERO_HASH
|
||||
WC_ASN_HASH_SHA256
|
||||
WC_ASN_RUNTIME_DATE_CHECK_CONTROL
|
||||
WC_ASYNC_ENABLE_ECC_KEYGEN
|
||||
@@ -653,8 +651,6 @@ WC_ASYNC_NO_SHA512
|
||||
WC_ASYNC_NO_X25519
|
||||
WC_ASYNC_THREAD_BIND
|
||||
WC_CACHE_RESISTANT_BASE64_TABLE
|
||||
WC_DILITHIUM_CACHE_PRIV_VECTORS
|
||||
WC_DILITHIUM_CACHE_PUB_VECTORS
|
||||
WC_DILITHIUM_FIXED_ARRAY
|
||||
WC_DISABLE_RADIX_ZERO_PAD
|
||||
WC_FLAG_DONT_USE_AESNI
|
||||
@@ -718,11 +714,9 @@ WOLFSSL_ASN_EXTRA
|
||||
WOLFSSL_ASN_TEMPLATE_NEED_SET_INT32
|
||||
WOLFSSL_ASN_TEMPLATE_TYPE_CHECK
|
||||
WOLFSSL_ATECC508
|
||||
WOLFSSL_ATECC508A_NOIDLE
|
||||
WOLFSSL_ATECC508A_NOSOFTECC
|
||||
WOLFSSL_ATECC508A_TLS
|
||||
WOLFSSL_ATECC_ECDH_IOENC
|
||||
WOLFSSL_ATECC_NO_ECDH_ENC
|
||||
WOLFSSL_ATECC_RNG
|
||||
WOLFSSL_ATECC_TFLXTLS
|
||||
WOLFSSL_ATECC_TNGTLS
|
||||
@@ -743,15 +737,11 @@ WOLFSSL_CLIENT_EXAMPLE
|
||||
WOLFSSL_CONTIKI
|
||||
WOLFSSL_CRL_ALLOW_MISSING_CDP
|
||||
WOLFSSL_DILITHIUM_ASSIGN_KEY
|
||||
WOLFSSL_DILITHIUM_NO_ASN1
|
||||
WOLFSSL_DILITHIUM_NO_CHECK_KEY
|
||||
WOLFSSL_DILITHIUM_NO_MAKE
|
||||
WOLFSSL_DILITHIUM_REVERSE_HASH_OID
|
||||
WOLFSSL_DILITHIUM_SIGN_CHECK_W0
|
||||
WOLFSSL_DILITHIUM_SIGN_CHECK_Y
|
||||
WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC
|
||||
WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A
|
||||
WOLFSSL_DILITHIUM_SMALL_MEM_POLY64
|
||||
WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
|
||||
WOLFSSL_DRBG_SHA256
|
||||
WOLFSSL_DTLS_DISALLOW_FUTURE
|
||||
@@ -808,10 +798,8 @@ WOLFSSL_LINUXKM_USE_GET_RANDOM_USER_KRETPROBE
|
||||
WOLFSSL_LINUXKM_USE_MUTEXES
|
||||
WOLFSSL_LMS_CACHE_BITS
|
||||
WOLFSSL_LMS_FULL_HASH
|
||||
WOLFSSL_LMS_LARGE_CACHES
|
||||
WOLFSSL_LMS_MAX_HEIGHT
|
||||
WOLFSSL_LMS_MAX_LEVELS
|
||||
WOLFSSL_LMS_NO_SIG_CACHE
|
||||
WOLFSSL_LMS_ROOT_LEVELS
|
||||
WOLFSSL_LPC43xx
|
||||
WOLFSSL_MAKE_SYSTEM_NAME_LINUX
|
||||
@@ -868,16 +856,10 @@ WOLFSSL_NO_TICKET_EXPIRE
|
||||
WOLFSSL_NO_TRUSTED_CERTS_VERIFY
|
||||
WOLFSSL_NO_WORD64_OPS
|
||||
WOLFSSL_NO_XOR_OPS
|
||||
WOLFSSL_NXP_LPC55S6X
|
||||
WOLFSSL_NXP_CASPER
|
||||
WOLFSSL_NXP_CASPER_ECC_MULMOD
|
||||
WOLFSSL_NXP_CASPER_ECC_MUL2ADD
|
||||
WOLFSSL_NXP_CASPER_RSA_PUB_EXPTMOD
|
||||
WOLFSSL_NXP_HASHCRYPT
|
||||
WOLFSSL_NXP_HASHCRYPT_AES
|
||||
WOLFSSL_NXP_HASHCRYPT_SHA
|
||||
WOLFSSL_NXP_RNG_1
|
||||
WOLFSSL_NRF51_AES
|
||||
WOLFSSL_NXP_CASPER_ECC_MUL2ADD
|
||||
WOLFSSL_NXP_CASPER_ECC_MULMOD
|
||||
WOLFSSL_NXP_LPC55S6X
|
||||
WOLFSSL_OLDTLS_AEAD_CIPHERSUITES
|
||||
WOLFSSL_OLD_SET_CURVES_LIST
|
||||
WOLFSSL_OLD_TIMINGPADVERIFY
|
||||
@@ -970,10 +952,8 @@ WOLFSSL_USE_FLASHMEM
|
||||
WOLFSSL_USE_FORCE_ZERO
|
||||
WOLFSSL_USE_OPTIONS_H
|
||||
WOLFSSL_VALIDATE_DH_KEYGEN
|
||||
WOLFSSL_WC_LMS_SERIALIZE_STATE
|
||||
WOLFSSL_WC_SLHDSA_RECURSIVE
|
||||
WOLFSSL_WC_XMSS_NO_SHA256
|
||||
WOLFSSL_WC_XMSS_NO_SHAKE256
|
||||
WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME
|
||||
WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE
|
||||
WOLFSSL_X509_STORE_CERTS
|
||||
@@ -982,7 +962,6 @@ WOLFSSL_XFREE_NO_NULLNESS_CHECK
|
||||
WOLFSSL_XILINX_CRYPTO_OLD
|
||||
WOLFSSL_XILINX_PATCH
|
||||
WOLFSSL_XIL_MSG_NO_SLEEP
|
||||
WOLFSSL_XMSS_LARGE_SECRET_KEY
|
||||
WOLFSSL_ZEPHYR
|
||||
WOLF_ALLOW_BUILTIN
|
||||
WOLF_CRYPTO_CB_CMD
|
||||
|
||||
@@ -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
|
||||
current_wc_pbkdf_max_iterations
|
||||
\return MEMORY_E on memory allocation error
|
||||
|
||||
\param key Output key buffer
|
||||
@@ -199,6 +200,8 @@ int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,
|
||||
\endcode
|
||||
|
||||
\sa wc_PBKDF1
|
||||
\sa wc_PBKDF_max_iterations_set
|
||||
\sa wc_PBKDF_max_iterations_get
|
||||
*/
|
||||
int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
|
||||
const byte* passwd, int passwdLen, const byte* salt, int saltLen,
|
||||
@@ -209,7 +212,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
|
||||
current_wc_pbkdf_max_iterations
|
||||
\return MEMORY_E on memory allocation error
|
||||
|
||||
\param output Output key buffer
|
||||
@@ -234,6 +238,8 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
|
||||
\endcode
|
||||
|
||||
\sa wc_PBKDF2
|
||||
\sa wc_PBKDF_max_iterations_set
|
||||
\sa wc_PBKDF_max_iterations_get
|
||||
*/
|
||||
int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen,
|
||||
const byte* salt, int sLen, int iterations, int kLen,
|
||||
@@ -244,7 +250,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
|
||||
current_wc_pbkdf_max_iterations
|
||||
\return MEMORY_E on memory allocation error
|
||||
|
||||
\param output Output key buffer
|
||||
@@ -268,6 +275,8 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen,
|
||||
\endcode
|
||||
|
||||
\sa wc_PKCS12_PBKDF
|
||||
\sa wc_PBKDF_max_iterations_set
|
||||
\sa wc_PBKDF_max_iterations_get
|
||||
*/
|
||||
int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd,int passLen,
|
||||
const byte* salt, int saltLen, int iterations, int kLen,
|
||||
@@ -338,3 +347,44 @@ int wc_scrypt(byte* output, const byte* passwd, int passLen,
|
||||
int wc_scrypt_ex(byte* output, const byte* passwd, int passLen,
|
||||
const byte* salt, int saltLen, word32 iterations, int blockSize,
|
||||
int parallel, int dkLen);
|
||||
|
||||
/*!
|
||||
\ingroup Password
|
||||
\brief Set the current iteration limit for PBKDF.
|
||||
|
||||
By default, the iteration limit is set to WC_PBKDF_DEFAULT_MAX_ITERATIONS,
|
||||
which can be overridden at build time. This function allows runtime
|
||||
override of the limit.
|
||||
|
||||
Note that `wc_PBKDF_max_iterations_set()` has no provisions for thread
|
||||
synchronization. Users should arrange to call it at startup or idle times,
|
||||
when there are no other PBKDF calls in progress.
|
||||
|
||||
\return Previous iteration limit on success
|
||||
\return BAD_FUNC_ARG on invalid arguments
|
||||
|
||||
\param iters The new iteration limit.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
int prev_iter_limit = wc_PBKDF_max_iterations_set(100000000);
|
||||
\endcode
|
||||
|
||||
\sa wc_scrypt
|
||||
*/
|
||||
int wc_PBKDF_max_iterations_set(int iters);
|
||||
|
||||
/*!
|
||||
\ingroup Password
|
||||
\brief Get the current iteration limit for PBKDF.
|
||||
|
||||
\return Current iteration limit
|
||||
|
||||
_Example_
|
||||
\code
|
||||
int cur_iter_limit = wc_PBKDF_max_iterations_get();
|
||||
\endcode
|
||||
|
||||
\sa wc_scrypt
|
||||
*/
|
||||
int wc_PBKDF_max_iterations_get(void);
|
||||
|
||||
+46
-16
@@ -54,6 +54,24 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
static int current_wc_pbkdf_max_iterations = WC_PBKDF_DEFAULT_MAX_ITERATIONS;
|
||||
|
||||
int wc_PBKDF_max_iterations_set(int iters)
|
||||
{
|
||||
if (iters <= 0)
|
||||
return BAD_FUNC_ARG;
|
||||
else {
|
||||
int prev = current_wc_pbkdf_max_iterations;
|
||||
current_wc_pbkdf_max_iterations = iters;
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
||||
int wc_PBKDF_max_iterations_get(void)
|
||||
{
|
||||
return current_wc_pbkdf_max_iterations;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PBKDF1
|
||||
|
||||
/* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */
|
||||
@@ -82,6 +100,11 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
|
||||
if (iterations <= 0)
|
||||
iterations = 1;
|
||||
|
||||
if (iterations > current_wc_pbkdf_max_iterations) {
|
||||
WOLFSSL_MSG("PBKDF1 iteration count exceeds current_wc_pbkdf_max_iterations");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
hashT = wc_HashTypeConvert(hashType);
|
||||
err = wc_HashGetDigestSize(hashT);
|
||||
if (err < 0)
|
||||
@@ -218,6 +241,11 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt,
|
||||
if (iterations <= 0)
|
||||
iterations = 1;
|
||||
|
||||
if (iterations > current_wc_pbkdf_max_iterations) {
|
||||
WOLFSSL_MSG("PBKDF2 iteration count exceeds current_wc_pbkdf_max_iterations");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
hashT = wc_HashTypeConvert(hashType);
|
||||
hLen = wc_HashGetDigestSize(hashT);
|
||||
if (hLen < 0)
|
||||
@@ -406,6 +434,12 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
|
||||
if (iterations <= 0)
|
||||
iterations = 1;
|
||||
|
||||
if (iterations > current_wc_pbkdf_max_iterations) {
|
||||
WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds "
|
||||
"current_wc_pbkdf_max_iterations");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
hashT = wc_HashTypeConvert(hashType);
|
||||
ret = wc_HashGetDigestSize(hashT);
|
||||
if (ret < 0)
|
||||
@@ -443,22 +477,17 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
|
||||
* must be 1 or greater here and is always 'true' */
|
||||
pLen = v * (((word32)passLen + v - 1) / v);
|
||||
|
||||
/* Guard against overflow in iLen = sLen + pLen and totalLen = dLen + iLen.
|
||||
* Individual sLen/pLen values fit in word32 (max 0x80000000 for INT_MAX
|
||||
* inputs), but their sum can overflow. */
|
||||
if (sLen > 0xFFFFFFFFU - pLen) {
|
||||
if (! WC_SAFE_SUM_UNSIGNED(word32, sLen, pLen, iLen)) {
|
||||
WC_FREE_VAR_EX(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
iLen = sLen + pLen;
|
||||
|
||||
if (iLen > 0xFFFFFFFFU - dLen) {
|
||||
if (! WC_SAFE_SUM_UNSIGNED(word32, dLen, sLen, totalLen)) {
|
||||
WC_FREE_VAR_EX(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
totalLen = dLen + sLen + pLen;
|
||||
|
||||
if (totalLen > sizeof(staticBuffer)) {
|
||||
buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
|
||||
@@ -634,6 +663,12 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
|
||||
iterations = 1;
|
||||
}
|
||||
|
||||
if (iterations > current_wc_pbkdf_max_iterations) {
|
||||
WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds "
|
||||
"current_wc_pbkdf_max_iterations");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* u = hash output size. */
|
||||
hashT = wc_HashTypeConvert(hashType);
|
||||
ret = wc_HashGetDigestSize(hashT);
|
||||
@@ -656,19 +691,14 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
|
||||
/* RFC 7292 B.2 step 3: P = password repeated to ceil(passLen/v)*v bytes */
|
||||
pLen = v * (((word32)passLen + v - 1) / v);
|
||||
|
||||
/* Guard against overflow in iLen = sLen + pLen and totalLen = v + iLen.
|
||||
* Individual sLen/pLen values fit in word32 (max 0x80000000 for INT_MAX
|
||||
* inputs), but their sum can overflow. */
|
||||
if (sLen > 0xFFFFFFFFU - pLen) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
/* RFC 7292 B.2 step 4: I = S || P */
|
||||
iLen = sLen + pLen;
|
||||
if (! WC_SAFE_SUM_UNSIGNED(word32, sLen, pLen, iLen)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (iLen > 0xFFFFFFFFU - v) {
|
||||
if (! WC_SAFE_SUM_UNSIGNED(word32, v, iLen, totalLen)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
totalLen = v + iLen;
|
||||
|
||||
nwc = v / (word32)sizeof(PKCS12_WORD);
|
||||
nBlocks = iLen / v;
|
||||
|
||||
+126
-3
@@ -917,12 +917,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openSSL_evpMD_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_evpSig_test(void);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PBKDF1) && !defined(NO_SHA)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf1_test(void);
|
||||
#endif
|
||||
#if defined(HAVE_PKCS12) && !defined(NO_SHA256)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_pbkdf_test(void);
|
||||
#endif
|
||||
#if defined(HAVE_PBKDF2) && !defined(NO_SHA256) && !defined(NO_HMAC)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void);
|
||||
#endif
|
||||
#if !defined(NO_PWDBASED) && defined(HAVE_SCRYPT)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void);
|
||||
#endif
|
||||
#ifdef HAVE_ECC
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test(void);
|
||||
#if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_AES_CBC) && \
|
||||
@@ -32207,7 +32213,31 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void)
|
||||
if (XMEMCMP(derived, verify, sizeof(verify)) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
return 0;
|
||||
{
|
||||
int cur_pbkdf_limit = wc_PBKDF_max_iterations_set(iterations - 1);
|
||||
if (cur_pbkdf_limit <= 0)
|
||||
return WC_TEST_RET_ENC_EC(cur_pbkdf_limit);
|
||||
ret = wc_PBKDF2_ex(derived, (byte*)passwd, (int)XSTRLEN(passwd),
|
||||
salt, (int)sizeof(salt), iterations,
|
||||
kLen, WC_SHA256, HEAP_HINT, devId);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
ret = wc_PBKDF_max_iterations_set(-1);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
ret = wc_PBKDF_max_iterations_set(0);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
ret = wc_PBKDF_max_iterations_get();
|
||||
if (ret != iterations - 1)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
ret = wc_PBKDF_max_iterations_set(cur_pbkdf_limit);
|
||||
if (ret != iterations - 1)
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
#endif /* HAVE_PBKDF2 && !NO_SHA256 && !NO_HMAC */
|
||||
@@ -32262,10 +32292,58 @@ 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) && !defined(WOLFSSL_NO_MALLOC)
|
||||
/* 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)
|
||||
ret = WC_TEST_RET_ENC_EC(ret);
|
||||
else {
|
||||
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);
|
||||
/* Parse must fail (iteration cap), not succeed or hang */
|
||||
if (ret == 0)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
else
|
||||
ret = 0;
|
||||
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);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_PKCS12 && !NO_ASN && !NO_PWDBASED && !NO_HMAC && !NO_CERTS && */
|
||||
/* !WOLFSSL_NO_MALLOC */
|
||||
#ifdef HAVE_SCRYPT
|
||||
ret = scrypt_test();
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@@ -32361,6 +32439,51 @@ 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) {
|
||||
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)
|
||||
|
||||
@@ -266,12 +266,18 @@ extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openSSL_evpMD_test(void);
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_evpSig_test(void);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PBKDF1) && !defined(NO_SHA)
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf1_test(void);
|
||||
#endif
|
||||
#if defined(HAVE_PKCS12) && !defined(NO_SHA256)
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_pbkdf_test(void);
|
||||
#endif
|
||||
#if defined(HAVE_PBKDF2) && !defined(NO_SHA256) && !defined(NO_HMAC)
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void);
|
||||
#endif
|
||||
#if !defined(NO_PWDBASED) && defined(HAVE_SCRYPT)
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void);
|
||||
#endif
|
||||
#ifdef HAVE_ECC
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test(void);
|
||||
#if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_AES_CBC) && \
|
||||
|
||||
@@ -35,6 +35,26 @@
|
||||
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_DEFAULT_MAX_ITERATIONS before including
|
||||
* this header, and override at runtime by calling
|
||||
* wc_PBKDF_max_iterations_set() at application startup.
|
||||
*
|
||||
* Note that typical PKCS12 files use 1k to 10k iterations.
|
||||
*/
|
||||
#ifndef WC_PBKDF_DEFAULT_MAX_ITERATIONS
|
||||
#define WC_PBKDF_DEFAULT_MAX_ITERATIONS 10000000
|
||||
#endif
|
||||
|
||||
/* Note that wc_PBKDF_max_iterations_set() has no provisions for thread
|
||||
* synchronization. Users should arrange to call it at startup or idle times,
|
||||
* when there are no other PBKDF calls in progress.
|
||||
*/
|
||||
WOLFSSL_API int wc_PBKDF_max_iterations_set(int iters);
|
||||
WOLFSSL_API int wc_PBKDF_max_iterations_get(void);
|
||||
|
||||
#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);
|
||||
|
||||
Reference in New Issue
Block a user