Merge branch 'feature/ecdsa_op_w_tee_sec_stg' into 'master'

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

Closes IDF-12183

See merge request espressif/esp-idf!37217
This commit is contained in:
Mahavir Jain
2025-04-04 12:47:53 +08:00
20 changed files with 588 additions and 113 deletions

View File

@@ -91,6 +91,12 @@ menu "ESP-TEE (Trusted Execution Environment)"
help help
eFuse block ID storing the TEE secure storage encryption key eFuse block ID storing the TEE secure storage encryption key
config SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
bool "Secure Storage: Support signing with the ECDSA SECP192R1 curve"
default n
help
Enable ECDSA signing with the SECP192R1 curve using the TEE secure storage.
config SECURE_TEE_ATTESTATION config SECURE_TEE_ATTESTATION
bool "Enable Attestation" bool "Enable Attestation"
default y default y

View File

@@ -248,11 +248,11 @@ secure_services:
- id: 177 - id: 177
type: custom type: custom
function: esp_tee_sec_storage_get_signature function: esp_tee_sec_storage_get_signature
args: 4 args: 5
- id: 178 - id: 178
type: custom type: custom
function: esp_tee_sec_storage_get_pubkey function: esp_tee_sec_storage_get_pubkey
args: 2 args: 3
- id: 179 - id: 179
type: custom type: custom
function: esp_tee_sec_storage_encrypt function: esp_tee_sec_storage_encrypt

View File

@@ -60,7 +60,7 @@ static esp_err_t gen_ecdsa_keypair_secp256r1(esp_att_ecdsa_keypair_t *keypair)
} }
} }
err = esp_tee_sec_storage_get_pubkey(slot_id, &pubkey); err = esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch ECDSA pubkey (%d)", err); ESP_LOGE(TAG, "Failed to fetch ECDSA pubkey (%d)", err);
return err; return err;
@@ -84,7 +84,7 @@ static esp_err_t get_ecdsa_sign_secp256r1(const esp_att_ecdsa_keypair_t *keypair
} }
esp_tee_sec_storage_sign_t sign = {}; esp_tee_sec_storage_sign_t sign = {};
esp_err_t err = esp_tee_sec_storage_get_signature(ESP_ATT_TK_KEY_ID, (uint8_t *)digest, len, &sign); esp_err_t err = esp_tee_sec_storage_get_signature(ESP_ATT_TK_KEY_ID, ESP_SEC_STG_KEY_ECDSA_SECP256R1, (uint8_t *)digest, len, &sign);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }

View File

