feat(mbedtls): Add support for ECDSA signing with TEE secure storage

This commit is contained in:
Laukik Hase
2025-02-13 14:22:30 +05:30
parent 1e8933d296
commit 3fd107aa04
8 changed files with 388 additions and 58 deletions

View File

@@ -12,6 +12,7 @@
#include "mbedtls/ecp.h" #include "mbedtls/ecp.h"
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
#include "ecdsa/ecdsa_alt.h"
#include "esp_tee.h" #include "esp_tee.h"
#include "esp_tee_sec_storage.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"); TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
} }
#endif #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

View File

@@ -294,27 +294,40 @@ if(CONFIG_MBEDTLS_HARDWARE_ECC)
"${COMPONENT_DIR}/port/ecc/ecc_alt.c") "${COMPONENT_DIR}/port/ecc/ecc_alt.c")
endif() endif()
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) 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") target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/ecdsa/ecdsa_alt.c")
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) set(WRAP_FUNCTIONS_SIGN
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign") mbedtls_ecdsa_sign
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_restartable") mbedtls_ecdsa_sign_restartable
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature") mbedtls_ecdsa_write_signature
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature_restartable") 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) 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_ext")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_det_restartable") target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_det_restartable")
endif() endif()
endif() endif()
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_verify") foreach(wrap ${WRAP_FUNCTIONS_VERIFY})
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_verify_restartable") target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_read_signature") endforeach()
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_read_signature_restartable") endif()
if(CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN)
target_link_libraries(mbedcrypto PRIVATE idf::tee_sec_storage)
endif() endif()
endif() endif()

View File

@@ -584,6 +584,11 @@ menu "mbedTLS"
The key should be burnt in little endian format. espefuse.py utility handles it internally 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 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" menu "Enable Software Countermeasure for ECDSA signing using on-chip ECDSA peripheral"
depends on MBEDTLS_HARDWARE_ECDSA_SIGN depends on MBEDTLS_HARDWARE_ECDSA_SIGN
depends on IDF_TARGET_ESP32H2 depends on IDF_TARGET_ESP32H2

View File

