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 config SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
bool "Development" bool "Development"
help 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 config SECURE_TEE_SEC_STG_MODE_RELEASE
depends on IDF_TARGET_ESP32C6 depends on IDF_TARGET_ESP32C6
bool "Release" bool "Release"
help help
Secure storage will be encrypted by the data stored in eFuse block 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 endchoice
config SECURE_TEE_SEC_STG_KEY_EFUSE_BLK config SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID
int "Secure Storage: Encryption key eFuse block" int "Secure Storage: eFuse HMAC key ID"
depends on SECURE_TEE_SEC_STG_MODE_RELEASE depends on SECURE_TEE_SEC_STG_MODE_RELEASE
range 4 10 range -1 5
default 10 default -1
help 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 config SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
bool "Secure Storage: Support signing with the ECDSA SECP192R1 curve" 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. 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 depends on SECURE_TEE_ATTESTATION
int "Attestation: Secure Storage slot ID for EAT signing" string "Attestation: Secure Storage key ID for EAT signing"
default 0 default "tee_att_key0"
range 0 14
help 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 storing the ECDSA keypair for executing sign/verify operations
from the TEE side for attestation. from the TEE side for attestation.

View File

@@ -252,36 +252,28 @@ secure_services:
entries: entries:
- id: 175 - id: 175
type: custom type: custom
function: esp_tee_sec_storage_init function: esp_tee_sec_storage_clear_key
args: 0 args: 1
- id: 176 - id: 176
type: custom type: custom
function: esp_tee_sec_storage_gen_key function: esp_tee_sec_storage_gen_key
args: 2 args: 1
- id: 177 - id: 177
type: custom type: custom
function: esp_tee_sec_storage_get_signature function: esp_tee_sec_storage_ecdsa_sign
args: 5 args: 4
- id: 178 - id: 178
type: custom type: custom
function: esp_tee_sec_storage_get_pubkey function: esp_tee_sec_storage_ecdsa_get_pubkey
args: 3 args: 2
- id: 179 - id: 179
type: custom type: custom
function: esp_tee_sec_storage_encrypt function: esp_tee_sec_storage_aead_encrypt
args: 8 args: 4
- id: 180 - id: 180
type: custom type: custom
function: esp_tee_sec_storage_decrypt function: esp_tee_sec_storage_aead_decrypt
args: 8 args: 4
- 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
# ID: 195-199 (5) - OTA # ID: 195-199 (5) - OTA
- family: ota - family: ota
entries: 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 * 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) { if (keypair == NULL) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
memset(keypair, 0x00, sizeof(esp_att_ecdsa_keypair_t)); memset(keypair, 0x00, sizeof(esp_att_ecdsa_keypair_t));
uint16_t slot_id = ESP_ATT_TK_KEY_ID; esp_tee_sec_storage_key_cfg_t key_cfg = {
esp_tee_sec_storage_pubkey_t pubkey = {0}; .id = (const char *)(ESP_ATT_TK_KEY_ID),
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1,
};
esp_err_t err = esp_tee_sec_storage_init(); esp_err_t err = esp_tee_sec_storage_gen_key(&key_cfg);
if (err != ESP_OK) { if (err == ESP_ERR_INVALID_STATE) {
return err; ESP_LOGW(TAG, "Using pre-existing key...");
} } else if (err != ESP_OK) {
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); ESP_LOGE(TAG, "Failed to generate ECDSA keypair (%d)", err);
return 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) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch ECDSA pubkey (%d)", err); ESP_LOGE(TAG, "Failed to fetch ECDSA pubkey (%d)", err);
return err; return err;
@@ -83,8 +80,13 @@ static esp_err_t get_ecdsa_sign_secp256r1(const esp_att_ecdsa_keypair_t *keypair
return ESP_ERR_INVALID_SIZE; return ESP_ERR_INVALID_SIZE;
} }
esp_tee_sec_storage_sign_t sign = {}; esp_tee_sec_storage_key_cfg_t key_cfg = {
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); .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) { if (err != ESP_OK) {
return err; 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, "encr_alg", NULL);
json_gen_obj_set_string(&json_gen, "sign_alg", ESP_ATT_TK_SIGN_ALG); 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 // End the top-level JSON object
json_gen_end_object(&json_gen); 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) #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 #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 #else
#define ESP_ATT_TK_KEY_ID (-1) #define ESP_ATT_TK_KEY_ID ("NULL")
#endif #endif
/** /**

View File

@@ -5,7 +5,7 @@ set(priv_requires efuse mbedtls spi_flash)
if(esp_tee_build) if(esp_tee_build)
list(APPEND srcs "tee_sec_storage.c") 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() else()
list(APPEND srcs "tee_sec_storage_wrapper.c") list(APPEND srcs "tee_sec_storage_wrapper.c")
set(priv_requires esp_tee) 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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,138 +12,142 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "esp_err.h"
#define MIN_SEC_STG_SLOT_ID 0 /*!< Minimum secure storage slot ID */ #include "esp_err.h"
#define MAX_SEC_STG_SLOT_ID 14 /*!< Maximum secure storage slot ID */ #include "esp_bit_defs.h"
#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key */ #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 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 * @brief Enum to represent the type of key stored in the secure storage
* *
*/ */
typedef enum { typedef enum {
ESP_SEC_STG_KEY_ECDSA_SECP256R1 = 0, ESP_SEC_STG_KEY_AES256 = 0,
ESP_SEC_STG_KEY_AES256 = 1, ESP_SEC_STG_KEY_ECDSA_SECP256R1 = 1,
ESP_SEC_STG_KEY_ECDSA_SECP192R1 = 2, ESP_SEC_STG_KEY_ECDSA_SECP192R1 = 2,
ESP_SEC_STG_MAX, ESP_SEC_STG_TYPE_MAX,
} esp_tee_sec_storage_type_t; } esp_tee_sec_storage_type_t;
/** /**
* @brief Structure holding the X and Y components * @brief Configuration structure for key generation/import
* of the ECDSA public key *
*/
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 { typedef struct {
uint8_t pub_x[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< X component */ uint8_t pub_x[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< X component */
uint8_t pub_y[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< Y 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 * @brief Structure holding the R and S components of the ECDSA signature
* of the ECDSA signature
* *
*/ */
typedef struct { typedef struct {
uint8_t sign_r[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< R component */ uint8_t sign_r[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< R component */
uint8_t sign_s[MAX_ECDSA_SUPPORTED_KEY_LEN]; /*!< S 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. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_init(void); 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_id Key identifier string
* @param key_type secure storage key type to generate
* *
* @return esp_err_t ESP_OK on success, appropriate error code otherwise. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_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 * @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] cfg Pointer to the key configuration
* @param[in] key_type secure storage key type
* @param[in] hash Message digest * @param[in] hash Message digest
* @param[in] hlen Digest length * @param[in] hlen Digest length
* @param[out] out_sign Output context holding the signature * @param[out] out_sign Output context holding the signature
* *
* @return esp_err_t ESP_OK on success, appropriate error code otherwise. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_get_signature(uint16_t slot_id, 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] cfg Pointer to the key configuration
* @param[in] key_type secure storage key type * @param[out] out_pubkey Output context holding the public key
* @param[out] pubkey Output context holding the public key
* *
* @return esp_err_t ESP_OK on success, appropriate error code otherwise. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_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 * @param[in] ctx Pointer to the AEAD operation context
*
* @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 Pointer to the authentication tag buffer
* @param[out] tag_len Length of the authentication tag * @param[in] tag_len Length of the authentication tag
* @param[out] output Pointer to the output data buffer * @param[out] output Pointer to the output data buffer
* *
* @return esp_err_t ESP_OK on success, appropriate error code otherwise. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, 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);
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 * @brief Perform decryption using AES256-GCM with the key from secure storage
* *
* @param[in] slot_id Secure storage slot ID containing the AES-GCM key * @param[in] ctx Pointer to the AEAD operation context
* @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 Pointer to the authentication tag buffer
* @param[in] tag_len Length of the authentication tag * @param[in] tag_len Length of the authentication tag
* @param[out] output Pointer to the output data buffer * @param[out] output Pointer to the output data buffer
* *
* @return esp_err_t ESP_OK on success, appropriate error code otherwise. * @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/ */
esp_err_t esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, 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);
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -5,53 +5,43 @@
*/ */
#include <string.h> #include <string.h>
#include "esp_log.h"
#include "esp_cpu.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/aes.h"
#include "mbedtls/gcm.h" #include "mbedtls/gcm.h"
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#include "mbedtls/error.h" #include "mbedtls/error.h"
#include "esp_flash.h" #include "rom/efuse.h"
#include "esp_efuse.h" #if SOC_HMAC_SUPPORTED
#include "soc/efuse_reg.h" #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_flash.h"
#include "esp_tee_sec_storage.h" #include "esp_tee_sec_storage.h"
#include "secure_service_num.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 AES256_KEY_LEN 32
#define AES256_KEY_BITS (AES256_KEY_LEN * 8)
#define SECURE_STORAGE_SIZE 2048 #define AES256_DEFAULT_IV_LEN 16
#define AES256_GCM_KEY_LEN 32
#define AES256_GCM_KEY_BITS (AES256_GCM_KEY_LEN * 8)
#define AES256_GCM_IV_LEN 12 #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_SECP256R1_KEY_LEN 32
#define ECDSA_SECP192R1_KEY_LEN 24 #define ECDSA_SECP192R1_KEY_LEN 24
/* Structure to hold metadata for secure storage slots */ #define EKEY_SEED 0xAEBE5A5A
typedef struct { #define TKEY_SEED 0xCEDEA5A5
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;
/* Structure to hold ECDSA SECP256R1 key pair */ /* Structure to hold ECDSA SECP256R1 key pair */
typedef struct { 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) */ 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; } __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 { typedef struct {
uint8_t key[AES256_GCM_KEY_LEN]; /* Key for AES-256 GCM */ uint8_t key[AES256_KEY_LEN]; /* Key for AES-256 */
uint8_t iv[AES256_GCM_IV_LEN]; /* Initialization vector for AES-256 GCM */ uint8_t iv[AES256_DEFAULT_IV_LEN]; /* Initialization vector for AES-256 */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_aes256_gcm_t; } __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_aes256_t;
/* Union to hold different types of cryptographic keys */ /* Structure to hold the cryptographic keys in NVS */
typedef union { 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_secp256r1_t ecdsa_secp256r1; /* ECDSA SECP256R1 key pair */
sec_stg_ecdsa_secp192r1_t ecdsa_secp192r1; /* ECDSA SECP192R1 key pair */ sec_stg_ecdsa_secp192r1_t ecdsa_secp192r1; /* ECDSA SECP192R1 key pair */
sec_stg_aes256_gcm_t aes256_gcm; /* AES-256 GCM key and IV */ sec_stg_aes256_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; } __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) == 256, "Incorrect sec_stg_key_t size");
_Static_assert(sizeof(sec_stg_key_t) == 96, "Incorrect sec_stg_key_t size");
// Need this buffer to read the flash data and then modify and write it back #define TEE_SEC_STG_PART_LABEL "tee_nvs"
// esp_rom_spiflash_write requires that we erase the region before writing to it #define TEE_SEC_STG_NVS_NAMESPACE "tee_sec_stg"
// TODO: IDF-7586
static uint8_t tmp_buf[SECURE_STORAGE_SIZE];
// AAD buffer static nvs_handle_t tee_nvs_hdl;
static uint8_t aad_buf[AES256_GCM_AAD_LEN];
// Partition for the secure storage partition
static esp_partition_pos_t part_pos;
static const char *TAG = "secure_storage"; static const char *TAG = "secure_storage";
/* ---------------------------------------------- Helper APIs ------------------------------------------------- */ /* ---------------------------------------------- Helper APIs ------------------------------------------------- */
#if CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK > 9 #if CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID < 0
#error "TEE Secure Storage: Configured eFuse block for encryption key out of range! (see CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK)" #error "TEE Secure Storage: Configured eFuse block (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID) out of range!"
#endif #endif
static int buffer_hexdump(const char *label, const void *buffer, size_t length) 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; 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) static int rand_func(void *rng_state, unsigned char *output, size_t len)
{ {
esp_fill_random(output, len); esp_fill_random(output, len);
return 0; 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]; uint32_t ekey_seed[8] = {[0 ... 7] = EKEY_SEED};
uint8_t tag[AES256_GCM_TAG_LEN]; uint32_t tkey_seed[8] = {[0 ... 7] = TKEY_SEED};
uint8_t key[AES256_GCM_KEY_LEN];
uint8_t out_data[256] = {0};
buffer_hexdump("Plaintext data", data, len); memset(cfg, 0x00, sizeof(nvs_sec_cfg_t));
mbedtls_gcm_context gcm; int ret = -1;
mbedtls_gcm_init(&gcm); 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) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from eFuse!"); return err;
goto exit; }
#else
memset(&cfg->eky, 0x33, sizeof(cfg->eky));
memset(&cfg->tky, 0xCC, sizeof(cfg->tky));
#endif
return ESP_OK;
} }
int ret = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, key, AES256_GCM_KEY_BITS); static esp_err_t secure_storage_find_key(const char *key_id)
if (ret != 0) { {
ESP_LOGE(TAG, "Error in setting key: %d", ret); nvs_type_t out_type;
err = ESP_FAIL; return nvs_find_key(tee_nvs_hdl, key_id, &out_type);
goto exit;
} }
// Generate different IV every time GCM encrypt is called static esp_err_t secure_storage_write(const char *key_id, const void *data, size_t len)
esp_fill_random(iv, AES256_GCM_IV_LEN); {
esp_err_t err = nvs_set_blob(tee_nvs_hdl, key_id, data, len);
ret = mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, len, iv, AES256_GCM_IV_LEN, if (err != ESP_OK) {
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);
return err; return err;
} }
static esp_err_t secure_storage_read(uint16_t slot_id, uint8_t *data, size_t len, uint8_t type) err = nvs_commit(tee_nvs_hdl);
{
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 err;
} }
static esp_err_t secure_storage_read(const char *key_id, void *data, size_t *len)
{
return nvs_get_blob(tee_nvs_hdl, key_id, data, len);
}
/* ---------------------------------------------- Interface APIs ------------------------------------------------- */ /* ---------------------------------------------- Interface APIs ------------------------------------------------- */
esp_err_t esp_tee_sec_storage_init(void) esp_err_t esp_tee_sec_storage_init(void)
{ {
ESP_LOGI(TAG, "Initializing secure storage..."); nvs_sec_cfg_t cfg = {};
esp_partition_info_t part_info = {}; esp_err_t err = read_security_cfg_hmac(&cfg);
esp_err_t err = esp_tee_flash_find_partition(PART_TYPE_DATA, PART_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL, &part_info);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "No secure storage partition found (0x%08x)", err);
return err; return err;
} else { }
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 #if CONFIG_SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
ESP_LOGW(TAG, "TEE Secure Storage enabled in insecure DEVELOPMENT mode"); ESP_LOGW(TAG, "TEE Secure Storage enabled in insecure DEVELOPMENT mode");
#endif #endif
// Take backup of the partition for future usage
part_pos = part_info.pos;
}
return ESP_OK; 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) static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t key_type)
{ {
if (keyctx == NULL) { 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; curve_id = MBEDTLS_ECP_DP_SECP192R1;
key_len = ECDSA_SECP192R1_KEY_LEN; key_len = ECDSA_SECP192R1_KEY_LEN;
#else #else
ESP_LOGE(TAG, "Unsupported key type!"); ESP_LOGE(TAG, "Unsupported key-type!");
return -1; return -1;
#endif #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_context ctxECDSA;
mbedtls_ecdsa_init(&ctxECDSA); mbedtls_ecdsa_init(&ctxECDSA);
int ret = mbedtls_ecdsa_genkey(&ctxECDSA, curve_id, rand_func, NULL); int ret = mbedtls_ecdsa_genkey(&ctxECDSA, curve_id, rand_func, NULL);
if (ret != 0) { if (ret != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA key");
goto exit; goto exit;
} }
@@ -425,48 +330,49 @@ exit:
return ret; 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) { if (keyctx == NULL) {
return -1; 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.key, AES256_KEY_LEN);
esp_fill_random(&keyctx->aes256_gcm.iv, AES256_GCM_IV_LEN); esp_fill_random(&keyctx->aes256.iv, AES256_DEFAULT_IV_LEN);
return 0; 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) { if (cfg == NULL || cfg->id == NULL) {
ESP_LOGE(TAG, "Invalid slot ID");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
if (!esp_tee_sec_storage_is_slot_empty(slot_id)) { if (secure_storage_find_key(cfg->id) == ESP_OK) {
ESP_LOGE(TAG, "Slot already occupied - clear before reuse"); ESP_LOGE(TAG, "Key ID already exists");
return ESP_ERR_INVALID_STATE; 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: case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP192R1: case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
#endif #endif
if (generate_ecdsa_key(&keyctx, key_type) != 0) { if (generate_ecdsa_key(&keyctx, cfg->type) != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA keypair (%d)", ret); ESP_LOGE(TAG, "Failed to generate ECDSA keypair");
return ESP_FAIL; return ESP_FAIL;
} }
break; break;
case ESP_SEC_STG_KEY_AES256: case ESP_SEC_STG_KEY_AES256:
if (generate_aes256_gcm_key(&keyctx) != 0) { if (generate_aes256_key(&keyctx) != 0) {
ESP_LOGE(TAG, "Failed to generate AES key (%d)", ret); ESP_LOGE(TAG, "Failed to generate AES key");
return ESP_FAIL; return ESP_FAIL;
} }
break; 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 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; return ESP_ERR_INVALID_ARG;
} }
if (hlen == 0) {
return ESP_ERR_INVALID_SIZE;
}
#if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN #if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) { if (cfg->type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
ESP_LOGE(TAG, "Unsupported key type!"); ESP_LOGE(TAG, "Unsupported key-type!");
return ESP_ERR_NOT_SUPPORTED; return ESP_ERR_NOT_SUPPORTED;
} }
#endif #endif
sec_stg_key_t keyctx; esp_err_t err = secure_storage_find_key(cfg->id);
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(sec_stg_key_t), key_type);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot"); ESP_LOGE(TAG, "Key ID not found");
return err; 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_mpi r, s;
mbedtls_ecp_keypair priv_key; mbedtls_ecp_keypair priv_key;
mbedtls_ecdsa_context sign_ctx; 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; size_t key_len = 0;
int ret = -1; 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)); 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; key_len = ECDSA_SECP256R1_KEY_LEN;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN #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)); 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; key_len = ECDSA_SECP192R1_KEY_LEN;
#endif #endif
} else {
ESP_LOGE(TAG, "Unsupported key type for signature generation");
err = ESP_ERR_NOT_SUPPORTED;
goto exit;
} }
if (ret != 0) { 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; 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, ret = mbedtls_ecdsa_sign(&sign_ctx.MBEDTLS_PRIVATE(grp), &r, &s, &sign_ctx.MBEDTLS_PRIVATE(d), hash, hlen,
rand_func, NULL); 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; 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); ret = mbedtls_mpi_write_binary(&r, out_sign->sign_r, key_len);
if (ret != 0) { if (ret != 0) {
@@ -572,142 +483,93 @@ exit:
return err; 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; return ESP_ERR_INVALID_ARG;
} }
esp_err_t err = secure_storage_find_key(cfg->id);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Key ID not found");
return err;
}
sec_stg_key_t keyctx; sec_stg_key_t keyctx;
size_t key_len; size_t keyctx_len = sizeof(keyctx);
uint8_t *pub_key_src; uint8_t *pub_key_src = NULL;
size_t pub_key_len = 0;
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) { switch (cfg->type) {
key_len = ECDSA_SECP256R1_KEY_LEN; case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
pub_key_src = keyctx.ecdsa_secp256r1.pub_key; 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 #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
} else if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) { case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
key_len = ECDSA_SECP192R1_KEY_LEN;
pub_key_src = keyctx.ecdsa_secp192r1.pub_key; pub_key_src = keyctx.ecdsa_secp192r1.pub_key;
pub_key_len = ECDSA_SECP192R1_KEY_LEN;
break;
#endif #endif
} else { default:
ESP_LOGE(TAG, "Unsupported key type"); ESP_LOGE(TAG, "Unsupported key-type");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(sec_stg_key_t), key_type); err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot"); ESP_LOGE(TAG, "Failed to read key from secure storage");
return err; return err;
} }
// Copy public key components in one shot if (keyctx.type != cfg->type) {
memcpy(pubkey->pub_x, pub_key_src, key_len); ESP_LOGE(TAG, "Key type mismatch");
memcpy(pubkey->pub_y, pub_key_src + key_len, key_len); 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; return ESP_OK;
} }
bool esp_tee_sec_storage_is_slot_empty(uint16_t slot_id) 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,
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,
bool is_encrypt) bool is_encrypt)
{ {
if (slot_id > MAX_SEC_STG_SLOT_ID) { if (key_id == NULL || input == NULL || output == NULL || tag == NULL) {
ESP_LOGE(TAG, "Invalid slot ID"); ESP_LOGE(TAG, "Invalid arguments");
return ESP_ERR_INVALID_ARG;
}
if (input == NULL || output == NULL || tag == NULL) {
ESP_LOGE(TAG, "Invalid input/output/tag buffer");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
if (len == 0 || tag_len == 0) { 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; return ESP_ERR_INVALID_SIZE;
} }
sec_stg_key_t keyctx; esp_err_t err = secure_storage_find_key(key_id);
esp_err_t err = secure_storage_read(slot_id, (uint8_t *)&keyctx, sizeof(keyctx), ESP_SEC_STG_KEY_AES256);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from slot"); ESP_LOGE(TAG, "Key ID not found");
return err; 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_context gcm;
mbedtls_gcm_init(&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) { if (ret != 0) {
ESP_LOGE(TAG, "Error in setting key: %d", ret); ESP_LOGE(TAG, "Error in setting key: %d", ret);
err = ESP_FAIL; 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) { 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); aad, aad_len, input, output, tag_len, tag);
if (ret != 0) { if (ret != 0) {
ESP_LOGE(TAG, "Error in encrypting data: %d", ret); 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; goto exit;
} }
} else { } 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); aad, aad_len, tag, tag_len, input, output);
if (ret != 0) { if (ret != 0) {
ESP_LOGE(TAG, "Error in decrypting data: %d", ret); ESP_LOGE(TAG, "Error in decrypting data: %d", ret);
@@ -738,14 +600,12 @@ exit:
return err; return err;
} }
esp_err_t esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, 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)
uint16_t aad_len, uint8_t *tag, uint16_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, 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)
uint16_t aad_len, uint8_t *tag, uint16_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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -8,46 +8,32 @@
#include "esp_err.h" #include "esp_err.h"
#include "esp_tee_sec_storage.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); return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_AEAD_DECRYPT, ctx, tag, tag_len, output);
}
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);
} }

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)) && 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))); 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) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; 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)); 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) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; 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 *)data) &&
esp_tee_ptr_in_ree((void *)signature)); 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) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; 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 *)data) &&
esp_tee_ptr_in_ree((void *)esp_ds_ctx)); 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) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
@@ -356,22 +372,12 @@ int _ss_esp_tee_ota_end(void)
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */ /* ---------------------------------------------- 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); return esp_tee_sec_storage_gen_key(cfg);
}
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);
} }

View File

@@ -85,46 +85,45 @@ void _ss_wdt_hal_deinit(wdt_hal_context_t *hal)
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */ /* ---------------------------------------------- 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 *)(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) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
ESP_FAULT_ASSERT(valid_addr); 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)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)out_pubkey)) &&
(esp_tee_ptr_in_ree((void *)((char *)pubkey + sizeof(esp_tee_sec_storage_pubkey_t))))); (esp_tee_ptr_in_ree((void *)((char *)out_pubkey + sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)))));
if (!valid_addr) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
ESP_FAULT_ASSERT(valid_addr); 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, 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)
uint16_t aad_len, uint8_t *tag, uint16_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 *)tag) &&
esp_tee_ptr_in_ree((void *)output)); 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 *)(tag + tag_len)) &&
esp_tee_ptr_in_ree((void *)(output + len))); esp_tee_ptr_in_ree((void *)(output + ctx->input_len)));
if (aad) { if (ctx->aad) {
valid_addr &= (esp_tee_ptr_in_ree((void *)aad) && esp_tee_ptr_in_ree((void *)(aad + aad_len))); valid_addr &= (esp_tee_ptr_in_ree((void *)ctx->aad) && esp_tee_ptr_in_ree((void *)(ctx->aad + ctx->aad_len)));
} }
if (!valid_addr) { 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); 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, 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)
uint16_t aad_len, uint8_t *tag, uint16_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 *)tag) &&
esp_tee_ptr_in_ree((void *)output)); 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 *)(tag + tag_len)) &&
esp_tee_ptr_in_ree((void *)(output + len))); esp_tee_ptr_in_ree((void *)(output + ctx->input_len)));
if (aad) { if (ctx->aad) {
valid_addr &= (esp_tee_ptr_in_ree((void *)aad) && esp_tee_ptr_in_ree((void *)(aad + aad_len))); valid_addr &= (esp_tee_ptr_in_ree((void *)ctx->aad) && esp_tee_ptr_in_ree((void *)(ctx->aad + ctx->aad_len)));
} }
if (!valid_addr) { 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); 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 ------------------------------------------------- */ /* ---------------------------------------------- MMU HAL ------------------------------------------------- */

