mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
feat(esp_tee): Restrict REE access to TEE-owned secure storage keys
This commit is contained in:
@@ -42,6 +42,8 @@ static esp_err_t gen_ecdsa_keypair_secp256r1(esp_att_ecdsa_keypair_t *keypair)
|
||||
esp_tee_sec_storage_key_cfg_t key_cfg = {
|
||||
.id = (const char *)(ESP_ATT_TK_KEY_ID),
|
||||
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1,
|
||||
/* The attestation key must never be usable from the REE */
|
||||
.flags = SEC_STORAGE_FLAG_TEE_ONLY,
|
||||
};
|
||||
|
||||
esp_err_t err = esp_tee_sec_storage_gen_key(&key_cfg);
|
||||
|
||||
+18
@@ -16,6 +16,8 @@ extern "C" {
|
||||
#include "esp_err.h"
|
||||
#include "esp_bit_defs.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
|
||||
#define MAX_ECDSA_SUPPORTED_KEY_LEN 48 /*!< Maximum supported size for the ECDSA key (SECP384R1) */
|
||||
#else
|
||||
@@ -25,6 +27,7 @@ extern "C" {
|
||||
|
||||
#define SEC_STORAGE_FLAG_NONE 0 /*!< No flags */
|
||||
#define SEC_STORAGE_FLAG_WRITE_ONCE BIT(0) /*!< Data can only be written once */
|
||||
#define SEC_STORAGE_FLAG_TEE_ONLY BIT(1) /*!< Key is owned exclusively by the TEE */
|
||||
|
||||
/**
|
||||
* @brief Enum to represent the type of key stored in the secure storage
|
||||
@@ -97,6 +100,21 @@ typedef struct {
|
||||
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
|
||||
*/
|
||||
esp_err_t esp_tee_sec_storage_init(void);
|
||||
|
||||
/**
|
||||
* @brief Check whether a key ID is owned exclusively by the TEE
|
||||
*
|
||||
* A key is TEE-owned if either:
|
||||
* - it refers to the reserved TEE attestation key
|
||||
* (`CONFIG_SECURE_TEE_ATT_KEY_STR_ID`); this also blocks the REE from
|
||||
* "squatting" the ID before the TEE creates the key, or
|
||||
* - the stored key carries the ::SEC_STORAGE_FLAG_TEE_ONLY flag.
|
||||
*
|
||||
* @param key_id NULL-terminated key identifier string (may be NULL)
|
||||
*
|
||||
* @return true if the key is TEE-owned (REE access must be denied), false otherwise
|
||||
*/
|
||||
bool esp_tee_sec_storage_is_key_tee_owned(const char *key_id);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -287,6 +287,29 @@ 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);
|
||||
}
|
||||
|
||||
bool esp_tee_sec_storage_is_key_tee_owned(const char *key_id)
|
||||
{
|
||||
if (key_id == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_att_key = false, is_tee_only = false;
|
||||
esp_err_t err = ESP_FAIL;
|
||||
|
||||
#if CONFIG_SECURE_TEE_ATTESTATION
|
||||
is_att_key = (strncmp(key_id, CONFIG_SECURE_TEE_ATT_KEY_STR_ID, NVS_KEY_NAME_MAX_SIZE) == 0);
|
||||
#endif
|
||||
|
||||
sec_stg_key_t keyctx = {};
|
||||
size_t keyctx_len = sizeof(keyctx);
|
||||
|
||||
err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len);
|
||||
is_tee_only = (err == ESP_OK) && ((keyctx.flags & SEC_STORAGE_FLAG_TEE_ONLY) != 0);
|
||||
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
|
||||
|
||||
return (is_att_key || is_tee_only);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------- Interface APIs ------------------------------------------------- */
|
||||
|
||||
esp_err_t esp_tee_sec_storage_init(void)
|
||||
|
||||
@@ -592,17 +592,24 @@ int _ss_esp_tee_ota_end(void)
|
||||
*/
|
||||
esp_err_t _ss_esp_tee_sec_storage_clear_key(const char *key_id)
|
||||
{
|
||||
bool valid_arg = !esp_tee_sec_storage_is_key_tee_owned(key_id);
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_clear_key(key_id);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
|
||||
{
|
||||
bool valid_addr = esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t));
|
||||
|
||||
if (!valid_addr) {
|
||||
bool valid_arg = esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
!(cfg->flags & SEC_STORAGE_FLAG_TEE_ONLY) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id);
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_gen_key(cfg);
|
||||
}
|
||||
|
||||
@@ -195,67 +195,69 @@ void _ss_wdt_hal_deinit(wdt_hal_context_t *hal)
|
||||
*/
|
||||
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_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(hash, hlen) &&
|
||||
esp_tee_buf_in_ree(out_sign, sizeof(esp_tee_sec_storage_ecdsa_sign_t)));
|
||||
|
||||
if (!valid_addr) {
|
||||
bool valid_arg = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(hash, hlen) &&
|
||||
esp_tee_buf_in_ree(out_sign, sizeof(esp_tee_sec_storage_ecdsa_sign_t)) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id));
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_ecdsa_sign(cfg, hash, hlen, out_sign);
|
||||
}
|
||||
|
||||
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_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(out_pubkey, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)));
|
||||
|
||||
if (!valid_addr) {
|
||||
bool valid_arg = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(out_pubkey, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id));
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_ecdsa_get_pubkey(cfg, out_pubkey);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len, uint8_t *output)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(iv, iv_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len));
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(iv, iv_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx->key_id));
|
||||
|
||||
if (ctx->aad_len != 0) {
|
||||
valid_addr &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
}
|
||||
|
||||
if (!valid_addr) {
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_aead_encrypt(ctx, iv, iv_len, tag, tag_len, output);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *output)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(iv, iv_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len));
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(iv, iv_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx->key_id));
|
||||
|
||||
if (ctx->aad_len != 0) {
|
||||
valid_addr &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
}
|
||||
|
||||
if (!valid_addr) {
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_aead_decrypt(ctx, iv, iv_len, tag, tag_len, output);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user