@@ -25,7 +25,8 @@ extern "C" {
*/ */
typedef enum { typedef enum {
ESP_SEC_STG_KEY_ECDSA_SECP256R1 = 0, ESP_SEC_STG_KEY_ECDSA_SECP256R1 = 0,
ESP_SEC_STG_KEY_AES256, ESP_SEC_STG_KEY_AES256 = 1,
ESP_SEC_STG_KEY_ECDSA_SECP192R1 = 2,
ESP_SEC_STG_MAX, ESP_SEC_STG_MAX,
} esp_tee_sec_storage_type_t; } esp_tee_sec_storage_type_t;
@@ -71,23 +72,25 @@ esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type
* the key pair located in the given secure storage slot. * the key pair located in the given secure storage slot.
* *
* @param[in] slot_id secure storage slot ID * @param[in] slot_id secure storage slot ID
* @param[in] key_type secure storage key type
* @param[in] hash Message digest * @param[in] hash Message digest
* @param[in] hlen Digest length * @param[in] hlen Digest length
* @param[out] out_sign Output context holding the signature * @param[out] out_sign Output context holding the signature
* *
* @return esp_err_t ESP_OK on success, appropriate error code otherwise. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign); esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign);
/** /**
* @brief Return the public key for the given secure storage slot * @brief Return the public key for the given secure storage slot
* *
* @param[in] slot_id secure storage slot ID * @param[in] slot_id secure storage slot ID
* @param[in] key_type secure storage key type
* @param[out] pubkey Output context holding the public key * @param[out] pubkey Output context holding the public key
* *
* @return esp_err_t ESP_OK on success, appropriate error code otherwise. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_pubkey_t *pubkey); esp_err_t esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, esp_tee_sec_storage_pubkey_t *pubkey);
/** /**
* @brief Check whether the given slot in the secure storage is empty or not * @brief Check whether the given slot in the secure storage is empty or not

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -40,6 +40,7 @@
#define AES256_GCM_AAD_LEN 16 #define AES256_GCM_AAD_LEN 16
#define ECDSA_SECP256R1_KEY_LEN 32 #define ECDSA_SECP256R1_KEY_LEN 32
#define ECDSA_SECP192R1_KEY_LEN 24
/* Structure to hold metadata for secure storage slots */ /* Structure to hold metadata for secure storage slots */
typedef struct { typedef struct {
@@ -58,6 +59,12 @@ typedef struct {
uint8_t pub_key[2 * ECDSA_SECP256R1_KEY_LEN]; /* Public key for ECDSA SECP256R1 (X and Y coordinates) */ uint8_t pub_key[2 * ECDSA_SECP256R1_KEY_LEN]; /* Public key for ECDSA SECP256R1 (X and Y coordinates) */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_ecdsa_secp256r1_t; } __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_ecdsa_secp256r1_t;
/* Structure to hold ECDSA SECP192R1 key pair */
typedef struct {
uint8_t priv_key[ECDSA_SECP192R1_KEY_LEN]; /* Private key for ECDSA SECP192R1 */
uint8_t pub_key[2 * ECDSA_SECP192R1_KEY_LEN]; /* Public key for ECDSA SECP192R1 (X and Y coordinates) */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_ecdsa_secp192r1_t;
/* Structure to hold AES-256 GCM key and IV */ /* Structure to hold AES-256 GCM key and IV */
typedef struct { typedef struct {
uint8_t key[AES256_GCM_KEY_LEN]; /* Key for AES-256 GCM */ uint8_t key[AES256_GCM_KEY_LEN]; /* Key for AES-256 GCM */
@@ -67,6 +74,7 @@ typedef struct {
/* Union to hold different types of cryptographic keys */ /* Union to hold different types of cryptographic keys */
typedef union { typedef union {
sec_stg_ecdsa_secp256r1_t ecdsa_secp256r1; /* ECDSA SECP256R1 key pair */ sec_stg_ecdsa_secp256r1_t ecdsa_secp256r1; /* ECDSA SECP256R1 key pair */
sec_stg_ecdsa_secp192r1_t ecdsa_secp192r1; /* ECDSA SECP192R1 key pair */
sec_stg_aes256_gcm_t aes256_gcm; /* AES-256 GCM key and IV */ sec_stg_aes256_gcm_t aes256_gcm; /* AES-256 GCM key and IV */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_key_t; } __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_key_t;
@@ -348,39 +356,69 @@ esp_err_t esp_tee_sec_storage_init(void)
return ESP_OK; return ESP_OK;
} }
static int generate_ecdsa_secp256r1_key(sec_stg_key_t *keyctx) static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t key_type)
{ {
if (keyctx == NULL) { if (keyctx == NULL) {
return -1; return -1;
} }
ESP_LOGI(TAG, "Generating ECDSA-SECP256R1 private key..."); mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_SECP256R1;
size_t key_len = ECDSA_SECP256R1_KEY_LEN;
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
curve_id = MBEDTLS_ECP_DP_SECP192R1;
key_len = ECDSA_SECP192R1_KEY_LEN;
#else
ESP_LOGE(TAG, "Unsupported key type!");
return -1;
#endif
}
ESP_LOGI(TAG, "Generating ECDSA key for curve %d...", curve_id);
mbedtls_ecdsa_context ctxECDSA; mbedtls_ecdsa_context ctxECDSA;
mbedtls_ecdsa_init(&ctxECDSA); mbedtls_ecdsa_init(&ctxECDSA);
int ret = mbedtls_ecdsa_genkey(&ctxECDSA, MBEDTLS_ECP_DP_SECP256R1, rand_func, NULL); int ret = mbedtls_ecdsa_genkey(&ctxECDSA, curve_id, rand_func, NULL);
if (ret != 0) { if (ret != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA key"); ESP_LOGE(TAG, "Failed to generate ECDSA key");
goto exit; goto exit;
} }
ret = mbedtls_mpi_write_binary(&ctxECDSA.MBEDTLS_PRIVATE(d), keyctx->ecdsa_secp256r1.priv_key, ECDSA_SECP256R1_KEY_LEN); uint8_t *priv_key = (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) ?
keyctx->ecdsa_secp256r1.priv_key :
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
keyctx->ecdsa_secp192r1.priv_key;
#else
NULL;
#endif
uint8_t *pub_key = (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) ?
keyctx->ecdsa_secp256r1.pub_key :
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
keyctx->ecdsa_secp192r1.pub_key;
#else
NULL;
#endif
ret = mbedtls_mpi_write_binary(&ctxECDSA.MBEDTLS_PRIVATE(d), priv_key, key_len);
if (ret != 0) { if (ret != 0) {
goto exit; goto exit;
} }
ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), &keyctx->ecdsa_secp256r1.pub_key[0], ECDSA_SECP256R1_KEY_LEN); ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), pub_key, key_len);
if (ret != 0) { if (ret != 0) {
goto exit; goto exit;
} }
ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), &keyctx->ecdsa_secp256r1.pub_key[ECDSA_SECP256R1_KEY_LEN], ECDSA_SECP256R1_KEY_LEN); ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), pub_key + key_len, key_len);
if (ret != 0) { if (ret != 0) {
goto exit; goto exit;
} }
buffer_hexdump("Private key", keyctx->ecdsa_secp256r1.priv_key, sizeof(keyctx->ecdsa_secp256r1.priv_key)); buffer_hexdump("Private key", priv_key, key_len);
buffer_hexdump("Public key", pub_key, key_len * 2);
exit: exit:
mbedtls_ecdsa_free(&ctxECDSA); mbedtls_ecdsa_free(&ctxECDSA);
@@ -418,7 +456,10 @@ esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type
switch (key_type) { switch (key_type) {
case ESP_SEC_STG_KEY_ECDSA_SECP256R1: case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
if (generate_ecdsa_secp256r1_key(&keyctx) != 0) { #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
#endif
if (generate_ecdsa_key(&keyctx, key_type) != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA keypair (%d)", ret); ESP_LOGE(TAG, "Failed to generate ECDSA keypair (%d)", ret);
return ESP_FAIL; return ESP_FAIL;
} }
@@ -437,7 +478,7 @@ esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type
return secure_storage_write(slot_id, (uint8_t *)&keyctx, sizeof(keyctx), key_type); return secure_storage_write(slot_id, (uint8_t *)&keyctx, sizeof(keyctx), key_type);
} }
esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign) esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign)
{ {
if (slot_id > MAX_SEC_STG_SLOT_ID || hash == NULL || out_sign == NULL) { if (slot_id > MAX_SEC_STG_SLOT_ID || hash == NULL || out_sign == NULL) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
@@ -447,9 +488,15 @@ esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, siz
return ESP_ERR_INVALID_SIZE; return ESP_ERR_INVALID_SIZE;
} }
sec_stg_key_t keyctx; #if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
ESP_LOGE(TAG, "Unsupported key type!");
return ESP_ERR_NOT_SUPPORTED;
}
#endif
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(sec_stg_key_t), ESP_SEC_STG_KEY_ECDSA_SECP256R1); sec_stg_key_t keyctx;
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(sec_stg_key_t), key_type);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot"); ESP_LOGE(TAG, "Failed to fetch key from slot");
return err; return err;
@@ -464,7 +511,19 @@ esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, siz
mbedtls_ecp_keypair_init(&priv_key); mbedtls_ecp_keypair_init(&priv_key);
mbedtls_ecdsa_init(&sign_ctx); mbedtls_ecdsa_init(&sign_ctx);
int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &priv_key, keyctx.ecdsa_secp256r1.priv_key, sizeof(keyctx.ecdsa_secp256r1.priv_key)); int ret = -1;
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) {
ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &priv_key, keyctx.ecdsa_secp256r1.priv_key, sizeof(keyctx.ecdsa_secp256r1.priv_key));
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
} else if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP192R1, &priv_key, keyctx.ecdsa_secp192r1.priv_key, sizeof(keyctx.ecdsa_secp192r1.priv_key));
#endif
} else {
ESP_LOGE(TAG, "Unsupported key type for signature generation");
err = ESP_ERR_NOT_SUPPORTED;
goto exit;
}
if (ret != 0) { if (ret != 0) {
err = ESP_FAIL; err = ESP_FAIL;
goto exit; goto exit;
@@ -476,7 +535,7 @@ esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, siz
goto exit; goto exit;
} }
ESP_LOGI(TAG, "Generating ECDSA-SECP256R1 signature..."); ESP_LOGI(TAG, "Generating ECDSA signature...");
ret = mbedtls_ecdsa_sign(&sign_ctx.MBEDTLS_PRIVATE(grp), &r, &s, &sign_ctx.MBEDTLS_PRIVATE(d), hash, hlen, ret = mbedtls_ecdsa_sign(&sign_ctx.MBEDTLS_PRIVATE(grp), &r, &s, &sign_ctx.MBEDTLS_PRIVATE(d), hash, hlen,
rand_func, NULL); rand_func, NULL);
@@ -486,13 +545,21 @@ esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, siz
goto exit; goto exit;
} }
ret = mbedtls_mpi_write_binary(&r, out_sign->sign_r, ECDSA_SECP256R1_KEY_LEN); memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_sign_t));
size_t key_len = (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) ? ECDSA_SECP256R1_KEY_LEN :
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
ECDSA_SECP192R1_KEY_LEN;
#else
0;
#endif
ret = mbedtls_mpi_write_binary(&r, out_sign->sign_r, key_len);
if (ret != 0) { if (ret != 0) {
err = ESP_FAIL; err = ESP_FAIL;
goto exit; goto exit;
} }
ret = mbedtls_mpi_write_binary(&s, out_sign->sign_s, ECDSA_SECP256R1_KEY_LEN); ret = mbedtls_mpi_write_binary(&s, out_sign->sign_s, key_len);
if (ret != 0) { if (ret != 0) {
err = ESP_FAIL; err = ESP_FAIL;
goto exit; goto exit;
@@ -508,22 +575,38 @@ exit:
return err; return err;
} }
esp_err_t esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_pubkey_t *pubkey) esp_err_t esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, esp_tee_sec_storage_pubkey_t *pubkey)
{ {
if (slot_id > MAX_SEC_STG_SLOT_ID || pubkey == NULL) { if (slot_id > MAX_SEC_STG_SLOT_ID || pubkey == NULL) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
sec_stg_key_t keyctx; sec_stg_key_t keyctx;
size_t key_len;
uint8_t *pub_key_src;
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(sec_stg_key_t), ESP_SEC_STG_KEY_ECDSA_SECP256R1); if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) {
key_len = ECDSA_SECP256R1_KEY_LEN;
pub_key_src = keyctx.ecdsa_secp256r1.pub_key;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
} else if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
key_len = ECDSA_SECP192R1_KEY_LEN;
pub_key_src = keyctx.ecdsa_secp192r1.pub_key;
#endif
} else {
ESP_LOGE(TAG, "Unsupported key type");
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(sec_stg_key_t), key_type);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot"); ESP_LOGE(TAG, "Failed to fetch key from slot");
return err; return err;
} }
memcpy(pubkey->pub_x, &keyctx.ecdsa_secp256r1.pub_key[0], ECDSA_SECP256R1_KEY_LEN); // Copy public key components in one shot
memcpy(pubkey->pub_y, &keyctx.ecdsa_secp256r1.pub_key[ECDSA_SECP256R1_KEY_LEN], ECDSA_SECP256R1_KEY_LEN); memcpy(pubkey->pub_x, pub_key_src, key_len);
memcpy(pubkey->pub_y, pub_key_src + key_len, key_len);
return ESP_OK; return ESP_OK;
} }
@@ -618,7 +701,7 @@ static esp_err_t tee_sec_storage_crypt_common(uint16_t slot_id, uint8_t *input,
} }
sec_stg_key_t keyctx; sec_stg_key_t keyctx;
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(keyctx), 1); esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(keyctx), ESP_SEC_STG_KEY_AES256);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot"); ESP_LOGE(TAG, "Failed to fetch key from slot");
return err; return err;

