Skip to content

Commit cf80eb8

Browse files
committed
DTLS 1.3: Don't error out on app data before finishing handshake
Check epoch for early data
1 parent 878cf3a commit cf80eb8

2 files changed

Lines changed: 235 additions & 28 deletions

File tree

src/internal.c

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20647,33 +20647,54 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
2064720647
#ifdef HAVE_LIBZ
2064820648
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
2064920649
#endif
20650-
2065120650
#ifdef WOLFSSL_EARLY_DATA
20652-
if (ssl->options.tls1_3 && ssl->options.handShakeDone == 0) {
20653-
int process = 0;
20651+
int isEarlyData = ssl->options.tls1_3 &&
20652+
ssl->options.handShakeDone == 0 &&
20653+
ssl->options.side == WOLFSSL_SERVER_END;
20654+
int acceptEarlyData = ssl->earlyData != no_early_data &&
20655+
ssl->options.clientState == CLIENT_HELLO_COMPLETE;
20656+
#endif
2065420657

20655-
if (ssl->options.side == WOLFSSL_SERVER_END) {
20656-
if ((ssl->earlyData != no_early_data) &&
20657-
(ssl->options.clientState == CLIENT_HELLO_COMPLETE)) {
20658-
process = 1;
20659-
}
20660-
if (!process) {
20661-
WOLFSSL_MSG("Ignoring EarlyData!");
20662-
*inOutIdx += ssl->curSize;
20663-
if (*inOutIdx > ssl->buffers.inputBuffer.length)
20664-
return BUFFER_E;
20658+
#if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_DTLS13)
20659+
if (ssl->options.tls1_3 && ssl->options.dtls)
20660+
isEarlyData = isEarlyData && w64Equal(ssl->keys.curEpoch64,
20661+
w64From32(0x0, DTLS13_EPOCH_EARLYDATA));
20662+
#endif
2066520663

20666-
return 0;
20667-
}
20668-
}
20669-
if (!process) {
20670-
WOLFSSL_MSG("Received App data before a handshake completed");
20671-
if (sniff == NO_SNIFF) {
20672-
SendAlert(ssl, alert_fatal, unexpected_message);
20673-
}
20674-
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
20675-
return OUT_OF_ORDER_E;
20676-
}
20664+
#ifdef WOLFSSL_EARLY_DATA
20665+
if (isEarlyData && acceptEarlyData) {
20666+
WOLFSSL_MSG("Processing EarlyData");
20667+
}
20668+
else if (isEarlyData && !acceptEarlyData) {
20669+
WOLFSSL_MSG("Ignoring EarlyData!");
20670+
*inOutIdx += ssl->curSize;
20671+
if (*inOutIdx > ssl->buffers.inputBuffer.length)
20672+
return BUFFER_E;
20673+
#ifdef WOLFSSL_DTLS13
20674+
/* Receiving app data from the traffic epoch before the handshake is
20675+
* done means that there was a disruption. */
20676+
if (ssl->options.dtls && !w64Equal(ssl->keys.curEpoch64,
20677+
w64From32(0x0, DTLS13_EPOCH_EARLYDATA)))
20678+
ssl->dtls13Rtx.sendAcks = 1;
20679+
#endif
20680+
return 0;
20681+
}
20682+
else
20683+
#endif
20684+
#ifdef WOLFSSL_DTLS
20685+
if (ssl->options.handShakeDone == 0 && ssl->options.dtls) {
20686+
WOLFSSL_MSG("Dropping app data received before handshake complete");
20687+
*inOutIdx += ssl->curSize;
20688+
if (*inOutIdx > ssl->buffers.inputBuffer.length)
20689+
return BUFFER_E;
20690+
#ifdef WOLFSSL_DTLS13
20691+
/* Receiving app data from the traffic epoch before the handshake is
20692+
* done means that there was a disruption. */
20693+
if (ssl->options.tls1_3 && !w64Equal(ssl->keys.curEpoch64,
20694+
w64From32(0x0, DTLS13_EPOCH_EARLYDATA)))
20695+
ssl->dtls13Rtx.sendAcks = 1;
20696+
#endif
20697+
return 0;
2067720698
}
2067820699
else
2067920700
#endif
@@ -24904,15 +24925,15 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
2490424925
groupMsgs = 1;
2490524926
#endif
2490624927
}
24907-
else if (IsAtLeastTLSv1_3(ssl->version) &&
24928+
else
24929+
#endif
24930+
if (IsAtLeastTLSv1_3(ssl->version) &&
2490824931
ssl->options.side == WOLFSSL_SERVER_END &&
2490924932
ssl->options.acceptState >= TLS13_ACCEPT_FINISHED_SENT) {
2491024933
/* We can send data without waiting on peer finished msg */
2491124934
WOLFSSL_MSG("server sending data before receiving client finished");
2491224935
}
24913-
else
24914-
#endif
24915-
if (ssl_in_handshake(ssl, 1)) {
24936+
else if (ssl_in_handshake(ssl, 1)) {
2491624937
int err;
2491724938
WOLFSSL_MSG("handshake not complete, trying to finish");
2491824939
if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {

tests/api.c

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96321,6 +96321,189 @@ static int test_dtls13_basic_connection_id(void)
9632196321
return EXPECT_RESULT();
9632296322
}
9632396323

96324+
static int test_dtls12_missing_finished(void)
96325+
{
96326+
EXPECT_DECLS;
96327+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
96328+
WOLFSSL_CTX *ctx_c = NULL;
96329+
WOLFSSL_CTX *ctx_s = NULL;
96330+
WOLFSSL *ssl_c = NULL;
96331+
WOLFSSL *ssl_s = NULL;
96332+
struct test_memio_ctx test_ctx;
96333+
const char test_str[] = "test string";
96334+
char test_buf[sizeof(test_str)];
96335+
96336+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
96337+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
96338+
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0);
96339+
96340+
/* CH1 */
96341+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96342+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96343+
/* HVR */
96344+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96345+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96346+
/* CH2 */
96347+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96348+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96349+
/* Server first flight */
96350+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96351+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96352+
/* Client second flight with finished */
96353+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96354+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96355+
/* Server second flight with finished */
96356+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
96357+
/* Let's clear the output */
96358+
test_ctx.c_len = 0;
96359+
/* Let's send some app data */
96360+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
96361+
sizeof(test_str));
96362+
/* Client should not error out on a missing finished */
96363+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96364+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96365+
/* Server rtx second flight with finished */
96366+
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), 1);
96367+
/* Client process rest of handshake */
96368+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
96369+
96370+
/* Let's send some app data */
96371+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
96372+
sizeof(test_str));
96373+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buf, sizeof(test_buf)),
96374+
sizeof(test_str));
96375+
ExpectBufEQ(test_buf, test_str, sizeof(test_str));
96376+
96377+
wolfSSL_free(ssl_c);
96378+
wolfSSL_free(ssl_s);
96379+
wolfSSL_CTX_free(ctx_c);
96380+
wolfSSL_CTX_free(ctx_s);
96381+
#endif
96382+
return EXPECT_RESULT();
96383+
}
96384+
96385+
static int test_dtls13_missing_finished_client(void)
96386+
{
96387+
EXPECT_DECLS;
96388+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
96389+
WOLFSSL_CTX *ctx_c = NULL;
96390+
WOLFSSL_CTX *ctx_s = NULL;
96391+
WOLFSSL *ssl_c = NULL;
96392+
WOLFSSL *ssl_s = NULL;
96393+
struct test_memio_ctx test_ctx;
96394+
const char test_str[] = "test string";
96395+
char test_buf[sizeof(test_str)];
96396+
96397+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
96398+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
96399+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
96400+
96401+
/* CH1 */
96402+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96403+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96404+
/* HRR */
96405+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96406+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96407+
/* CH2 */
96408+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96409+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96410+
/* Server first flight with finished */
96411+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96412+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96413+
/* Let's clear the output */
96414+
test_ctx.c_len = 0;
96415+
/* Let's send some app data */
96416+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
96417+
sizeof(test_str));
96418+
/* Client second flight with finished */
96419+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96420+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96421+
/* Server should not error out on a missing finished */
96422+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96423+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96424+
/* Client rtx second flight with finished */
96425+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96426+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96427+
/* Server */
96428+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
96429+
/* Client */
96430+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
96431+
/* Let's send some app data */
96432+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
96433+
sizeof(test_str));
96434+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buf, sizeof(test_buf)),
96435+
sizeof(test_str));
96436+
ExpectBufEQ(test_buf, test_str, sizeof(test_str));
96437+
96438+
wolfSSL_free(ssl_c);
96439+
wolfSSL_free(ssl_s);
96440+
wolfSSL_CTX_free(ctx_c);
96441+
wolfSSL_CTX_free(ctx_s);
96442+
#endif
96443+
return EXPECT_RESULT();
96444+
}
96445+
96446+
static int test_dtls13_missing_finished_server(void)
96447+
{
96448+
EXPECT_DECLS;
96449+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
96450+
WOLFSSL_CTX *ctx_c = NULL;
96451+
WOLFSSL_CTX *ctx_s = NULL;
96452+
WOLFSSL *ssl_c = NULL;
96453+
WOLFSSL *ssl_s = NULL;
96454+
struct test_memio_ctx test_ctx;
96455+
const char test_str[] = "test string";
96456+
char test_buf[sizeof(test_str)];
96457+
96458+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
96459+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
96460+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
96461+
96462+
/* CH1 */
96463+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96464+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96465+
/* HRR */
96466+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96467+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96468+
/* CH2 */
96469+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96470+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96471+
/* Server first flight with finished */
96472+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96473+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96474+
/* Client second flight with finished */
96475+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96476+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96477+
/* Let's clear the output */
96478+
test_ctx.s_len = 0;
96479+
/* We should signal that the handshake is done */
96480+
ExpectTrue(wolfSSL_is_init_finished(ssl_c));
96481+
/* Let's send some app data */
96482+
ExpectIntEQ(wolfSSL_write(ssl_c, test_str, sizeof(test_str)),
96483+
sizeof(test_str));
96484+
/* Server should not error out on a missing finished */
96485+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
96486+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
96487+
/* Client rtx second flight with finished */
96488+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
96489+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
96490+
/* Server first flight with finished */
96491+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
96492+
/* Let's send some app data */
96493+
ExpectIntEQ(wolfSSL_write(ssl_c, test_str, sizeof(test_str)),
96494+
sizeof(test_str));
96495+
ExpectIntEQ(wolfSSL_read(ssl_s, test_buf, sizeof(test_buf)),
96496+
sizeof(test_str));
96497+
ExpectBufEQ(test_buf, test_str, sizeof(test_str));
96498+
96499+
wolfSSL_free(ssl_c);
96500+
wolfSSL_free(ssl_s);
96501+
wolfSSL_CTX_free(ctx_c);
96502+
wolfSSL_CTX_free(ctx_s);
96503+
#endif
96504+
return EXPECT_RESULT();
96505+
}
96506+
9632496507
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
9632596508
defined(HAVE_LIBOQS)
9632696509
static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx)
@@ -98736,6 +98919,9 @@ TEST_CASE testCases[] = {
9873698919
TEST_DECL(test_dtls_old_seq_number),
9873798920
TEST_DECL(test_dtls12_basic_connection_id),
9873898921
TEST_DECL(test_dtls13_basic_connection_id),
98922+
TEST_DECL(test_dtls12_missing_finished),
98923+
TEST_DECL(test_dtls13_missing_finished_client),
98924+
TEST_DECL(test_dtls13_missing_finished_server),
9873998925
TEST_DECL(test_tls13_pq_groups),
9874098926
TEST_DECL(test_tls13_early_data),
9874198927
TEST_DECL(test_tls_multi_handshakes_one_record),

0 commit comments

Comments
 (0)