@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <string.h> #include <string.h>
#include "hal/ecc_ll.h"
#include "hal/ecdsa_ll.h" #include "esp_err.h"
#include "hal/ecdsa_hal.h" #include "esp_log.h"
#ifdef SOC_MPI_SUPPORTED
#include "hal/mpi_ll.h" #include "hal/ecdsa_types.h"
#endif #include "ecdsa/ecdsa_alt.h"
#include "soc/soc_caps.h"
#include "esp_crypto_lock.h" #include "esp_crypto_lock.h"
#include "esp_efuse.h"
#include "esp_private/esp_crypto_lock_internal.h" #include "esp_private/esp_crypto_lock_internal.h"
#include "mbedtls/error.h" #include "mbedtls/error.h"
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#include "mbedtls/asn1.h" #include "mbedtls/asn1.h"
#include "mbedtls/asn1write.h" #include "mbedtls/asn1write.h"
#include "mbedtls/platform_util.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 (short) 0xECD5A
#define ECDSA_KEY_MAGIC_TEE (short) 0xA5DCE
#define ECDSA_SHA_LEN 32 #define ECDSA_SHA_LEN 32
#define MAX_ECDSA_COMPONENT_LEN 32 #define MAX_ECDSA_COMPONENT_LEN 32
@@ -51,6 +64,7 @@
__attribute__((unused)) static const char *TAG = "ecdsa_alt"; __attribute__((unused)) static const char *TAG = "ecdsa_alt";
#if SOC_ECDSA_SUPPORTED
static void esp_ecdsa_acquire_hardware(void) static void esp_ecdsa_acquire_hardware(void)
{ {
esp_crypto_ecdsa_lock_acquire(); esp_crypto_ecdsa_lock_acquire();
@@ -66,7 +80,7 @@ static void esp_ecdsa_acquire_hardware(void)
ecc_ll_reset_register(); ecc_ll_reset_register();
} }
#ifdef SOC_ECDSA_USES_MPI #if SOC_ECDSA_USES_MPI
/* We need to reset the MPI peripheral because ECDSA peripheral /* We need to reset the MPI peripheral because ECDSA peripheral
* of some targets use the MPI peripheral as well. * of some targets use the MPI peripheral as well.
*/ */
@@ -88,7 +102,7 @@ static void esp_ecdsa_release_hardware(void)
ecc_ll_power_down(); ecc_ll_power_down();
} }
#ifdef SOC_ECDSA_USES_MPI #if SOC_ECDSA_USES_MPI
MPI_RCC_ATOMIC() { MPI_RCC_ATOMIC() {
mpi_ll_enable_bus_clock(false); mpi_ll_enable_bus_clock(false);
} }
@@ -96,8 +110,9 @@ static void esp_ecdsa_release_hardware(void)
esp_crypto_ecdsa_lock_release(); 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*/ /* When the size is 24 bytes, it should be padded with 0 bytes*/
memset(le_point, 0x0, 32); 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 esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk)
{ {
int ret = -1; int ret = -1;
@@ -181,7 +196,31 @@ cleanup:
} }
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ #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) int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk)
{ {
if (!key) { 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 ret = -1;
int efuse_key_block = -1; int efuse_key_block = -1;
ret = validate_ecdsa_pk_input(key_ctx, conf);
if (ret != 0) {
return ret;
}
if (conf->use_km_key) { if (conf->use_km_key) {
efuse_key_block = USE_ECDSA_KEY_FROM_KEY_MANAGER; efuse_key_block = USE_ECDSA_KEY_FROM_KEY_MANAGER;
} else { } else {
efuse_key_block = conf->efuse_block; 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) { 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); 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; return ret;
} }
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY #if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
if (conf->load_pubkey) { if (conf->load_pubkey) {
if ((ret = esp_ecdsa_load_pubkey(keypair, efuse_key_block)) != 0) { 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); 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; 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; * 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 * 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 // Use hardware ECDSA peripheral
return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); 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, 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 * 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 // Use hardware ECDSA peripheral
return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); 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 #ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
@@ -572,7 +755,9 @@ int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
void *p_rng, void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx) 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); 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(&r);
mbedtls_mpi_init(&s); 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 * 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 // 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, k_type));
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 */
} }
#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)); 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, ctx, md_alg, hash, hlen, sig, sig_size, slen,
f_rng, p_rng, NULL); 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 #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY
static int esp_ecdsa_verify(mbedtls_ecp_group *grp, static int esp_ecdsa_verify(mbedtls_ecp_group *grp,

View File

@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -27,13 +27,20 @@ extern "C" {
*/ */
typedef struct { typedef struct {
mbedtls_ecp_group_id grp_id; /*!< MbedTLS ECP group identifier */ mbedtls_ecp_group_id grp_id; /*!< MbedTLS ECP group identifier */
uint8_t efuse_block; /*!< EFuse block id for ECDSA private key */ union {
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY 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 */ bool load_pubkey; /*!< Export ECDSA public key from the hardware */
#endif #endif
bool use_km_key; /*!< Use key deployed in the key manager for ECDSA operation. 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 */ 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) } 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__ #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__ #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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -2,3 +2,4 @@
CONFIG_SECURE_ENABLE_TEE=y CONFIG_SECURE_ENABLE_TEE=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y
CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN=n

View File

@@ -2,3 +2,4 @@
CONFIG_SECURE_ENABLE_TEE=y CONFIG_SECURE_ENABLE_TEE=y
CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y
CONFIG_SECURE_TEE_ATTESTATION=n CONFIG_SECURE_TEE_ATTESTATION=n
CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN=n

View File

@@ -2,3 +2,4 @@
CONFIG_SECURE_ENABLE_TEE=y CONFIG_SECURE_ENABLE_TEE=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y
CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN=n