Skip to content

Commit 97e9fa0

Browse files
authored
Merge pull request #9330 from rizlik/dtls13_want_write_fix
Dtls13: Fix handshake hangs on WANT_WRITE I/O error
2 parents 3d99090 + 33be31a commit 97e9fa0

File tree

5 files changed

+169
-5
lines changed

5 files changed

+169
-5
lines changed

src/dtls13.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1898,11 +1898,11 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
18981898

18991899
ret = DoTls13HandShakeMsgType(ssl, input, &idx, handshakeType,
19001900
messageLength, size);
1901+
*processedSize = idx;
19011902
if (ret != 0)
19021903
return ret;
19031904

19041905
Dtls13MsgWasProcessed(ssl, (enum HandShakeType)handshakeType);
1905-
*processedSize = idx;
19061906

19071907
/* check if we have buffered some message */
19081908
if (Dtls13NextMessageComplete(ssl))

tests/api.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47055,7 +47055,7 @@ static int test_multiple_shutdown_nonblocking(void)
4705547055
ExpectIntEQ(test_ctx.s_len, 0);
4705647056
ExpectIntEQ(ssl_c->buffers.outputBuffer.length, 0);
4705747057

47058-
test_memio_simulate_want_write(&test_ctx, 0, 1);
47058+
test_memio_simulate_want_write(&test_ctx, 1, 1);
4705947059

4706047060
/*
4706147061
* We call wolfSSL_shutdown multiple times to to check that it doesn't add
@@ -47078,7 +47078,7 @@ static int test_multiple_shutdown_nonblocking(void)
4707847078
ExpectIntEQ(ssl_c->buffers.outputBuffer.length, size_of_last_packet);
4707947079

4708047080
/* now send the CLOSE_NOTIFY to the server for real, expecting shutdown not done */
47081-
test_memio_simulate_want_write(&test_ctx, 0, 0);
47081+
test_memio_simulate_want_write(&test_ctx, 1, 0);
4708247082
ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE);
4708347083

4708447084
/* output buffer should be empty and socket buffer should contain the message */

tests/api/test_dtls.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,166 @@ int test_dtls13_basic_connection_id(void)
568568
return EXPECT_RESULT();
569569
}
570570

