Merge pull request #1595 from bjwtaylor/info-leak-in-ssl_write_new_session_ticket

Info leak in ssl write new session ticket
This commit is contained in:
Gilles Peskine 2026-06-24 09:42:13 +02:00 committed by GitHub
commit 98e4a7b02a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 104 additions and 3 deletions

View File

@ -0,0 +1,6 @@
Security
* Fix a potential information disclosure in TLS 1.2 servers using session
tickets. If the session ticket write callback failed without setting the
lifetime output parameter, Mbed TLS could send 4 bytes of uninitialized
stack memory to the peer in the NewSessionTicket message. Fixes #1570.
Reported by James Love. CVE-2026-50586.

View File

@ -3367,8 +3367,8 @@ MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t tlen;
uint32_t lifetime;
size_t tlen = 0;
uint32_t lifetime = 0;
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write new session ticket"));
@ -3395,7 +3395,6 @@ static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl)
ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
&tlen, &lifetime)) != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_write", ret);
tlen = 0;
}
MBEDTLS_PUT_UINT32_BE(lifetime, ssl->out_msg, 4);

View File

@ -3566,3 +3566,7 @@ send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:0
Negative Test: Server using sig_alg not offered by the client - ECDSA with SHA512
depends_on:MBEDTLS_CAN_HANDLE_ECDSA_TEST_KEY:MBEDTLS_CAN_HANDLE_ECDSA_CLIENT_TEST_KEY:PSA_WANT_ALG_SHA_512
send_invalid_sig_alg:MBEDTLS_SSL_SIG_ECDSA:MBEDTLS_SSL_HASH_SHA512:MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER
TLS 1.2 NewSessionTicket: failing ticket callback leaves lifetime unset
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY
write_new_session_ticket_mem

View File

@ -25,6 +25,36 @@
#define TEST_EARLY_DATA_NO_INITIAL_ALPN 6
#define TEST_EARLY_DATA_NO_LATER_ALPN 7
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \
defined(PSA_HAVE_ALG_SOME_RSA_SIGN) && \
defined(PSA_WANT_ECC_SECP_R1_384) && \
defined(PSA_WANT_ALG_SHA_256) && \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
defined(MBEDTLS_CAN_HANDLE_RSA_TEST_KEY)
static int failing_ticket_write_unset_lifetime(
void *p_ticket, const mbedtls_ssl_session *session,
unsigned char *start, const unsigned char *end,
size_t *tlen, uint32_t *lifetime)
{
((void) p_ticket);
((void) session);
((void) start);
((void) end);
((void) tlen);
((void) lifetime);
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_SESSION_TICKETS &&
MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SRV_C &&
MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED &&
PSA_HAVE_ALG_SOME_RSA_SIGN && PSA_WANT_ECC_SECP_R1_384 &&
PSA_WANT_ALG_SHA_256 && PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY &&
MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
#if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \
defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \
defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \
@ -6553,3 +6583,65 @@ exit:
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_HAVE_ALG_SOME_RSA_SIGN:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
void write_new_session_ticket_mem()
{
enum { BUFFSIZE = 1024 };
mbedtls_test_ssl_endpoint server_ep, client_ep;
mbedtls_test_handshake_test_options options;
int ret = -1;
memset(&server_ep, 0, sizeof(server_ep));
memset(&client_ep, 0, sizeof(client_ep));
mbedtls_test_init_handshake_options(&options);
options.pk_alg = MBEDTLS_PK_RSA;
options.client_min_version = MBEDTLS_SSL_VERSION_TLS1_2;
options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_2;
options.server_min_version = MBEDTLS_SSL_VERSION_TLS1_2;
options.server_max_version = MBEDTLS_SSL_VERSION_TLS1_2;
MD_OR_USE_PSA_INIT();
ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER,
&options);
TEST_EQUAL(ret, 0);
mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf,
failing_ticket_write_unset_lifetime,
mbedtls_test_ticket_parse,
NULL);
ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT,
&options);
TEST_EQUAL(ret, 0);
ret = mbedtls_test_mock_socket_connect(&(server_ep.socket),
&(client_ep.socket),
BUFFSIZE);
TEST_EQUAL(ret, 0);
ret = mbedtls_test_move_handshake_to_state(&(server_ep.ssl),
&(client_ep.ssl),
MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC);
TEST_EQUAL(ret, 0);
ret = mbedtls_ssl_handshake_step(&(server_ep.ssl));
TEST_EQUAL(ret, 0);
/* Force a read of the lifetime value from the outgoing message.
* This is a non-regression test for a bug where the lifetime was set from
* uninitialized memory.
* The read here causes MSan and Valgrind to complain if the bug isn't fixed.
*/
volatile uint32_t lifetime = MBEDTLS_GET_UINT32_BE(server_ep.ssl.out_msg, 4);
(void) lifetime;
exit:
mbedtls_test_ssl_endpoint_free(&client_ep);
mbedtls_test_ssl_endpoint_free(&server_ep);
mbedtls_test_free_handshake_options(&options);
MD_OR_USE_PSA_DONE();
}
/* END_CASE */