diff --git a/crypto/pkcs8/internal.h b/crypto/pkcs8/internal.h index 97c86c4fd..c3302f751 100644 --- a/crypto/pkcs8/internal.h +++ b/crypto/pkcs8/internal.h @@ -119,6 +119,10 @@ int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, const char *pass, size_t pass_len, const uint8_t *salt, size_t salt_len); +// pkcs12_iterations_acceptable returns one if |iterations| is a reasonable +// number of PBKDF2 iterations and zero otherwise. +int pkcs12_iterations_acceptable(uint64_t iterations); + #if defined(__cplusplus) } // extern C diff --git a/crypto/pkcs8/p5_pbev2.c b/crypto/pkcs8/p5_pbev2.c index 6686cf379..7497b000f 100644 --- a/crypto/pkcs8/p5_pbev2.c +++ b/crypto/pkcs8/p5_pbev2.c @@ -244,7 +244,7 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx, return 0; } - if (iterations == 0 || iterations > UINT_MAX) { + if (!pkcs12_iterations_acceptable(iterations)) { OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); return 0; } diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c index 3453113b0..ee25ee29f 100644 --- a/crypto/pkcs8/pkcs8.c +++ b/crypto/pkcs8/pkcs8.c @@ -268,7 +268,7 @@ static int pkcs12_pbe_decrypt_init(const struct pbe_suite *suite, return 0; } - if (iterations == 0 || iterations > UINT_MAX) { + if (!pkcs12_iterations_acceptable(iterations)) { OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); return 0; } diff --git a/crypto/pkcs8/pkcs8_x509.c b/crypto/pkcs8/pkcs8_x509.c index c5a065199..dc74d968c 100644 --- a/crypto/pkcs8/pkcs8_x509.c +++ b/crypto/pkcs8/pkcs8_x509.c @@ -75,6 +75,21 @@ #include "../internal.h" +int pkcs12_iterations_acceptable(uint64_t iterations) { +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + static const uint64_t kIterationsLimit = 2048; +#else + // Windows imposes a limit of 600K. Mozilla say: “so them increasing + // maximum to something like 100M or 1G (to have few decades of breathing + // room) would be very welcome”[1]. So here we set the limit to 100M. + // + // [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1436873#c14 + static const uint64_t kIterationsLimit = 100 * 1000000; +#endif + + return 0 < iterations && iterations <= kIterationsLimit; +} + // Minor tweak to operation: zero private key data static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) { @@ -669,22 +684,11 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs, goto err; } -#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) - static const uint64_t kIterationsLimit = 2048; -#else - // Windows imposes a limit of 600K. Mozilla say: “so them increasing - // maximum to something like 100M or 1G (to have few decades of breathing - // room) would be very welcome”[1]. So here we set the limit to 100M. - // - // [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1436873#c14 - static const uint64_t kIterationsLimit = 100 * 1000000; -#endif - // The iteration count is optional and the default is one. uint64_t iterations = 1; if (CBS_len(&mac_data) > 0) { if (!CBS_get_asn1_uint64(&mac_data, &iterations) || - iterations > kIterationsLimit) { + !pkcs12_iterations_acceptable(iterations)) { OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); goto err; }