571+
/** Test DTLS 1.3 behavior when server hits WANT_WRITE during HRR
572+
* The test sets up a DTLS 1.3 connection where the server is forced to
573+
* return WANT_WRITE when sending the HelloRetryRequest. After the handshake,
574+
* application data is exchanged in both directions to verify the connection
575+
* works as expected.
576+
*/
577+
int test_dtls13_hrr_want_write(void)
578+
{
579+
EXPECT_DECLS;
580+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
581+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
582+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
583+
const char msg[] = "hello";
584+
const int msgLen = sizeof(msg);
585+
struct test_memio_ctx test_ctx;
586+
char readBuf[sizeof(msg)];
587+
588+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
589+
590+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
591+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
592+
0);
593+
594+
/* Client sends first ClientHello */
595+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
596+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
597+
598+
/* Force server to hit WANT_WRITE when producing the HRR */
599+
test_memio_simulate_want_write(&test_ctx, 0, 1);
600+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
601+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE);
602+
603+
/* Allow the server to flush the HRR and proceed */
604+
test_memio_simulate_want_write(&test_ctx, 0, 0);
605+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
606+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
607+
608+
/* Resume the DTLS 1.3 handshake */
609+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
610+
611+
/* Verify post-handshake application data in both directions */
612+
XMEMSET(readBuf, 0, sizeof(readBuf));
613+
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
614+
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
615+
ExpectStrEQ(readBuf, msg);
616+
617+
XMEMSET(readBuf, 0, sizeof(readBuf));
618+
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
619+
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
620+
ExpectStrEQ(readBuf, msg);
621+
622+
wolfSSL_free(ssl_c);
623+
wolfSSL_CTX_free(ctx_c);
624+
wolfSSL_free(ssl_s);
625+
wolfSSL_CTX_free(ctx_s);
626+
#endif
627+
return EXPECT_RESULT();
628+
}
629+
630+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
631+
struct test_dtls13_wwrite_ctx {
632+
int want_write;
633+
struct test_memio_ctx *text_ctx;
634+
};
635+
static int test_dtls13_want_write_send_cb(WOLFSSL *ssl, char *data, int sz, void *ctx)
636+
{
637+
struct test_dtls13_wwrite_ctx *wwctx = (struct test_dtls13_wwrite_ctx *)ctx;
638+
wwctx->want_write = !wwctx->want_write;
639+
if (wwctx->want_write) {
640+
return WOLFSSL_CBIO_ERR_WANT_WRITE;
641+
}
642+
return test_memio_write_cb(ssl, data, sz, wwctx->text_ctx);
643+
}
644+
#endif
645+
/** Test DTLS 1.3 behavior when every other write returns WANT_WRITE
646+
* The test sets up a DTLS 1.3 connection where both client and server
647+
* alternate between WANT_WRITE and successful writes. After the handshake,
648+
* application data is exchanged in both directions to verify the connection
649+
* works as expected.
650+
*
651+
* Data exchanged after the handshake is also tested with simulated WANT_WRITE
652+
* conditions to ensure the connection remains functional.
653+
*/
654+
int test_dtls13_every_write_want_write(void)
655+
{
656+
EXPECT_DECLS;
657+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
658+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
659+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
660+
struct test_memio_ctx test_ctx;
661+
const char msg[] = "want-write";
662+
const int msgLen = sizeof(msg);
663+
char readBuf[sizeof(msg)];
664+
struct test_dtls13_wwrite_ctx wwctx_c;
665+
struct test_dtls13_wwrite_ctx wwctx_s;
666+
667+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
668+
669+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
670+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
671+
0);
672+
673+
wwctx_c.want_write = 0;
674+
wwctx_c.text_ctx = &test_ctx;
675+
wolfSSL_SetIOWriteCtx(ssl_c, &wwctx_c);
676+
wolfSSL_SSLSetIOSend(ssl_c, test_dtls13_want_write_send_cb);
677+
wwctx_s.want_write = 0;
678+
wwctx_s.text_ctx = &test_ctx;
679+
wolfSSL_SetIOWriteCtx(ssl_s, &wwctx_s);
680+
wolfSSL_SSLSetIOSend(ssl_s, test_dtls13_want_write_send_cb);
681+
682+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 20, NULL), 0);
683+
684+
ExpectTrue(wolfSSL_is_init_finished(ssl_c));
685+
ExpectTrue(wolfSSL_is_init_finished(ssl_s));
686+
687+
test_memio_simulate_want_write(&test_ctx, 0, 0);
688+
test_memio_simulate_want_write(&test_ctx, 1, 0);
689+
690+
wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx);
691+
wolfSSL_SSLSetIOSend(ssl_c, test_memio_write_cb);
692+
wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx);
693+
wolfSSL_SSLSetIOSend(ssl_s, test_memio_write_cb);
694+
695+
XMEMSET(readBuf, 0, sizeof(readBuf));
696+
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
697+
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
698+
ExpectStrEQ(readBuf, msg);
699+
700+
XMEMSET(readBuf, 0, sizeof(readBuf));
701+
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
702+
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
703+
ExpectStrEQ(readBuf, msg);
704+
705+
test_memio_simulate_want_write(&test_ctx, 0, 1);
706+
XMEMSET(readBuf, 0, sizeof(readBuf));
707+
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), -1);
708+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE);
709+
test_memio_simulate_want_write(&test_ctx, 0, 0);
710+
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
711+
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
712+
ExpectStrEQ(readBuf, msg);
713+
714+
XMEMSET(readBuf, 0, sizeof(readBuf));
715+
test_memio_simulate_want_write(&test_ctx, 1, 1);
716+
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), -1);
717+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_WRITE);
718+
test_memio_simulate_want_write(&test_ctx, 1, 0);
719+
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
720+
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
721+
ExpectStrEQ(readBuf, msg);
722+
723+
wolfSSL_free(ssl_c);
724+
wolfSSL_CTX_free(ctx_c);
725+
wolfSSL_free(ssl_s);
726+
wolfSSL_CTX_free(ctx_s);
727+
#endif
728+
return EXPECT_RESULT();
729+
}
730+
571731
int test_wolfSSL_dtls_cid_parse(void)
572732
{
573733
EXPECT_DECLS;

tests/api/test_dtls.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
int test_dtls12_basic_connection_id(void);
2626
int test_dtls13_basic_connection_id(void);
27+
int test_dtls13_hrr_want_write(void);
28+
int test_dtls13_every_write_want_write(void);
2729
int test_wolfSSL_dtls_cid_parse(void);
2830
int test_wolfSSL_dtls_set_pending_peer(void);
2931
int test_dtls13_epochs(void);
@@ -47,6 +49,8 @@ int test_dtls_certreq_order(void);
4749
#define TEST_DTLS_DECLS \
4850
TEST_DECL_GROUP("dtls", test_dtls12_basic_connection_id), \
4951
TEST_DECL_GROUP("dtls", test_dtls13_basic_connection_id), \
52+
TEST_DECL_GROUP("dtls", test_dtls13_hrr_want_write), \
53+
TEST_DECL_GROUP("dtls", test_dtls13_every_write_want_write), \
5054
TEST_DECL_GROUP("dtls", test_wolfSSL_dtls_cid_parse), \
5155
TEST_DECL_GROUP("dtls", test_wolfSSL_dtls_set_pending_peer), \
5256
TEST_DECL_GROUP("dtls", test_dtls13_epochs), \

tests/utils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz, void *ctx)
5757
len = &test_ctx->c_len;
5858
msg_sizes = test_ctx->c_msg_sizes;
5959
msg_count = &test_ctx->c_msg_count;
60-
forceWantWrite = &test_ctx->c_force_want_write;
60+
forceWantWrite = &test_ctx->s_force_want_write;
6161
}
6262
else {
6363
buf = test_ctx->s_buff;
6464
len = &test_ctx->s_len;
6565
msg_sizes = test_ctx->s_msg_sizes;
6666
msg_count = &test_ctx->s_msg_count;
67-
forceWantWrite = &test_ctx->s_force_want_write;
67+
forceWantWrite = &test_ctx->c_force_want_write;
6868
}
6969

7070
if (*forceWantWrite)

0 commit comments

Comments
 (0)