From e9f3bd5dddaa10a9a91dbb3aa271e0640cf104a3 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Mon, 15 Dec 2025 17:32:52 +0100 Subject: [PATCH] dtls: test precise header headroom computation --- tests/api/test_dtls.c | 113 ++++++++++++++++++++++++++++++++++++++++++ tests/api/test_dtls.h | 2 + 2 files changed, 115 insertions(+) diff --git a/tests/api/test_dtls.c b/tests/api/test_dtls.c index fe13b1a45..94d57a786 100644 --- a/tests/api/test_dtls.c +++ b/tests/api/test_dtls.c @@ -1487,6 +1487,119 @@ int test_records_span_network_boundaries(void) #endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) */ +int test_dtls_mtu_fragment_headroom(void) +{ +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS_MTU) && \ + defined(HAVE_AESGCM) && defined(HAVE_ECC) + EXPECT_DECLS; + struct { + method_provider client_meth; + method_provider server_meth; + const char* cipher; + int use_cid; + } params[] = { +#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_TLS13) + { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, + "TLS13-AES128-GCM-SHA256", 0 }, +#ifdef WOLFSSL_DTLS_CID + { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, + "TLS13-AES128-GCM-SHA256", 1 }, +#endif +#endif +#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) + { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, + "ECDHE-RSA-AES128-GCM-SHA256", 0 }, +#ifdef WOLFSSL_DTLS_CID + { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, + "ECDHE-RSA-AES128-GCM-SHA256", 1 }, +#endif +#if !defined(WOLFSSL_AEAD_ONLY) && !defined(NO_AES) && !defined(NO_SHA) + { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, + "ECDHE-RSA-AES128-SHA", 0 }, +#endif +#endif + }; + size_t i; + + for (i = 0; i < XELEM_CNT(params) && EXPECT_SUCCESS(); i++) { + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + struct test_memio_ctx test_ctx; + unsigned char payload[33]; + word16 mtu; + int recordLen; + int overhead; + int ret; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + params[i].client_meth, params[i].server_meth), + 0); + + ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, params[i].cipher), 1); + ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, params[i].cipher), 1); + +#ifdef WOLFSSL_DTLS_CID + if (params[i].use_cid) { + unsigned char cid_c[] = { 0,1,2,3 }; + unsigned char cid_s[] = { 4,5,6,7,8,9 }; + ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_c), 1); + ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_s), 1); + ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_c, cid_s, (int)sizeof(cid_s)), + 1); + ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_s, cid_c, (int)sizeof(cid_c)), + 1); + } +#endif + + /* Complete handshake and clear any leftover records. */ + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + test_memio_clear_buffer(&test_ctx, 1); + test_memio_clear_buffer(&test_ctx, 0); + + /* Measure application-data record overhead. */ + ExpectIntEQ(wolfSSL_write(ssl_c, "A", 1), 1); + ExpectIntEQ(test_ctx.s_msg_count, 1); + recordLen = test_ctx.s_len; + ExpectIntGT(recordLen, 1); + overhead = recordLen - 1; + + /* Reset buffers before MTU-limited send. */ + test_memio_clear_buffer(&test_ctx, 0); + test_memio_clear_buffer(&test_ctx, 1); + + /* Set MTU to overhead + 32 bytes of payload. */ + mtu = (word16)(overhead + 32); + ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, mtu), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_s, mtu), WOLFSSL_SUCCESS); + + /* With the tightened MTU, we should still be able to send 32 bytes. */ + ExpectIntEQ(wolfSSL_write(ssl_c, payload, 32), 32); + ExpectIntEQ(test_ctx.s_msg_count, 1); + recordLen = test_ctx.s_len; + ExpectIntEQ(recordLen, overhead + 32); + ExpectIntLE(recordLen, mtu); + + /* Underestimation: drop MTU by 1 and expect DTLS_SIZE_ERROR. */ + test_memio_clear_buffer(&test_ctx, 0); + test_memio_clear_buffer(&test_ctx, 1); + ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, mtu - 1), WOLFSSL_SUCCESS); + ret = wolfSSL_write(ssl_c, payload, 32); + ExpectIntNE(ret, 32); + ExpectIntEQ(wolfSSL_get_error(ssl_c, ret), DTLS_SIZE_ERROR); + + wolfSSL_free(ssl_c); + wolfSSL_CTX_free(ctx_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_s); + } + return EXPECT_RESULT(); +#else + return TEST_SKIPPED; +#endif +} + int test_dtls_rtx_across_epoch_change(void) { EXPECT_DECLS; diff --git a/tests/api/test_dtls.h b/tests/api/test_dtls.h index c0fb4bcfb..a058e54a6 100644 --- a/tests/api/test_dtls.h +++ b/tests/api/test_dtls.h @@ -47,6 +47,7 @@ int test_dtls_timeout(void); int test_dtls_certreq_order(void); int test_dtls_memio_wolfio(void); int test_dtls_memio_wolfio_stateless(void); +int test_dtls_mtu_fragment_headroom(void); #define TEST_DTLS_DECLS \ TEST_DECL_GROUP("dtls", test_dtls12_basic_connection_id), \ @@ -73,5 +74,6 @@ int test_dtls_memio_wolfio_stateless(void); TEST_DECL_GROUP("dtls", test_dtls_certreq_order), \ TEST_DECL_GROUP("dtls", test_dtls_timeout), \ TEST_DECL_GROUP("dtls", test_dtls_memio_wolfio), \ + TEST_DECL_GROUP("dtls", test_dtls_mtu_fragment_headroom), \ TEST_DECL_GROUP("dtls", test_dtls_memio_wolfio_stateless) #endif /* TESTS_API_DTLS_H */