Resume asynchronous TLS 1.3 handshake operations

Signed-off-by: Cal Abel <crabel@mac.com>
This commit is contained in:
Cal Abel 2026-07-10 12:50:48 -04:00
parent 7816ed7e36
commit 7016e506de
4 changed files with 198 additions and 11 deletions

View File

@ -724,6 +724,8 @@ struct mbedtls_ssl_handshake_params {
ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */
ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */
ssl_ecrs_ske_sign, /*!< ServerKeyExchange: pk_sign() */
ssl_ecrs_tls13_server_hello_finalize, /*!< ServerHello: key schedule */
ssl_ecrs_tls13_server_hello_postprocess, /*!< ServerHello: peer key schedule */
ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */
ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */
} ecrs_state; /*!< current (or last) operation */

View File

@ -970,12 +970,22 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,
size_t padding =
ssl_compute_padding_length(rec->data_len,
MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY);
if (ssl_build_inner_plaintext(data,
&rec->data_len,
post_avail,
rec->type,
padding) != 0) {
return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
if (transform->async_hardware_aead_pending != 0) {
if (post_avail < padding + 1) {
return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
}
rec->data_len += padding + 1;
} else
#endif
{
if (ssl_build_inner_plaintext(data,
&rec->data_len,
post_avail,
rec->type,
padding) != 0) {
return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
}
}
rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA;

View File

@ -1859,6 +1859,13 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (handshake->ecrs_state ==
ssl_ecrs_tls13_server_hello_postprocess) {
goto compute_handshake_transform;
}
#endif
/* Determine the key exchange mode:
* 1) If both the pre_shared_key and key_share extensions were received
* then the key exchange mode is PSK with EPHEMERAL.
@ -1932,7 +1939,16 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
}
}
compute_handshake_transform:
ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl);
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
ssl->handshake->ecrs_state =
ssl_ecrs_tls13_server_hello_postprocess;
goto cleanup;
}
ssl->handshake->ecrs_state = ssl_ecrs_none;
#endif
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1,
"mbedtls_ssl_tls13_compute_handshake_transform",
@ -1945,7 +1961,7 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
ssl->session_in = ssl->session_negotiate;
cleanup:
if (ret != 0) {
if (ret != 0 && ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
@ -1997,6 +2013,18 @@ static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__));
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ssl->handshake->ecrs_state ==
ssl_ecrs_tls13_server_hello_postprocess) {
ret = ssl_tls13_postprocess_server_hello(ssl);
if (ret == 0) {
mbedtls_ssl_handshake_set_state(
ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
}
goto cleanup;
}
#endif
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len));
@ -2628,18 +2656,46 @@ static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl)
/*
* Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE
*/
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
static int ssl_tls13_resume_pending_record(mbedtls_ssl_context *ssl)
{
if (ssl->transform_out == NULL ||
ssl->transform_out->async_hardware_aead_pending == 0) {
return 0;
}
int ret = mbedtls_ssl_write_record(ssl, 1);
return ret == 0 ? 1 : ret;
}
#endif
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl)
{
int non_empty_certificate_msg = 0;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
int ret;
#endif
MBEDTLS_SSL_DEBUG_MSG(1,
("Switch to handshake traffic keys for outbound traffic"));
mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake);
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
ret = ssl_tls13_resume_pending_record(ssl);
if (ret < 0) {
return ret;
}
if (ret > 0) {
non_empty_certificate_msg = mbedtls_ssl_own_cert(ssl) != NULL;
goto client_certificate_written;
}
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
if (ssl->handshake->client_auth) {
int ret = mbedtls_ssl_tls13_write_certificate(ssl);
ret = mbedtls_ssl_tls13_write_certificate(ssl);
if (ret != 0) {
return ret;
}
@ -2652,6 +2708,9 @@ static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl)
}
#endif
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
client_certificate_written:
#endif
if (non_empty_certificate_msg) {
mbedtls_ssl_handshake_set_state(ssl,
MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY);
@ -2670,8 +2729,22 @@ static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_write_client_certificate_verify(mbedtls_ssl_context *ssl)
{
int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);
int ret;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
ret = ssl_tls13_resume_pending_record(ssl);
if (ret < 0) {
return ret;
}
if (ret > 0) {
ret = 0;
goto client_certificate_verify_written;
}
#endif
ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
client_certificate_verify_written:
#endif
if (ret == 0) {
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);
}
@ -2688,11 +2761,25 @@ static int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl)
{
int ret;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
ret = ssl_tls13_resume_pending_record(ssl);
if (ret < 0) {
return ret;
}
if (ret > 0) {
ret = 0;
goto client_finished_written;
}
#endif
ret = mbedtls_ssl_tls13_write_finished_message(ssl);
if (ret != 0) {
return ret;
}
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
client_finished_written:
#endif
ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl);
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(

View File

@ -2410,6 +2410,12 @@ static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello"));
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ssl->handshake->ecrs_state == ssl_ecrs_tls13_server_hello_finalize) {
goto finalize_server_hello;
}
#endif
MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl));
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
@ -2426,7 +2432,20 @@ static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
ssl, buf_len, msg_len));
MBEDTLS_SSL_PROC_CHK(ssl_tls13_finalize_server_hello(ssl));
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
finalize_server_hello:
#endif
ret = ssl_tls13_finalize_server_hello(ssl);
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
ssl->handshake->ecrs_state = ssl_ecrs_tls13_server_hello_finalize;
goto cleanup;
}
ssl->handshake->ecrs_state = ssl_ecrs_none;
#endif
if (ret != 0) {
goto cleanup;
}
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/* The server sends a dummy change_cipher_spec record immediately
@ -2522,6 +2541,19 @@ cleanup:
* Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
*/
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
static int ssl_tls13_resume_pending_record(mbedtls_ssl_context *ssl)
{
if (ssl->transform_out == NULL ||
ssl->transform_out->async_hardware_aead_pending == 0) {
return 0;
}
int ret = mbedtls_ssl_write_record(ssl, 1);
return ret == 0 ? 1 : ret;
}
#endif
/*
* struct {
* Extension extensions<0..2 ^ 16 - 1>;
@ -2607,6 +2639,17 @@ static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write encrypted extensions"));
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
ret = ssl_tls13_resume_pending_record(ssl);
if (ret < 0) {
goto cleanup;
}
if (ret > 0) {
ret = 0;
goto encrypted_extensions_written;
}
#endif
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
&buf, &buf_len));
@ -2621,6 +2664,9 @@ static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
ssl, buf_len, msg_len));
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
encrypted_extensions_written:
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
@ -2781,6 +2827,17 @@ static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
ret = ssl_tls13_resume_pending_record(ssl);
if (ret < 0) {
return ret;
}
if (ret > 0) {
ret = 0;
goto server_certificate_written;
}
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if ((ssl_tls13_pick_key_cert(ssl) != 0) ||
mbedtls_ssl_own_cert(ssl) == NULL) {
@ -2795,6 +2852,9 @@ static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl)
if (ret != 0) {
return ret;
}
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
server_certificate_written:
#endif
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY);
return 0;
}
@ -2805,10 +2865,24 @@ static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl)
{
int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);
int ret;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
ret = ssl_tls13_resume_pending_record(ssl);
if (ret < 0) {
return ret;
}
if (ret > 0) {
ret = 0;
goto certificate_verify_written;
}
#endif
ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);
if (ret != 0) {
return ret;
}
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
certificate_verify_written:
#endif
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
return 0;
}
@ -2875,11 +2949,25 @@ static int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
ret = ssl_tls13_resume_pending_record(ssl);
if (ret < 0) {
return ret;
}
if (ret > 0) {
ret = 0;
goto server_finished_written;
}
#endif
ret = mbedtls_ssl_tls13_write_finished_message(ssl);
if (ret != 0) {
return ret;
}
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
server_finished_written:
#endif
ret = mbedtls_ssl_tls13_compute_application_transform(ssl);
if (ret != 0) {
MBEDTLS_SSL_PEND_FATAL_ALERT(