Add async TLS 1.3 key exchange and AEAD record support

Signed-off-by: Cal Abel <crabel@mac.com>
This commit is contained in:
Cal Abel 2026-07-02 22:05:22 -04:00
parent c7948dfd41
commit 43e1bed40c
3 changed files with 145 additions and 1 deletions

View File

@ -789,6 +789,7 @@ struct mbedtls_ssl_handshake_params {
size_t xxdh_psa_peerkey_len;
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
psa_key_agreement_iop_t xxdh_psa_iop;
uint8_t xxdh_psa_iop_active;
#endif
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */
@ -1763,6 +1764,16 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
#endif
void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform);
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_configure_async_aead_transform(
mbedtls_ssl_transform *transform,
psa_key_type_t key_type,
psa_algorithm_t alg,
const unsigned char *key_enc,
const unsigned char *key_dec,
size_t key_len);
#endif
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,
mbedtls_ssl_transform *transform,

View File

@ -98,6 +98,61 @@ static int samd_mbedtls_ssl_transform_has_aead(
sizeof(transform->samd_aead_key_enc) &&
transform->ivlen == 12;
}
int mbedtls_ssl_configure_async_aead_transform(
mbedtls_ssl_transform *transform,
psa_key_type_t key_type,
psa_algorithm_t alg,
const unsigned char *key_enc,
const unsigned char *key_dec,
size_t key_len)
{
unsigned char async_algorithm = 0;
if (transform == NULL || key_enc == NULL || key_dec == NULL ||
key_len == 0 || key_len > sizeof(transform->samd_aead_key_enc) ||
transform->ivlen != 12 || transform->taglen != 16) {
return 0;
}
if (key_type == PSA_KEY_TYPE_AES && alg == PSA_ALG_GCM) {
if (key_len == 16) {
async_algorithm = MBEDTLS_ASYNC_HARDWARE_TLS_AEAD_AES_128_GCM;
} else if (key_len == 32) {
async_algorithm = MBEDTLS_ASYNC_HARDWARE_TLS_AEAD_AES_256_GCM;
}
} else if (key_type == PSA_KEY_TYPE_CHACHA20 &&
alg == PSA_ALG_CHACHA20_POLY1305 && key_len == 32) {
async_algorithm = MBEDTLS_ASYNC_HARDWARE_TLS_AEAD_CHACHA20_POLY1305;
}
if (async_algorithm == 0) {
return 0;
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
if (transform->fixed_ivlen != 12) {
return 0;
}
} else
#endif
{
if (transform->fixed_ivlen != 4 &&
!(key_type == PSA_KEY_TYPE_CHACHA20 &&
alg == PSA_ALG_CHACHA20_POLY1305 &&
transform->fixed_ivlen == 12)) {
return 0;
}
}
memcpy(transform->samd_aead_key_enc, key_enc, key_len);
memcpy(transform->samd_aead_key_dec, key_dec, key_len);
transform->samd_aead_key_len = key_len;
transform->samd_aead_algorithm = async_algorithm;
transform->samd_aead_keys_configured = 1;
return 1;
}
#endif
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
@ -4881,7 +4936,9 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl)
if (ssl->transform_in != NULL &&
ssl->transform_in->samd_aead_pending != 0) {
const size_t header_len = mbedtls_ssl_in_hdr_len(ssl);
const size_t explicit_iv_len = sizeof(rec.ctr);
const size_t explicit_iv_len =
ssl_transform_aead_dynamic_iv_is_explicit(ssl->transform_in) ?
sizeof(rec.ctr) : 0;
const size_t record_len = MBEDTLS_GET_UINT16_BE(ssl->in_len, 0);
if (record_len < explicit_iv_len + ssl->transform_in->taglen) {

View File

@ -1012,6 +1012,12 @@ int mbedtls_ssl_tls13_populate_transform(
transform->psa_alg = alg;
#if defined(MBEDTLS_ASYNC_HARDWARE_AEAD)
int async_aead_configured = mbedtls_ssl_configure_async_aead_transform(
transform, key_type, alg, key_enc, key_dec, PSA_BITS_TO_BYTES(key_bits));
(void) async_aead_configured;
#endif
if (alg != MBEDTLS_SSL_NULL_CIPHER) {
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, alg);
@ -1440,11 +1446,16 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
/* Compute ECDH shared secret. */
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t shared_secret_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t shared_secret_key_destruction_status =
PSA_ERROR_GENERIC_ERROR;
status = psa_get_key_attributes(handshake->xxdh_psa_privkey,
&key_attributes);
if (status != PSA_SUCCESS) {
ret = PSA_TO_MBEDTLS_ERR(status);
MBEDTLS_SSL_DEBUG_RET(1, "psa_get_key_attributes", ret);
goto cleanup;
}
shared_secret_len = PSA_BITS_TO_BYTES(
@ -1454,6 +1465,70 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
#if defined(MBEDTLS_ASYNC_HARDWARE_ECDH) && \
defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (handshake->xxdh_psa_iop_active == 0) {
psa_key_attributes_t secret_attributes =
psa_key_attributes_init();
psa_set_key_usage_flags(&secret_attributes,
PSA_KEY_USAGE_EXPORT);
psa_set_key_type(&secret_attributes, PSA_KEY_TYPE_RAW_DATA);
psa_set_key_bits(&secret_attributes,
PSA_BYTES_TO_BITS(shared_secret_len));
status = psa_key_agreement_iop_setup(
&handshake->xxdh_psa_iop,
handshake->xxdh_psa_privkey,
handshake->xxdh_psa_peerkey,
handshake->xxdh_psa_peerkey_len,
alg,
&secret_attributes);
if (status != PSA_SUCCESS) {
(void) psa_key_agreement_iop_abort(
&handshake->xxdh_psa_iop);
ret = PSA_TO_MBEDTLS_ERR(status);
MBEDTLS_SSL_DEBUG_RET(1, "psa_key_agreement_iop_setup",
ret);
goto cleanup;
}
handshake->xxdh_psa_iop_active = 1;
}
status = psa_key_agreement_iop_complete(
&handshake->xxdh_psa_iop,
&shared_secret_key);
if (status == PSA_OPERATION_INCOMPLETE) {
mbedtls_free(shared_secret);
return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
}
(void) psa_key_agreement_iop_abort(&handshake->xxdh_psa_iop);
handshake->xxdh_psa_iop_active = 0;
if (status != PSA_SUCCESS) {
ret = PSA_TO_MBEDTLS_ERR(status);
MBEDTLS_SSL_DEBUG_RET(1, "psa_key_agreement_iop_complete",
ret);
goto cleanup;
}
status = psa_export_key(shared_secret_key,
shared_secret,
shared_secret_len,
&shared_secret_len);
shared_secret_key_destruction_status =
psa_destroy_key(shared_secret_key);
if (status != PSA_SUCCESS) {
ret = PSA_TO_MBEDTLS_ERR(status);
MBEDTLS_SSL_DEBUG_RET(1, "psa_export_key", ret);
goto cleanup;
}
if (shared_secret_key_destruction_status != PSA_SUCCESS) {
ret = PSA_TO_MBEDTLS_ERR(shared_secret_key_destruction_status);
MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
goto cleanup;
}
#else
status = psa_raw_key_agreement(
alg, handshake->xxdh_psa_privkey,
handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len,
@ -1463,6 +1538,7 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret);
goto cleanup;
}
#endif
status = psa_destroy_key(handshake->xxdh_psa_privkey);
if (status != PSA_SUCCESS) {