From 3c0072b58e1a6ff4678ef79ff367e6dae848278b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 22 Nov 2023 10:00:14 +0100 Subject: [PATCH] ssl_ticket.c: Base ticket age check on the ticket creation time Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 45 +++++++++++++++++++++++++++++++++++++- library/ssl_ticket.c | 35 ++++++++++------------------- library/ssl_tls12_server.c | 3 +++ library/ssl_tls13_server.c | 7 +++--- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 542340b9bc..f4b96d80fd 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1230,7 +1230,22 @@ struct mbedtls_ssl_session { #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_HAVE_TIME) - /*! Time in milliseconds when the ticket was created. */ + /*! When a ticket is created by a TLS server as part of an established TLS + * session, the ticket creation time may need to be saved for the ticket + * module to be able to check the ticket age when the ticket is used. + * That's the purpose of this field. + * Before creating a new ticket, an Mbed TLS server set this field with + * its current time in milliseconds. This time may then be saved in the + * session ticket data by the session ticket writing function and + * recovered by the ticket parsing function later when the ticket is used. + * The ticket module may then use this time to compute the ticket age and + * determine if it has expired or not. + * The Mbed TLS implementations of the session ticket writing and parsing + * functions save and retrieve the ticket creation time as part of the + * session ticket data. The session ticket parsing function relies on + * the mbedtls_ssl_session_get_ticket_creation_time() API to get the + * ticket creation time from the session ticket data. + */ mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time); #endif @@ -2573,6 +2588,34 @@ void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, mbedtls_ssl_ticket_write_t *f_ticket_write, mbedtls_ssl_ticket_parse_t *f_ticket_parse, void *p_ticket); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Get the creation time of a session ticket. + * + * \note See the documentation of \c ticket_creation_time for information about + * the intended usage of this function. + * + * \param session SSL session + * \param ticket_creation_time On exit, holds the ticket creation time in + * milliseconds. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if an input is not valid. + */ +static inline int mbedtls_ssl_session_get_ticket_creation_time( + mbedtls_ssl_session *session, mbedtls_ms_time_t *ticket_creation_time) +{ + if (session == NULL || ticket_creation_time == NULL || + session->MBEDTLS_PRIVATE(endpoint) != MBEDTLS_SSL_IS_SERVER) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + *ticket_creation_time = session->MBEDTLS_PRIVATE(ticket_creation_time); + + return 0; +} +#endif /* MBEDTLS_HAVE_TIME */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ /** diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c index 1ea7a50c49..5da3887b81 100644 --- a/library/ssl_ticket.c +++ b/library/ssl_ticket.c @@ -502,33 +502,22 @@ int mbedtls_ssl_ticket_parse(void *p_ticket, } #if defined(MBEDTLS_HAVE_TIME) -#if defined(MBEDTLS_SSL_PROTO_TLS1_3) - if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { - /* Check for expiration */ - mbedtls_ms_time_t ticket_age = mbedtls_ms_time() - - session->ticket_creation_time; - mbedtls_ms_time_t ticket_lifetime = - (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000; + mbedtls_ms_time_t ticket_creation_time, ticket_age; + mbedtls_ms_time_t ticket_lifetime = + (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000; - if (ticket_age < 0 || ticket_age > ticket_lifetime) { - ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; - goto cleanup; - } + ret = mbedtls_ssl_session_get_ticket_creation_time(session, + &ticket_creation_time); + if (ret != 0) { + goto cleanup; } -#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { - /* Check for expiration */ - mbedtls_time_t current_time = mbedtls_time(NULL); - if (current_time < session->start || - (uint32_t) (current_time - session->start) > key->lifetime) { - ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; - goto cleanup; - } + ticket_age = mbedtls_ms_time() - ticket_creation_time; + if (ticket_age < 0 || ticket_age > ticket_lifetime) { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_HAVE_TIME */ +#endif cleanup: #if defined(MBEDTLS_THREADING_C) diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index e433627a0b..38f322c932 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -4282,6 +4282,9 @@ static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl) * 10 . 9+n ticket content */ +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time(); +#endif if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, ssl->session_negotiate, ssl->out_msg + 10, diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index fa1f4786d7..ceb07ba22a 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -3140,10 +3140,6 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg")); -#if defined(MBEDTLS_HAVE_TIME) - session->ticket_creation_time = mbedtls_ms_time(); -#endif - /* Set ticket_flags depends on the advertised psk key exchange mode */ mbedtls_ssl_tls13_session_clear_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); @@ -3278,6 +3274,9 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2); /* Generate ticket and ticket_lifetime */ +#if defined(MBEDTLS_HAVE_TIME) + session->ticket_creation_time = mbedtls_ms_time(); +#endif ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, session, p + 9 + ticket_nonce_size + 2,