Skip to content

Commit 20a667c

Browse files
committed
dtls13: CH can't reset message seq after stateful
1 parent b580c05 commit 20a667c

2 files changed

Lines changed: 124 additions & 0 deletions

File tree

tests/api/test_dtls.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,128 @@ int test_dtls13_ch2_rtx_no_ch1(void)
19281928
return EXPECT_RESULT();
19291929
}
19301930

1931+
int test_dtls13_frag_ch2_with_ch1_rtx(void)
1932+
{
1933+
EXPECT_DECLS;
1934+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
1935+
defined(WOLFSSL_DTLS13) && defined(WOLFSSL_DTLS) && \
1936+
defined(WOLFSSL_DTLS_MTU) && defined(WOLFSSL_DTLS_CH_FRAG)
1937+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
1938+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
1939+
struct test_memio_ctx test_ctx;
1940+
char hrr[TEST_MEMIO_BUF_SZ];
1941+
int hrrSz = (int)sizeof(hrr);
1942+
char ch1Rtx[TEST_MEMIO_BUF_SZ];
1943+
int ch1RtxSz = (int)sizeof(ch1Rtx);
1944+
char ch2[TEST_MEMIO_BUF_SZ];
1945+
int ch2Sz = 0;
1946+
int ch2MsgCount = 0;
1947+
int ch2MsgSizes[TEST_MEMIO_MAX_MSGS] = {0};
1948+
/* The DTLS record sequence number occupies the last 8 bytes of the
1949+
* record header. */
1950+
int recordSeqOff = DTLS_RECORD_HEADER_SZ - 8;
1951+
int ch2Seq = 0;
1952+
int ch1RtxSeq = 0;
1953+
int off;
1954+
int i;
1955+
1956+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
1957+
1958+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
1959+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
1960+
0);
1961+
1962+
/* To force HRR */
1963+
ExpectIntEQ(wolfSSL_NoKeyShares(ssl_c), WOLFSSL_SUCCESS);
1964+
ExpectIntEQ(wolfSSL_dtls13_allow_ch_frag(ssl_s, 1), WOLFSSL_SUCCESS);
1965+
1966+
/* CH1 */
1967+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
1968+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
1969+
1970+
/* HRR */
1971+
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
1972+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
1973+
ExpectIntEQ(test_memio_copy_message(&test_ctx, 1, hrr, &hrrSz, 0), 0);
1974+
1975+
/* Drop HRR, trigger CH1 retransmission, copy and drop it */
1976+
test_memio_clear_buffer(&test_ctx, 1);
1977+
if (wolfSSL_dtls13_use_quick_timeout(ssl_c))
1978+
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
1979+
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
1980+
ExpectIntEQ(test_memio_copy_message(&test_ctx, 0, ch1Rtx, &ch1RtxSz, 0), 0);
1981+
test_memio_clear_buffer(&test_ctx, 0);
1982+
1983+
/* Force CH2 fragmentation */
1984+
ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, 256), WOLFSSL_SUCCESS);
1985+
1986+
/* Forward HRR and let the client create fragmented CH2 */
1987+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, hrr, hrrSz), 0);
1988+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
1989+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
1990+
1991+
ExpectIntGT(test_ctx.s_msg_count, 1);
1992+
ExpectIntLE(test_ctx.s_msg_count, TEST_MEMIO_MAX_MSGS);
1993+
ExpectIntLE(test_ctx.s_len, (int)sizeof(ch2));
1994+
if (EXPECT_SUCCESS()) {
1995+
ch2Sz = test_ctx.s_len;
1996+
ch2MsgCount = test_ctx.s_msg_count;
1997+
XMEMCPY(ch2, test_ctx.s_buff, ch2Sz);
1998+
XMEMCPY(ch2MsgSizes, test_ctx.s_msg_sizes,
1999+
sizeof(ch2MsgSizes[0]) * (size_t)ch2MsgCount);
2000+
2001+
ch2Seq = ((byte)ch2[recordSeqOff + 4] << 8) |
2002+
(byte)ch2[recordSeqOff + 5];
2003+
ch1RtxSeq = ch2Seq + ch2MsgCount;
2004+
2005+
/* Synthesize a CH1 retransmission that can pass the replay window after
2006+
* the first CH2 fragment makes the server stateful. The handshake
2007+
* message_seq remains the original CH1 value; only the DTLS record
2008+
* sequence is moved past the fragmented CH2 flight */
2009+
ch1Rtx[recordSeqOff + 0] = 0;
2010+
ch1Rtx[recordSeqOff + 1] = 0;
2011+
ch1Rtx[recordSeqOff + 2] = 0;
2012+
ch1Rtx[recordSeqOff + 3] = 0;
2013+
ch1Rtx[recordSeqOff + 4] = (byte)(ch1RtxSeq >> 8);
2014+
ch1Rtx[recordSeqOff + 5] = (byte)ch1RtxSeq;
2015+
}
2016+
2017+
test_memio_clear_buffer(&test_ctx, 0);
2018+
2019+
/* Deliver CH2 first fragment only. Now server is stateful */
2020+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, ch2, ch2MsgSizes[0]), 0);
2021+
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
2022+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
2023+
2024+
/* Deliver the retransmitted CH1 between CH2 fragments, it should be
2025+
* discarded as rtx */
2026+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, ch1Rtx, ch1RtxSz), 0);
2027+
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
2028+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
2029+
test_memio_clear_buffer(&test_ctx, 1);
2030+
2031+
/* Deliver the rest of CH2 */
2032+
off = ch2MsgSizes[0];
2033+
for (i = 1; i < ch2MsgCount && EXPECT_SUCCESS(); i++) {
2034+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, ch2 + off,
2035+
ch2MsgSizes[i]), 0);
2036+
off += ch2MsgSizes[i];
2037+
}
2038+
2039+
/* Restore MTU so the client's input buffer can hold the full server
2040+
* flight (e.g. an SH carrying a hybrid PQC key share). */
2041+
ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, 1500), WOLFSSL_SUCCESS);
2042+
2043+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
2044+
2045+
wolfSSL_free(ssl_c);
2046+
wolfSSL_CTX_free(ctx_c);
2047+
wolfSSL_free(ssl_s);
2048+
wolfSSL_CTX_free(ctx_s);
2049+
#endif
2050+
return EXPECT_RESULT();
2051+
}
2052+
19312053
int test_dtls_drop_client_ack(void)
19322054
{
19332055
EXPECT_DECLS;

tests/api/test_dtls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int test_records_span_network_boundaries(void);
4242
int test_dtls_record_cross_boundaries(void);
4343
int test_dtls_rtx_across_epoch_change(void);
4444
int test_dtls13_ch2_rtx_no_ch1(void);
45+
int test_dtls13_frag_ch2_with_ch1_rtx(void);
4546
int test_dtls_drop_client_ack(void);
4647
int test_dtls_bogus_finished_epoch_zero(void);
4748
int test_dtls_replay(void);
@@ -77,6 +78,7 @@ int test_dtls13_oversized_cert_chain(void);
7778
TEST_DECL_GROUP("dtls", test_dtls_record_cross_boundaries), \
7879
TEST_DECL_GROUP("dtls", test_dtls_rtx_across_epoch_change), \
7980
TEST_DECL_GROUP("dtls", test_dtls13_ch2_rtx_no_ch1), \
81+
TEST_DECL_GROUP("dtls", test_dtls13_frag_ch2_with_ch1_rtx), \
8082
TEST_DECL_GROUP("dtls", test_dtls_drop_client_ack), \
8183
TEST_DECL_GROUP("dtls", test_dtls_bogus_finished_epoch_zero), \
8284
TEST_DECL_GROUP("dtls", test_dtls_replay), \

0 commit comments

Comments
 (0)