mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-26 21:32:26 +01:00
Merge pull request #9330 from rizlik/dtls13_want_write_fix
Dtls13: Fix handshake hangs on WANT_WRITE I/O error
This commit is contained in:
@@ -1898,11 +1898,11 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
|
||||
|
||||
ret = DoTls13HandShakeMsgType(ssl, input, &idx, handshakeType,
|
||||
messageLength, size);
|
||||
*processedSize = idx;
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
Dtls13MsgWasProcessed(ssl, (enum HandShakeType)handshakeType);
|
||||
*processedSize = idx;
|
||||
|
||||
/* check if we have buffered some message */
|
||||
if (Dtls13NextMessageComplete(ssl))
|
||||
|
||||
@@ -47055,7 +47055,7 @@ static int test_multiple_shutdown_nonblocking(void)
|
||||
ExpectIntEQ(test_ctx.s_len, 0);
|
||||
ExpectIntEQ(ssl_c->buffers.outputBuffer.length, 0);
|
||||
|
||||
test_memio_simulate_want_write(&test_ctx, 0, 1);
|
||||
test_memio_simulate_want_write(&test_ctx, 1, 1);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
ExpectIntEQ(ssl_c->buffers.outputBuffer.length, size_of_last_packet);
|
||||
|
||||
/* now send the CLOSE_NOTIFY to the server for real, expecting shutdown not done */
|
||||
test_memio_simulate_want_write(&test_ctx, 0, 0);
|
||||
test_memio_simulate_want_write(&test_ctx, 1, 0);
|
||||
ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE);
|
||||
|
||||
/* output buffer should be empty and socket buffer should contain the message */
|
||||
|
||||
@@ -568,6 +568,166 @@ int test_dtls13_basic_connection_id(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/** Test DTLS 1.3 behavior when server hits WANT_WRITE during HRR
|
||||
* The test sets up a DTLS 1.3 connection where the server is forced to
|
||||
* return WANT_WRITE when sending the HelloRetryRequest. After the handshake,
|
||||
* application data is exchanged in both directions to verify the connection
|
||||
* works as expected.
|
||||
*/
|
||||
int test_dtls13_hrr_want_write(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
|
||||
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
||||
const char msg[] = "hello";
|
||||
const int msgLen = sizeof(msg);
|
||||
struct test_memio_ctx test_ctx;
|
||||
char readBuf[sizeof(msg)];
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
|
||||
0);
|
||||
|
||||
/* Client sends first ClientHello */
|
||||
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Force server to hit WANT_WRITE when producing the HRR */
|
||||
test_memio_simulate_want_write(&test_ctx, 0, 1);
|
||||
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE);
|
||||
|
||||
/* Allow the server to flush the HRR and proceed */
|
||||
test_memio_simulate_want_write(&test_ctx, 0, 0);
|
||||
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Resume the DTLS 1.3 handshake */
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
|
||||
/* Verify post-handshake application data in both directions */
|
||||
XMEMSET(readBuf, 0, sizeof(readBuf));
|
||||
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
|
||||
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
|
||||
ExpectStrEQ(readBuf, msg);
|
||||
|
||||
XMEMSET(readBuf, 0, sizeof(readBuf));
|
||||
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
|
||||
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
|
||||
ExpectStrEQ(readBuf, msg);
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
|
||||
struct test_dtls13_wwrite_ctx {
|
||||
int want_write;
|
||||
struct test_memio_ctx *text_ctx;
|
||||
};
|
||||
static int test_dtls13_want_write_send_cb(WOLFSSL *ssl, char *data, int sz, void *ctx)
|
||||
{
|
||||
struct test_dtls13_wwrite_ctx *wwctx = (struct test_dtls13_wwrite_ctx *)ctx;
|
||||
wwctx->want_write = !wwctx->want_write;
|
||||
if (wwctx->want_write) {
|
||||
return WOLFSSL_CBIO_ERR_WANT_WRITE;
|
||||
}
|
||||
return test_memio_write_cb(ssl, data, sz, wwctx->text_ctx);
|
||||
}
|
||||
#endif
|
||||
/** Test DTLS 1.3 behavior when every other write returns WANT_WRITE
|
||||
* The test sets up a DTLS 1.3 connection where both client and server
|
||||
* alternate between WANT_WRITE and successful writes. After the handshake,
|
||||
* application data is exchanged in both directions to verify the connection
|
||||
* works as expected.
|
||||
*
|
||||
* Data exchanged after the handshake is also tested with simulated WANT_WRITE
|
||||
* conditions to ensure the connection remains functional.
|
||||
*/
|
||||
int test_dtls13_every_write_want_write(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
|
||||
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
const char msg[] = "want-write";
|
||||
const int msgLen = sizeof(msg);
|
||||
char readBuf[sizeof(msg)];
|
||||
struct test_dtls13_wwrite_ctx wwctx_c;
|
||||
struct test_dtls13_wwrite_ctx wwctx_s;
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
|
||||
0);
|
||||
|
||||
wwctx_c.want_write = 0;
|
||||
wwctx_c.text_ctx = &test_ctx;
|
||||
wolfSSL_SetIOWriteCtx(ssl_c, &wwctx_c);
|
||||
wolfSSL_SSLSetIOSend(ssl_c, test_dtls13_want_write_send_cb);
|
||||
wwctx_s.want_write = 0;
|
||||
wwctx_s.text_ctx = &test_ctx;
|
||||
wolfSSL_SetIOWriteCtx(ssl_s, &wwctx_s);
|
||||
wolfSSL_SSLSetIOSend(ssl_s, test_dtls13_want_write_send_cb);
|
||||
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 20, NULL), 0);
|
||||
|
||||
ExpectTrue(wolfSSL_is_init_finished(ssl_c));
|
||||
ExpectTrue(wolfSSL_is_init_finished(ssl_s));
|
||||
|
||||
test_memio_simulate_want_write(&test_ctx, 0, 0);
|
||||
test_memio_simulate_want_write(&test_ctx, 1, 0);
|
||||
|
||||
wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx);
|
||||
wolfSSL_SSLSetIOSend(ssl_c, test_memio_write_cb);
|
||||
wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx);
|
||||
wolfSSL_SSLSetIOSend(ssl_s, test_memio_write_cb);
|
||||
|
||||
XMEMSET(readBuf, 0, sizeof(readBuf));
|
||||
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
|
||||
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
|
||||
ExpectStrEQ(readBuf, msg);
|
||||
|
||||
XMEMSET(readBuf, 0, sizeof(readBuf));
|
||||
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
|
||||
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
|
||||
ExpectStrEQ(readBuf, msg);
|
||||
|
||||
test_memio_simulate_want_write(&test_ctx, 0, 1);
|
||||
XMEMSET(readBuf, 0, sizeof(readBuf));
|
||||
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), -1);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE);
|
||||
test_memio_simulate_want_write(&test_ctx, 0, 0);
|
||||
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
|
||||
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
|
||||
ExpectStrEQ(readBuf, msg);
|
||||
|
||||
XMEMSET(readBuf, 0, sizeof(readBuf));
|
||||
test_memio_simulate_want_write(&test_ctx, 1, 1);
|
||||
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), -1);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_WRITE);
|
||||
test_memio_simulate_want_write(&test_ctx, 1, 0);
|
||||
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
|
||||
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
|
||||
ExpectStrEQ(readBuf, msg);
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wolfSSL_dtls_cid_parse(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
int test_dtls12_basic_connection_id(void);
|
||||
int test_dtls13_basic_connection_id(void);
|
||||
int test_dtls13_hrr_want_write(void);
|
||||
int test_dtls13_every_write_want_write(void);
|
||||
int test_wolfSSL_dtls_cid_parse(void);
|
||||
int test_wolfSSL_dtls_set_pending_peer(void);
|
||||
int test_dtls13_epochs(void);
|
||||
@@ -47,6 +49,8 @@ int test_dtls_certreq_order(void);
|
||||
#define TEST_DTLS_DECLS \
|
||||
TEST_DECL_GROUP("dtls", test_dtls12_basic_connection_id), \
|
||||
TEST_DECL_GROUP("dtls", test_dtls13_basic_connection_id), \
|
||||
TEST_DECL_GROUP("dtls", test_dtls13_hrr_want_write), \
|
||||
TEST_DECL_GROUP("dtls", test_dtls13_every_write_want_write), \
|
||||
TEST_DECL_GROUP("dtls", test_wolfSSL_dtls_cid_parse), \
|
||||
TEST_DECL_GROUP("dtls", test_wolfSSL_dtls_set_pending_peer), \
|
||||
TEST_DECL_GROUP("dtls", test_dtls13_epochs), \
|
||||
|
||||
@@ -57,14 +57,14 @@ int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz, void *ctx)
|
||||
len = &test_ctx->c_len;
|
||||
msg_sizes = test_ctx->c_msg_sizes;
|
||||
msg_count = &test_ctx->c_msg_count;
|
||||
forceWantWrite = &test_ctx->c_force_want_write;
|
||||
forceWantWrite = &test_ctx->s_force_want_write;
|
||||
}
|
||||
else {
|
||||
buf = test_ctx->s_buff;
|
||||
len = &test_ctx->s_len;
|
||||
msg_sizes = test_ctx->s_msg_sizes;
|
||||
msg_count = &test_ctx->s_msg_count;
|
||||
forceWantWrite = &test_ctx->s_force_want_write;
|
||||
forceWantWrite = &test_ctx->c_force_want_write;
|
||||
}
|
||||
|
||||
if (*forceWantWrite)
|
||||
|
||||
Reference in New Issue
Block a user