Skip to content

Commit a9ff710

Browse files
committed
Fix DTLS 1.3 extSz out-of-bounds and word16 truncation on oversized certificate chains
1 parent 76a498f commit a9ff710

4 files changed

Lines changed: 111 additions & 2 deletions

File tree

src/dtls13.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,10 @@ static int Dtls13SendFragmentedInternal(WOLFSSL* ssl)
10121012
Dtls13FreeFragmentsBuffer(ssl);
10131013
return recordLength;
10141014
}
1015+
if ((word32)outputSz > WOLFSSL_MAX_16BIT) {
1016+
Dtls13FreeFragmentsBuffer(ssl);
1017+
return BUFFER_E;
1018+
}
10151019

10161020
ret = CheckAvailableSize(ssl, outputSz);
10171021
if (ret != 0) {
@@ -1606,6 +1610,10 @@ static int Dtls13RtxSendBuffered(WOLFSSL* ssl)
16061610
if (!w64IsZero(r->epoch))
16071611
sendSz += MAX_MSG_EXTRA;
16081612

1613+
if ((word32)sendSz > WOLFSSL_MAX_16BIT) {
1614+
return BUFFER_E;
1615+
}
1616+
16091617
ret = CheckAvailableSize(ssl, sendSz);
16101618
if (ret != 0)
16111619
return ret;

src/tls13.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9213,7 +9213,7 @@ static int SendTls13Certificate(WOLFSSL* ssl)
92139213
break;
92149214
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
92159215
!defined(NO_WOLFSSL_SERVER)
9216-
if (MAX_CERT_EXTENSIONS > extIdx)
9216+
if (extIdx + 1 < MAX_CERT_EXTENSIONS)
92179217
extIdx++;
92189218
#endif
92199219
}
@@ -9246,6 +9246,10 @@ static int SendTls13Certificate(WOLFSSL* ssl)
92469246
/* DTLS1.3 uses a separate variable and logic for fragments */
92479247
ssl->options.buildingMsg = 0;
92489248
ssl->fragOffset = 0;
9249+
if ((word32)sendSz > WOLFSSL_MAX_16BIT || i > WOLFSSL_MAX_16BIT) {
9250+
WOLFSSL_MSG("Send Cert DTLS size exceeds word16");
9251+
return BUFFER_E;
9252+
}
92499253
ret = Dtls13HandshakeSend(ssl, output, (word16)sendSz, (word16)i,
92509254
certificate, 1);
92519255
}

