@@ -20491,6 +20491,83 @@ static int test_wolfSSL_d2i_PrivateKeys_bio(void)
2049120491}
2049220492#endif /* OPENSSL_ALL || (WOLFSSL_ASIO && !NO_RSA) */
2049320493
20494+ /* Build gate for the hook + test so they can't drift: OPENSSL_EXTRA (compat
20495+ * BIO/RSA) + a d2i_RSAPrivateKey_bio profile + RSA/key-gen + swappable alloc.
20496+ * DEBUG_MEMORY excluded on purpose: the hook is single-arg only. */
20497+ #if defined(OPENSSL_EXTRA) && \
20498+ (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
20499+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) && \
20500+ !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \
20501+ defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \
20502+ !defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY)
20503+ #define TEST_DER_CAP_MALLOC_HOOK
20504+ #endif
20505+
20506+ #ifdef TEST_DER_CAP_MALLOC_HOOK
20507+ /* Refuses allocations >= der_cap_threshold; forwards the rest to the installed
20508+ * allocator (native if none) so the alloc triple stays consistent. */
20509+ static wolfSSL_Malloc_cb der_cap_prev_malloc = NULL;
20510+ static size_t der_cap_threshold = 0; /* 0 = disabled */
20511+ static int der_cap_attempts = 0;
20512+
20513+ static void* der_cap_malloc_cb(size_t size)
20514+ {
20515+ if (der_cap_threshold != 0 && size >= der_cap_threshold) {
20516+ der_cap_attempts++;
20517+ return NULL; /* refuse; records the attempt */
20518+ }
20519+ if (der_cap_prev_malloc != NULL)
20520+ return der_cap_prev_malloc(size);
20521+ return malloc(size);
20522+ }
20523+ #endif /* TEST_DER_CAP_MALLOC_HOOK */
20524+
20525+ /* Oversized-DER cap must reject before allocating. NULL alone doesn't prove it
20526+ * (uncapped returns NULL too), so assert no large alloc was attempted. */
20527+ static int test_wolfSSL_d2i_RSAPrivateKey_bio_oversized(void)
20528+ {
20529+ EXPECT_DECLS;
20530+ #ifdef TEST_DER_CAP_MALLOC_HOOK
20531+ /* SEQUENCE, canonical 4-byte length 0x01000000 (16 MB), over the cap.
20532+ * Must be canonical -- 0x00FFFFFF is rejected by the parser first. */
20533+ static const unsigned char hugeSeq[] =
20534+ { 0x30, 0x84, 0x01, 0x00, 0x00, 0x00 };
20535+ BIO* bio = NULL;
20536+ RSA* rsa = NULL;
20537+ wolfSSL_Malloc_cb prev_mc = NULL;
20538+ wolfSSL_Free_cb prev_fc = NULL;
20539+ wolfSSL_Realloc_cb prev_rc = NULL;
20540+ int allocators_set = 0;
20541+
20542+ ExpectIntEQ(wolfSSL_GetAllocators(&prev_mc, &prev_fc, &prev_rc), 0);
20543+ der_cap_prev_malloc = prev_mc;
20544+ /* Override only malloc; keep the installed free/realloc. */
20545+ ExpectIntEQ(wolfSSL_SetAllocators(der_cap_malloc_cb, prev_fc, prev_rc), 0);
20546+ if (EXPECT_SUCCESS())
20547+ allocators_set = 1;
20548+
20549+ ExpectNotNull(bio = BIO_new(BIO_s_mem()));
20550+ ExpectIntGT(BIO_write(bio, hugeSeq, (int)sizeof(hugeSeq)), 0);
20551+
20552+ der_cap_attempts = 0;
20553+ der_cap_threshold = 0x10000;
20554+ ExpectNull(d2i_RSAPrivateKey_bio(bio, &rsa));
20555+ der_cap_threshold = 0;
20556+
20557+ ExpectIntEQ(der_cap_attempts, 0);
20558+
20559+ BIO_free(bio);
20560+ RSA_free(rsa);
20561+
20562+ if (allocators_set)
20563+ (void)wolfSSL_SetAllocators(prev_mc, prev_fc, prev_rc);
20564+ der_cap_prev_malloc = NULL;
20565+ #endif
20566+ return EXPECT_RESULT();
20567+ }
20568+
20569+ #undef TEST_DER_CAP_MALLOC_HOOK
20570+
2049420571#endif /* !NO_BIO */
2049520572
2049620573
@@ -38233,6 +38310,9 @@ TEST_CASE testCases[] = {
3823338310 TEST_DECL(test_wolfSSL_d2i_PrivateKeys_bio),
3823438311#endif /* !NO_BIO */
3823538312#endif
38313+ #ifndef NO_BIO
38314+ TEST_DECL(test_wolfSSL_d2i_RSAPrivateKey_bio_oversized),
38315+ #endif /* !NO_BIO */
3823638316
3823738317
3823838318#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
0 commit comments