Skip to content

Commit ec335cd

Browse files
committed
Prevent DTLS clients from replaying ClientHello
messages when receiving bogus Finished messages in epoch 0 by ensuring Finished messages are only ignored in encrypted epochs (1).
1 parent d4f8c9c commit ec335cd

File tree

4 files changed

+85
-2
lines changed

4 files changed

+85
-2
lines changed

src/internal.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18922,8 +18922,9 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1892218922

1892318923
if (type == finished && ssl->keys.dtls_peer_handshake_number >=
1892418924
ssl->keys.dtls_expected_peer_handshake_number &&
18925-
ssl->keys.curEpoch == ssl->keys.dtls_epoch) {
18926-
/* finished msg should be ignore from the current epoch
18925+
ssl->keys.curEpoch == ssl->keys.dtls_epoch &&
18926+
ssl->keys.curEpoch != 0) {
18927+
/* finished msg should be ignored from the current epoch
1892718928
* if it comes from a previous handshake */
1892818929
if (ssl->options.side == WOLFSSL_CLIENT_END) {
1892918930
ignoreFinished = ssl->options.connectState < FINISHED_DONE;

tests/api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51225,6 +51225,7 @@ TEST_DECL(test_wc_RsaPSS_DigitalSignVerify),
5122551225
TEST_DECL(test_dtls13_epochs),
5122651226
TEST_DECL(test_dtls_rtx_across_epoch_change),
5122751227
TEST_DECL(test_dtls_drop_client_ack),
51228+
TEST_DECL(test_dtls_bogus_finished_epoch_zero),
5122851229
TEST_DECL(test_dtls_replay),
5122951230
TEST_DECL(test_dtls13_ack_order),
5123051231
TEST_DECL(test_dtls_version_checking),

tests/api/test_dtls.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,86 @@ int test_dtls_drop_client_ack(void)
14741474
return EXPECT_RESULT();
14751475
}
14761476

1477+
int test_dtls_bogus_finished_epoch_zero(void)
1478+
{
1479+
EXPECT_DECLS;
1480+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \
1481+
!defined(WOLFSSL_NO_TLS12) && !defined(NO_PSK) && defined(HAVE_AES_CBC) && \
1482+
defined(WOLFSSL_AES_128) && !defined(NO_SHA256) && defined(WOLFSSL_STATIC_PSK)
1483+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
1484+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
1485+
struct test_memio_ctx test_ctx;
1486+
int error;
1487+
1488+
/* bogus Finished message bytes from the original bug report (epoch 0)
1489+
* https://github.com/wolfSSL/wolfssl/issues/9188 */
1490+
static const unsigned char bogus_finished[] = {
1491+
0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1492+
0x18, 0x14, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1493+
0x0c, 0xd9, 0xc6, 0xe3, 0x01, 0x59, 0xf2, 0xc2, 0x4f, 0xfa, 0xfd, 0x20,
1494+
0xd7
1495+
};
1496+
1497+
/* serverHelloDone message bytes */
1498+
static const unsigned char server_hello_done_message[] = {
1499+
0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1500+
0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1501+
0x00
1502+
};
1503+
1504+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
1505+
1506+
/* setting up dtls 1.2 contexts with psk */
1507+
test_ctx.c_ciphers = "PSK-AES128-CBC-SHA256";
1508+
test_ctx.s_ciphers = "PSK-AES128-CBC-SHA256";
1509+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
1510+
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0);
1511+
1512+
/* configuring PSK callbacks */
1513+
wolfSSL_CTX_set_psk_client_callback(ctx_c, my_psk_client_cb);
1514+
wolfSSL_CTX_set_psk_server_callback(ctx_s, my_psk_server_cb);
1515+
1516+
/* start handshake, send first ClientHelloDone */
1517+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
1518+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
1519+
1520+
/* clearing server buffer to inject the wrong Finished packet */
1521+
test_memio_clear_buffer(&test_ctx, 1);
1522+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
1523+
(const char*)bogus_finished, sizeof(bogus_finished)), 0);
1524+
1525+
/* continue client handshake to process it */
1526+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
1527+
1528+
/* client should terminate with dtls sequence error */
1529+
error = wolfSSL_get_error(ssl_c, -1);
1530+
1531+
/* check if the error is SEQUENCE_ERROR, handshake should not
1532+
* expect a finished packet in that moment, in particular should not
1533+
* be in epoch = 0 (should be epoch = 1) */
1534+
ExpectTrue(error == WC_NO_ERR_TRACE(SEQUENCE_ERROR) ||
1535+
error == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_READ));
1536+
1537+
/* forcing injection ServerHelloDone to test if client would replay
1538+
* ClientHello */
1539+
test_memio_clear_buffer(&test_ctx, 0);
1540+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
1541+
(const char*)server_hello_done_message, sizeof(server_hello_done_message)), 0);
1542+
wolfSSL_connect(ssl_c);
1543+
1544+
/* verifying no ClientHello replay occurred,
1545+
* buffer should empty since we exit early on
1546+
* because of the bogus finished packet */
1547+
ExpectIntLE(test_ctx.s_len, 0);
1548+
1549+
wolfSSL_free(ssl_c);
1550+
wolfSSL_CTX_free(ctx_c);
1551+
wolfSSL_free(ssl_s);
1552+
wolfSSL_CTX_free(ctx_s);
1553+
#endif
1554+
return EXPECT_RESULT();
1555+
}
1556+
14771557
int test_dtls_replay(void)
14781558
{
14791559
EXPECT_DECLS;

tests/api/test_dtls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@ int test_records_span_network_boundaries(void);
3838
int test_dtls_record_cross_boundaries(void);
3939
int test_dtls_rtx_across_epoch_change(void);
4040
int test_dtls_drop_client_ack(void);
41+
int test_dtls_bogus_finished_epoch_zero(void);
4142
int test_dtls_replay(void);
4243
#endif /* TESTS_API_DTLS_H */

0 commit comments

Comments
 (0)