View File

@@ -18,14 +18,14 @@ esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type
return esp_tee_service_call_with_noniram_intr_disabled(3, SS_ESP_TEE_SEC_STORAGE_GEN_KEY, slot_id, key_type); return esp_tee_service_call_with_noniram_intr_disabled(3, SS_ESP_TEE_SEC_STORAGE_GEN_KEY, slot_id, key_type);
} }
esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *sign) esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *sign)
{ {
return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_GET_SIGNATURE, slot_id, hash, hlen, sign); return esp_tee_service_call_with_noniram_intr_disabled(6, SS_ESP_TEE_SEC_STORAGE_GET_SIGNATURE, slot_id, key_type, hash, hlen, sign);
} }
esp_err_t esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_pubkey_t *pubkey) esp_err_t esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, esp_tee_sec_storage_pubkey_t *pubkey)
{ {
return esp_tee_service_call_with_noniram_intr_disabled(3, SS_ESP_TEE_SEC_STORAGE_GET_PUBKEY, slot_id, pubkey); return esp_tee_service_call_with_noniram_intr_disabled(4, SS_ESP_TEE_SEC_STORAGE_GET_PUBKEY, slot_id, key_type, pubkey);
} }
bool esp_tee_sec_storage_is_slot_empty(uint16_t slot_id) bool esp_tee_sec_storage_is_slot_empty(uint16_t slot_id)

