diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c index 1422dc27df..f1f4d0375f 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c @@ -12,6 +12,7 @@ #include "mbedtls/ecp.h" #include "mbedtls/ecdsa.h" #include "mbedtls/sha256.h" +#include "ecdsa/ecdsa_alt.h" #include "esp_tee.h" #include "esp_tee_sec_storage.h" @@ -322,3 +323,77 @@ TEST_CASE("Test TEE Secure Storage - Corruption from non-secure world", "[secure TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); } #endif + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN +static const uint8_t sha[] = { + 0x0c, 0xaa, 0x08, 0xb4, 0xf0, 0x89, 0xd3, 0x45, + 0xbb, 0x55, 0x98, 0xd9, 0xc2, 0xe9, 0x65, 0x5d, + 0x7e, 0xa3, 0xa9, 0xc3, 0xcd, 0x69, 0xb1, 0xcf, + 0x91, 0xbe, 0x58, 0x10, 0xfe, 0x80, 0x65, 0x6e +}; + +static void test_ecdsa_sign(mbedtls_ecp_group_id gid, const uint8_t *hash, int slot_id) +{ + TEST_ESP_OK(esp_tee_sec_storage_init()); + TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); + + bool is_crv_p192 = false; + esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; + size_t key_len = ECDSA_SECP256R1_KEY_LEN; + + if (gid == MBEDTLS_ECP_DP_SECP192R1) { + is_crv_p192 = true; + key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1; + key_len = ECDSA_SECP192R1_KEY_LEN; + } + + TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, key_type)); + + esp_tee_sec_storage_pubkey_t pubkey = {}; + TEST_ESP_OK(esp_tee_sec_storage_get_pubkey(slot_id, key_type, &pubkey)); + + mbedtls_mpi r, s; + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecdsa_context ecdsa_context; + mbedtls_ecdsa_init(&ecdsa_context); + + TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), gid)); + + mbedtls_pk_context key_ctx; + + esp_ecdsa_pk_conf_t conf = { + .grp_id = gid, + .tee_slot_id = slot_id, + .load_pubkey = true, + .use_tee_sec_stg_key = true, + }; + TEST_ASSERT_EQUAL(0, esp_ecdsa_tee_set_pk_context(&key_ctx, &conf)); + + mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(key_ctx); + mbedtls_mpi key_mpi = keypair->MBEDTLS_PRIVATE(d); + + TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, SHA256_DIGEST_SZ, NULL, NULL)); + + esp_tee_sec_storage_sign_t sign = {}; + TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&r, sign.sign_r, key_len)); + TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&s, sign.sign_s, key_len)); + + ESP_LOGI(TAG, "Verifying generated signature..."); + TEST_ESP_OK(verify_ecdsa_sign(sha, sizeof(sha), &pubkey, &sign, is_crv_p192)); + + mbedtls_pk_free(&key_ctx); + mbedtls_ecdsa_free(&ecdsa_context); + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); +} + +TEST_CASE("Test TEE Secure Storage - mbedtls ECDSA signing", "[mbedtls]") +{ + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, MIN_SEC_STG_SLOT_ID); +#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, MAX_SEC_STG_SLOT_ID); +#endif +} +#endif diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index a0bb4df88f..bfd405f7c1 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -294,27 +294,40 @@ if(CONFIG_MBEDTLS_HARDWARE_ECC) "${COMPONENT_DIR}/port/ecc/ecc_alt.c") endif() -if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) - target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/ecdsa/ecdsa_alt.c") +if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) + target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/ecdsa/ecdsa_alt.c") - if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_restartable") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature_restartable") + set(WRAP_FUNCTIONS_SIGN + mbedtls_ecdsa_sign + mbedtls_ecdsa_sign_restartable + mbedtls_ecdsa_write_signature + mbedtls_ecdsa_write_signature_restartable) + + set(WRAP_FUNCTIONS_VERIFY + mbedtls_ecdsa_verify + mbedtls_ecdsa_verify_restartable + mbedtls_ecdsa_read_signature + mbedtls_ecdsa_read_signature_restartable) + + if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) + foreach(wrap ${WRAP_FUNCTIONS_SIGN}) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}") + endforeach() if(CONFIG_SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE) target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_det_ext") target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_det_restartable") endif() - endif() if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_verify") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_verify_restartable") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_read_signature") - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_read_signature_restartable") + foreach(wrap ${WRAP_FUNCTIONS_VERIFY}) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}") + endforeach() + endif() + + if(CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) + target_link_libraries(mbedcrypto PRIVATE idf::tee_sec_storage) endif() endif() diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index ab633bff38..d499956a2c 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -584,6 +584,11 @@ menu "mbedTLS" The key should be burnt in little endian format. espefuse.py utility handles it internally but care needs to be taken while burning using esp_efuse APIs + config MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + bool "Enable ECDSA signing using TEE secure storage" + default y + depends on SECURE_ENABLE_TEE + menu "Enable Software Countermeasure for ECDSA signing using on-chip ECDSA peripheral" depends on MBEDTLS_HARDWARE_ECDSA_SIGN depends on IDF_TARGET_ESP32H2 diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index 7dd3e6d01e..0fe826fb3e 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -1,27 +1,40 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include -#include "hal/ecc_ll.h" -#include "hal/ecdsa_ll.h" -#include "hal/ecdsa_hal.h" -#ifdef SOC_MPI_SUPPORTED -#include "hal/mpi_ll.h" -#endif + +#include "esp_err.h" +#include "esp_log.h" + +#include "hal/ecdsa_types.h" +#include "ecdsa/ecdsa_alt.h" +#include "soc/soc_caps.h" + #include "esp_crypto_lock.h" -#include "esp_efuse.h" #include "esp_private/esp_crypto_lock_internal.h" + #include "mbedtls/error.h" #include "mbedtls/ecdsa.h" #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" #include "mbedtls/platform_util.h" -#include "ecdsa/ecdsa_alt.h" -#include "soc/soc_caps.h" + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN +#include "esp_tee_sec_storage.h" +#else +#include "hal/ecc_ll.h" +#include "hal/ecdsa_ll.h" +#include "hal/ecdsa_hal.h" +#if SOC_MPI_SUPPORTED +#include "hal/mpi_ll.h" +#endif +#include "esp_efuse.h" +#endif #define ECDSA_KEY_MAGIC (short) 0xECD5A +#define ECDSA_KEY_MAGIC_TEE (short) 0xA5DCE #define ECDSA_SHA_LEN 32 #define MAX_ECDSA_COMPONENT_LEN 32 @@ -51,6 +64,7 @@ __attribute__((unused)) static const char *TAG = "ecdsa_alt"; +#if SOC_ECDSA_SUPPORTED static void esp_ecdsa_acquire_hardware(void) { esp_crypto_ecdsa_lock_acquire(); @@ -66,7 +80,7 @@ static void esp_ecdsa_acquire_hardware(void) ecc_ll_reset_register(); } -#ifdef SOC_ECDSA_USES_MPI +#if SOC_ECDSA_USES_MPI /* We need to reset the MPI peripheral because ECDSA peripheral * of some targets use the MPI peripheral as well. */ @@ -88,7 +102,7 @@ static void esp_ecdsa_release_hardware(void) ecc_ll_power_down(); } -#ifdef SOC_ECDSA_USES_MPI +#if SOC_ECDSA_USES_MPI MPI_RCC_ATOMIC() { mpi_ll_enable_bus_clock(false); } @@ -96,8 +110,9 @@ static void esp_ecdsa_release_hardware(void) esp_crypto_ecdsa_lock_release(); } +#endif /* SOC_ECDSA_SUPPORTED */ -static void ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) +static void __attribute__((unused)) ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) { /* When the size is 24 bytes, it should be padded with 0 bytes*/ memset(le_point, 0x0, 32); @@ -107,7 +122,7 @@ static void ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t l } } -#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY +#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk) { int ret = -1; @@ -181,7 +196,31 @@ cleanup: } #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ -#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN +static int validate_ecdsa_pk_input(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf) +{ + int ret = -1; + + if (!key_ctx) { + ESP_LOGE(TAG, "mbedtls_pk_context cannot be NULL"); + return ret; + } + + if (!conf) { + ESP_LOGE(TAG, "esp_ecdsa_pk_conf_t cannot be NULL"); + return ret; + } + + if (conf->grp_id != MBEDTLS_ECP_DP_SECP192R1 && conf->grp_id != MBEDTLS_ECP_DP_SECP256R1) { + ESP_LOGE(TAG, "Invalid EC curve group id mentioned in esp_ecdsa_pk_conf_t"); + return ret; + } + + return 0; +} +#endif + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk) { if (!key) { @@ -247,25 +286,18 @@ int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *c { int ret = -1; int efuse_key_block = -1; + + ret = validate_ecdsa_pk_input(key_ctx, conf); + if (ret != 0) { + return ret; + } + if (conf->use_km_key) { efuse_key_block = USE_ECDSA_KEY_FROM_KEY_MANAGER; } else { efuse_key_block = conf->efuse_block; } - if (!key_ctx) { - ESP_LOGE(TAG, "mbedtls_pk_context cannot be NULL"); - return ret; - } - if (!conf) { - ESP_LOGE(TAG, "esp_ecdsa_pk_conf_t cannot be NULL"); - return ret; - } - - if (conf->grp_id != MBEDTLS_ECP_DP_SECP192R1 && conf->grp_id != MBEDTLS_ECP_DP_SECP256R1) { - ESP_LOGE(TAG, "Invalid EC curve group id mentioned in esp_ecdsa_pk_conf_t"); - return ret; - } if ((ret = esp_ecdsa_privkey_load_pk_context(key_ctx, efuse_key_block)) != 0) { ESP_LOGE(TAG, "Loading private key context failed, esp_ecdsa_privkey_load_pk_context() returned %d", ret); @@ -278,7 +310,7 @@ int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *c return ret; } -#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY +#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY if (conf->load_pubkey) { if ((ret = esp_ecdsa_load_pubkey(keypair, efuse_key_block)) != 0) { ESP_LOGE(TAG, "Loading public key context failed, esp_ecdsa_load_pubkey() returned %d", ret); @@ -390,7 +422,138 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s return 0; } +#endif + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN +int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, int slot_id) +{ + int ret = -1; + uint16_t len; + esp_tee_sec_storage_type_t key_type; + + if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) { + len = 32; + key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; + } else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP192R1) { + len = 24; + key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1; + } else { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + esp_tee_sec_storage_pubkey_t pubkey = {}; + if (esp_tee_sec_storage_get_pubkey(slot_id, key_type, &pubkey) != ESP_OK) { + ESP_LOGE(TAG, "Failed to get public key from secure storage"); + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), pubkey.pub_x, len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), pubkey.pub_y, len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z)), 1)); + + return 0; + +cleanup: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +} + +int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf) +{ + int ret = -1; + + ret = validate_ecdsa_pk_input(key_ctx, conf); + if (ret != 0) { + ESP_LOGE(TAG, "Invalid input, validate_input() returned %d", ret); + return ret; + } + + if (!conf->use_tee_sec_stg_key) { + ESP_LOGE(TAG, "Invalid esp_ecdsa_pk_conf_t configuration"); + return ret; + } + + int slot_id = conf->tee_slot_id; + if (slot_id < MIN_SEC_STG_SLOT_ID || slot_id > MAX_SEC_STG_SLOT_ID) { + ESP_LOGE(TAG, "Invalid slot id"); + return ret; + } + + const mbedtls_pk_info_t *pk_info; + mbedtls_ecp_keypair *keypair; + + mbedtls_pk_init(key_ctx); + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); + mbedtls_pk_setup(key_ctx, pk_info); + keypair = mbedtls_pk_ec(*key_ctx); + + mbedtls_mpi_init(&(keypair->MBEDTLS_PRIVATE(d))); + keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) = ECDSA_KEY_MAGIC_TEE; + keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(n) = slot_id; + keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) = NULL; + + if ((ret = mbedtls_ecp_group_load(&(keypair->MBEDTLS_PRIVATE(grp)), conf->grp_id)) != 0) { + ESP_LOGE(TAG, "Loading ecp group failed, mbedtls_pk_ec() returned %d", ret); + return ret; + } + + if (conf->load_pubkey) { + if ((ret = esp_ecdsa_tee_load_pubkey(keypair, slot_id)) != 0) { + ESP_LOGE(TAG, "Loading public key context failed, esp_ecdsa_load_pubkey() returned %d", ret); + return ret; + } + } + + return 0; +} + +static int esp_ecdsa_tee_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s, + const mbedtls_mpi *d, const unsigned char* msg, size_t msg_len, + ecdsa_sign_type_t k_type) +{ + uint16_t len; + esp_tee_sec_storage_type_t key_type; + + if (!grp || !r || !s || !d || !msg) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (msg_len != ECDSA_SHA_LEN) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { + len = 32; + key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; + } else if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { + len = 24; + key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1; + } else { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (k_type != ECDSA_K_TYPE_TRNG) { + ESP_LOGE(TAG, "ECDSA deterministic mode not supported"); + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + int slot_id = d->MBEDTLS_PRIVATE(n); + + esp_tee_sec_storage_sign_t sign = {}; + esp_err_t err = esp_tee_sec_storage_get_signature(slot_id, key_type, (uint8_t *)msg, msg_len, &sign); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to get signature"); + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + mbedtls_mpi_read_binary(r, sign.sign_r, len); + mbedtls_mpi_read_binary(s, sign.sign_s, len); + + return 0; +} +#endif + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN /* * Compute ECDSA signature of a hashed message; */ @@ -409,12 +572,22 @@ int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mp /* * Check `d` whether it contains the hardware key */ - if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + signed short key_magic = d->MBEDTLS_PRIVATE(s); +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN + if (key_magic == ECDSA_KEY_MAGIC) { // Use hardware ECDSA peripheral return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); - } else { - return __real_mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, f_rng, p_rng); } +#endif +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + if (key_magic == ECDSA_KEY_MAGIC_TEE) { + // Use TEE secure storage + return esp_ecdsa_tee_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); + } +#endif + + // Fallback to software implementation + return __real_mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, f_rng, p_rng); } extern int __real_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, @@ -438,12 +611,22 @@ int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r /* * Check `d` whether it contains the hardware key */ - if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + signed short key_magic = d->MBEDTLS_PRIVATE(s); +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN + if (key_magic == ECDSA_KEY_MAGIC) { // Use hardware ECDSA peripheral return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); - } else { - return __real_mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, f_rng, p_rng, f_rng_blind, p_rng_blind, rs_ctx); } +#endif +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + if (key_magic == ECDSA_KEY_MAGIC_TEE) { + // Use TEE secure storage + return esp_ecdsa_tee_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); + } +#endif + + // Fallback to software implementation + return __real_mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, f_rng, p_rng, f_rng_blind, p_rng_blind, rs_ctx); } #ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE @@ -572,7 +755,9 @@ int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx) { - if (ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) != ECDSA_KEY_MAGIC) { + signed short key_magic = ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s); + + if (key_magic != ECDSA_KEY_MAGIC && key_magic != ECDSA_KEY_MAGIC_TEE) { return __real_mbedtls_ecdsa_write_signature_restartable(ctx, md_alg, hash, hlen, sig, sig_size, slen, f_rng, p_rng, rs_ctx); } @@ -582,17 +767,27 @@ int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); +#if defined(SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE) && defined(CONFIG_MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_sign_type_t k_type = ECDSA_K_TYPE_DETERMINISITIC; +#else + ecdsa_sign_type_t k_type = ECDSA_K_TYPE_TRNG; +#endif + /* * Check `d` whether it contains the hardware key */ - if (ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN + if (key_magic == ECDSA_KEY_MAGIC) { // Use hardware ECDSA peripheral -#if defined(SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE) && defined(CONFIG_MBEDTLS_ECDSA_DETERMINISTIC) - MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, ECDSA_K_TYPE_DETERMINISITIC)); -#else - MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, ECDSA_K_TYPE_TRNG)); -#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, k_type)); } +#endif +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + if (key_magic == ECDSA_KEY_MAGIC_TEE) { + // Use TEE secure storage + MBEDTLS_MPI_CHK(esp_ecdsa_tee_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, k_type)); + } +#endif MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); @@ -621,7 +816,7 @@ int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, ctx, md_alg, hash, hlen, sig, sig_size, slen, f_rng, p_rng, NULL); } -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */ #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY static int esp_ecdsa_verify(mbedtls_ecp_group *grp, diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h index 637617a70c..aef572c1c5 100644 --- a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h +++ b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,13 +27,20 @@ extern "C" { */ typedef struct { mbedtls_ecp_group_id grp_id; /*!< MbedTLS ECP group identifier */ - uint8_t efuse_block; /*!< EFuse block id for ECDSA private key */ -#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY + union { + uint8_t efuse_block; /*!< EFuse block id for ECDSA private key */ + uint8_t tee_slot_id; /*!< TEE secure storage slot id for ECDSA private key */ + }; /*!< Union to hold either EFuse block id or TEE secure storage slot id for ECDSA private key */ +#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN bool load_pubkey; /*!< Export ECDSA public key from the hardware */ #endif bool use_km_key; /*!< Use key deployed in the key manager for ECDSA operation. Note: The key must be already deployed by the application and it must be activated for the lifetime of this context */ +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + bool use_tee_sec_stg_key; /*!< Use key deployed in the TEE secure storage for ECDSA operation. + Note: The key must be already deployed by the application and it must be activated for the lifetime of this context */ +#endif } esp_ecdsa_pk_conf_t; //TODO: IDF-9008 (Add a config to select the ecdsa key from the key manager peripheral) #if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || __DOXYGEN__ @@ -106,6 +113,38 @@ int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *c #endif // CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || __DOXYGEN__ +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN || __DOXYGEN__ + +/** + * @brief Populate the public key buffer of the mbedtls_ecp_keypair context from + * the TEE secure storage. + * + * @param keypair The mbedtls ECP key-pair structure + * @param slot_id The TEE secure storage slot id that holds the private key. + * + * @return - 0 if successful else MBEDTLS_ERR_ECP_BAD_INPUT_DATA + */ +int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, int slot_id); + +/** + * @brief Initialize PK context and fully populate the mbedtls_ecp_keypair context. + * This function modifies the MPI struct used to represent the private key `d` + * in the ECP keypair to differentiate between TEE secure storage keys and software keys. + * It also populates the ECP group field in the mbedtls_ecp_keypair context. + * Additionally, if the load_pubkey flag is set in the esp_ecdsa_pk_conf_t config argument, + * the public key buffer of the mbedtls_ecp_keypair context will be populated. + * + * @param key_ctx The context in which this function stores the TEE secure storage context. + * This must be uninitialized. + * @param conf ESP-ECDSA private key context initialization config structure. + * + * @return - 0 if successful + * - -1 otherwise + */ +int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf); + +#endif // CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN || __DOXYGEN__ + #ifdef __cplusplus } #endif diff --git a/examples/security/tee/tee_attestation/sdkconfig.defaults b/examples/security/tee/tee_attestation/sdkconfig.defaults index 8fb9806965..f5c31a41d7 100644 --- a/examples/security/tee/tee_attestation/sdkconfig.defaults +++ b/examples/security/tee/tee_attestation/sdkconfig.defaults @@ -2,3 +2,4 @@ CONFIG_SECURE_ENABLE_TEE=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y +CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN=n diff --git a/examples/security/tee/tee_basic/sdkconfig.defaults b/examples/security/tee/tee_basic/sdkconfig.defaults index ed1842d64c..4c3a898568 100644 --- a/examples/security/tee/tee_basic/sdkconfig.defaults +++ b/examples/security/tee/tee_basic/sdkconfig.defaults @@ -2,3 +2,4 @@ CONFIG_SECURE_ENABLE_TEE=y CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y CONFIG_SECURE_TEE_ATTESTATION=n +CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN=n diff --git a/examples/security/tee/tee_secure_ota/sdkconfig.defaults b/examples/security/tee/tee_secure_ota/sdkconfig.defaults index 8fb9806965..f5c31a41d7 100644 --- a/examples/security/tee/tee_secure_ota/sdkconfig.defaults +++ b/examples/security/tee/tee_secure_ota/sdkconfig.defaults @@ -2,3 +2,4 @@ CONFIG_SECURE_ENABLE_TEE=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y +CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN=n