refactor(esp_tee): Update TEE secure storage interface APIs

This commit is contained in:
Laukik Hase
2025-04-30 11:55:54 +05:30
parent c9f7bcd452
commit d116567a66
18 changed files with 481 additions and 610 deletions

View File

@ -72,24 +72,24 @@ menu "ESP-TEE (Trusted Execution Environment)"
config SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
bool "Development"
help
Secure storage will be encrypted by the data stored in eFuse BLK2
Secure storage will be encrypted by a constant key embedded in the TEE firmware
config SECURE_TEE_SEC_STG_MODE_RELEASE
depends on IDF_TARGET_ESP32C6
bool "Release"
help
Secure storage will be encrypted by the data stored in eFuse block
configured through the SECURE_TEE_SEC_STG_KEY_EFUSE_BLK option
configured through the SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID option
endchoice
config SECURE_TEE_SEC_STG_KEY_EFUSE_BLK
int "Secure Storage: Encryption key eFuse block"
config SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID
int "Secure Storage: eFuse HMAC key ID"
depends on SECURE_TEE_SEC_STG_MODE_RELEASE
range 4 10
default 10
range -1 5
default -1
help
eFuse block ID storing the TEE secure storage encryption key
eFuse block key ID storing the HMAC key for deriving the TEE secure storage encryption keys
config SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
bool "Secure Storage: Support signing with the ECDSA SECP192R1 curve"
@ -104,13 +104,12 @@ menu "ESP-TEE (Trusted Execution Environment)"
This configuration enables the support for the Attestation service.
config SECURE_TEE_ATT_KEY_SLOT_ID
config SECURE_TEE_ATT_KEY_STR_ID
depends on SECURE_TEE_ATTESTATION
int "Attestation: Secure Storage slot ID for EAT signing"
default 0
range 0 14
string "Attestation: Secure Storage key ID for EAT signing"
default "tee_att_key0"
help
This configuration sets the slot ID from the TEE secure storage
This configuration sets the key ID from the TEE secure storage
storing the ECDSA keypair for executing sign/verify operations
from the TEE side for attestation.

View File

@ -252,36 +252,28 @@ secure_services:
entries:
- id: 175
type: custom
function: esp_tee_sec_storage_init
args: 0
function: esp_tee_sec_storage_clear_key
args: 1
- id: 176
type: custom
function: esp_tee_sec_storage_gen_key
args: 2
args: 1
- id: 177
type: custom
function: esp_tee_sec_storage_get_signature
args: 5
function: esp_tee_sec_storage_ecdsa_sign
args: 4
- id: 178
type: custom
function: esp_tee_sec_storage_get_pubkey
args: 3
function: esp_tee_sec_storage_ecdsa_get_pubkey
args: 2
- id: 179
type: custom
function: esp_tee_sec_storage_encrypt
args: 8
function: esp_tee_sec_storage_aead_encrypt
args: 4
- id: 180
type: custom
function: esp_tee_sec_storage_decrypt
args: 8
- id: 181
type: custom
function: esp_tee_sec_storage_is_slot_empty
args: 1
- id: 182
type: custom
function: esp_tee_sec_storage_clear_slot
args: 1
function: esp_tee_sec_storage_aead_decrypt
args: 4
# ID: 195-199 (5) - OTA
- family: ota
entries:

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
*/
@ -41,26 +41,23 @@ static esp_err_t gen_ecdsa_keypair_secp256r1(esp_att_ecdsa_keypair_t *keypair)
if (keypair == NULL) {
return ESP_ERR_INVALID_ARG;
}
memset(keypair, 0x00, sizeof(esp_att_ecdsa_keypair_t));
uint16_t slot_id = ESP_ATT_TK_KEY_ID;
esp_tee_sec_storage_pubkey_t pubkey = {0};
esp_tee_sec_storage_key_cfg_t key_cfg = {
.id = (const char *)(ESP_ATT_TK_KEY_ID),
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1,
};
esp_err_t err = esp_tee_sec_storage_init();
if (err != ESP_OK) {
esp_err_t err = esp_tee_sec_storage_gen_key(&key_cfg);
if (err == ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "Using pre-existing key...");
} else if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to generate ECDSA keypair (%d)", err);
return err;
}
if (esp_tee_sec_storage_is_slot_empty(slot_id)) {
err = esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to generate ECDSA keypair (%d)", err);
return err;
}
}
err = esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey);
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
err = esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch ECDSA pubkey (%d)", err);
return err;
@ -83,8 +80,13 @@ static esp_err_t get_ecdsa_sign_secp256r1(const esp_att_ecdsa_keypair_t *keypair
return ESP_ERR_INVALID_SIZE;
}
esp_tee_sec_storage_sign_t 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);
esp_tee_sec_storage_key_cfg_t key_cfg = {
.id = (const char *)(ESP_ATT_TK_KEY_ID),
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1,
};
esp_tee_sec_storage_ecdsa_sign_t sign = {};
esp_err_t err = esp_tee_sec_storage_ecdsa_sign(&key_cfg, (uint8_t *)digest, len, &sign);
if (err != ESP_OK) {
return err;
}

View File

