diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 97ae51cb72..eac6326009 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -1892,36 +1892,6 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl) ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; goto cleanup; } -#if defined(MBEDTLS_SSL_EARLY_DATA) - if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA) && - (handshake->selected_identity != 0 || - handshake->ciphersuite_info->id != - ssl->session_negotiate->ciphersuite)) { - /* RFC8446 4.2.11 - * If the server supplies an "early_data" extension, the - * client MUST verify that the server's selected_identity - * is 0. If any other value is returned, the client MUST - * abort the handshake with an "illegal_parameter" alert. - * - * RFC 8446 4.2.10 - * In order to accept early data, the server MUST have accepted a PSK - * cipher suite and selected the first key offered in the client's - * "pre_shared_key" extension. In addition, it MUST verify that the - * following values are the same as those associated with the - * selected PSK: - * - The TLS version number - * - The selected cipher suite - * - The selected ALPN [RFC7301] protocol, if any - * - * We check here that when early data is involved the server - * selected the cipher suite associated to the pre-shared key - * as it must have. - */ - MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, - MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; - } -#endif if (!mbedtls_ssl_conf_tls13_check_kex_modes( ssl, handshake->key_exchange_mode)) { @@ -2197,6 +2167,9 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) int ret; unsigned char *buf; size_t buf_len; +#if defined(MBEDTLS_SSL_EARLY_DATA) + mbedtls_ssl_handshake_params *handshake = ssl->handshake; +#endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions")); @@ -2209,8 +2182,37 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len)); #if defined(MBEDTLS_SSL_EARLY_DATA) - if (ssl->handshake->received_extensions & - MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { + if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { + /* RFC8446 4.2.11 + * If the server supplies an "early_data" extension, the + * client MUST verify that the server's selected_identity + * is 0. If any other value is returned, the client MUST + * abort the handshake with an "illegal_parameter" alert. + * + * RFC 8446 4.2.10 + * In order to accept early data, the server MUST have accepted a PSK + * cipher suite and selected the first key offered in the client's + * "pre_shared_key" extension. In addition, it MUST verify that the + * following values are the same as those associated with the + * selected PSK: + * - The TLS version number + * - The selected cipher suite + * - The selected ALPN [RFC7301] protocol, if any + * + * We check here that when early data is involved the server + * selected the cipher suite associated to the pre-shared key + * as it must have. + */ + if (handshake->selected_identity != 0 || + handshake->ciphersuite_info->id != + ssl->session_negotiate->ciphersuite) { + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; } #endif diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 954ddffb2d..061dcf7fd6 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -152,6 +152,12 @@ static int ssl_tls13_offered_psks_check_identity_match_ticket( /* We delete the temporary buffer */ mbedtls_free(ticket_buffer); + if (ret == 0 && session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3.")); + /* TODO: Define new return value for this case. */ + ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + } + if (ret != 0) { goto exit; } @@ -1784,9 +1790,59 @@ static void ssl_tls13_update_early_data_status(mbedtls_ssl_context *ssl) return; } - /* We do not accept early data for the time being */ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; + if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) { + MBEDTLS_SSL_DEBUG_MSG( + 1, + ("EarlyData: rejected, feature disabled in server configuration.")); + return; + } + + if (!handshake->resume) { + /* We currently support early data only in the case of PSKs established + via a NewSessionTicket message thus in the case of a session + resumption. */ + MBEDTLS_SSL_DEBUG_MSG( + 1, ("EarlyData: rejected, not a session resumption.")); + return; + } + + /* RFC 8446 4.2.10 + * + * In order to accept early data, the server MUST have accepted a PSK cipher + * suite and selected the first key offered in the client's "pre_shared_key" + * extension. In addition, it MUST verify that the following values are the + * same as those associated with the selected PSK: + * - The TLS version number + * - The selected cipher suite + * - The selected ALPN [RFC7301] protocol, if any + * + * NOTE: + * - The TLS version number is checked in + * ssl_tls13_offered_psks_check_identity_match_ticket(). + * - ALPN is not checked for the time being (TODO). + */ + + if (handshake->selected_identity != 0) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("EarlyData: rejected, the selected key in " + "`pre_shared_key` is not the first one.")); + return; + } + + if (handshake->ciphersuite_info->id != + ssl->session_negotiate->ciphersuite) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("EarlyData: rejected, the selected ciphersuite is not the one " + "of the selected pre-shared key.")); + return; + + } + + + ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; + } #endif /* MBEDTLS_SSL_EARLY_DATA */ @@ -2446,6 +2502,16 @@ static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl, p += output_len; #endif /* MBEDTLS_SSL_ALPN */ +#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); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + extensions_len = (p - p_extensions_len) - 2; MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh index 27c3453a83..3816a2b459 100755 --- a/tests/opt-testcases/tls13-misc.sh +++ b/tests/opt-testcases/tls13-misc.sh @@ -485,6 +485,9 @@ run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_all/psk_all." \ -s "found matched identity" \ -s "key exchange mode: psk_ephemeral" +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 \ @@ -500,3 +503,20 @@ run_test "TLS 1.3 G->m: EarlyData: feature is disabled, fail." \ -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 \ + 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 enabled, fail." \ + "$P_SRV force_version=tls13 debug_level=4 max_early_data_size=$EARLY_DATA_INPUT_LEN" \ + "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+GROUP-ALL:+KX-ALL \ + -d 10 -r --earlydata $EARLY_DATA_INPUT " \ + 1 \ + -s "ClientHello: early_data(42) extension exists." \ + -s "EncryptedExtensions: early_data(42) extension exists." \ + -s "NewSessionTicket: early_data(42) extension does not exist." \ + -s "Last error was: -29056 - SSL - Verification of the message MAC failed"