tests/api/test_dtls.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2609,3 +2609,98 @@ int test_dtls13_min_rtx_interval(void)
26092609
#endif
26102610
return EXPECT_RESULT();
26112611
}
2612+
2613+
/* Test that a DTLS 1.3 handshake with an oversized certificate chain does
2614+
* not crash or cause out-of-bounds access in SendTls13Certificate. */
2615+
int test_dtls13_oversized_cert_chain(void)
2616+
{
2617+
EXPECT_DECLS;
2618+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \
2619+
&& !defined(NO_FILESYSTEM) && !defined(NO_RSA)
2620+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
2621+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
2622+
struct test_memio_ctx test_ctx;
2623+
XFILE f = XBADFILE;
2624+
long sz = 0;
2625+
byte *cert = NULL;
2626+
byte *chain = NULL;
2627+
int copies, off, i;
2628+
2629+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
2630+
2631+
/* Read server cert */
2632+
f = XFOPEN(svrCertFile, "rb");
2633+
ExpectTrue(f != XBADFILE);
2634+
if (EXPECT_SUCCESS()) {
2635+
XFSEEK(f, 0, XSEEK_END);
2636+
sz = XFTELL(f);
2637+
XFSEEK(f, 0, XSEEK_SET);
2638+
}
2639+
ExpectTrue(sz > 0);
2640+
cert = (byte*)XMALLOC((size_t)(sz + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
2641+
ExpectNotNull(cert);
2642+
if (EXPECT_SUCCESS())
2643+
ExpectIntEQ((int)XFREAD(cert, 1, (size_t)sz, f), (int)sz);
2644+
if (f != XBADFILE)
2645+
XFCLOSE(f);
2646+
2647+
/* Build an oversized chain by duplicating the cert */
2648+
copies = (int)(70000 / sz) + 2;
2649+
chain = (byte*)XMALLOC((size_t)(sz * copies + 1), NULL,
2650+
DYNAMIC_TYPE_TMP_BUFFER);
2651+
ExpectNotNull(chain);
2652+
off = 0;
2653+
if (EXPECT_SUCCESS()) {
2654+
for (i = 0; i < copies; i++) {
2655+
XMEMCPY(chain + off, cert, (size_t)sz);
2656+
off += (int)sz;
2657+
}
2658+
}
2659+
2660+
/* Server context: load the oversized chain */
2661+
ExpectNotNull(ctx_s = wolfSSL_CTX_new(wolfDTLSv1_3_server_method()));
2662+
ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(ctx_s,
2663+
chain, (long)off), WOLFSSL_SUCCESS);
2664+
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile,
2665+
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
2666+
if (EXPECT_SUCCESS()) {
2667+
wolfSSL_SetIORecv(ctx_s, test_memio_read_cb);
2668+
wolfSSL_SetIOSend(ctx_s, test_memio_write_cb);
2669+
}
2670+
2671+
/* Client context: no verification (chain certs are duplicates) */
2672+
ExpectNotNull(ctx_c = wolfSSL_CTX_new(wolfDTLSv1_3_client_method()));
2673+
if (EXPECT_SUCCESS()) {
2674+
wolfSSL_CTX_set_verify(ctx_c, WOLFSSL_VERIFY_NONE, NULL);
2675+
wolfSSL_SetIORecv(ctx_c, test_memio_read_cb);
2676+
wolfSSL_SetIOSend(ctx_c, test_memio_write_cb);
2677+
}
2678+
2679+
ExpectNotNull(ssl_s = wolfSSL_new(ctx_s));
2680+
if (EXPECT_SUCCESS()) {
2681+
wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx);
2682+
wolfSSL_SetIOReadCtx(ssl_s, &test_ctx);
2683+
}
2684+
2685+
ExpectNotNull(ssl_c = wolfSSL_new(ctx_c));
2686+
if (EXPECT_SUCCESS()) {
2687+
wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx);
2688+
wolfSSL_SetIOReadCtx(ssl_c, &test_ctx);
2689+
}
2690+
2691+
/* Handshake must not crash. If SendTls13Certificate mishandles the
2692+
* oversized chain this will trigger a wild pointer dereference or stack
2693+
* overflow resulting with the test failing.
2694+
* The correct behaviour either returns BUFFER_E or succeeds
2695+
* if the build config truncated the chain during loading. */
2696+
(void)test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
2697+
2698+
wolfSSL_free(ssl_c);
2699+
wolfSSL_free(ssl_s);
2700+
wolfSSL_CTX_free(ctx_c);
2701+
wolfSSL_CTX_free(ctx_s);
2702+
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2703+
XFREE(chain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2704+
#endif
2705+
return EXPECT_RESULT();
2706+
}

tests/api/test_dtls.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ int test_dtls_memio_wolfio_stateless(void);
5050
int test_dtls_mtu_fragment_headroom(void);
5151
int test_dtls_mtu_split_messages(void);
5252
int test_dtls13_min_rtx_interval(void);
53+
int test_dtls13_oversized_cert_chain(void);
5354

5455
#define TEST_DTLS_DECLS \
5556
TEST_DECL_GROUP("dtls", test_dtls12_basic_connection_id), \
@@ -79,5 +80,6 @@ int test_dtls13_min_rtx_interval(void);
7980
TEST_DECL_GROUP("dtls", test_dtls_mtu_fragment_headroom), \
8081
TEST_DECL_GROUP("dtls", test_dtls_mtu_split_messages), \
8182
TEST_DECL_GROUP("dtls", test_dtls_memio_wolfio_stateless), \
82-
TEST_DECL_GROUP("dtls", test_dtls13_min_rtx_interval)
83+
TEST_DECL_GROUP("dtls", test_dtls13_min_rtx_interval), \
84+
TEST_DECL_GROUP("dtls", test_dtls13_oversized_cert_chain)
8385
#endif /* TESTS_API_DTLS_H */

0 commit comments

Comments
 (0)