Skip to content

Commit 7756bd9

Browse files
committed
cap derLen at largest valid DER size
Test oversized DER is rejected before allocation
1 parent 44f582a commit 7756bd9

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

src/pk_rsa.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,12 @@ static int wolfssl_read_der_bio(WOLFSSL_BIO* bio, unsigned char** out)
651651
WOLFSSL_ERROR_MSG("DER SEQUENCE decode failed");
652652
err = 1;
653653
}
654+
/* Cap at 8x the maximum modulus size, leaves headroom for the full
655+
* private key encoding. */
656+
if ((!err) && (derLen > RSA_MAX_SIZE)) {
657+
WOLFSSL_ERROR_MSG("DER length too large");
658+
err = 1;
659+
}
654660
/* Allocate a buffer to read DER data into. */
655661
if ((!err) && ((der = (unsigned char*)XMALLOC((size_t)derLen, bio->heap,
656662
DYNAMIC_TYPE_TMP_BUFFER)) == NULL)) {

tests/api.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)