fix(esp-tls): fixes DS peripheral use case with tf-psa-crypto 1.1

This commit is contained in:
Ashish Sharma
2026-05-21 13:43:28 +08:00
parent c6e86872d6
commit 8cb64703ff

View File

@@ -495,36 +495,17 @@ void esp_mbedtls_cleanup(esp_tls_t *tls)
/* For opaque keys (DS peripheral, hardware ECDSA), mbedtls_pk_free() does /* For opaque keys (DS peripheral, hardware ECDSA), mbedtls_pk_free() does
* not destroy the PSA key — ownership is external. Destroy it manually * not destroy the PSA key — ownership is external. Destroy it manually
* before calling mbedtls_pk_free(). */ * before calling mbedtls_pk_free(). mbedtls_pk_wrap_psa() sets the pk_info
#ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL * to mbedtls_{rsa,ecdsa}_opaque_info, both of which have type
if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_RSASSA_PSS) { * MBEDTLS_PK_OPAQUE — so a single check covers both DS and ECDSA paths.
* clientkey and serverkey share storage via union, so one branch suffices. */
#if defined(CONFIG_ESP_TLS_USE_DS_PERIPHERAL) || defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN)
if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_OPAQUE) {
if (tls->clientkey.MBEDTLS_PRIVATE(priv_id) != PSA_KEY_ID_NULL) { if (tls->clientkey.MBEDTLS_PRIVATE(priv_id) != PSA_KEY_ID_NULL) {
psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id)); psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id));
tls->clientkey.MBEDTLS_PRIVATE(priv_id) = PSA_KEY_ID_NULL; tls->clientkey.MBEDTLS_PRIVATE(priv_id) = PSA_KEY_ID_NULL;
} }
} }
if (mbedtls_pk_get_type(&tls->serverkey) == MBEDTLS_PK_RSASSA_PSS) {
if (tls->serverkey.MBEDTLS_PRIVATE(priv_id) != PSA_KEY_ID_NULL) {
psa_destroy_key(tls->serverkey.MBEDTLS_PRIVATE(priv_id));
tls->serverkey.MBEDTLS_PRIVATE(priv_id) = PSA_KEY_ID_NULL;
}
}
#endif
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_ECDSA) {
ESP_LOGD(TAG, "Cleaning up client key");
if (tls->clientkey.MBEDTLS_PRIVATE(priv_id) != PSA_KEY_ID_NULL) {
psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id));
tls->clientkey.MBEDTLS_PRIVATE(priv_id) = PSA_KEY_ID_NULL;
}
}
if (mbedtls_pk_get_type(&tls->serverkey) == MBEDTLS_PK_ECDSA) {
if (tls->serverkey.MBEDTLS_PRIVATE(priv_id) != PSA_KEY_ID_NULL) {
psa_destroy_key(tls->serverkey.MBEDTLS_PRIVATE(priv_id));
tls->serverkey.MBEDTLS_PRIVATE(priv_id) = PSA_KEY_ID_NULL;
}
}
#endif #endif
mbedtls_pk_free(&tls->clientkey); mbedtls_pk_free(&tls->clientkey);
@@ -624,6 +605,7 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
// Import opaque key reference // Import opaque key reference
psa_status_t status = psa_import_key(&key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); psa_status_t status = psa_import_key(&key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id);
psa_reset_key_attributes(&key_attr);
if (status != PSA_SUCCESS) { if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to import opaque key reference"); ESP_LOGE(TAG, "Failed to import opaque key reference");
return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED;
@@ -632,10 +614,9 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
ret = mbedtls_pk_wrap_psa(pki->pk_key, priv_key_id); ret = mbedtls_pk_wrap_psa(pki->pk_key, priv_key_id);
if (ret != 0) { if (ret != 0) {
ESP_LOGE(TAG, "Failed to wrap opaque key reference"); ESP_LOGE(TAG, "Failed to wrap opaque key reference");
psa_destroy_key(priv_key_id);
return ret; return ret;
} }
psa_reset_key_attributes(&key_attr);
} else } else
#endif #endif
if (pki->privkey_pem_buf != NULL) { if (pki->privkey_pem_buf != NULL) {
@@ -1384,46 +1365,73 @@ static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, const void *pki)
#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */ #endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */
#ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
/*
* tf-psa-crypto 1.1 made mbedtls_pk_wrap_psa() call psa_export_public_key() on
* the imported PSA key. The DS peripheral cannot expose any key material
* (private or public), so the export fails with PK_INVALID_ALG. Copy the
* already-parsed raw public key from the device certificate so wrap_psa()'s
* export step short-circuits (pk.c:145-148, returns early when pub_raw_len>0).
*/
static esp_err_t inject_rsa_pubkey_from_cert(mbedtls_pk_context *dst, const mbedtls_x509_crt *cert)
{
const mbedtls_pk_context *src = &cert->pk;
size_t src_len = src->MBEDTLS_PRIVATE(pub_raw_len);
if (src_len == 0 || src_len > sizeof(dst->MBEDTLS_PRIVATE(pub_raw))) {
ESP_LOGE(TAG, "Invalid cert pubkey length: %zu", src_len);
return ESP_ERR_INVALID_STATE;
}
memcpy(dst->MBEDTLS_PRIVATE(pub_raw), src->MBEDTLS_PRIVATE(pub_raw), src_len);
dst->MBEDTLS_PRIVATE(pub_raw_len) = src_len;
dst->MBEDTLS_PRIVATE(bits) = src->MBEDTLS_PRIVATE(bits);
dst->MBEDTLS_PRIVATE(psa_type) = PSA_KEY_TYPE_RSA_PUBLIC_KEY;
return ESP_OK;
}
static psa_status_t import_ds_key(const esp_ds_data_ctx_t *ds_data, psa_key_id_t *out_key_id)
{
esp_rsa_ds_opaque_key_t rsa_ds_opaque_key = {0};
rsa_ds_opaque_key.ds_data_ctx = (esp_ds_data_ctx_t *)ds_data;
psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_type(&attrs, PSA_KEY_TYPE_RSA_KEY_PAIR);
psa_set_key_bits(&attrs, ds_data->rsa_length_bits);
psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_SIGN_HASH);
psa_set_key_algorithm(&attrs, PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH));
#ifdef CONFIG_MBEDTLS_SSL_PROTO_TLS1_3
psa_set_key_enrollment_algorithm(&attrs, PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH));
#endif
psa_set_key_lifetime(&attrs, PSA_KEY_LIFETIME_ESP_RSA_DS_VOLATILE);
psa_status_t status = psa_import_key(&attrs,
(const uint8_t *)&rsa_ds_opaque_key,
sizeof(rsa_ds_opaque_key),
out_key_id);
psa_reset_key_attributes(&attrs);
return status;
}
static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki) static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki)
{ {
esp_ds_data_ctx_t *ds_data = ((const esp_tls_pki_t*)pki)->esp_ds_data; const esp_tls_pki_t *pki_l = (const esp_tls_pki_t *)pki;
if (ds_data == NULL) { if (pki_l->esp_ds_data == NULL || pki_l->pk_key == NULL || pki_l->public_cert == NULL) {
ESP_LOGE(TAG, "DS data context is NULL"); ESP_LOGE(TAG, "DS pki context missing required fields");
return ESP_ERR_INVALID_ARG;
}
esp_tls_pki_t *pki_l = (esp_tls_pki_t *) pki;
if (pki_l->pk_key == NULL) {
ESP_LOGE(TAG, "PK key context is NULL");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
psa_key_id_t ds_key_id = 0; psa_key_id_t ds_key_id = 0;
psa_status_t status = PSA_ERROR_GENERIC_ERROR; psa_status_t status = import_ds_key(pki_l->esp_ds_data, &ds_key_id);
esp_rsa_ds_opaque_key_t rsa_ds_opaque_key = {0};
rsa_ds_opaque_key.ds_data_ctx = ds_data;
psa_key_attributes_t ds_key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH);
#ifdef CONFIG_MBEDTLS_SSL_PROTO_TLS1_3
psa_set_key_enrollment_algorithm(&ds_key_attributes, PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH));
#endif /* CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 */
psa_set_key_type(&ds_key_attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
psa_set_key_bits(&ds_key_attributes, rsa_ds_opaque_key.ds_data_ctx->rsa_length_bits);
psa_set_key_usage_flags(&ds_key_attributes, PSA_KEY_USAGE_SIGN_HASH);
psa_set_key_algorithm(&ds_key_attributes, alg);
psa_set_key_lifetime(&ds_key_attributes, PSA_KEY_LIFETIME_ESP_RSA_DS_VOLATILE);
status = psa_import_key(&ds_key_attributes,
(const uint8_t *)&rsa_ds_opaque_key,
sizeof(rsa_ds_opaque_key),
&ds_key_id);
psa_reset_key_attributes(&ds_key_attributes);
if (status != PSA_SUCCESS) { if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to import DS key to PSA, status = %d", status); ESP_LOGE(TAG, "Failed to import DS key to PSA, status = %d", status);
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
/* Pre-populate pub_raw so wrap_psa() does not attempt to export it. */
esp_err_t esp_ret = inject_rsa_pubkey_from_cert(pki_l->pk_key, pki_l->public_cert);
if (esp_ret != ESP_OK) {
psa_destroy_key(ds_key_id);
return esp_ret;
}
int ret = mbedtls_pk_wrap_psa(pki_l->pk_key, ds_key_id); int ret = mbedtls_pk_wrap_psa(pki_l->pk_key, ds_key_id);
if (ret != 0) { if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_pk_wrap_psa failed with -0x%04X", -ret); ESP_LOGE(TAG, "mbedtls_pk_wrap_psa failed with -0x%04X", -ret);