@ -126,7 +126,7 @@ esp_err_t esp_att_utils_header_to_json(const esp_att_token_hdr_t *tk_hdr, char *
json_gen_obj_set_string(&json_gen, "encr_alg", NULL);
json_gen_obj_set_string(&json_gen, "sign_alg", ESP_ATT_TK_SIGN_ALG);
json_gen_obj_set_int(&json_gen, "key_id", ESP_ATT_TK_KEY_ID);
json_gen_obj_set_string(&json_gen, "key_id", ESP_ATT_TK_KEY_ID);
// End the top-level JSON object
json_gen_end_object(&json_gen);

View File

@ -42,9 +42,9 @@ extern "C" {
#define ESP_ATT_TK_MIN_SIZE (ESP_ATT_HDR_JSON_MAX_SZ + ESP_ATT_EAT_JSON_MAX_SZ + ESP_ATT_PUBKEY_JSON_MAX_SZ + ESP_ATT_SIGN_JSON_MAX_SZ)
#if ESP_TEE_BUILD && CONFIG_SECURE_TEE_ATTESTATION
#define ESP_ATT_TK_KEY_ID (CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID)
#define ESP_ATT_TK_KEY_ID (CONFIG_SECURE_TEE_ATT_KEY_STR_ID)
#else
#define ESP_ATT_TK_KEY_ID (-1)
#define ESP_ATT_TK_KEY_ID ("NULL")
#endif
/**

View File

@ -5,7 +5,7 @@ set(priv_requires efuse mbedtls spi_flash)
if(esp_tee_build)
list(APPEND srcs "tee_sec_storage.c")
list(APPEND priv_requires log tee_flash_mgr)
list(APPEND priv_requires esp_partition log nvs_flash tee_flash_mgr)
else()
list(APPEND srcs "tee_sec_storage_wrapper.c")
set(priv_requires esp_tee)

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
*/
@ -12,138 +12,142 @@ extern "C" {
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#define MIN_SEC_STG_SLOT_ID 0 /*!< Minimum secure storage slot ID */
#define MAX_SEC_STG_SLOT_ID 14 /*!< Maximum secure storage slot ID */
#include "esp_err.h"
#include "esp_bit_defs.h"
#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key */
#define MAX_AES_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the AES key */
#define SEC_STORAGE_FLAG_NONE 0 /*!< No flags */
#define SEC_STORAGE_FLAG_WRITE_ONCE BIT(0) /*!< Data can only be written once */
/**
* @brief Enum to represent the type of key stored in the secure storage
*
*/
typedef enum {
ESP_SEC_STG_KEY_ECDSA_SECP256R1 = 0,
ESP_SEC_STG_KEY_AES256 = 1,
ESP_SEC_STG_KEY_AES256 = 0,
ESP_SEC_STG_KEY_ECDSA_SECP256R1 = 1,
ESP_SEC_STG_KEY_ECDSA_SECP192R1 = 2,
ESP_SEC_STG_MAX,
ESP_SEC_STG_TYPE_MAX,
} esp_tee_sec_storage_type_t;
/**
* @brief Structure holding the X and Y components
* of the ECDSA public key
* @brief Configuration structure for key generation/import
*
*/
typedef struct {
const char *id; /*!< Unique identifier for the key */
esp_tee_sec_storage_type_t type; /*!< Type of key (AES256, ECDSA_SECP256R1, etc.) */
uint32_t flags; /*!< Key flags (e.g. WRITE_ONCE) */
} esp_tee_sec_storage_key_cfg_t;
/**
* @brief Context structure for AES-GCM AEAD encryption/decryption operations
*
*/
typedef struct {
const char *key_id; /*!< Identifier of the key to use */
const uint8_t *aad; /*!< Additional authenticated data */
size_t aad_len; /*!< Length of additional authenticated data */
const uint8_t *input; /*!< Input data buffer */
size_t input_len; /*!< Length of input data */
} esp_tee_sec_storage_aead_ctx_t;
/**
* @brief Structure holding the X and Y components of the ECDSA public key
*
*/
typedef struct {
uint8_t pub_x[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< X component */
uint8_t pub_y[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< Y component */
} __attribute__((__packed__)) esp_tee_sec_storage_pubkey_t;
} __attribute__((__packed__)) esp_tee_sec_storage_ecdsa_pubkey_t;
/**
* @brief Structure holding the R and S components
* of the ECDSA signature
* @brief Structure holding the R and S components of the ECDSA signature
*
*/
typedef struct {
uint8_t sign_r[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< R component */
uint8_t sign_s[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< S component */
} __attribute__((__packed__)) esp_tee_sec_storage_sign_t;
} __attribute__((__packed__)) esp_tee_sec_storage_ecdsa_sign_t;
#if ESP_TEE_BUILD && !(__DOXYGEN__)
/**
* @brief Initialize the TEE secure storage partition
* @brief Initialize the secure storage
*
* @note Must be invoked as part of the TEE initialization sequence.
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_init(void);
#endif
/**
* @brief Generate a unique key and store it in the given secure storage slot
* @brief Clear a key from secure storage
*
* @param slot_id secure storage slot ID
* @param key_type secure storage key type to generate
* @param key_id Key identifier string
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type_t key_type);
esp_err_t esp_tee_sec_storage_clear_key(const char *key_id);
/**
* @brief Generate a unique key and store it in the secure storage
*
* @param cfg Pointer to the key configuration
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg);
/**
* @brief Generate and return the signature for the specified message digest using
* the key pair located in the given secure storage slot.
* the key pair located in the secure storage.
*
* @param[in] slot_id secure storage slot ID
* @param[in] key_type secure storage key type
* @param[in] cfg Pointer to the key configuration
* @param[in] hash Message digest
* @param[in] hlen Digest length
* @param[out] out_sign Output context holding the signature
*
* @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, esp_tee_sec_storage_type_t key_type, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign);
esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_sign);
/**
* @brief Return the public key for the given secure storage slot
* @brief Return the public key from secure storage
*
* @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[in] cfg Pointer to the key configuration
* @param[out] out_pubkey Output context holding the public key
*
* @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_type_t key_type, esp_tee_sec_storage_pubkey_t *pubkey);
esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg_t *cfg, esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey);
/**
* @brief Check whether the given slot in the secure storage is empty or not
* @brief Perform encryption using AES256-GCM with the key from secure storage
*
* @param slot_id secure storage slot ID
*
* @return bool true: slot is empty; false otherwise.
*/
bool esp_tee_sec_storage_is_slot_empty(uint16_t slot_id);
/**
* @brief Erase the given secure storage slot
*
* @param slot_id secure storage slot ID
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_clear_slot(uint16_t slot_id);
/**
* @brief Perform encryption using AES256-GCM with the key stored in the specified slot
*
* @param[in] slot_id Secure storage slot ID containing the AES-GCM key
* @param[in] input Pointer to the input data buffer
* @param[in] len Length of the input data
* @param[in] aad Pointer to the Additional Authenticated Data (AAD)
* @param[in] aad_len Length of the AAD
* @param[out] tag Pointer to the authentication tag buffer
* @param[out] tag_len Length of the authentication tag
* @param[out] output Pointer to the output data buffer
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output);
/**
* @brief Perform decryption using AES256-GCM with the key stored in the specified slot
*
* @param[in] slot_id Secure storage slot ID containing the AES-GCM key
* @param[in] input Pointer to the input data buffer
* @param[in] len Length of the input data
* @param[in] aad Pointer to the Additional Authenticated Data (AAD)
* @param[in] aad_len Length of the AAD
* @param[in] tag Pointer to the authentication tag buffer
* @param[in] tag_len Length of the authentication tag
* @param[in] ctx Pointer to the AEAD operation context
* @param[out] tag Pointer to the authentication tag buffer
* @param[in] tag_len Length of the authentication tag
* @param[out] output Pointer to the output data buffer
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output);
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output);
/**
* @brief Perform decryption using AES256-GCM with the key from secure storage
*
* @param[in] ctx Pointer to the AEAD operation context
* @param[in] tag Pointer to the authentication tag buffer
* @param[in] tag_len Length of the authentication tag
* @param[out] output Pointer to the output data buffer
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output);
#ifdef __cplusplus
}

View File

@ -5,53 +5,43 @@
*/
#include <string.h>
#include "esp_log.h"
#include "esp_cpu.h"
#include "esp_fault.h"
#include "esp_flash.h"
#include "esp_efuse.h"
#include "esp_random.h"
#include "spi_flash_mmap.h"
#include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#include "mbedtls/sha256.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/error.h"
#include "esp_flash.h"
#include "esp_efuse.h"
#include "soc/efuse_reg.h"
#include "rom/efuse.h"
#if SOC_HMAC_SUPPORTED
#include "rom/hmac.h"
#endif
#include "esp_rom_sys.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_random.h"
#include "esp_tee.h"
#include "esp_tee_flash.h"
#include "esp_tee_sec_storage.h"
#include "secure_service_num.h"
#include "esp_rom_sys.h"
#include "esp_log.h"
#include "spi_flash_mmap.h"
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define SECURE_STORAGE_SIZE 2048
#define AES256_GCM_KEY_LEN 32
#define AES256_GCM_KEY_BITS (AES256_GCM_KEY_LEN * 8)
#define AES256_KEY_LEN 32
#define AES256_KEY_BITS (AES256_KEY_LEN * 8)
#define AES256_DEFAULT_IV_LEN 16
#define AES256_GCM_IV_LEN 12
#define AES256_GCM_TAG_LEN 16
#define AES256_GCM_AAD_LEN 16
#define ECDSA_SECP256R1_KEY_LEN 32
#define ECDSA_SECP192R1_KEY_LEN 24
/* Structure to hold metadata for secure storage slots */
typedef struct {
uint16_t owner_id; /* Identifier for the owner of this slot */
uint16_t slot_id; /* Unique identifier for this storage slot */
uint8_t reserved; /* Reserved for future use */
uint8_t iv[AES256_GCM_IV_LEN]; /* Initialization vector for AES-GCM */
uint8_t tag[AES256_GCM_TAG_LEN]; /* Authentication tag for AES-GCM */
uint8_t data_type; /* Type of data stored in this slot */
uint16_t data_len; /* Length of the data stored in this slot */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_metadata_t;
#define EKEY_SEED 0xAEBE5A5A
#define TKEY_SEED 0xCEDEA5A5
/* Structure to hold ECDSA SECP256R1 key pair */
typedef struct {
@ -65,38 +55,36 @@ typedef struct {
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 key and IV */
typedef struct {
uint8_t key[AES256_GCM_KEY_LEN]; /* Key for AES-256 GCM */
uint8_t iv[AES256_GCM_IV_LEN]; /* Initialization vector for AES-256 GCM */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_aes256_gcm_t;
uint8_t key[AES256_KEY_LEN]; /* Key for AES-256 */
uint8_t iv[AES256_DEFAULT_IV_LEN]; /* Initialization vector for AES-256 */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_aes256_t;
/* Union to hold different types of cryptographic keys */
typedef union {
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 */
/* Structure to hold the cryptographic keys in NVS */
typedef struct {
const esp_tee_sec_storage_type_t type; /* Type of the key */
uint32_t flags; /* Flags associated with the key */
union {
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_t aes256; /* AES-256 key and IV */
};
uint32_t reserved[38]; /* Reserved space for future use */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_key_t;
_Static_assert(sizeof(sec_stg_metadata_t) == 36, "Incorrect sec_stg_metadata_t size");
_Static_assert(sizeof(sec_stg_key_t) == 96, "Incorrect sec_stg_key_t size");
_Static_assert(sizeof(sec_stg_key_t) == 256, "Incorrect sec_stg_key_t size");
// Need this buffer to read the flash data and then modify and write it back
// esp_rom_spiflash_write requires that we erase the region before writing to it
// TODO: IDF-7586
static uint8_t tmp_buf[SECURE_STORAGE_SIZE];
#define TEE_SEC_STG_PART_LABEL "tee_nvs"
#define TEE_SEC_STG_NVS_NAMESPACE "tee_sec_stg"
// AAD buffer
static uint8_t aad_buf[AES256_GCM_AAD_LEN];
// Partition for the secure storage partition
static esp_partition_pos_t part_pos;
static nvs_handle_t tee_nvs_hdl;
static const char *TAG = "secure_storage";
/* ---------------------------------------------- Helper APIs ------------------------------------------------- */
#if CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK > 9
#error "TEE Secure Storage: Configured eFuse block for encryption key out of range! (see CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK)"
#if CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID < 0
#error "TEE Secure Storage: Configured eFuse block (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID) out of range!"
#endif
static int buffer_hexdump(const char *label, const void *buffer, size_t length)
@ -138,224 +126,142 @@ static int buffer_hexdump(const char *label, const void *buffer, size_t length)
return 0;
}
static esp_err_t get_sec_stg_encr_key(uint8_t *key_buf, size_t key_buf_len)
{
// NOTE: Key should strictly be of 256-bits
if (!key_buf || key_buf_len != AES256_GCM_KEY_LEN) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = ESP_OK;
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
esp_efuse_block_t blk = (esp_efuse_block_t)(CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK);
if (blk < EFUSE_BLK_KEY0 || blk >= EFUSE_BLK_KEY_MAX) {
ESP_LOGE(TAG, "Invalid eFuse block - %d", blk);
return ESP_ERR_INVALID_ARG;
}
esp_efuse_purpose_t blk_purpose = esp_efuse_get_key_purpose(blk);
if (blk_purpose != ESP_EFUSE_KEY_PURPOSE_USER) {
ESP_LOGE(TAG, "Invalid eFuse block purpose - %d", blk_purpose);
return ESP_ERR_INVALID_STATE;
}
memset(key_buf, 0x00, key_buf_len);
err = esp_efuse_read_block(blk, key_buf, 0, AES256_GCM_KEY_BITS);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to read eFuse block (err - %d)", err);
return err;
}
#else
memset(key_buf, 0xA5, key_buf_len);
#endif
// Check if eFuse is empty
uint8_t empty_key_buf[AES256_GCM_KEY_LEN] = {0};
if (memcmp(empty_key_buf, key_buf, key_buf_len) == 0) {
ESP_LOGE(TAG, "All-zeroes key read from eFuse");
return ESP_FAIL;
}
return err;
}
static int rand_func(void *rng_state, unsigned char *output, size_t len)
{
esp_fill_random(output, len);
return 0;
}
static int secure_storage_write(uint16_t slot_id, uint8_t *data, size_t len, uint8_t type)
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
static esp_err_t compute_nvs_keys_with_hmac(ets_efuse_block_t hmac_key, nvs_sec_cfg_t *cfg)
{
uint8_t iv[AES256_GCM_IV_LEN];
uint8_t tag[AES256_GCM_TAG_LEN];
uint8_t key[AES256_GCM_KEY_LEN];
uint8_t out_data[256] = {0};
uint32_t ekey_seed[8] = {[0 ... 7] = EKEY_SEED};
uint32_t tkey_seed[8] = {[0 ... 7] = TKEY_SEED};
buffer_hexdump("Plaintext data", data, len);
memset(cfg, 0x00, sizeof(nvs_sec_cfg_t));
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);
int ret = -1;
ets_hmac_enable();
ret = ets_hmac_calculate_message(hmac_key, ekey_seed, sizeof(ekey_seed), (uint8_t *)cfg->eky);
ret = ets_hmac_calculate_message(hmac_key, tkey_seed, sizeof(tkey_seed), (uint8_t *)cfg->tky);
ets_hmac_disable();
esp_err_t err = get_sec_stg_encr_key(key, sizeof(key));
if (ret != 0) {
ESP_LOGE(TAG, "Failed to calculate seed HMAC");
return ESP_FAIL;
}
ESP_FAULT_ASSERT(ret == 0);
/* NOTE: If the XTS E-key and T-key are the same, we have a hash collision */
ESP_FAULT_ASSERT(memcmp(cfg->eky, cfg->tky, NVS_KEY_SIZE) != 0);
return ESP_OK;
}
#endif
static esp_err_t read_security_cfg_hmac(nvs_sec_cfg_t *cfg)
{
if (cfg == NULL) {
return ESP_ERR_INVALID_ARG;
}
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
ets_efuse_block_t hmac_key = (ets_efuse_block_t)(ETS_EFUSE_BLOCK_KEY0 + CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
ets_efuse_purpose_t hmac_efuse_blk_purpose = ets_efuse_get_key_purpose(hmac_key);
if (hmac_efuse_blk_purpose != ETS_EFUSE_KEY_PURPOSE_HMAC_UP) {
ESP_LOGE(TAG, "HMAC key is not burnt in eFuse block");
return ESP_ERR_NOT_FOUND;
}
esp_err_t err = compute_nvs_keys_with_hmac(hmac_key, cfg);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from eFuse!");
goto exit;
return err;
}
#else
memset(&cfg->eky, 0x33, sizeof(cfg->eky));
memset(&cfg->tky, 0xCC, sizeof(cfg->tky));
#endif
return ESP_OK;
}
static esp_err_t secure_storage_find_key(const char *key_id)
{
nvs_type_t out_type;
return nvs_find_key(tee_nvs_hdl, key_id, &out_type);
}
static esp_err_t secure_storage_write(const char *key_id, const void *data, size_t len)
{
esp_err_t err = nvs_set_blob(tee_nvs_hdl, key_id, data, len);
if (err != ESP_OK) {
return err;
}
int ret = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, key, AES256_GCM_KEY_BITS);
if (ret != 0) {
ESP_LOGE(TAG, "Error in setting key: %d", ret);
err = ESP_FAIL;
goto exit;
}
// Generate different IV every time GCM encrypt is called
esp_fill_random(iv, AES256_GCM_IV_LEN);
ret = mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, len, iv, AES256_GCM_IV_LEN,
aad_buf, AES256_GCM_AAD_LEN, data, out_data, AES256_GCM_TAG_LEN, tag);
if (ret != 0) {
ESP_LOGE(TAG, "Error in encrypting data: %d", ret);
err = ESP_FAIL;
goto exit;
}
buffer_hexdump("Encrypted data", out_data, len);
buffer_hexdump("TAG data", tag, sizeof(tag));
// Currently keeping the owner ID as 0
sec_stg_metadata_t metadata;
metadata.owner_id = 0;
metadata.slot_id = slot_id;
memcpy(metadata.iv, iv, AES256_GCM_IV_LEN);
memcpy(metadata.tag, tag, AES256_GCM_TAG_LEN);
metadata.data_type = type;
metadata.data_len = len;
uint32_t slot_offset = (sizeof(sec_stg_metadata_t) + sizeof(sec_stg_key_t)) * slot_id;
/* ROM flash APIs require the region to be erased before writing to it.
* For that, we read the entire sector, make changes in read buffer, and then write
* the entire data back in flash.
*
* This opens up a small window when the sector has been erased but the device resets before writing the
* data back in flash. This can lead to loss of data.
*
* TODO: IDF-7586
*/
ret = esp_tee_flash_read(part_pos.offset, (uint32_t *)tmp_buf, SECURE_STORAGE_SIZE, false);
if (ret != 0) {
ESP_LOGE(TAG, "Error reading flash contents: %d", ret);
err = ESP_ERR_FLASH_OP_FAIL;
goto exit;
}
memcpy(&tmp_buf[slot_offset], &metadata, sizeof(sec_stg_metadata_t));
memcpy(&tmp_buf[slot_offset + sizeof(sec_stg_metadata_t)], out_data, len);
ret = esp_tee_flash_erase_range(part_pos.offset, ALIGN_UP(SECURE_STORAGE_SIZE, FLASH_SECTOR_SIZE));
ret |= esp_tee_flash_write(part_pos.offset, (uint32_t *)tmp_buf, SECURE_STORAGE_SIZE, false);
if (ret != 0) {
ESP_LOGE(TAG, "Error writing encrypted data: %d", ret);
err = ESP_ERR_FLASH_OP_FAIL;
goto exit;
}
err = ESP_OK;
exit:
mbedtls_gcm_free(&gcm);
err = nvs_commit(tee_nvs_hdl);
return err;
}
static esp_err_t secure_storage_read(uint16_t slot_id, uint8_t *data, size_t len, uint8_t type)
static esp_err_t secure_storage_read(const char *key_id, void *data, size_t *len)
{
esp_err_t err;
sec_stg_metadata_t metadata;
uint32_t slot_offset = (sizeof(sec_stg_metadata_t) + sizeof(sec_stg_key_t)) * slot_id;
uint8_t key[AES256_GCM_KEY_BITS / 8];
uint8_t flash_data[256] = {0};
int ret = esp_tee_flash_read(part_pos.offset + slot_offset, (uint32_t *)&metadata, sizeof(sec_stg_metadata_t), false);
if (ret != 0) {
ESP_LOGE(TAG, "Error reading metadata: %d", ret);
err = ESP_ERR_FLASH_OP_FAIL;
goto exit;
}
if (metadata.data_type != type || metadata.data_len != len) {
ESP_LOGE(TAG, "Data type/length mismatch");
err = ESP_ERR_NOT_FOUND;
goto exit;
}
ret = esp_tee_flash_read(part_pos.offset + slot_offset + sizeof(sec_stg_metadata_t), (uint32_t *)flash_data, metadata.data_len, false);
if (ret != 0) {
ESP_LOGE(TAG, "Error reading data: %d", ret);
err = ESP_ERR_FLASH_OP_FAIL;
goto exit;
}
buffer_hexdump("Encrypted data", flash_data, len);
buffer_hexdump("TAG data", metadata.tag, AES256_GCM_TAG_LEN);
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);
err = get_sec_stg_encr_key(key, sizeof(key));
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from eFuse!");
goto cleanup;
}
ret = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, key, AES256_GCM_KEY_BITS);
if (ret != 0) {
err = ESP_FAIL;
goto cleanup;
}
ret = mbedtls_gcm_auth_decrypt(&gcm, metadata.data_len, metadata.iv, AES256_GCM_IV_LEN,
aad_buf, AES256_GCM_AAD_LEN, metadata.tag, AES256_GCM_TAG_LEN, flash_data, data);
if (ret != 0) {
ESP_LOGE(TAG, "Error in decrypting data: %d", ret);
err = ESP_FAIL;
goto cleanup;
}
buffer_hexdump("Decrypted data", data, len);
err = ESP_OK;
cleanup:
mbedtls_gcm_free(&gcm);
exit:
return err;
return nvs_get_blob(tee_nvs_hdl, key_id, data, len);
}
/* ---------------------------------------------- Interface APIs ------------------------------------------------- */
esp_err_t esp_tee_sec_storage_init(void)
{
ESP_LOGI(TAG, "Initializing secure storage...");
esp_partition_info_t part_info = {};
esp_err_t err = esp_tee_flash_find_partition(PART_TYPE_DATA, PART_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL, &part_info);
nvs_sec_cfg_t cfg = {};
esp_err_t err = read_security_cfg_hmac(&cfg);
if (err != ESP_OK) {
ESP_LOGE(TAG, "No secure storage partition found (0x%08x)", err);
return err;
} else {
#if CONFIG_SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
ESP_LOGW(TAG, "TEE Secure Storage enabled in insecure DEVELOPMENT mode");
#endif
// Take backup of the partition for future usage
part_pos = part_info.pos;
}
err = nvs_flash_secure_init_partition(TEE_SEC_STG_PART_LABEL, &cfg);
if (err != ESP_OK) {
return err;
}
err = nvs_open_from_partition(TEE_SEC_STG_PART_LABEL, TEE_SEC_STG_NVS_NAMESPACE, NVS_READWRITE, &tee_nvs_hdl);
if (err != ESP_OK) {
return err;
}
#if CONFIG_SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
ESP_LOGW(TAG, "TEE Secure Storage enabled in insecure DEVELOPMENT mode");
#endif
return ESP_OK;
}
esp_err_t esp_tee_sec_storage_clear_key(const char *key_id)
{
if (secure_storage_find_key(key_id) != ESP_OK) {
return ESP_ERR_NOT_FOUND;
}
sec_stg_key_t keyctx;
size_t keyctx_len = sizeof(keyctx);
esp_err_t err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
return err;
}
if (keyctx.flags & SEC_STORAGE_FLAG_WRITE_ONCE) {
ESP_LOGE(TAG, "Key is write-once only and cannot be cleared!");
return ESP_ERR_INVALID_STATE;
}
err = nvs_erase_key(tee_nvs_hdl, key_id);
if (err != ESP_OK) {
return err;
}
err = nvs_commit(tee_nvs_hdl);
return err;
}
static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t key_type)
{
if (keyctx == NULL) {
@ -370,19 +276,18 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
curve_id = MBEDTLS_ECP_DP_SECP192R1;
key_len = ECDSA_SECP192R1_KEY_LEN;
#else
ESP_LOGE(TAG, "Unsupported key type!");
ESP_LOGE(TAG, "Unsupported key-type!");
return -1;
#endif
}
ESP_LOGI(TAG, "Generating ECDSA key for curve %d...", curve_id);
ESP_LOGD(TAG, "Generating ECDSA key for curve %d...", curve_id);
mbedtls_ecdsa_context ctxECDSA;
mbedtls_ecdsa_init(&ctxECDSA);
int ret = mbedtls_ecdsa_genkey(&ctxECDSA, curve_id, rand_func, NULL);
if (ret != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA key");
goto exit;
}
@ -425,48 +330,49 @@ exit:
return ret;
}
static int generate_aes256_gcm_key(sec_stg_key_t *keyctx)
static int generate_aes256_key(sec_stg_key_t *keyctx)
{
if (keyctx == NULL) {
return -1;
}
ESP_LOGI(TAG, "Generating AES-256-GCM key...");
ESP_LOGD(TAG, "Generating AES-256 key...");
esp_fill_random(&keyctx->aes256_gcm.key, AES256_GCM_KEY_LEN);
esp_fill_random(&keyctx->aes256_gcm.iv, AES256_GCM_IV_LEN);
esp_fill_random(&keyctx->aes256.key, AES256_KEY_LEN);
esp_fill_random(&keyctx->aes256.iv, AES256_DEFAULT_IV_LEN);
return 0;
}
esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type_t key_type)
esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
{
if (slot_id > MAX_SEC_STG_SLOT_ID) {
ESP_LOGE(TAG, "Invalid slot ID");
if (cfg == NULL || cfg->id == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!esp_tee_sec_storage_is_slot_empty(slot_id)) {
ESP_LOGE(TAG, "Slot already occupied - clear before reuse");
if (secure_storage_find_key(cfg->id) == ESP_OK) {
ESP_LOGE(TAG, "Key ID already exists");
return ESP_ERR_INVALID_STATE;
}
int ret = -1;
sec_stg_key_t keyctx;
sec_stg_key_t keyctx = {
.type = cfg->type,
.flags = cfg->flags,
};
switch (key_type) {
switch (cfg->type) {
case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
#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);
if (generate_ecdsa_key(&keyctx, cfg->type) != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA keypair");
return ESP_FAIL;
}
break;
case ESP_SEC_STG_KEY_AES256:
if (generate_aes256_gcm_key(&keyctx) != 0) {
ESP_LOGE(TAG, "Failed to generate AES key (%d)", ret);
if (generate_aes256_key(&keyctx) != 0) {
ESP_LOGE(TAG, "Failed to generate AES key");
return ESP_FAIL;
}
break;
@ -475,33 +381,41 @@ esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type
return ESP_ERR_NOT_SUPPORTED;
}
return secure_storage_write(slot_id, (uint8_t *)&keyctx, sizeof(keyctx), key_type);
return secure_storage_write(cfg->id, (void *)&keyctx, sizeof(keyctx));
}
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)
esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_sign)
{
if (slot_id > MAX_SEC_STG_SLOT_ID || hash == NULL || out_sign == NULL) {
if (cfg == NULL || cfg->id == NULL || hash == NULL || out_sign == NULL || hlen == 0) {
return ESP_ERR_INVALID_ARG;
}
if (hlen == 0) {
return ESP_ERR_INVALID_SIZE;
}
#if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
ESP_LOGE(TAG, "Unsupported key type!");
if (cfg->type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
ESP_LOGE(TAG, "Unsupported key-type!");
return ESP_ERR_NOT_SUPPORTED;
}
#endif
sec_stg_key_t keyctx;
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(sec_stg_key_t), key_type);
esp_err_t err = secure_storage_find_key(cfg->id);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot");
ESP_LOGE(TAG, "Key ID not found");
return err;
}
sec_stg_key_t keyctx;
size_t keyctx_len = sizeof(keyctx);
err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from storage");
return err;
}
if (keyctx.type != cfg->type) {
ESP_LOGE(TAG, "Key type mismatch");
return ESP_ERR_INVALID_STATE;
}
mbedtls_mpi r, s;
mbedtls_ecp_keypair priv_key;
mbedtls_ecdsa_context sign_ctx;
@ -513,18 +427,15 @@ esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, esp_tee_sec_storag
size_t key_len = 0;
int ret = -1;
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) {
if (cfg->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));
key_len = ECDSA_SECP256R1_KEY_LEN;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
} else if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
} else if (cfg->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));
key_len = ECDSA_SECP192R1_KEY_LEN;
#endif
} else {
ESP_LOGE(TAG, "Unsupported key type for signature generation");
err = ESP_ERR_NOT_SUPPORTED;
goto exit;
}
if (ret != 0) {
@ -538,7 +449,7 @@ esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, esp_tee_sec_storag
goto exit;
}
ESP_LOGI(TAG, "Generating ECDSA signature...");
ESP_LOGD(TAG, "Generating ECDSA signature...");
ret = mbedtls_ecdsa_sign(&sign_ctx.MBEDTLS_PRIVATE(grp), &r, &s, &sign_ctx.MBEDTLS_PRIVATE(d), hash, hlen,
rand_func, NULL);
@ -548,7 +459,7 @@ esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, esp_tee_sec_storag
goto exit;
}
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_sign_t));
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
ret = mbedtls_mpi_write_binary(&r, out_sign->sign_r, key_len);
if (ret != 0) {
@ -572,142 +483,93 @@ exit:
return err;
}
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)
esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg_t *cfg, esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey)
{
if (slot_id > MAX_SEC_STG_SLOT_ID || pubkey == NULL) {
if (cfg == NULL || cfg->id == NULL || out_pubkey == NULL) {
return ESP_ERR_INVALID_ARG;
}
sec_stg_key_t keyctx;
size_t key_len;
uint8_t *pub_key_src;
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);
esp_err_t err = secure_storage_find_key(cfg->id);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot");
ESP_LOGE(TAG, "Key ID not found");
return err;
}
// Copy public key components in one shot
memcpy(pubkey->pub_x, pub_key_src, key_len);
memcpy(pubkey->pub_y, pub_key_src + key_len, key_len);
sec_stg_key_t keyctx;
size_t keyctx_len = sizeof(keyctx);
uint8_t *pub_key_src = NULL;
size_t pub_key_len = 0;
switch (cfg->type) {
case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
pub_key_src = keyctx.ecdsa_secp256r1.pub_key;
pub_key_len = ECDSA_SECP256R1_KEY_LEN;
break;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
pub_key_src = keyctx.ecdsa_secp192r1.pub_key;
pub_key_len = ECDSA_SECP192R1_KEY_LEN;
break;
#endif
default:
ESP_LOGE(TAG, "Unsupported key-type");
return ESP_ERR_INVALID_ARG;
}
err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to read key from secure storage");
return err;
}
if (keyctx.type != cfg->type) {
ESP_LOGE(TAG, "Key type mismatch");
return ESP_ERR_INVALID_STATE;
}
memcpy(out_pubkey->pub_x, pub_key_src, pub_key_len);
memcpy(out_pubkey->pub_y, pub_key_src + pub_key_len, pub_key_len);
return ESP_OK;
}
bool esp_tee_sec_storage_is_slot_empty(uint16_t slot_id)
{
if (slot_id > MAX_SEC_STG_SLOT_ID) {
ESP_LOGE(TAG, "Invalid slot ID");
return false;
}
sec_stg_metadata_t metadata, blank_metadata;
memset(&blank_metadata, 0xFF, sizeof(sec_stg_metadata_t));
uint32_t slot_offset = (sizeof(sec_stg_metadata_t) + sizeof(sec_stg_key_t)) * slot_id;
bool ret = false;
int err = esp_tee_flash_read(part_pos.offset + slot_offset, (uint32_t *)&metadata, sizeof(sec_stg_metadata_t), false);
if (err != 0) {
goto exit;
}
if (memcmp(&metadata, &blank_metadata, sizeof(sec_stg_metadata_t)) && metadata.slot_id == slot_id) {
goto exit;
}
ret = true;
exit:
return ret;
}
esp_err_t esp_tee_sec_storage_clear_slot(uint16_t slot_id)
{
if (slot_id > MAX_SEC_STG_SLOT_ID) {
ESP_LOGE(TAG, "Invalid slot ID");
return ESP_ERR_INVALID_ARG;
}
if (esp_tee_sec_storage_is_slot_empty(slot_id)) {
return ESP_OK;
}
sec_stg_key_t blank_data;
memset(&blank_data, 0xFF, sizeof(blank_data));
sec_stg_metadata_t blank_metadata;
memset(&blank_metadata, 0xFF, sizeof(sec_stg_metadata_t));
uint32_t slot_offset = (sizeof(sec_stg_metadata_t) + sizeof(sec_stg_key_t)) * slot_id;
esp_err_t err;
int ret = esp_tee_flash_read(part_pos.offset, (uint32_t *)tmp_buf, SECURE_STORAGE_SIZE, false);
if (ret != 0) {
ESP_LOGE(TAG, "Error reading flash contents: %d", ret);
err = ESP_ERR_FLASH_OP_FAIL;
goto exit;
}
memcpy(&tmp_buf[slot_offset], &blank_metadata, sizeof(sec_stg_metadata_t));
memcpy(&tmp_buf[slot_offset + sizeof(sec_stg_metadata_t)], &blank_data, sizeof(sec_stg_key_t));
ret = esp_tee_flash_erase_range(part_pos.offset, ALIGN_UP(SECURE_STORAGE_SIZE, FLASH_SECTOR_SIZE));
ret |= esp_tee_flash_write(part_pos.offset, (uint32_t *)tmp_buf, SECURE_STORAGE_SIZE, false);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Error clearing slot: %d", ret);
err = ESP_ERR_FLASH_OP_FAIL;
goto exit;
}
err = ESP_OK;
exit:
return err;
}
static esp_err_t tee_sec_storage_crypt_common(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output,
static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t *input, size_t len, const uint8_t *aad,
size_t aad_len, uint8_t *tag, size_t tag_len, uint8_t *output,
bool is_encrypt)
{
if (slot_id > MAX_SEC_STG_SLOT_ID) {
ESP_LOGE(TAG, "Invalid slot ID");
return ESP_ERR_INVALID_ARG;
}
if (input == NULL || output == NULL || tag == NULL) {
ESP_LOGE(TAG, "Invalid input/output/tag buffer");
if (key_id == NULL || input == NULL || output == NULL || tag == NULL) {
ESP_LOGE(TAG, "Invalid arguments");
return ESP_ERR_INVALID_ARG;
}
if (len == 0 || tag_len == 0) {
ESP_LOGE(TAG, "Invalid length/tag length");
ESP_LOGE(TAG, "Invalid input/tag length");
return ESP_ERR_INVALID_SIZE;
}
sec_stg_key_t keyctx;
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(keyctx), ESP_SEC_STG_KEY_AES256);
esp_err_t err = secure_storage_find_key(key_id);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot");
ESP_LOGE(TAG, "Key ID not found");
return err;
}
sec_stg_key_t keyctx;
size_t keyctx_len = sizeof(keyctx);
err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from storage");
return err;
}
if (keyctx.type != ESP_SEC_STG_KEY_AES256) {
ESP_LOGE(TAG, "Key type mismatch");
return ESP_ERR_INVALID_STATE;
}
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);
int ret = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, keyctx.aes256_gcm.key, AES256_GCM_KEY_BITS);
int ret = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, keyctx.aes256.key, AES256_KEY_BITS);
if (ret != 0) {
ESP_LOGE(TAG, "Error in setting key: %d", ret);
err = ESP_FAIL;
@ -715,7 +577,7 @@ static esp_err_t tee_sec_storage_crypt_common(uint16_t slot_id, uint8_t *input,
}
if (is_encrypt) {
ret = mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, len, keyctx.aes256_gcm.iv, AES256_GCM_IV_LEN,
ret = mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, len, keyctx.aes256.iv, AES256_GCM_IV_LEN,
aad, aad_len, input, output, tag_len, tag);
if (ret != 0) {
ESP_LOGE(TAG, "Error in encrypting data: %d", ret);
@ -723,7 +585,7 @@ static esp_err_t tee_sec_storage_crypt_common(uint16_t slot_id, uint8_t *input,
goto exit;
}
} else {
ret = mbedtls_gcm_auth_decrypt(&gcm, len, keyctx.aes256_gcm.iv, AES256_GCM_IV_LEN,
ret = mbedtls_gcm_auth_decrypt(&gcm, len, keyctx.aes256.iv, AES256_GCM_IV_LEN,
aad, aad_len, tag, tag_len, input, output);
if (ret != 0) {
ESP_LOGE(TAG, "Error in decrypting data: %d", ret);
@ -738,14 +600,12 @@ exit:
return err;
}
esp_err_t esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
{
return tee_sec_storage_crypt_common(slot_id, input, len, aad, aad_len, tag, tag_len, output, true);
return tee_sec_storage_crypt_common(ctx->key_id, ctx->input, ctx->input_len, ctx->aad, ctx->aad_len, tag, tag_len, output, true);
}
esp_err_t esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
esp_err_t esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output)
{
return tee_sec_storage_crypt_common(slot_id, input, len, aad, aad_len, tag, tag_len, output, false);
return tee_sec_storage_crypt_common(ctx->key_id, ctx->input, ctx->input_len, ctx->aad, ctx->aad_len, (uint8_t *)tag, tag_len, output, false);
}

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
*/
@ -8,46 +8,32 @@
#include "esp_err.h"
#include "esp_tee_sec_storage.h"
esp_err_t esp_tee_sec_storage_init(void)
esp_err_t esp_tee_sec_storage_clear_key(const char *key_id)
{
return esp_tee_service_call_with_noniram_intr_disabled(1, SS_ESP_TEE_SEC_STORAGE_INIT);
return esp_tee_service_call_with_noniram_intr_disabled(2, SS_ESP_TEE_SEC_STORAGE_CLEAR_KEY, key_id);
}
esp_err_t esp_tee_sec_storage_gen_key(uint16_t slot_id, esp_tee_sec_storage_type_t key_type)
esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
{
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(2, SS_ESP_TEE_SEC_STORAGE_GEN_KEY, cfg);
}
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)
esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_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);
return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_ECDSA_SIGN, cfg, hash, hlen, out_sign);
}
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)
esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg_t *cfg, esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey)
{
return esp_tee_service_call_with_noniram_intr_disabled(4, SS_ESP_TEE_SEC_STORAGE_GET_PUBKEY, slot_id, key_type, pubkey);
return esp_tee_service_call_with_noniram_intr_disabled(3, SS_ESP_TEE_SEC_STORAGE_ECDSA_GET_PUBKEY, cfg, out_pubkey);
}
bool esp_tee_sec_storage_is_slot_empty(uint16_t slot_id)
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
{
return esp_tee_service_call_with_noniram_intr_disabled(2, SS_ESP_TEE_SEC_STORAGE_IS_SLOT_EMPTY, slot_id);
return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_AEAD_ENCRYPT, ctx, tag, tag_len, output);
}
esp_err_t esp_tee_sec_storage_clear_slot(uint16_t slot_id)
esp_err_t esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output)
{
return esp_tee_service_call_with_noniram_intr_disabled(2, SS_ESP_TEE_SEC_STORAGE_CLEAR_SLOT, slot_id);
}
esp_err_t esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
{
return esp_tee_service_call_with_noniram_intr_disabled(9, SS_ESP_TEE_SEC_STORAGE_ENCRYPT, slot_id,
input, len, aad, aad_len, tag, tag_len, output);
}
esp_err_t esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
{
return esp_tee_service_call_with_noniram_intr_disabled(9, SS_ESP_TEE_SEC_STORAGE_DECRYPT, slot_id,
input, len, aad, aad_len, tag, tag_len, output);
return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_AEAD_DECRYPT, ctx, tag, tag_len, output);
}

