diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 8359a9fd6..9e8ae37c7 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -1579,6 +1579,16 @@ */ #define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32 +/** + * \def MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS + * + * Default number of NewSessionTicket messages to be sent by a TLS 1.3 server + * after handshake completion. This is not used in TLS 1.2 and relevant only if + * the MBEDTLS_SSL_SESSION_TICKETS option is enabled. + * + */ +#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1 + /** * \def MBEDTLS_SSL_PROTO_DTLS * diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index b40b4f458..eda6bc2f2 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1323,9 +1323,17 @@ struct mbedtls_ssl_config #if defined(MBEDTLS_SSL_RENEGOTIATION) uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation? */ #endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_CLI_C) + uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */ #endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint16_t MBEDTLS_PRIVATE(new_session_tickets_count); /*!< number of NewSessionTicket */ +#endif + #if defined(MBEDTLS_SSL_SRV_C) uint8_t MBEDTLS_PRIVATE(cert_req_ca_list); /*!< enable sending CA list in Certificate Request messages? */ @@ -4103,7 +4111,8 @@ int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_c void mbedtls_ssl_conf_preference_order( mbedtls_ssl_config *conf, int order ); #endif /* MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_CLI_C) /** * \brief Enable / Disable session tickets (client only). * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) @@ -4115,7 +4124,34 @@ void mbedtls_ssl_conf_preference_order( mbedtls_ssl_config *conf, int order ); * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) */ void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_3) +/** + * \brief Number of NewSessionTicket messages for the server to send + * after handshake completion. + * + * \note The default value is + * \c MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS. + * + * \note In case of a session resumption, this setting only partially apply. + * At most one ticket is sent in that case to just renew the pool of + * tickets of the client. The rationale is to avoid the number of + * tickets on the server to become rapidly out of control when the + * server has the same configuration for all its connection instances. + * + * \param conf SSL configuration + * \param num_tickets Number of NewSessionTicket. + * + */ +void mbedtls_ssl_conf_new_session_tickets( mbedtls_ssl_config *conf, + uint16_t num_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_SRV_C && + MBEDTLS_SSL_PROTO_TLS1_3*/ #if defined(MBEDTLS_SSL_RENEGOTIATION) /** diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 2e35e6c8e..afacb76f0 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -624,6 +624,9 @@ struct mbedtls_ssl_handshake_params #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */ #endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint16_t new_session_tickets_count; /*!< number of session tickets */ +#endif #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 12e1c1b03..f0615ea7d 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -763,6 +763,13 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl ) mbedtls_ssl_transform_init( ssl->transform_negotiate ); ssl_handshake_params_init( ssl->handshake ); +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl->handshake->new_session_tickets_count = + ssl->conf->new_session_tickets_count ; +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { @@ -2611,6 +2618,15 @@ void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets #endif #if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +void mbedtls_ssl_conf_new_session_tickets( mbedtls_ssl_config *conf, + uint16_t num_tickets ) +{ + conf->new_session_tickets_count = num_tickets; +} +#endif + 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, @@ -4644,6 +4660,10 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_new_session_tickets( + conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS ); +#endif /* * Allow all TLS 1.3 key exchange modes by default. */ diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 94a07c831..bf281bf4a 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -2619,7 +2619,21 @@ static int ssl_tls13_write_new_session_ticket_coordinate( mbedtls_ssl_context *s /* Check whether the use of session tickets is enabled */ if( ssl->conf->f_ticket_write == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "new session ticket is not enabled" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "NewSessionTicket: disabled," + " callback is not set" ) ); + return( SSL_NEW_SESSION_TICKET_SKIP ); + } + if( ssl->conf->new_session_tickets_count == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "NewSessionTicket: disabled," + " configured count is zero" ) ); + return( SSL_NEW_SESSION_TICKET_SKIP ); + } + + if( ssl->handshake->new_session_tickets_count == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "NewSessionTicket: all tickets have " + "been sent." ) ); return( SSL_NEW_SESSION_TICKET_SKIP ); } @@ -2852,6 +2866,15 @@ static int ssl_tls13_write_new_session_ticket( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len ) ); + /* Limit session tickets count to one when resumption connection. + * + * See document of mbedtls_ssl_conf_new_session_tickets. + */ + if( ssl->handshake->resume == 1 ) + ssl->handshake->new_session_tickets_count = 0; + else + ssl->handshake->new_session_tickets_count--; + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH ); } @@ -3002,7 +3025,11 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl ) * as part of ssl_prepare_handshake_step. */ ret = 0; - mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_OVER ); + + if( ssl->handshake->new_session_tickets_count == 0 ) + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_OVER ); + else + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_NEW_SESSION_TICKET ); break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 6beaa12d7..64baa196d 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1139,7 +1139,7 @@ int main( int argc, char *argv[] ) else if( strcmp( p, "tickets" ) == 0 ) { opt.tickets = atoi( q ); - if( opt.tickets < 0 || opt.tickets > 2 ) + if( opt.tickets < 0 ) goto usage; } else if( strcmp( p, "alpn" ) == 0 ) @@ -2668,6 +2668,9 @@ send_request: */ if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) + int ticket_id = 0; +#endif do { len = sizeof( buf ) - 1; @@ -2715,7 +2718,8 @@ send_request: case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET: /* We were waiting for application data but got * a NewSessionTicket instead. */ - mbedtls_printf( " got new session ticket.\n" ); + mbedtls_printf( " got new session ticket ( %d ).\n", + ticket_id++ ); if( opt.reconnect != 0 ) { mbedtls_printf(" . Saving session for reuse..." ); @@ -2749,7 +2753,6 @@ send_request: (unsigned) session_data_len ); } } - continue; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 3113d1bb5..a129de65e 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -1997,7 +1997,7 @@ int main( int argc, char *argv[] ) else if( strcmp( p, "tickets" ) == 0 ) { opt.tickets = atoi( q ); - if( opt.tickets < 0 || opt.tickets > 1 ) + if( opt.tickets < 0 ) goto usage; } else if( strcmp( p, "ticket_rotate" ) == 0 ) @@ -2915,7 +2915,7 @@ int main( int argc, char *argv[] ) #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) - if( opt.tickets == MBEDTLS_SSL_SESSION_TICKETS_ENABLED ) + if( opt.tickets != MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) { if( ( ret = mbedtls_ssl_ticket_setup( &ticket_ctx, rng_get, &rng, @@ -2930,7 +2930,9 @@ int main( int argc, char *argv[] ) mbedtls_ssl_ticket_write, mbedtls_ssl_ticket_parse, &ticket_ctx ); - +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_conf_new_session_tickets( &conf, opt.tickets ); +#endif /* exercise manual ticket rotation (not required for typical use) * (used for external synchronization of session ticket encryption keys) */ diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 84bcd3c09..f51d94551 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -12781,14 +12781,32 @@ run_test "TLS 1.3: NewSessionTicket: Basic check, m->G" \ -c "HTTP/1.0 200 OK" \ -s "This is a resumed session" +requires_openssl_tls1_3 +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS +requires_config_enabled MBEDTLS_SSL_SRV_C +requires_config_enabled MBEDTLS_DEBUG_C +requires_config_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE +# https://github.com/openssl/openssl/issues/10714 +# Until now, OpenSSL client does not support reconnect. +skip_next_test +run_test "TLS 1.3: NewSessionTicket: Basic check, O->m" \ + "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=4" \ + "$O_NEXT_CLI -msg -debug -tls1_3 -reconnect" \ + 0 \ + -s "=> write NewSessionTicket msg" \ + -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \ + -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" + requires_gnutls_tls1_3 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS requires_config_enabled MBEDTLS_SSL_SRV_C requires_config_enabled MBEDTLS_DEBUG_C +requires_config_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE run_test "TLS 1.3: NewSessionTicket: Basic check, G->m" \ - "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=1" \ - "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%DISABLE_TLS13_COMPAT_MODE -V -r" \ + "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=4" \ + "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 -V -r" \ 0 \ -c "Connecting again- trying to resume previous session" \ -c "NEW SESSION TICKET (4) was received" \ @@ -12805,11 +12823,11 @@ requires_config_enabled MBEDTLS_SSL_SRV_C requires_config_enabled MBEDTLS_SSL_CLI_C requires_config_enabled MBEDTLS_DEBUG_C run_test "TLS 1.3: NewSessionTicket: Basic check, m->m" \ - "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=1" \ + "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=4" \ "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \ 0 \ -c "Protocol is TLSv1.3" \ - -c "got new session ticket." \ + -c "got new session ticket ( 3 )" \ -c "Saving session for reuse... ok" \ -c "Reconnecting with saved session" \ -c "HTTP/1.0 200 OK" \