diff --git a/components/esp_tee/Kconfig.projbuild b/components/esp_tee/Kconfig.projbuild index 67353de593..155333f9bd 100644 --- a/components/esp_tee/Kconfig.projbuild +++ b/components/esp_tee/Kconfig.projbuild @@ -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. diff --git a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml index fdcf6f4ca0..6d9ef94841 100644 --- a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml @@ -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: diff --git a/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c b/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c index de4f699061..1ea6b72496 100644 --- a/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c +++ b/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c @@ -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; } diff --git a/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c b/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c index 79bce76c7e..0954122bde 100644 --- a/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c +++ b/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c @@ -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); diff --git a/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h b/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h index cb025e02e8..31963a248a 100644 --- a/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h +++ b/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h @@ -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 /** diff --git a/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt b/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt index dc7650dd56..6dcd248d19 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt +++ b/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt @@ -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) diff --git a/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h b/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h index 91feb91ca6..97ae8ae432 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h +++ b/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h @@ -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 #include #include -#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 } diff --git a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c index 012813e963..8383e72401 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c +++ b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c @@ -5,53 +5,43 @@ */ #include + +#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); } diff --git a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c index ea69a0b916..2d5bba684f 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c +++ b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c @@ -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); } diff --git a/components/esp_tee/subproject/main/core/esp_secure_services.c b/components/esp_tee/subproject/main/core/esp_secure_services.c index b081dfff33..cf1a9cd542 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.c @@ -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); } diff --git a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c index ac170dece8..ffa5110662 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c @@ -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 ------------------------------------------------- */ diff --git a/components/esp_tee/subproject/main/core/esp_tee_init.c b/components/esp_tee/subproject/main/core/esp_tee_init.c index 01e129bc98..9bdfb06f99 100644 --- a/components/esp_tee/subproject/main/core/esp_tee_init.c +++ b/components/esp_tee/subproject/main/core/esp_tee_init.c @@ -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) { diff --git a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_apm_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_apm_prot_cfg.c index c1a873bc03..352375467f 100644 --- a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_apm_prot_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_apm_prot_cfg.c @@ -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 diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.ota b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.ota index 5224e6bc4b..09d30653ea 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.ota +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.ota @@ -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 diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index 8a30aa89fd..e31a46f527 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -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; diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h index aef572c1c5..81e51d7bb5 100644 --- a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h +++ b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h @@ -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. diff --git a/components/partition_table/partitions_singleapp_tee.csv b/components/partition_table/partitions_singleapp_tee.csv index aefbee66f6..0916323b32 100644 --- a/components/partition_table/partitions_singleapp_tee.csv +++ b/components/partition_table/partitions_singleapp_tee.csv @@ -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, diff --git a/components/partition_table/partitions_two_ota_tee.csv b/components/partition_table/partitions_two_ota_tee.csv index 98ee581e0e..441fdeaa83 100644 --- a/components/partition_table/partitions_two_ota_tee.csv +++ b/components/partition_table/partitions_two_ota_tee.csv @@ -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,