View File

@ -205,6 +205,10 @@ esp_err_t _ss_esp_hmac_calculate(hmac_key_id_t key_id, const void *message, size
bool valid_addr = ((esp_tee_ptr_in_ree((void *)message) && esp_tee_ptr_in_ree((void *)hmac)) &&
esp_tee_ptr_in_ree((void *)((char *)message + message_len)));
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
#endif
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
@ -217,6 +221,10 @@ esp_err_t _ss_esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
{
bool valid_addr = (esp_tee_ptr_in_ree((void *)token));
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
#endif
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
@ -239,6 +247,10 @@ esp_err_t _ss_esp_ds_sign(const void *message,
esp_tee_ptr_in_ree((void *)data) &&
esp_tee_ptr_in_ree((void *)signature));
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
#endif
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
@ -256,6 +268,10 @@ esp_err_t _ss_esp_ds_start_sign(const void *message,
esp_tee_ptr_in_ree((void *)data) &&
esp_tee_ptr_in_ree((void *)esp_ds_ctx));
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
#endif
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
@ -356,22 +372,12 @@ int _ss_esp_tee_ota_end(void)
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */
esp_err_t _ss_esp_tee_sec_storage_init(void)
esp_err_t _ss_esp_tee_sec_storage_clear_key(const char *key_id)
{
return esp_tee_sec_storage_init();
return esp_tee_sec_storage_clear_key(key_id);
}
esp_err_t _ss_esp_tee_sec_storage_gen_key(uint16_t slot_id, uint8_t key_type)
esp_err_t _ss_esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
{
return esp_tee_sec_storage_gen_key(slot_id, key_type);
}
bool _ss_esp_tee_sec_storage_is_slot_empty(uint16_t slot_id)
{
return esp_tee_sec_storage_is_slot_empty(slot_id);
}
esp_err_t _ss_esp_tee_sec_storage_clear_slot(uint16_t slot_id)
{
return esp_tee_sec_storage_clear_slot(slot_id);
return esp_tee_sec_storage_gen_key(cfg);
}

View File

@ -85,46 +85,45 @@ void _ss_wdt_hal_deinit(wdt_hal_context_t *hal)
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */
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)
esp_err_t _ss_esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_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 *)((char *)out_sign + sizeof(esp_tee_sec_storage_sign_t)))));
esp_tee_ptr_in_ree((void *)((char *)out_sign + sizeof(esp_tee_sec_storage_ecdsa_sign_t)))));
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_get_signature(slot_id, key_type, hash, hlen, out_sign);
return esp_tee_sec_storage_ecdsa_sign(cfg, hash, hlen, out_sign);
}
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)
esp_err_t _ss_esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg_t *cfg, esp_tee_sec_storage_ecdsa_pubkey_t *out_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)))));
bool valid_addr = ((esp_tee_ptr_in_ree((void *)out_pubkey)) &&
(esp_tee_ptr_in_ree((void *)((char *)out_pubkey + sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)))));
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_get_pubkey(slot_id, key_type, pubkey);
return esp_tee_sec_storage_ecdsa_get_pubkey(cfg, out_pubkey);
}
esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
{
bool valid_addr = (esp_tee_ptr_in_ree((void *)input) &&
bool valid_addr = (esp_tee_ptr_in_ree((void *)ctx->input) &&
esp_tee_ptr_in_ree((void *)tag) &&
esp_tee_ptr_in_ree((void *)output));
valid_addr &= (esp_tee_ptr_in_ree((void *)(input + len)) &&
valid_addr &= (esp_tee_ptr_in_ree((void *)(ctx->input + ctx->input_len)) &&
esp_tee_ptr_in_ree((void *)(tag + tag_len)) &&
esp_tee_ptr_in_ree((void *)(output + len)));
esp_tee_ptr_in_ree((void *)(output + ctx->input_len)));
if (aad) {
valid_addr &= (esp_tee_ptr_in_ree((void *)aad) && esp_tee_ptr_in_ree((void *)(aad + aad_len)));
if (ctx->aad) {
valid_addr &= (esp_tee_ptr_in_ree((void *)ctx->aad) && esp_tee_ptr_in_ree((void *)(ctx->aad + ctx->aad_len)));
}
if (!valid_addr) {
@ -132,22 +131,21 @@ esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint
}
ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_encrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output);
return esp_tee_sec_storage_aead_encrypt(ctx, tag, tag_len, output);
}
esp_err_t _ss_esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
esp_err_t _ss_esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output)
{
bool valid_addr = (esp_tee_ptr_in_ree((void *)input) &&
bool valid_addr = (esp_tee_ptr_in_ree((void *)ctx->input) &&
esp_tee_ptr_in_ree((void *)tag) &&
esp_tee_ptr_in_ree((void *)output));
valid_addr &= (esp_tee_ptr_in_ree((void *)(input + len)) &&
valid_addr &= (esp_tee_ptr_in_ree((void *)(ctx->input + ctx->input_len)) &&
esp_tee_ptr_in_ree((void *)(tag + tag_len)) &&
esp_tee_ptr_in_ree((void *)(output + len)));
esp_tee_ptr_in_ree((void *)(output + ctx->input_len)));
if (aad) {
valid_addr &= (esp_tee_ptr_in_ree((void *)aad) && esp_tee_ptr_in_ree((void *)(aad + aad_len)));
if (ctx->aad) {
valid_addr &= (esp_tee_ptr_in_ree((void *)ctx->aad) && esp_tee_ptr_in_ree((void *)(ctx->aad + ctx->aad_len)));
}
if (!valid_addr) {
@ -155,7 +153,7 @@ esp_err_t _ss_esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint
}
ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_decrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output);
return esp_tee_sec_storage_aead_decrypt(ctx, tag, tag_len, output);
}
/* ---------------------------------------------- MMU HAL ------------------------------------------------- */

View File

@ -14,6 +14,7 @@
#include "esp_tee_brownout.h"
#include "esp_tee_flash.h"
#include "esp_tee_sec_storage.h"
#include "bootloader_utility_tee.h"
#if __has_include("esp_app_desc.h")
@ -23,11 +24,8 @@
/* TEE symbols */
extern uint32_t _tee_stack;
extern uint32_t _tee_intr_stack_bottom;
extern uint32_t _tee_bss_start;
extern uint32_t _tee_bss_end;
extern uint32_t _sec_world_entry;
extern uint32_t _tee_s_intr_handler;
extern uint8_t _tee_heap_start[];
@ -159,6 +157,14 @@ void __attribute__((noreturn)) esp_tee_init(uint32_t ree_entry_addr, uint32_t re
}
ESP_FAULT_ASSERT(err == ESP_OK);
/* Initializing the secure storage */
err = esp_tee_sec_storage_init();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize the secure storage! (0x%08x)", err);
abort();
}
ESP_FAULT_ASSERT(err == ESP_OK);
/* Setting up the running non-secure app partition as per the address provided by the bootloader */
err = esp_tee_flash_set_running_ree_partition(ree_drom_addr);
if (err != ESP_OK) {

View File

@ -19,14 +19,14 @@ static const char *TAG = "esp_tee_apm_prot_cfg";
/* NOTE: Figuring out the eFuse protection range based on where the TEE secure storage key is stored */
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
#if CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK > 9
#error "TEE: eFuse protection region for APM out of range! (see CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK)"
#if CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID < 0
#error "TEE: eFuse protection region for APM out of range! (see CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID)"
#endif
#define LP_APM_EFUSE_REG_START \
(EFUSE_RD_KEY0_DATA0_REG + (((CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK) - 4) * 0x20))
(EFUSE_RD_KEY0_DATA0_REG + (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID * 0x20))
#define LP_APM_EFUSE_REG_END \
(EFUSE_RD_KEY1_DATA0_REG + (((CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK) - 4) * 0x20))
(EFUSE_RD_KEY1_DATA0_REG + (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID * 0x20))
#elif CONFIG_SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
#define LP_APM_EFUSE_REG_START EFUSE_RD_KEY5_DATA0_REG
#if CONFIG_SECURE_TEE_TEST_MODE

View File

@ -11,7 +11,7 @@ CONFIG_SECURE_TEE_LOG_LEVEL_DEBUG=y
CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN=y
# secure storage key slot for attestation
CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID=14
CONFIG_SECURE_TEE_ATT_KEY_STR_ID="tee_att_keyN"
# Enabling flash protection over SPI1
CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1=y

View File

@ -410,7 +410,7 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, int slot_id)
int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, const char *tee_key_id)
{
int ret = -1;
uint16_t len;
@ -426,8 +426,13 @@ int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, int slot_id)
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_tee_sec_storage_key_cfg_t cfg = {
.id = tee_key_id,
.type = key_type
};
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
if (esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey) != ESP_OK) {
ESP_LOGE(TAG, "Failed to get public key from secure storage");
goto cleanup;
}
@ -457,9 +462,9 @@ int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_
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");
const char *key_id = conf->tee_key_id;
if (!key_id) {
ESP_LOGE(TAG, "Invalid TEE key id");
return ret;
}
@ -477,8 +482,14 @@ int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_
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;
keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(n) = 1;
mbedtls_mpi_uint *key_id_mpi = malloc(sizeof(mbedtls_mpi_uint));
if (!key_id_mpi) {
return -1;
}
key_id_mpi[0] = (mbedtls_mpi_uint)(uintptr_t)key_id;
keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) = key_id_mpi;
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);
@ -486,7 +497,7 @@ int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_
}
if (conf->load_pubkey) {
if ((ret = esp_ecdsa_tee_load_pubkey(keypair, slot_id)) != 0) {
if ((ret = esp_ecdsa_tee_load_pubkey(keypair, key_id)) != 0) {
ESP_LOGE(TAG, "Loading public key context failed, esp_ecdsa_load_pubkey() returned %d", ret);
return ret;
}
@ -525,10 +536,15 @@ static int esp_ecdsa_tee_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mp
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
int slot_id = d->MBEDTLS_PRIVATE(n);
const char *key_id = (const char *)(uintptr_t)(d->MBEDTLS_PRIVATE(p)[0]);
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);
esp_tee_sec_storage_key_cfg_t cfg = {
.id = key_id,
.type = key_type
};
esp_tee_sec_storage_ecdsa_sign_t sign = {};
esp_err_t err = esp_tee_sec_storage_ecdsa_sign(&cfg, (uint8_t *)msg, msg_len, &sign);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get signature");
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;

View File

@ -29,8 +29,8 @@ typedef struct {
mbedtls_ecp_group_id grp_id; /*!< MbedTLS ECP group identifier */
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 */
const char *tee_key_id; /*!< TEE secure storage key id for ECDSA private key */
}; /*!< Union to hold either EFuse block id or TEE secure storage key 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 */
@ -120,11 +120,11 @@ int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *c
* 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.
* @param tee_key_id The TEE secure storage key id of 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);
int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, const char *tee_key_id);
/**
* @brief Initialize PK context and fully populate the mbedtls_ecp_keypair context.

View File

@ -1,7 +1,8 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
tee, app, tee_0, , 192K,
secure_storage, data, tee_sec_stg, , 64K,
tee_nvs, data, nvs, , 32K,
secure_storage, data, tee_sec_stg, , 32K,
factory, app, factory, , 1536K,
nvs, data, nvs, , 24K,
phy_init, data, phy, , 4K,

1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 tee, app, tee_0, , 192K,
4 secure_storage, data, tee_sec_stg, , 64K, tee_nvs, data, nvs, , 32K,
5 secure_storage, data, tee_sec_stg, , 32K,
6 factory, app, factory, , 1536K,
7 nvs, data, nvs, , 24K,
8 phy_init, data, phy, , 4K,

View File

@ -3,7 +3,8 @@
tee_0, app, tee_0, , 192K,
tee_1, app, tee_1, , 192K,
tee_otadata, data, tee_ota, , 8K,
secure_storage, data, tee_sec_stg, , 56K,
tee_nvs, data, nvs, , 32K,
secure_storage, data, tee_sec_stg, , 24K,
ota_0, app, ota_0, , 1536K,
ota_1, app, ota_1, , 1536K,
otadata, data, ota, , 8K,

1 # Name, Type, SubType, Offset, Size, Flags
3 tee_0, app, tee_0, , 192K,
4 tee_1, app, tee_1, , 192K,
5 tee_otadata, data, tee_ota, , 8K,
6 secure_storage, data, tee_sec_stg, , 56K, tee_nvs, data, nvs, , 32K,
7 secure_storage, data, tee_sec_stg, , 24K,
8 ota_0, app, ota_0, , 1536K,
9 ota_1, app, ota_1, , 1536K,
10 otadata, data, ota, , 8K,