mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(esp_tee): Restrict REE access to TEE-owned secure storage keys
This commit is contained in:
@@ -18,6 +18,8 @@ options:
|
||||
-o, --output OUTPUT output binary file name
|
||||
-i, --input INPUT input key file (.pem for ecdsa, .bin for aes)
|
||||
--write-once make key persistent - cannot be modified or deleted once written
|
||||
--tee-only mark key as owned exclusively by the TEE - the REE cannot use, generate or clear it
|
||||
-h, --help Show this message and exit
|
||||
```
|
||||
|
||||
### ECDSA Keys
|
||||
@@ -31,7 +33,7 @@ python esp_tee_sec_stg_keygen.py -k ecdsa_p384 -o ecdsa_p384_k0.bin
|
||||
|
||||
```bash
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out ecdsa_p256.pem
|
||||
python esp_tee_sec_stg_keygen.py -k ecdsa_p256 -o ecdsa_p256_k1.bin -i ecdsa_p256.pem --write-once
|
||||
python esp_tee_sec_stg_keygen.py -k ecdsa_p256 -o ecdsa_p256_k1.bin -i ecdsa_p256.pem --write-once --tee-only
|
||||
```
|
||||
|
||||
### AES-256 Key
|
||||
|
||||
@@ -31,6 +31,7 @@ class KeyType(Enum):
|
||||
class Flags(IntFlag):
|
||||
NONE = 0x00000000
|
||||
WRITE_ONCE = 0x00000001
|
||||
TEE_ONLY = 0x00000002
|
||||
|
||||
|
||||
# === Key Generators ===
|
||||
@@ -112,6 +113,11 @@ def parse_args() -> argparse.Namespace:
|
||||
action='store_true',
|
||||
help='make key persistent - cannot be modified or deleted once written',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--tee-only',
|
||||
action='store_true',
|
||||
help='mark key as owned exclusively by the TEE - the REE cannot use, generate or clear it',
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -122,12 +128,16 @@ def main() -> None:
|
||||
flags = Flags.NONE
|
||||
if args.write_once:
|
||||
flags |= Flags.WRITE_ONCE
|
||||
if args.tee_only:
|
||||
flags |= Flags.TEE_ONLY
|
||||
|
||||
print(f'[+] Generating key of type: {key_type.name} (value: {key_type.value})')
|
||||
if args.input:
|
||||
print(f'[+] Using user-provided key file: {args.input}')
|
||||
if args.write_once:
|
||||
print('[+] WRITE_ONCE flag is set')
|
||||
if args.tee_only:
|
||||
print('[+] TEE_ONLY flag is set')
|
||||
|
||||
key_data = generate_key_data(key_type, flags, args.input)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) &&
|
||||
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)));
|
||||
|
||||
if (!valid_addr) {
|
||||
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)) &&
|
||||
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_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)) &&
|
||||
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_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);
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ static int tee_sec_stg_gen_key(int argc, char **argv)
|
||||
|
||||
err = esp_tee_sec_storage_clear_key(cfg.id);
|
||||
if (err != ESP_OK && err != ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "Failed to clear key %d!", cfg.id);
|
||||
ESP_LOGE(TAG, "Failed to clear key %s!", cfg.id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import hashlib
|
||||
import http.server
|
||||
@@ -135,10 +135,6 @@ def test_tee_cli_attestation(dut: Dut) -> None:
|
||||
dut.expect('ESP-TEE: Secure services demonstration', timeout=30)
|
||||
time.sleep(1)
|
||||
|
||||
att_key_id = dut.app.sdkconfig.get('SECURE_TEE_ATT_KEY_STR_ID')
|
||||
dut.write(f'tee_sec_stg_gen_key {att_key_id} 1')
|
||||
dut.expect(r'Generated ECDSA_SECP256R1 key with ID (\S+)', timeout=30)
|
||||
|
||||
# Get the Entity Attestation token from TEE and verify its signature
|
||||
dut.write('tee_att_info')
|
||||
dut.expect(r'Attestation token - Length: (\d+)', timeout=30)
|
||||
|
||||
@@ -5,8 +5,8 @@ CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5
|
||||
# Reducing TEE I/DRAM sizes
|
||||
# 24KB
|
||||
CONFIG_SECURE_TEE_IRAM_SIZE=0x6000
|
||||
# 16KB
|
||||
CONFIG_SECURE_TEE_DRAM_SIZE=0x4000
|
||||
# 17KB
|
||||
CONFIG_SECURE_TEE_DRAM_SIZE=0x4400
|
||||
|
||||
# Disable TEE logs (also disable all panic logs)
|
||||
CONFIG_SECURE_TEE_DEBUG_MODE=n
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# builds across various configurations - and is not intended for production use.
|
||||
|
||||
# Reducing TEE IRAM size
|
||||
# 30KB
|
||||
CONFIG_SECURE_TEE_IRAM_SIZE=0x7800
|
||||
# 31KB
|
||||
CONFIG_SECURE_TEE_IRAM_SIZE=0x7C00
|
||||
|
||||
# TEE Secure Storage: Release mode
|
||||
CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y
|
||||
|
||||
@@ -418,6 +418,7 @@ class TEESerial(IdfSerial):
|
||||
'type': 'ecdsa_p256',
|
||||
'input': 'ecdsa_p256_key.pem',
|
||||
'write_once': True,
|
||||
'tee_only': True,
|
||||
'b64': (
|
||||
'LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUlNU1VpUktHaVZjSTIvbUZFekI3eXRIOVJj'
|
||||
'd0wyUThkNDhONHNFUHFYc0RvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkYxYXRZQUxrdnB4cCt4N3c1dmVPQ1Vj'
|
||||
@@ -493,6 +494,7 @@ class TEESerial(IdfSerial):
|
||||
[sys.executable, ESP_TEE_SEC_STG_KEYGEN, '-k', entry['type'], '-o', str(tmp_dir / f'{entry["key"]}.bin')]
|
||||
+ (['-i', entry['input']] if entry['input'] else [])
|
||||
+ (['--write-once'] if entry['write_once'] else [])
|
||||
+ (['--tee-only'] if entry.get('tee_only') else [])
|
||||
for entry in self.KEY_DEFS
|
||||
]
|
||||
|
||||
|
||||
@@ -365,6 +365,38 @@ TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[sec_storag
|
||||
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_TEE_ATTESTATION
|
||||
TEST_CASE("Test TEE Secure Storage - Attestation key is not REE-accessible", "[sec_storage]")
|
||||
{
|
||||
const char *att_key_id = CONFIG_SECURE_TEE_ATT_KEY_STR_ID;
|
||||
|
||||
esp_tee_sec_storage_key_cfg_t key_cfg = {
|
||||
.id = att_key_id,
|
||||
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1
|
||||
};
|
||||
|
||||
uint8_t digest[SHA256_DIGEST_SZ];
|
||||
esp_fill_random(digest, sizeof(digest));
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_gen_key(&key_cfg));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_clear_key(att_key_id));
|
||||
|
||||
esp_tee_sec_storage_ecdsa_sign_t sign = {};
|
||||
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_sign(&key_cfg, digest, sizeof(digest), &sign));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey));
|
||||
|
||||
uint8_t data[31], tag[12], iv[12];
|
||||
esp_tee_sec_storage_aead_ctx_t aead_ctx = {
|
||||
.key_id = att_key_id,
|
||||
.input = data,
|
||||
.input_len = sizeof(data),
|
||||
};
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), data));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_decrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), data));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("Test TEE Secure Storage - Verify data encryption", "[sec_storage_encr]")
|
||||
{
|
||||
ESP_LOGI(TAG, "Populating NVS-based TEE Secure Storage; encrypted with XTS-AES-512");
|
||||
@@ -423,6 +455,22 @@ TEST_CASE("Test TEE Secure Storage - WRITE_ONCE keys", "[sec_storage]")
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(key_cfg.id));
|
||||
}
|
||||
|
||||
TEST_CASE("Test TEE Secure Storage - TEE_ONLY keys", "[sec_storage]")
|
||||
{
|
||||
const char *key_id = "key_id_tee_only";
|
||||
esp_tee_sec_storage_key_cfg_t key_cfg = {
|
||||
.id = key_id,
|
||||
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1,
|
||||
.flags = SEC_STORAGE_FLAG_TEE_ONLY,
|
||||
};
|
||||
|
||||
esp_err_t err = esp_tee_sec_storage_clear_key(key_cfg.id);
|
||||
TEST_ASSERT_TRUE(err == ESP_OK || err == ESP_ERR_NOT_FOUND);
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_gen_key(&key_cfg));
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_clear_key(key_cfg.id));
|
||||
}
|
||||
|
||||
static void test_aead_encrypt_decrypt(const char *key_id, const uint8_t *input, size_t len)
|
||||
{
|
||||
uint8_t *ciphertext = heap_caps_malloc(len, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
@@ -524,10 +572,19 @@ TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_ke
|
||||
size_t token_len = 0;
|
||||
TEST_ESP_OK(psa_initial_attest_get_token(auth_challenge, challenge_size, token_buf, token_buf_size, &token_len));
|
||||
free(token_buf);
|
||||
#endif /* CONFIG_SECURE_TEE_ATTESTATION */
|
||||
|
||||
const char *attest_key_id = "attest_key";
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(attest_key_id));
|
||||
#endif /* CONFIG_SECURE_TEE_ATTESTATION */
|
||||
esp_tee_sec_storage_key_cfg_t attest_cfg = {
|
||||
.id = attest_key_id,
|
||||
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1,
|
||||
};
|
||||
esp_tee_sec_storage_ecdsa_sign_t attest_sign = {0};
|
||||
esp_tee_sec_storage_ecdsa_pubkey_t attest_pubkey = {0};
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_sign(&attest_cfg, digest_buf, SHA256_DIGEST_SZ, &attest_sign));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_get_pubkey(&attest_cfg, &attest_pubkey));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_clear_key(attest_key_id));
|
||||
}
|
||||
|
||||
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||
|
||||
@@ -14,6 +14,10 @@ To ensure security, the EAT is cryptographically protected. The remote relying p
|
||||
|
||||
- Support for Attestation can be toggled using the option :ref:`CONFIG_SECURE_TEE_ATTESTATION` (enabled by default).
|
||||
|
||||
- The attestation signing key (identified by :ref:`CONFIG_SECURE_TEE_ATT_KEY_STR_ID`) is owned exclusively by the TEE. When the TEE generates this key, it is marked with the ``SEC_STORAGE_FLAG_TEE_ONLY`` flag, and the REE is denied any access to it through the secure service interface - it cannot use the key for signing, regenerate it, or clear it. This ensures that the attestation evidence can only ever be signed from within the TEE.
|
||||
|
||||
- In addition, the reserved key ID is treated as TEE-owned even before the key exists, which prevents the REE from "squatting" the ID with a key of its own before the TEE provisions it. If the key is pre-provisioned as part of an NVS image (see :doc:`Secure Storage <tee-sec-storage>`), it **must** be generated with the ``--tee-only`` flag of the :component_file:`esp_tee_sec_stg_keygen.py<esp_tee/scripts/esp_tee_sec_stg_keygen/esp_tee_sec_stg_keygen.py>` tool.
|
||||
|
||||
Attestation Flow
|
||||
----------------
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter)
|
||||
|
||||
esp_err_t err = esp_tee_sec_storage_clear_key(cfg.id);
|
||||
if (err != ESP_OK && err != ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "Failed to clear key %d!", cfg.id);
|
||||
ESP_LOGE(TAG, "Failed to clear key %s!", cfg.id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ static void example_tee_sec_stg_encrypt_decrypt(void *pvParameter)
|
||||
|
||||
err = esp_tee_sec_storage_clear_key(cfg.id);
|
||||
if (err != ESP_OK && err != ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "Failed to clear key %d!", cfg.id);
|
||||
ESP_LOGE(TAG, "Failed to clear key %s!", cfg.id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user