View File

@@ -368,7 +368,7 @@ esp_err_t _ss_esp_tee_sec_storage_gen_key(uint16_t slot_id, uint8_t key_type)
return esp_tee_sec_storage_gen_key(slot_id, key_type); return esp_tee_sec_storage_gen_key(slot_id, key_type);
} }
esp_err_t _ss_esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign) esp_err_t _ss_esp_tee_sec_storage_get_signature(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign)
{ {
bool valid_addr = ((esp_tee_ptr_in_ree((void *)hash) && esp_tee_ptr_in_ree((void *)out_sign)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)hash) && esp_tee_ptr_in_ree((void *)out_sign)) &
(esp_tee_ptr_in_ree((void *)(hash + hlen)) && (esp_tee_ptr_in_ree((void *)(hash + hlen)) &&
@@ -379,10 +379,10 @@ esp_err_t _ss_esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash,
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_get_signature(slot_id, hash, hlen, out_sign); return esp_tee_sec_storage_get_signature(slot_id, key_type, hash, hlen, out_sign);
} }
esp_err_t _ss_esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_pubkey_t *pubkey) esp_err_t _ss_esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_type_t key_type, esp_tee_sec_storage_pubkey_t *pubkey)
{ {
bool valid_addr = ((esp_tee_ptr_in_ree((void *)pubkey)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)pubkey)) &
(esp_tee_ptr_in_ree((void *)((char *)pubkey + sizeof(esp_tee_sec_storage_pubkey_t))))); (esp_tee_ptr_in_ree((void *)((char *)pubkey + sizeof(esp_tee_sec_storage_pubkey_t)))));
@@ -392,7 +392,7 @@ esp_err_t _ss_esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_stora
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_get_pubkey(slot_id, pubkey); return esp_tee_sec_storage_get_pubkey(slot_id, key_type, pubkey);
} }
esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,