View File

@@ -14,6 +14,7 @@
#include "esp_tee_brownout.h" #include "esp_tee_brownout.h"
#include "esp_tee_flash.h" #include "esp_tee_flash.h"
#include "esp_tee_sec_storage.h"
#include "bootloader_utility_tee.h" #include "bootloader_utility_tee.h"
#if __has_include("esp_app_desc.h") #if __has_include("esp_app_desc.h")
@@ -23,11 +24,8 @@
/* TEE symbols */ /* TEE symbols */
extern uint32_t _tee_stack; extern uint32_t _tee_stack;
extern uint32_t _tee_intr_stack_bottom;
extern uint32_t _tee_bss_start; extern uint32_t _tee_bss_start;
extern uint32_t _tee_bss_end; extern uint32_t _tee_bss_end;
extern uint32_t _sec_world_entry;
extern uint32_t _tee_s_intr_handler; extern uint32_t _tee_s_intr_handler;
extern uint8_t _tee_heap_start[]; 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); 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 */ /* 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); err = esp_tee_flash_set_running_ree_partition(ree_drom_addr);
if (err != ESP_OK) { 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 */ /* 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_MODE_RELEASE
#if CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK > 9 #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_KEY_EFUSE_BLK)" #error "TEE: eFuse protection region for APM out of range! (see CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID)"
#endif #endif
#define LP_APM_EFUSE_REG_START \ #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 \ #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 #elif CONFIG_SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
#define LP_APM_EFUSE_REG_START EFUSE_RD_KEY5_DATA0_REG #define LP_APM_EFUSE_REG_START EFUSE_RD_KEY5_DATA0_REG
#if CONFIG_SECURE_TEE_TEST_MODE #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 CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN=y
# secure storage key slot for attestation # secure storage key slot for attestation
CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID=14 CONFIG_SECURE_TEE_ATT_KEY_STR_ID="tee_att_keyN"
# Enabling flash protection over SPI1 # Enabling flash protection over SPI1
CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1=y 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 #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; int ret = -1;
uint16_t len; 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; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
esp_tee_sec_storage_pubkey_t pubkey = {}; esp_tee_sec_storage_key_cfg_t cfg = {
if (esp_tee_sec_storage_get_pubkey(slot_id, key_type, &pubkey) != ESP_OK) { .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"); ESP_LOGE(TAG, "Failed to get public key from secure storage");
goto cleanup; goto cleanup;
} }
@@ -457,9 +462,9 @@ int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_
return ret; return ret;
} }
int slot_id = conf->tee_slot_id; const char *key_id = conf->tee_key_id;
if (slot_id < MIN_SEC_STG_SLOT_ID || slot_id > MAX_SEC_STG_SLOT_ID) { if (!key_id) {
ESP_LOGE(TAG, "Invalid slot id"); ESP_LOGE(TAG, "Invalid TEE key id");
return ret; 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))); mbedtls_mpi_init(&(keypair->MBEDTLS_PRIVATE(d)));
keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) = ECDSA_KEY_MAGIC_TEE; 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(n) = 1;
keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) = NULL;
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) { 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); 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 (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); ESP_LOGE(TAG, "Loading public key context failed, esp_ecdsa_load_pubkey() returned %d", ret);
return 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; 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_tee_sec_storage_key_cfg_t cfg = {
esp_err_t err = esp_tee_sec_storage_get_signature(slot_id, key_type, (uint8_t *)msg, msg_len, &sign); .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) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get signature"); ESP_LOGE(TAG, "Failed to get signature");
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 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 */ mbedtls_ecp_group_id grp_id; /*!< MbedTLS ECP group identifier */
union { union {
uint8_t efuse_block; /*!< EFuse block id for ECDSA private key */ 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 */ 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 slot 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 #if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
bool load_pubkey; /*!< Export ECDSA public key from the hardware */ bool load_pubkey; /*!< Export ECDSA public key from the hardware */
@@ -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. * the TEE secure storage.
* *
* @param keypair The mbedtls ECP key-pair structure * @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 * @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. * @brief Initialize PK context and fully populate the mbedtls_ecp_keypair context.

View File

@@ -1,7 +1,8 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
tee, app, tee_0, , 192K, 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, factory, app, factory, , 1536K,
nvs, data, nvs, , 24K, nvs, data, nvs, , 24K,
phy_init, data, phy, , 4K, 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_0, app, tee_0, , 192K,
tee_1, app, tee_1, , 192K, tee_1, app, tee_1, , 192K,
tee_otadata, data, tee_ota, , 8K, 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_0, app, ota_0, , 1536K,
ota_1, app, ota_1, , 1536K, ota_1, app, ota_1, , 1536K,
otadata, data, ota, , 8K, 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,