diff --git a/library/ssl_misc.h b/library/ssl_misc.h index eae192bacb..b9801a06c3 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -2113,6 +2113,7 @@ int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( #if defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, + int in_new_session_ticket, unsigned char *buf, const unsigned char *end, size_t *out_len); @@ -2795,6 +2796,13 @@ static inline unsigned int mbedtls_ssl_session_ticket_allow_psk_ephemeral( MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION); } +static inline unsigned int mbedtls_ssl_session_ticket_allow_early_data( + mbedtls_ssl_session *session) +{ + return !mbedtls_ssl_session_check_ticket_flags(session, + MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); +} + static inline void mbedtls_ssl_session_set_ticket_flags( mbedtls_ssl_session *session, unsigned int flags) { diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 052df7e66e..ae1136431e 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -695,10 +695,8 @@ static int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl) mbedtls_ssl_session *session = ssl->session_negotiate; return ssl->handshake->resume && session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && - (session->ticket_flags & - MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) && - mbedtls_ssl_tls13_cipher_suite_is_offered( - ssl, session->ciphersuite); + mbedtls_ssl_session_ticket_allow_early_data(session) && + mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, session->ciphersuite); } #endif @@ -1176,7 +1174,9 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, if (mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) && ssl_tls13_early_data_has_valid_ticket(ssl) && ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { - ret = mbedtls_ssl_tls13_write_early_data_ext(ssl, p, end, &ext_len); + + ret = mbedtls_ssl_tls13_write_early_data_ext( + ssl, 0, p, end, &ext_len); if (ret != 0) { return ret; } diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index cc77a9438e..fe2a2eba78 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -1402,7 +1402,7 @@ cleanup: * * struct { * select ( Handshake.msg_type ) { - * ... + * case new_session_ticket: uint32 max_early_data_size; * case client_hello: Empty; * case encrypted_extensions: Empty; * }; @@ -1410,20 +1410,37 @@ cleanup: */ #if defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, + int in_new_session_ticket, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; - *out_len = 0; - ((void) ssl); - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); +#if defined(MBEDTLS_SSL_SRV_C) + const size_t needed = in_new_session_ticket ? 8 : 4; +#else + const size_t needed = 4; + ((void) in_new_session_ticket); +#endif + + *out_len = 0; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, needed); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0); - MBEDTLS_PUT_UINT16_BE(0, p, 2); + MBEDTLS_PUT_UINT16_BE(needed - 4, p, 2); - *out_len = 4; +#if defined(MBEDTLS_SSL_SRV_C) + if (in_new_session_ticket) { + MBEDTLS_PUT_UINT32_BE(ssl->conf->max_early_data_size, p, 4); + MBEDTLS_SSL_DEBUG_MSG( + 4, ("Sent max_early_data_size=%u", + (unsigned int) ssl->conf->max_early_data_size)); + } +#endif + + *out_len = needed; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA); diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index bfe805f496..fe7a674d66 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1845,6 +1845,13 @@ static void ssl_tls13_update_early_data_status(mbedtls_ssl_context *ssl) } + if (!mbedtls_ssl_session_ticket_allow_early_data(ssl->session_negotiate)) { + MBEDTLS_SSL_DEBUG_MSG( + 1, + ("EarlyData: rejected, early_data not allowed in ticket " + "permission bits.")); + return; + } ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; @@ -2517,7 +2524,8 @@ static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) { - ret = mbedtls_ssl_tls13_write_early_data_ext(ssl, p, end, &output_len); + ret = mbedtls_ssl_tls13_write_early_data_ext( + ssl, 0, p, end, &output_len); if (ret != 0) { return ret; } @@ -3129,6 +3137,15 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, mbedtls_ssl_session_set_ticket_flags( session, ssl->handshake->tls13_kex_modes); #endif + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED && + ssl->conf->max_early_data_size > 0) { + mbedtls_ssl_session_set_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); /* Generate ticket_age_add */ @@ -3212,12 +3229,13 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, * The following fields are placed inside the ticket by the * f_ticket_write() function: * - * - creation time (start) - * - flags (flags) + * - creation time (ticket_creation_time) + * - flags (ticket_flags) * - age add (ticket_age_add) - * - key (key) - * - key length (key_len) + * - key (resumption_key) + * - key length (resumption_key_len) * - ciphersuite (ciphersuite) + * - max_early_data_size (max_early_data_size) */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, @@ -3232,6 +3250,7 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, mbedtls_ssl_session *session = ssl->session; size_t ticket_len; uint32_t ticket_lifetime; + unsigned char *p_extensions_len; *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg")); @@ -3293,15 +3312,35 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, /* Ticket Extensions * - * Note: We currently don't have any extensions. - * Set length to zero. + * Extension extensions<0..2^16-2>; */ ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); - MBEDTLS_PUT_UINT16_BE(0, p, 0); + p_extensions_len = p; p += 2; +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (mbedtls_ssl_session_ticket_allow_early_data(session)) { + size_t output_len; + + if ((ret = mbedtls_ssl_tls13_write_early_data_ext( + ssl, 1, p, end, &output_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_write_early_data_ext", ret); + return ret; + } + p += output_len; + } else { + MBEDTLS_SSL_DEBUG_MSG( + 4, ("early_data not allowed, " + "skip early_data extension in NewSessionTicket")); + } + +#endif /* MBEDTLS_SSL_EARLY_DATA */ + + MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); + *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket")); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index c96128b94c..e6ebd8e1df 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -556,6 +556,7 @@ int main(void) USAGE_GROUPS \ USAGE_SIG_ALGS \ USAGE_KEY_OPAQUE_ALGS \ + USAGE_EARLY_DATA \ "\n" #if defined(MBEDTLS_SSL_PROTO_TLS1_3) diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh index e4df1fe2f0..a4742030bc 100755 --- a/tests/opt-testcases/tls13-misc.sh +++ b/tests/opt-testcases/tls13-misc.sh @@ -490,22 +490,6 @@ run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_all/psk_all." \ EARLY_DATA_INPUT_LEN_BLOCKS=$(( ( $( cat $EARLY_DATA_INPUT | wc -c ) + 31 ) / 32 )) EARLY_DATA_INPUT_LEN=$(( $EARLY_DATA_INPUT_LEN_BLOCKS * 32 )) -requires_gnutls_next -requires_all_configs_enabled MBEDTLS_SSL_EARLY_DATA MBEDTLS_SSL_SESSION_TICKETS \ - MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \ - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \ - MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE -requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \ - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED -run_test "TLS 1.3 G->m: EarlyData: feature is disabled, fail." \ - "$P_SRV force_version=tls13 debug_level=4 max_early_data_size=-1" \ - "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+GROUP-ALL -d 10 -r --earlydata $EARLY_DATA_INPUT" \ - 1 \ - -s "ClientHello: early_data(42) extension exists." \ - -s "EncryptedExtensions: early_data(42) extension does not exist." \ - -s "NewSessionTicket: early_data(42) extension does not exist." \ - -s "Last error was: -29056 - SSL - Verification of the message MAC failed" - requires_gnutls_next requires_all_configs_enabled MBEDTLS_SSL_EARLY_DATA MBEDTLS_SSL_SESSION_TICKETS \ MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \ @@ -518,7 +502,8 @@ run_test "TLS 1.3 G->m: EarlyData: feature is enabled, good." \ "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+GROUP-ALL:+KX-ALL \ -d 10 -r --earlydata $EARLY_DATA_INPUT " \ 0 \ + -s "NewSessionTicket: early_data(42) extension exists." \ + -s "Sent max_early_data_size=$EARLY_DATA_INPUT_LEN" \ -s "ClientHello: early_data(42) extension exists." \ -s "EncryptedExtensions: early_data(42) extension exists." \ - -s "NewSessionTicket: early_data(42) extension does not exist." \ -s "$( tail -1 $EARLY_DATA_INPUT )"