View File

@@ -289,7 +289,7 @@ static int tee_sec_stg_sign(int argc, char **argv)
} }
esp_tee_sec_storage_sign_t sign = {}; esp_tee_sec_storage_sign_t sign = {};
err = esp_tee_sec_storage_get_signature(slot_id, digest, sizeof(digest), &sign); err = esp_tee_sec_storage_get_signature(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, digest, sizeof(digest), &sign);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to generate signature!"); ESP_LOGE(TAG, "Failed to generate signature!");
goto exit; goto exit;
@@ -307,7 +307,7 @@ static int tee_sec_stg_sign(int argc, char **argv)
free(sign_hexstr); free(sign_hexstr);
esp_tee_sec_storage_pubkey_t pubkey = {}; esp_tee_sec_storage_pubkey_t pubkey = {};
err = esp_tee_sec_storage_get_pubkey(slot_id, &pubkey); err = esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch public-key!"); ESP_LOGE(TAG, "Failed to fetch public-key!");
goto exit; goto exit;

View File

@@ -36,7 +36,7 @@
static const char *TAG = "test_esp_tee_att"; static const char *TAG = "test_esp_tee_att";
extern int verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign); extern int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign, bool is_crv_p192);
static uint8_t hexchar_to_byte(char hex) static uint8_t hexchar_to_byte(char hex)
{ {
@@ -277,7 +277,7 @@ TEST_CASE("Test TEE Attestation - Generate and verify the EAT", "[attestation]")
ESP_LOGI(TAG, "Verifying the generated EAT..."); ESP_LOGI(TAG, "Verifying the generated EAT...");
// Verifying the generated token // Verifying the generated token
TEST_ASSERT_EQUAL(0, verify_ecdsa_secp256r1_sign(digest, sizeof(digest), &pubkey_ctx, &sign_ctx)); TEST_ASSERT_EQUAL(0, verify_ecdsa_sign(digest, sizeof(digest), &pubkey_ctx, &sign_ctx, false));
free(token_buf); free(token_buf);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -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"
@@ -20,6 +21,7 @@
#include "esp_random.h" #include "esp_random.h"
#include "unity.h" #include "unity.h"
#include "sdkconfig.h"
/* Note: negative value here so that assert message prints a grep-able /* Note: negative value here so that assert message prints a grep-able
error hex value (mbedTLS uses -N for error codes) */ error hex value (mbedTLS uses -N for error codes) */
@@ -27,11 +29,16 @@
#define SHA256_DIGEST_SZ (32) #define SHA256_DIGEST_SZ (32)
#define ECDSA_SECP256R1_KEY_LEN (32) #define ECDSA_SECP256R1_KEY_LEN (32)
#define ECDSA_SECP192R1_KEY_LEN (24)
static const char *TAG = "test_esp_tee_sec_storage"; static const char *TAG = "test_esp_tee_sec_storage";
int verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign) int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign, bool is_crv_p192)
{ {
#if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
TEST_ASSERT_FALSE(is_crv_p192);
#endif
TEST_ASSERT_NOT_NULL(pubkey); TEST_ASSERT_NOT_NULL(pubkey);
TEST_ASSERT_NOT_NULL(digest); TEST_ASSERT_NOT_NULL(digest);
TEST_ASSERT_NOT_NULL(sign); TEST_ASSERT_NOT_NULL(sign);
@@ -44,7 +51,12 @@ int verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee
mbedtls_ecdsa_context ecdsa_context; mbedtls_ecdsa_context ecdsa_context;
mbedtls_ecdsa_init(&ecdsa_context); mbedtls_ecdsa_init(&ecdsa_context);
TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1)); mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_SECP256R1;
if (is_crv_p192) {
curve_id = MBEDTLS_ECP_DP_SECP192R1;
}
TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), curve_id));
size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P); size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P);
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&r, sign->sign_r, plen)); TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&r, sign->sign_r, plen));
@@ -81,19 +93,54 @@ TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp256r1) with all key-
TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1)); TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1));
esp_tee_sec_storage_sign_t sign = {}; esp_tee_sec_storage_sign_t sign = {};
TEST_ESP_OK(esp_tee_sec_storage_get_signature(slot_id, msg_digest, sizeof(msg_digest), &sign)); TEST_ESP_OK(esp_tee_sec_storage_get_signature(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, msg_digest, sizeof(msg_digest), &sign));
esp_tee_sec_storage_pubkey_t pubkey = {}; esp_tee_sec_storage_pubkey_t pubkey = {};
TEST_ESP_OK(esp_tee_sec_storage_get_pubkey(slot_id, &pubkey)); TEST_ESP_OK(esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey));
ESP_LOGI(TAG, "Verifying generated signature..."); ESP_LOGI(TAG, "Verifying generated signature...");
TEST_ESP_OK(verify_ecdsa_secp256r1_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign)); TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, false));
TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id));
TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id)); TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id));
} }
} }
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp192r1) with all key-slot IDs", "[secure_storage]")
{
const size_t buf_sz = 16 * 1024 + 6; // NOTE: Not an exact multiple of SHA block size
unsigned char *message = heap_caps_malloc(buf_sz, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(message);
esp_fill_random(message, buf_sz);
uint8_t msg_digest[SHA256_DIGEST_SZ];
TEST_ASSERT_MBEDTLS_OK(mbedtls_sha256(message, buf_sz, msg_digest, false));
free(message);
TEST_ESP_OK(esp_tee_sec_storage_init());
for (uint16_t slot_id = 0; slot_id <= MAX_SEC_STG_SLOT_ID; slot_id++) {
ESP_LOGI(TAG, "Slot ID: %u", slot_id);
TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id));
TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP192R1));
esp_tee_sec_storage_sign_t sign = {};
TEST_ESP_OK(esp_tee_sec_storage_get_signature(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP192R1, msg_digest, sizeof(msg_digest), &sign));
esp_tee_sec_storage_pubkey_t pubkey = {};
TEST_ESP_OK(esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP192R1, &pubkey));
ESP_LOGI(TAG, "Verifying generated signature...");
TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, true));
TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id));
TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id));
}
}
#endif
TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm) with all key-slot IDs", "[secure_storage]") TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm) with all key-slot IDs", "[secure_storage]")
{ {
const uint8_t SZ = 100; const uint8_t SZ = 100;
@@ -161,7 +208,9 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys",
const uint16_t slot_id = 7; const uint16_t slot_id = 7;
ESP_LOGI(TAG, "Slot ID: %u - Trying AES operation with ECDSA key...", slot_id); ESP_LOGI(TAG, "Slot ID: %u - Trying AES operation with ECDSA key...", slot_id);
TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id));
TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1));
esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;
TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, key_type));
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_encrypt(slot_id, plaintext, SZ, aad, sizeof(aad), TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_encrypt(slot_id, plaintext, SZ, aad, sizeof(aad),
tag, sizeof(tag), ciphertext)); tag, sizeof(tag), ciphertext));
@@ -172,7 +221,7 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys",
TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_AES256)); TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_AES256));
esp_tee_sec_storage_sign_t sign = {}; esp_tee_sec_storage_sign_t sign = {};
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_get_signature(slot_id, msg_digest, sizeof(msg_digest), &sign)); TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_get_signature(slot_id, key_type, msg_digest, sizeof(msg_digest), &sign));
TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id));
TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id)); TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id));
@@ -242,14 +291,16 @@ TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[secure_sto
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_decrypt(slot_id, data, sizeof(data), NULL, 0, tag, 0, data)); TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_decrypt(slot_id, data, sizeof(data), NULL, 0, tag, 0, data));
TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id));
TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1));
esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;
TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, key_type));
esp_tee_sec_storage_sign_t sign = {}; esp_tee_sec_storage_sign_t sign = {};
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_signature(slot_id, NULL, sizeof(data), &sign)); TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_signature(slot_id, key_type, NULL, sizeof(data), &sign));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_get_signature(slot_id, data, 0, &sign)); TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_get_signature(slot_id, key_type, data, 0, &sign));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_signature(slot_id, data, sizeof(data), NULL)); TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_signature(slot_id, key_type, data, sizeof(data), NULL));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_pubkey(slot_id, NULL)); TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_pubkey(slot_id, key_type, NULL));
TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id));
} }
@@ -272,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

