Skip to content

Commit ff68099

Browse files
authored
Merge pull request wolfSSL#8146 from julek-wolfssl/dtls13-ooo-app-data
DTLS 1.3: Don't error out on app data before finishing handshake
2 parents 49393ec + cf80eb8 commit ff68099

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
@@ -20622,33 +20622,54 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
2062220622
#ifdef HAVE_LIBZ
2062320623
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
2062420624
#endif
20625-
2062620625
#ifdef WOLFSSL_EARLY_DATA
20627-
if (ssl->options.tls1_3 && ssl->options.handShakeDone == 0) {
20628-
int process = 0;
20626+
int isEarlyData = ssl->options.tls1_3 &&
20627+
ssl->options.handShakeDone == 0 &&
20628+
ssl->options.side == WOLFSSL_SERVER_END;
20629+
int acceptEarlyData = ssl->earlyData != no_early_data &&
20630+
ssl->options.clientState == CLIENT_HELLO_COMPLETE;
20631+
#endif
2062920632

20630-
if (ssl->options.side == WOLFSSL_SERVER_END) {
20631-
if ((ssl->earlyData != no_early_data) &&
20632-
(ssl->options.clientState == CLIENT_HELLO_COMPLETE)) {
20633-
process = 1;
20634-
}
20635-
if (!process) {
20636-
WOLFSSL_MSG("Ignoring EarlyData!");
20637-
*inOutIdx += ssl->curSize;
20638-
if (*inOutIdx > ssl->buffers.inputBuffer.length)
20639-
return BUFFER_E;
20633+
#if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_DTLS13)
20634+
if (ssl->options.tls1_3 && ssl->options.dtls)
20635+
isEarlyData = isEarlyData && w64Equal(ssl->keys.curEpoch64,
20636+
w64From32(0x0, DTLS13_EPOCH_EARLYDATA));
20637+
#endif
2064020638

20641-
return 0;
20642-
}
20643-
}
20644-
if (!process) {
20645-
WOLFSSL_MSG("Received App data before a handshake completed");
20646-
if (sniff == NO_SNIFF) {
20647-
SendAlert(ssl, alert_fatal, unexpected_message);
20648-
}
20649-
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
20650-
return OUT_OF_ORDER_E;
20651-
}
20639+
#ifdef WOLFSSL_EARLY_DATA
20640+
if (isEarlyData && acceptEarlyData) {
20641+
WOLFSSL_MSG("Processing EarlyData");
20642+
}
20643+
else if (isEarlyData && !acceptEarlyData) {
20644+
WOLFSSL_MSG("Ignoring EarlyData!");
20645+
*inOutIdx += ssl->curSize;
20646+
if (*inOutIdx > ssl->buffers.inputBuffer.length)
20647+
return BUFFER_E;
20648+
#ifdef WOLFSSL_DTLS13
20649+
/* Receiving app data from the traffic epoch before the handshake is
20650+
* done means that there was a disruption. */
20651+
if (ssl->options.dtls && !w64Equal(ssl->keys.curEpoch64,
20652+
w64From32(0x0, DTLS13_EPOCH_EARLYDATA)))
20653+
ssl->dtls13Rtx.sendAcks = 1;
20654+
#endif
20655+
return 0;
20656+
}
20657+
else
20658+
#endif
20659+
#ifdef WOLFSSL_DTLS
20660+
if (ssl->options.handShakeDone == 0 && ssl->options.dtls) {
20661+
WOLFSSL_MSG("Dropping app data received before handshake complete");
20662+
*inOutIdx += ssl->curSize;
20663+
if (*inOutIdx > ssl->buffers.inputBuffer.length)
20664+
return BUFFER_E;
20665+
#ifdef WOLFSSL_DTLS13
20666+
/* Receiving app data from the traffic epoch before the handshake is
20667+
* done means that there was a disruption. */
20668+
if (ssl->options.tls1_3 && !w64Equal(ssl->keys.curEpoch64,
20669+
w64From32(0x0, DTLS13_EPOCH_EARLYDATA)))
20670+
ssl->dtls13Rtx.sendAcks = 1;
20671+
#endif
20672+
return 0;
2065220673
}
2065320674
else
2065420675
#endif
@@ -24879,15 +24900,15 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
2487924900
groupMsgs = 1;
2488024901
#endif
2488124902
}
24882-
else if (IsAtLeastTLSv1_3(ssl->version) &&
24903+
else
24904+
#endif
24905+
if (IsAtLeastTLSv1_3(ssl->version) &&
2488324906
ssl->options.side == WOLFSSL_SERVER_END &&
2488424907
ssl->options.acceptState >= TLS13_ACCEPT_FINISHED_SENT) {
2488524908
/* We can send data without waiting on peer finished msg */
2488624909
WOLFSSL_MSG("server sending data before receiving client finished");
2488724910
}
24888-
else
24889-
#endif
24890-
if (ssl_in_handshake(ssl, 1)) {
24911+
else if (ssl_in_handshake(ssl, 1)) {
2489124912
int err;
2489224913
WOLFSSL_MSG("handshake not complete, trying to finish");
2489324914
if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {

tests/api.c

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98785,6 +98785,189 @@ static int test_dtls13_basic_connection_id(void)
9878598785
return EXPECT_RESULT();
9878698786
}
9878798787

98788+
static int test_dtls12_missing_finished(void)
98789+
{
98790+
EXPECT_DECLS;
98791+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
98792+
WOLFSSL_CTX *ctx_c = NULL;
98793+
WOLFSSL_CTX *ctx_s = NULL;
98794+
WOLFSSL *ssl_c = NULL;
98795+
WOLFSSL *ssl_s = NULL;
98796+
struct test_memio_ctx test_ctx;
98797+
const char test_str[] = "test string";
98798+
char test_buf[sizeof(test_str)];
98799+
98800+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
98801+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
98802+
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0);
98803+
98804+
/* CH1 */
98805+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98806+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98807+
/* HVR */
98808+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98809+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98810+
/* CH2 */
98811+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98812+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98813+
/* Server first flight */
98814+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98815+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98816+
/* Client second flight with finished */
98817+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98818+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98819+
/* Server second flight with finished */
98820+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
98821+
/* Let's clear the output */
98822+
test_ctx.c_len = 0;
98823+
/* Let's send some app data */
98824+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
98825+
sizeof(test_str));
98826+
/* Client should not error out on a missing finished */
98827+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98828+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98829+
/* Server rtx second flight with finished */
98830+
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), 1);
98831+
/* Client process rest of handshake */
98832+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
98833+
98834+
/* Let's send some app data */
98835+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
98836+
sizeof(test_str));
98837+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buf, sizeof(test_buf)),
98838+
sizeof(test_str));
98839+
ExpectBufEQ(test_buf, test_str, sizeof(test_str));
98840+
98841+
wolfSSL_free(ssl_c);
98842+
wolfSSL_free(ssl_s);
98843+
wolfSSL_CTX_free(ctx_c);
98844+
wolfSSL_CTX_free(ctx_s);
98845+
#endif
98846+
return EXPECT_RESULT();
98847+
}
98848+
98849+
static int test_dtls13_missing_finished_client(void)
98850+
{
98851+
EXPECT_DECLS;
98852+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
98853+
WOLFSSL_CTX *ctx_c = NULL;
98854+
WOLFSSL_CTX *ctx_s = NULL;
98855+
WOLFSSL *ssl_c = NULL;
98856+
WOLFSSL *ssl_s = NULL;
98857+
struct test_memio_ctx test_ctx;
98858+
const char test_str[] = "test string";
98859+
char test_buf[sizeof(test_str)];
98860+
98861+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
98862+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
98863+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
98864+
98865+
/* CH1 */
98866+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98867+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98868+
/* HRR */
98869+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98870+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98871+
/* CH2 */
98872+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98873+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98874+
/* Server first flight with finished */
98875+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98876+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98877+
/* Let's clear the output */
98878+
test_ctx.c_len = 0;
98879+
/* Let's send some app data */
98880+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
98881+
sizeof(test_str));
98882+
/* Client second flight with finished */
98883+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98884+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98885+
/* Server should not error out on a missing finished */
98886+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98887+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98888+
/* Client rtx second flight with finished */
98889+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98890+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98891+
/* Server */
98892+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
98893+
/* Client */
98894+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
98895+
/* Let's send some app data */
98896+
ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)),
98897+
sizeof(test_str));
98898+
ExpectIntEQ(wolfSSL_read(ssl_c, test_buf, sizeof(test_buf)),
98899+
sizeof(test_str));
98900+
ExpectBufEQ(test_buf, test_str, sizeof(test_str));
98901+
98902+
wolfSSL_free(ssl_c);
98903+
wolfSSL_free(ssl_s);
98904+
wolfSSL_CTX_free(ctx_c);
98905+
wolfSSL_CTX_free(ctx_s);
98906+
#endif
98907+
return EXPECT_RESULT();
98908+
}
98909+
98910+
static int test_dtls13_missing_finished_server(void)
98911+
{
98912+
EXPECT_DECLS;
98913+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
98914+
WOLFSSL_CTX *ctx_c = NULL;
98915+
WOLFSSL_CTX *ctx_s = NULL;
98916+
WOLFSSL *ssl_c = NULL;
98917+
WOLFSSL *ssl_s = NULL;
98918+
struct test_memio_ctx test_ctx;
98919+
const char test_str[] = "test string";
98920+
char test_buf[sizeof(test_str)];
98921+
98922+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
98923+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
98924+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
98925+
98926+
/* CH1 */
98927+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98928+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98929+
/* HRR */
98930+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98931+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98932+
/* CH2 */
98933+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98934+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98935+
/* Server first flight with finished */
98936+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98937+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98938+
/* Client second flight with finished */
98939+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98940+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98941+
/* Let's clear the output */
98942+
test_ctx.s_len = 0;
98943+
/* We should signal that the handshake is done */
98944+
ExpectTrue(wolfSSL_is_init_finished(ssl_c));
98945+
/* Let's send some app data */
98946+
ExpectIntEQ(wolfSSL_write(ssl_c, test_str, sizeof(test_str)),
98947+
sizeof(test_str));
98948+
/* Server should not error out on a missing finished */
98949+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
98950+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
98951+
/* Client rtx second flight with finished */
98952+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
98953+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
98954+
/* Server first flight with finished */
98955+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
98956+
/* Let's send some app data */
98957+
ExpectIntEQ(wolfSSL_write(ssl_c, test_str, sizeof(test_str)),
98958+
sizeof(test_str));
98959+
ExpectIntEQ(wolfSSL_read(ssl_s, test_buf, sizeof(test_buf)),
98960+
sizeof(test_str));
98961+
ExpectBufEQ(test_buf, test_str, sizeof(test_str));
98962+
98963+
wolfSSL_free(ssl_c);
98964+
wolfSSL_free(ssl_s);
98965+
wolfSSL_CTX_free(ctx_c);
98966+
wolfSSL_CTX_free(ctx_s);
98967+
#endif
98968+
return EXPECT_RESULT();
98969+
}
98970+
9878898971
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
9878998972
defined(HAVE_LIBOQS)
9879098973
static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx)
@@ -101220,6 +101403,9 @@ TEST_CASE testCases[] = {
101220101403
TEST_DECL(test_dtls_old_seq_number),
101221101404
TEST_DECL(test_dtls12_basic_connection_id),
101222101405
TEST_DECL(test_dtls13_basic_connection_id),
101406+
TEST_DECL(test_dtls12_missing_finished),
101407+
TEST_DECL(test_dtls13_missing_finished_client),
101408+
TEST_DECL(test_dtls13_missing_finished_server),
101223101409
TEST_DECL(test_tls13_pq_groups),
101224101410
TEST_DECL(test_tls13_early_data),
101225101411
TEST_DECL(test_tls_multi_handshakes_one_record),

0 commit comments

Comments
 (0)