diff --git a/library/ssl_msg.c b/library/ssl_msg.c index bf9a8ca7c0..2fe084c4dc 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -4109,6 +4109,32 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, } +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) + /* + * Although the server rejected early data because it needed to send an + * HelloRetryRequest message, it might receive early data as long as it has + * not received the client Finished message. + * The early data is encrypted with early keys and should be ignored as + * stated in section 4.2.10 of RFC 8446 (second case): + * + * "The server then ignores early data by skipping all records with an + * external content type of "application_data" (indicating that they are + * encrypted), up to the configured max_early_data_size. Ignore application + * data message before 2nd ClientHello when early_data was received in 1st + * ClientHello." + */ + if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) { + if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("EarlyData: Ignore application message before 2nd ClientHello")); + /* TODO: Add max_early_data_size check here. */ + return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) { + ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; + } + } +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ + #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_dtls_replay_update(ssl); diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 404818dfc4..e5e4c1e007 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3279,3 +3279,6 @@ tls13_early_data:"reference" TLS 1.3 early data, deprotect and discard tls13_early_data:"deprotect and discard" + +TLS 1.3 early data, discard after HRR +tls13_early_data:"discard after HRR" diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 31a973b6f0..949356a1c5 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3674,6 +3674,11 @@ void tls13_early_data(char *scenario_string) mbedtls_test_handshake_test_options server_options; mbedtls_ssl_session saved_session; mbedtls_test_ssl_log_pattern server_pattern = { NULL, 0 }; + uint16_t group_list[3] = { + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, + MBEDTLS_SSL_IANA_TLS_GROUP_NONE + }; /* * Determine scenario. @@ -3682,6 +3687,8 @@ void tls13_early_data(char *scenario_string) scenario = 0; } else if (strcmp(scenario_string, "deprotect and discard") == 0) { scenario = 1; + } else if (strcmp(scenario_string, "discard after HRR") == 0) { + scenario = 2; } else { TEST_FAIL("Unknown scenario."); } @@ -3700,7 +3707,7 @@ void tls13_early_data(char *scenario_string) client_options.pk_alg = MBEDTLS_PK_ECDSA; ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, &client_options, NULL, NULL, NULL, - NULL); + group_list); TEST_EQUAL(ret, 0); mbedtls_ssl_conf_early_data(&client_ep.conf, MBEDTLS_SSL_EARLY_DATA_ENABLED); @@ -3709,7 +3716,7 @@ void tls13_early_data(char *scenario_string) server_options.srv_log_obj = &server_pattern; ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, &server_options, NULL, NULL, NULL, - NULL); + group_list); TEST_EQUAL(ret, 0); mbedtls_ssl_conf_early_data(&server_ep.conf, MBEDTLS_SSL_EARLY_DATA_ENABLED); mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, @@ -3763,6 +3770,19 @@ void tls13_early_data(char *scenario_string) mbedtls_ssl_conf_early_data(&server_ep.conf, MBEDTLS_SSL_EARLY_DATA_DISABLED); break; + + case 2: /* discard after HRR */ + mbedtls_debug_set_threshold(3); + server_pattern.pattern = + "EarlyData: Ignore application message before 2nd ClientHello"; + mbedtls_ssl_conf_groups(&server_ep.conf, group_list + 1); + /* + * Need to reset again to reconstruct the group list in the + * handshake structure from the configured one. + */ + ret = mbedtls_ssl_session_reset(&(server_ep.ssl)); + TEST_EQUAL(ret, 0); + break; } TEST_EQUAL(mbedtls_test_move_handshake_to_state( @@ -3793,7 +3813,8 @@ void tls13_early_data(char *scenario_string) MBEDTLS_SSL_HANDSHAKE_WRAPUP), 0); break; - case 1: + case 1: /* Intentional fallthrough */ + case 2: TEST_EQUAL(ret, 0); TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0); TEST_EQUAL(server_pattern.counter, 1);