@@ -7,6 +7,8 @@ CONFIG_PARTITION_TABLE_FILENAME="partitions_tee_ota.csv"
# Increasing Bootloader log verbosity # Increasing Bootloader log verbosity
CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG=y CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG=y
CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN=y
# secure storage key slot for attestation # secure storage key slot for attestation
CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID=14 CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID=14

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

@@ -42,6 +42,7 @@
#define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_BIGNUM_C #define MBEDTLS_BIGNUM_C
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
#define MBEDTLS_ECP_C #define MBEDTLS_ECP_C
#define MBEDTLS_ECDSA_C #define MBEDTLS_ECDSA_C

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

View File

@@ -125,7 +125,7 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter)
} }
esp_tee_sec_storage_sign_t sign = {}; esp_tee_sec_storage_sign_t sign = {};
err = esp_tee_sec_storage_get_signature(KEY_SLOT_ID, msg_digest, sizeof(msg_digest), &sign); err = esp_tee_sec_storage_get_signature(KEY_SLOT_ID, ESP_SEC_STG_KEY_ECDSA_SECP256R1, msg_digest, sizeof(msg_digest), &sign);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to generate signature!"); ESP_LOGE(TAG, "Failed to generate signature!");
goto exit; goto exit;
@@ -134,7 +134,7 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter)
ESP_LOG_BUFFER_HEX("Signature", &sign, sizeof(sign)); ESP_LOG_BUFFER_HEX("Signature", &sign, sizeof(sign));
esp_tee_sec_storage_pubkey_t pubkey = {}; esp_tee_sec_storage_pubkey_t pubkey = {};
err = esp_tee_sec_storage_get_pubkey(KEY_SLOT_ID, &pubkey); err = esp_tee_sec_storage_get_pubkey(KEY_SLOT_ID, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch public-key!"); ESP_LOGE(TAG, "Failed to fetch public-key!");
goto exit; goto exit;