Skip to content

Commit be7f934

Browse files
committed
Add test case
1 parent 1875348 commit be7f934

5 files changed

Lines changed: 77 additions & 6 deletions

File tree

src/tls.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,7 +2135,7 @@ static void TLSX_SNI_FreeAll(SNI* list, void* heap)
21352135
}
21362136

21372137
/** Tells the buffered size of the SNI objects in a list. */
2138-
static word16 TLSX_SNI_GetSize(SNI* list)
2138+
WOLFSSL_TEST_VIS word16 TLSX_SNI_GetSize(SNI* list)
21392139
{
21402140
SNI* sni;
21412141
word32 length = OPAQUE16_LEN; /* list length */
@@ -3241,15 +3241,19 @@ word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr, byte isRequest,
32413241
if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL &&
32423242
SSL_CM(csr->ssl)->ocsp_stapling != NULL &&
32433243
SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL) {
3244+
if (WOLFSSL_MAX_16BIT - OPAQUE8_LEN - OPAQUE24_LEN <
3245+
csr->ssl->ocspCsrResp[idx].length) {
3246+
return 0;
3247+
}
32443248
size = OPAQUE8_LEN + OPAQUE24_LEN +
32453249
csr->ssl->ocspCsrResp[idx].length;
3246-
if (size > WOLFSSL_MAX_16BIT)
3247-
return 0;
32483250
return (word16)size;
32493251
}
3250-
size = OPAQUE8_LEN + OPAQUE24_LEN + csr->responses[idx].length;
3251-
if (size > WOLFSSL_MAX_16BIT)
3252+
if (WOLFSSL_MAX_16BIT - OPAQUE8_LEN - OPAQUE24_LEN <
3253+
csr->responses[idx].length) {
32523254
return 0;
3255+
}
3256+
size = OPAQUE8_LEN + OPAQUE24_LEN + csr->responses[idx].length;
32533257
return (word16)size;
32543258
}
32553259
#else

tests/api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32914,6 +32914,7 @@ TEST_CASE testCases[] = {
3291432914
TEST_DECL(test_certificate_authorities_certificate_request),
3291532915
TEST_DECL(test_certificate_authorities_client_hello),
3291632916
TEST_DECL(test_TLSX_TCA_Find),
32917+
TEST_DECL(test_TLSX_SNI_GetSize_overflow),
3291732918
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
3291832919
TEST_DECL(test_wolfSSL_SCR_Reconnect),
3291932920
TEST_DECL(test_wolfSSL_SCR_check_enabled),

tests/api/test_tls_ext.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,3 +545,67 @@ int test_certificate_authorities_client_hello(void) {
545545
#endif
546546
return EXPECT_RESULT();
547547
}
548+
549+
/* Test that the SNI size calculation returns 0 on overflow instead of
550+
* wrapping around to a small value (integer overflow vulnerability). */
551+
int test_TLSX_SNI_GetSize_overflow(void)
552+
{
553+
EXPECT_DECLS;
554+
#if defined(HAVE_SNI) && !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
555+
WOLFSSL_CTX* ctx = NULL;
556+
WOLFSSL* ssl = NULL;
557+
TLSX* sni_ext = NULL;
558+
SNI* head = NULL;
559+
SNI* sni = NULL;
560+
int i;
561+
/* Each SNI adds ENUM_LEN(1) + OPAQUE16_LEN(2) + hostname_len to the size.
562+
* With a 1-byte hostname, each entry adds 4 bytes. Starting from
563+
* OPAQUE16_LEN(2) base, we need enough entries to exceed UINT16_MAX. */
564+
const int num_sni = (0xFFFF / 4) + 2;
565+
566+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
567+
ExpectNotNull(ssl = wolfSSL_new(ctx));
568+
569+
/* Add initial SNI via public API */
570+
ExpectIntEQ(WOLFSSL_SUCCESS,
571+
wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "a", 1));
572+
573+
/* Find the SNI extension and manually build a long chain */
574+
if (EXPECT_SUCCESS()) {
575+
sni_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
576+
ExpectNotNull(sni_ext);
577+
}
578+
579+
if (EXPECT_SUCCESS()) {
580+
head = (SNI*)sni_ext->data;
581+
ExpectNotNull(head);
582+
}
583+
584+
/* Append many SNI nodes to force overflow in the size calculation */
585+
for (i = 1; EXPECT_SUCCESS() && i < num_sni; i++) {
586+
sni = (SNI*)XMALLOC(sizeof(SNI), NULL, DYNAMIC_TYPE_TLSX);
587+
ExpectNotNull(sni);
588+
if (sni != NULL) {
589+
XMEMSET(sni, 0, sizeof(SNI));
590+
sni->type = WOLFSSL_SNI_HOST_NAME;
591+
sni->data.host_name = (char*)XMALLOC(2, NULL, DYNAMIC_TYPE_TLSX);
592+
ExpectNotNull(sni->data.host_name);
593+
if (sni->data.host_name != NULL) {
594+
sni->data.host_name[0] = 'a';
595+
sni->data.host_name[1] = '\0';
596+
}
597+
sni->next = head->next;
598+
head->next = sni;
599+
}
600+
}
601+
602+
if (EXPECT_SUCCESS()) {
603+
/* The fixed calculation should return 0 (overflow detected) */
604+
ExpectIntEQ(TLSX_SNI_GetSize((SNI*)sni_ext->data), 0);
605+
}
606+
607+
wolfSSL_free(ssl);
608+
wolfSSL_CTX_free(ctx);
609+
#endif
610+
return EXPECT_RESULT();
611+
}

tests/api/test_tls_ext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ int test_wolfSSL_DisableExtendedMasterSecret(void);
2727
int test_certificate_authorities_certificate_request(void);
2828
int test_certificate_authorities_client_hello(void);
2929
int test_TLSX_TCA_Find(void);
30+
int test_TLSX_SNI_GetSize_overflow(void);
3031

3132
#endif /* TESTS_API_TEST_TLS_EMS_H */

wolfssl/internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3169,7 +3169,7 @@ struct TLSX {
31693169
struct TLSX* next; /* List Behavior */
31703170
};
31713171

3172-
WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
3172+
WOLFSSL_TEST_VIS TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
31733173
WOLFSSL_LOCAL void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap);
31743174
WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list, void* heap);
31753175
WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl);
@@ -3237,6 +3237,7 @@ WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data,
32373237
WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type);
32383238
WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type,
32393239
void** data, byte ignoreStatus);
3240+
WOLFSSL_TEST_VIS word16 TLSX_SNI_GetSize(SNI* list);
32403241

32413242
#ifndef NO_WOLFSSL_SERVER
32423243
WOLFSSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type,

0 commit comments

Comments
 (0)