Merge pull request #1486 from ronald-cron-arm/tls12-2nd-client-hello

Fix TLS 1.2 client hello after HRR
This commit is contained in:
Manuel Pégourié-Gonnard
2026-03-16 10:58:50 +01:00
committed by GitHub
4 changed files with 166 additions and 7 deletions
+3
View File
@@ -3527,3 +3527,6 @@ ssl_tls_exporter_too_early:MBEDTLS_SSL_VERSION_TLS1_3:1:MBEDTLS_SSL_SERVER_CERTI
TLS fatal alert getter
ssl_get_alert_after_fatal
TLS 1.3 - HRR then TLS 1.2 second ClientHello
tls13_hrr_then_tls12_second_client_hello
+139
View File
@@ -6040,3 +6040,142 @@ exit:
USE_PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_HAS_TLS1_3_CHACHA20_POLY1305_SHA256:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_HAVE_ALG_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_DEBUG_C */
void tls13_hrr_then_tls12_second_client_hello()
{
int ret = -1;
mbedtls_test_ssl_endpoint client_ep, server_ep;
memset(&client_ep, 0, sizeof(client_ep));
memset(&server_ep, 0, sizeof(server_ep));
mbedtls_test_handshake_test_options client_options;
mbedtls_test_handshake_test_options server_options;
mbedtls_ssl_session saved_session;
mbedtls_test_ssl_log_pattern server_pattern =
{ "Non compliant 2nd ClientHello, TLS 1.2 version", 0 };
uint16_t group_list[3] = {
MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
MBEDTLS_SSL_IANA_TLS_GROUP_NONE
};
const int tls12_ciphersuite_list[2] = {
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
0
};
mbedtls_test_init_handshake_options(&client_options);
mbedtls_test_init_handshake_options(&server_options);
mbedtls_ssl_session_init(&saved_session);
PSA_INIT();
/*
* Run first handshake to get a ticket from the server.
*/
client_options.pk_alg = MBEDTLS_PK_ECDSA;
client_options.group_list = group_list;
client_options.cipher = "TLS1-3-CHACHA20-POLY1305-SHA256";
server_options.pk_alg = MBEDTLS_PK_ECDSA;
server_options.group_list = group_list;
ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options,
&saved_session);
TEST_EQUAL(ret, 0);
/*
* Prepare for handshake with the ticket.
*/
/* Remove the group SECP256R1 from the list of groups supported by the
* server. Since it is the client's preferred group, the client will
* send a key share only for SECP256R1, forcing the server to send a HRR.
*/
server_options.group_list = group_list + 1;
ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT,
&client_options);
TEST_EQUAL(ret, 0);
server_options.srv_log_fun = mbedtls_test_ssl_log_analyzer;
server_options.srv_log_obj = &server_pattern;
ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER,
&server_options);
TEST_EQUAL(ret, 0);
mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf,
mbedtls_test_ticket_write,
mbedtls_test_ticket_parse,
NULL);
ret = mbedtls_test_mock_socket_connect(&(client_ep.socket),
&(server_ep.socket), 1024);
TEST_EQUAL(ret, 0);
ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session);
TEST_EQUAL(ret, 0);
/*
* Progress the handshake up to the point where the server has sent the
* HRR and the client has received and processed the server HRR but not
* written the second ClientHello in response to the HRR.
*/
ret = mbedtls_test_move_handshake_to_state(
&(server_ep.ssl), &(client_ep.ssl),
MBEDTLS_SSL_HELLO_RETRY_REQUEST);
TEST_EQUAL(ret, 0);
TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
ret = mbedtls_test_move_handshake_to_state(
&(client_ep.ssl), &(server_ep.ssl),
MBEDTLS_SSL_CLIENT_HELLO);
TEST_EQUAL(ret, 0);
TEST_EQUAL(server_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO);
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/* If the compatibility mode is enabled, filter the dummy change_cipher_spec
* record sent by the server after the HRR. Otherwise, as we have switched
* the client to TLS 1.2 it would fail when reading this record.
*/
ret = mbedtls_ssl_read_record(&(client_ep.ssl), 0);
TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ);
#endif
/*
* The client has just received the server's HRR and is expected to send a
* second ClientHello. Instead of sending a compliant second TLS 1.3
* ClientHello, we want it to send a TLS 1.2-only ClientHello. To achieve
* this, we reset the client with a TLS 1.2-only configuration before
* resuming the handshake with the server.
*/
client_ep.ssl.tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
mbedtls_ssl_conf_min_tls_version(&client_ep.conf, MBEDTLS_SSL_VERSION_TLS1_2);
mbedtls_ssl_conf_max_tls_version(&client_ep.conf, MBEDTLS_SSL_VERSION_TLS1_2);
mbedtls_ssl_conf_ciphersuites(&client_ep.conf, tls12_ciphersuite_list);
ret = mbedtls_ssl_session_reset(&(client_ep.ssl));
TEST_EQUAL(ret, 0);
/*
* Restart and try to complete the handshake on server side which is
* expected to fail early.
*/
mbedtls_debug_set_threshold(1);
ret = mbedtls_test_move_handshake_to_state(
&(server_ep.ssl), &(client_ep.ssl),
MBEDTLS_SSL_HANDSHAKE_OVER);
TEST_EQUAL(ret, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
TEST_EQUAL(server_pattern.counter, 1);
TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
TEST_EQUAL(server_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO);
exit:
mbedtls_test_ssl_endpoint_free(&client_ep);
mbedtls_test_ssl_endpoint_free(&server_ep);
mbedtls_test_free_handshake_options(&client_options);
mbedtls_test_free_handshake_options(&server_options);
mbedtls_ssl_session_free(&saved_session);
mbedtls_debug_set_threshold(0);
PSA_DONE();
}
/* END_CASE */