From bfe7bc0fccdc8f223e9a59f3cdde3d8d99bd729c Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 28 Jul 2023 17:51:47 +0200 Subject: [PATCH] Recover when the client sends a 0-length session ID when using tickets Fixes ZD16477 --- src/internal.c | 26 +++++++++++------- tests/api.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/internal.c b/src/internal.c index 896c73d04..2c6269802 100644 --- a/src/internal.c +++ b/src/internal.c @@ -16114,7 +16114,23 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case certificate_request: case server_hello_done: if (ssl->options.resuming) { -#ifdef WOLFSSL_WPAS + /* https://www.rfc-editor.org/rfc/rfc5077.html#section-3.4 + * Alternatively, the client MAY include an empty Session ID + * in the ClientHello. In this case, the client ignores the + * Session ID sent in the ServerHello and determines if the + * server is resuming a session by the subsequent handshake + * messages. + */ + if (ssl->session->sessionIDSz != 0) { +#ifndef WOLFSSL_WPAS + /* Fatal error. Only try to send an alert. RFC 5246 does not + * allow for reverting back to a full handshake after the + * server has indicated the intention to do a resumption. */ + (void)SendAlert(ssl, alert_fatal, unexpected_message); + WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); + return OUT_OF_ORDER_E; +#endif + } /* This can occur when ssl->sessionSecretCb is set. EAP-FAST * (RFC 4851) allows for detecting server session resumption * based on the msg received after the ServerHello. */ @@ -16122,14 +16138,6 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ssl->options.resuming = 0; /* No longer resuming, reset peer authentication state. */ ssl->options.peerAuthGood = 0; -#else - /* Fatal error. Only try to send an alert. RFC 5246 does not - * allow for reverting back to a full handshake after the - * server has indicated the intention to do a resumption. */ - (void)SendAlert(ssl, alert_fatal, unexpected_message); - WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); - return OUT_OF_ORDER_E; -#endif } } } diff --git a/tests/api.c b/tests/api.c index f0e78eb7e..ed54dd6af 100644 --- a/tests/api.c +++ b/tests/api.c @@ -63172,6 +63172,76 @@ static int test_dtls_1_0_hvr_downgrade(void) } #endif +#if defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12) && \ + defined(HAVE_SESSION_TICKET) + +static WOLFSSL_SESSION* test_session_ticket_no_id_session = NULL; + +static void test_session_ticket_no_id_on_result(WOLFSSL* ssl) +{ + test_session_ticket_no_id_session = wolfSSL_get1_session(ssl); + AssertNotNull(test_session_ticket_no_id_session); +} + +static void test_session_ticket_no_id_ctx_ready(WOLFSSL_CTX* ctx) +{ + AssertIntEQ(wolfSSL_CTX_UseSessionTicket(ctx), WOLFSSL_SUCCESS); +} + +static void test_session_ticket_no_id_ssl_ready(WOLFSSL* ssl) +{ + test_session_ticket_no_id_session->sessionIDSz = 0; + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_set_session(ssl, test_session_ticket_no_id_session)); +} + +static int test_session_ticket_no_id(void) +{ + /* We are testing an expired (invalid crypto context in out case since the + * ctx changes) session ticket being sent with the session ID being 0 + * length. */ + EXPECT_DECLS; + callback_functions func_cb_client; + callback_functions func_cb_server; + + XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); + XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); + func_cb_client.method = wolfTLSv1_2_client_method; + func_cb_client.ctx_ready = test_session_ticket_no_id_ctx_ready; + func_cb_client.on_result = test_session_ticket_no_id_on_result; + func_cb_server.method = wolfTLSv1_2_server_method; + func_cb_server.ctx_ready = test_session_ticket_no_id_ctx_ready; + + test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); + + ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); + ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); + + XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); + XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); + func_cb_client.method = wolfTLSv1_2_client_method; + func_cb_client.ctx_ready = test_session_ticket_no_id_ctx_ready; + func_cb_client.ssl_ready = test_session_ticket_no_id_ssl_ready; + func_cb_server.method = wolfTLSv1_2_server_method; + func_cb_server.ctx_ready = test_session_ticket_no_id_ctx_ready; + + test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); + + ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); + ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); + + wolfSSL_SESSION_free(test_session_ticket_no_id_session); + + return EXPECT_RESULT(); +} +#else +static int test_session_ticket_no_id(void) +{ + EXPECT_DECLS; + return EXPECT_RESULT(); +} +#endif + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -64425,6 +64495,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_dtls_no_extensions), TEST_DECL(test_TLSX_CA_NAMES_bad_extension), TEST_DECL(test_dtls_1_0_hvr_downgrade), + TEST_DECL(test_session_ticket_no_id), /* This test needs to stay at the end to clean up any caches allocated. */ TEST_DECL(test_wolfSSL_Cleanup) };