feat(esp_tee): Clear out all sensitive buffers explicitly after TEE crypto operations

This commit is contained in:
Laukik Hase
2026-05-26 11:44:47 +05:30
parent a88716153b
commit 2c38c285cf
11 changed files with 417 additions and 341 deletions
@@ -176,6 +176,13 @@ esp_err_t esp_att_generate_token(const uint32_t nonce, const uint32_t client_id,
}
esp_att_ecdsa_keypair_t keypair = {};
mbedtls_sha256_context ctx;
mbedtls_sha256_init(&ctx);
char *hdr_json = NULL;
char *eat_json = NULL;
char *pubkey_json = NULL;
char *sign_json = NULL;
err = esp_att_utils_ecdsa_gen_keypair_secp256r1(&keypair);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to generate ECDSA key-pair!");
@@ -196,13 +203,10 @@ esp_err_t esp_att_generate_token(const uint32_t nonce, const uint32_t client_id,
memset(token_buf, 0x00, token_buf_size);
mbedtls_sha256_context ctx;
mbedtls_sha256_init(&ctx);
int ret = mbedtls_sha256_starts(&ctx, false);
if (ret != 0) {
mbedtls_sha256_free(&ctx);
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
json_gen_str_t jstr;
@@ -211,79 +215,83 @@ esp_err_t esp_att_generate_token(const uint32_t nonce, const uint32_t client_id,
/* Pushing the Header object */
const esp_att_token_hdr_t tk_hdr = {};
char *hdr_json = NULL;
int hdr_len = -1;
/* NOTE: Token header is not yet configurable */
err = esp_att_utils_header_to_json(&tk_hdr, &hdr_json, &hdr_len);
if (err != ESP_OK || hdr_json == NULL || hdr_len <= 0) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to format the token header as JSON!");
return err;
goto exit;
}
json_gen_push_object_str(&jstr, "header", hdr_json);
ret = mbedtls_sha256_update(&ctx, (const unsigned char *)hdr_json, hdr_len - 1);
if (ret != 0) {
mbedtls_sha256_free(&ctx);
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
free(hdr_json);
hdr_json = NULL;
/* Pushing the EAT object */
char *eat_json = NULL;
int eat_len = -1;
err = esp_att_utils_eat_data_to_json(&sw_claim_data, &cfg, &eat_json, &eat_len);
if (err != ESP_OK || eat_json == NULL || eat_len <= 0) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to format the EAT data to JSON!");
return err;
goto exit;
}
json_gen_push_object_str(&jstr, "eat", eat_json);
ret = mbedtls_sha256_update(&ctx, (const unsigned char *)eat_json, eat_len - 1);
if (ret != 0) {
mbedtls_sha256_free(&ctx);
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
free(eat_json);
eat_json = NULL;
char *pubkey_json = NULL;
int pubkey_len = -1;
err = esp_att_utils_pubkey_to_json(&keypair, &pubkey_json, &pubkey_len);
if (err != ESP_OK || pubkey_json == NULL || pubkey_len <= 0) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to format the public key data to JSON!");
return err;
goto exit;
}
json_gen_push_object_str(&jstr, "public_key", pubkey_json);
ret = mbedtls_sha256_update(&ctx, (const unsigned char *)pubkey_json, pubkey_len - 1);
if (ret != 0) {
mbedtls_sha256_free(&ctx);
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
free(pubkey_json);
pubkey_json = NULL;
uint8_t digest[SHA256_DIGEST_SZ] = {0};
ret = mbedtls_sha256_finish(&ctx, digest);
if (ret != 0) {
mbedtls_sha256_free(&ctx);
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
mbedtls_sha256_free(&ctx);
char *sign_json = NULL;
int sign_len = -1;
err = esp_att_utils_sign_to_json(&keypair, digest, sizeof(digest), &sign_json, &sign_len);
if (err != ESP_OK || sign_json == NULL || sign_len <= 0) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to format the token signature to JSON!");
return err;
goto exit;
}
json_gen_push_object_str(&jstr, "sign", sign_json);
free(sign_json);
sign_json = NULL;
json_gen_end_object(&jstr);
*token_len = json_gen_str_end(&jstr);
err = ESP_OK;
exit:
mbedtls_sha256_free(&ctx);
free(hdr_json);
free(eat_json);
free(pubkey_json);
free(sign_json);
free_sw_claim_list();
return err;
}
@@ -22,6 +22,7 @@
#include "mbedtls/ecdsa.h"
#include "mbedtls/error.h"
#include "esp_hmac_pbkdf2.h"
#include "mbedtls/platform_util.h"
#include "esp_rom_sys.h"
#include "nvs.h"
@@ -148,6 +149,7 @@ static esp_err_t compute_nvs_keys_with_hmac(hmac_key_id_t hmac_key_id, nvs_sec_c
err |= esp_hmac_calculate(hmac_key_id, tkey_seed, sizeof(tkey_seed), (uint8_t *)cfg->tky);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to calculate seed HMAC");
mbedtls_platform_zeroize(cfg, sizeof(nvs_sec_cfg_t));
return ESP_FAIL;
}
ESP_FAULT_ASSERT(err == ESP_OK);
@@ -245,20 +247,24 @@ esp_err_t esp_tee_sec_storage_clear_key(const char *key_id)
esp_err_t err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
return err;
goto cleanup;
}
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 = ESP_ERR_INVALID_STATE;
goto cleanup;
}
err = nvs_erase_key(tee_nvs_hdl, key_id);
if (err != ESP_OK) {
return err;
goto cleanup;
}
err = nvs_commit(tee_nvs_hdl);
cleanup:
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
return err;
}
@@ -353,6 +359,7 @@ esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
return ESP_ERR_INVALID_STATE;
}
esp_err_t err;
sec_stg_key_t keyctx = {
.type = cfg->type,
.flags = cfg->flags,
@@ -365,21 +372,28 @@ esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
#endif
if (generate_ecdsa_key(&keyctx, cfg->type) != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA keypair");
return ESP_FAIL;
err = ESP_FAIL;
goto cleanup;
}
break;
case ESP_SEC_STG_KEY_AES256:
if (generate_aes256_key(&keyctx) != 0) {
ESP_LOGE(TAG, "Failed to generate AES key");
return ESP_FAIL;
err = ESP_FAIL;
goto cleanup;
}
break;
default:
ESP_LOGE(TAG, "Unsupported key-type!");
return ESP_ERR_NOT_SUPPORTED;
err = ESP_ERR_NOT_SUPPORTED;
goto cleanup;
}
return secure_storage_write(cfg->id, (void *)&keyctx, sizeof(keyctx));
err = secure_storage_write(cfg->id, (void *)&keyctx, sizeof(keyctx));
cleanup:
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
return err;
}
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)
@@ -403,16 +417,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
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) {
return err;
}
if (keyctx.type != cfg->type) {
ESP_LOGE(TAG, "Key type mismatch");
return ESP_ERR_INVALID_STATE;
}
mbedtls_mpi r, s;
mbedtls_ecp_keypair priv_key;
mbedtls_ecdsa_context sign_ctx;
@@ -422,6 +426,18 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
mbedtls_ecp_keypair_init(&priv_key);
mbedtls_ecdsa_init(&sign_ctx);
err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from storage");
goto exit;
}
if (keyctx.type != cfg->type) {
ESP_LOGE(TAG, "Key type mismatch");
err = ESP_ERR_INVALID_STATE;
goto exit;
}
size_t key_len = 0;
int ret = -1;
@@ -475,6 +491,7 @@ exit:
mbedtls_ecp_keypair_free(&priv_key);
mbedtls_mpi_free(&s);
mbedtls_mpi_free(&r);
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
return err;
}
@@ -515,18 +532,22 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to read key from secure storage");
return err;
goto cleanup;
}
if (keyctx.type != cfg->type) {
ESP_LOGE(TAG, "Key type mismatch");
return ESP_ERR_INVALID_STATE;
err = ESP_ERR_INVALID_STATE;
goto cleanup;
}
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);
err = ESP_OK;
return ESP_OK;
cleanup:
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
return err;
}
static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t *input, size_t len, const uint8_t *aad,
@@ -550,19 +571,21 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
sec_stg_key_t keyctx;
size_t keyctx_len = sizeof(keyctx);
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);
err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
return err;
ESP_LOGE(TAG, "Failed to fetch key from storage");
goto exit;
}
if (keyctx.type != ESP_SEC_STG_KEY_AES256) {
ESP_LOGE(TAG, "Key type mismatch");
return ESP_ERR_INVALID_STATE;
err = ESP_ERR_INVALID_STATE;
goto exit;
}
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);
int ret = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, keyctx.aes256.key, AES256_KEY_BITS);
if (ret != 0) {
ESP_LOGE(TAG, "Error in setting key: %d", ret);
@@ -595,6 +618,7 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
exit:
mbedtls_gcm_free(&gcm);
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
return err;
}
@@ -743,7 +767,7 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2
exit:
if (derived_key) {
memset(derived_key, 0x00, key_len);
mbedtls_platform_zeroize(derived_key, key_len);
free(derived_key);
}
mbedtls_ecp_keypair_free(&keypair);
@@ -0,0 +1,223 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Shared assembly helpers (macros + assembler-time constants) for the TEE
* M-mode runtime. Included from esp_tee_vectors_{plic,clic}.S
*/
#pragma once
#include "sdkconfig.h"
#include "riscv/rvruntime-frames.h"
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
#include "esp_private/hw_stack_guard.h"
#endif
/* Shared assembler-time constants used by the macros */
.equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
.equ MAGIC, 0x1f
/* Macro which first allocates space on the stack to save general
* purpose registers, and then save them. GP register is excluded.
* The default size allocated on the stack is CONTEXT_SIZE, but it
* can be overridden. */
.macro save_general_regs cxt_size=CONTEXT_SIZE
addi sp, sp, -\cxt_size
sw ra, RV_STK_RA(sp)
sw tp, RV_STK_TP(sp)
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp)
sw t2, RV_STK_T2(sp)
sw s0, RV_STK_S0(sp)
sw s1, RV_STK_S1(sp)
sw a0, RV_STK_A0(sp)
sw a1, RV_STK_A1(sp)
sw a2, RV_STK_A2(sp)
sw a3, RV_STK_A3(sp)
sw a4, RV_STK_A4(sp)
sw a5, RV_STK_A5(sp)
sw a6, RV_STK_A6(sp)
sw a7, RV_STK_A7(sp)
sw s2, RV_STK_S2(sp)
sw s3, RV_STK_S3(sp)
sw s4, RV_STK_S4(sp)
sw s5, RV_STK_S5(sp)
sw s6, RV_STK_S6(sp)
sw s7, RV_STK_S7(sp)
sw s8, RV_STK_S8(sp)
sw s9, RV_STK_S9(sp)
sw s10, RV_STK_S10(sp)
sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
.endm
.macro save_mepc
csrr t0, mepc
sw t0, RV_STK_MEPC(sp)
.endm
.macro save_mcsr
csrr t0, mstatus
sw t0, RV_STK_MSTATUS(sp)
csrr t0, mtvec
sw t0, RV_STK_MTVEC(sp)
csrr t0, mtval
sw t0, RV_STK_MTVAL(sp)
csrr t0, mhartid
sw t0, RV_STK_MHARTID(sp)
csrr t0, mcause
sw t0, RV_STK_MCAUSE(sp)
.endm
/* Restore the general purpose registers (excluding gp) from the context on
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
* but it can be overridden. */
.macro restore_general_regs cxt_size=CONTEXT_SIZE
lw ra, RV_STK_RA(sp)
lw tp, RV_STK_TP(sp)
lw t0, RV_STK_T0(sp)
lw t1, RV_STK_T1(sp)
lw t2, RV_STK_T2(sp)
lw s0, RV_STK_S0(sp)
lw s1, RV_STK_S1(sp)
lw a0, RV_STK_A0(sp)
lw a1, RV_STK_A1(sp)
lw a2, RV_STK_A2(sp)
lw a3, RV_STK_A3(sp)
lw a4, RV_STK_A4(sp)
lw a5, RV_STK_A5(sp)
lw a6, RV_STK_A6(sp)
lw a7, RV_STK_A7(sp)
lw s2, RV_STK_S2(sp)
lw s3, RV_STK_S3(sp)
lw s4, RV_STK_S4(sp)
lw s5, RV_STK_S5(sp)
lw s6, RV_STK_S6(sp)
lw s7, RV_STK_S7(sp)
lw s8, RV_STK_S8(sp)
lw s9, RV_STK_S9(sp)
lw s10, RV_STK_S10(sp)
lw s11, RV_STK_S11(sp)
lw t3, RV_STK_T3(sp)
lw t4, RV_STK_T4(sp)
lw t5, RV_STK_T5(sp)
lw t6, RV_STK_T6(sp)
addi sp, sp, \cxt_size
.endm
.macro restore_mepc
lw t0, RV_STK_MEPC(sp)
csrw mepc, t0
.endm
.macro store_magic_general_regs
lui ra, MAGIC
lui tp, MAGIC
lui t0, MAGIC
lui t1, MAGIC
lui t2, MAGIC
lui s0, MAGIC
lui s1, MAGIC
lui a0, MAGIC
lui a1, MAGIC
lui a2, MAGIC
lui a3, MAGIC
lui a4, MAGIC
lui a5, MAGIC
lui a6, MAGIC
lui a7, MAGIC
lui s2, MAGIC
lui s3, MAGIC
lui s4, MAGIC
lui s5, MAGIC
lui s6, MAGIC
lui s7, MAGIC
lui s8, MAGIC
lui s9, MAGIC
lui s10, MAGIC
lui s11, MAGIC
lui t3, MAGIC
lui t4, MAGIC
lui t5, MAGIC
lui t6, MAGIC
.endm
/**
* STACK_GUARD_PRE_SWITCH
* Stops HW stack-guard monitoring and optionally saves current bounds.
*
* Args:
* op_reg – output register for "monitoring enabled" state (must be reused)
* to_save – 1=save bounds to memory, 0=skip saving
* sp_min – symbol to store lower bound (if to_save=1)
* sp_max – symbol to store upper bound (if to_save=1)
*
* Clobbers: t0, t1, t2, op_reg
*/
.macro STACK_GUARD_PRE_SWITCH op_reg, to_save, sp_min, sp_max
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
/* Query if monitoring is enabled: result goes into \op_reg */
ESP_HW_STACK_GUARD_MONITOR_QUERY_CUR_CORE t2 \op_reg
beqz \op_reg, 1f
.if \to_save
/* Save current REE/U-mode stack bounds */
ESP_HW_STACK_GUARD_GET_BOUNDS_CUR_CORE t2 t0 t1
la t2, \sp_min
sw t0, 0(t2)
la t2, \sp_max
sw t1, 0(t2)
.endif
/* Stop monitoring */
ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE t0 t1
fence
1:
#endif
.endm
/**
* STACK_GUARD_POST_SWITCH
* Restores or applies new bounds after switching stacks, then restarts monitoring.
*
* Args:
* op_reg – saved monitoring state from PRE_SWITCH
* to_restore – 1=restore from memory, 0=set static bounds
* sp_min – saved bound (restore) or static lower bound (S-mode)
* sp_max – saved bound (restore) or static upper bound (S-mode)
*
* Clobbers: t0, t1, t2
*/
.macro STACK_GUARD_POST_SWITCH op_reg, to_restore, sp_min, sp_max
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
/* Check if monitoring was enabled (using saved state from op_reg) */
beqz \op_reg, 1f
.if \to_restore
/* Restore saved REE/U-mode bounds from memory */
la t2, \sp_min
lw t0, 0(t2)
la t2, \sp_max
lw t1, 0(t2)
.else
/* Use new TEE/S-mode stack bounds (static symbols) */
la t0, \sp_min
la t1, \sp_max
.endif
/* Apply bounds to hardware stack guard */
ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE t2 t0 t1
/* Restart monitoring */
ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE t0 t1
1:
#endif
.endm
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -16,11 +16,10 @@
#include "esp_tee_intr_defs.h"
#include "sdkconfig.h"
.equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
#include "esp_tee_asm_utils.inc"
.equ panic_from_exception, tee_panic_from_exc
.equ panic_from_isr, tee_panic_from_isr
.equ MAGIC, 0x1f
.equ RTNVAL, 0xc0de
.equ ECALL_U_MODE, 0x8
.equ ECALL_M_MODE, 0xb
@@ -48,133 +47,13 @@ _s_sp:
_s_intr_thresh:
.word 0
/* Macro which first allocates space on the stack to save general
* purpose registers, and then save them. GP register is excluded.
* The default size allocated on the stack is CONTEXT_SIZE, but it
* can be overridden. */
.macro save_general_regs cxt_size=CONTEXT_SIZE
addi sp, sp, -\cxt_size
sw ra, RV_STK_RA(sp)
sw tp, RV_STK_TP(sp)
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp)
sw t2, RV_STK_T2(sp)
sw s0, RV_STK_S0(sp)
sw s1, RV_STK_S1(sp)
sw a0, RV_STK_A0(sp)
sw a1, RV_STK_A1(sp)
sw a2, RV_STK_A2(sp)
sw a3, RV_STK_A3(sp)
sw a4, RV_STK_A4(sp)
sw a5, RV_STK_A5(sp)
sw a6, RV_STK_A6(sp)
sw a7, RV_STK_A7(sp)
sw s2, RV_STK_S2(sp)
sw s3, RV_STK_S3(sp)
sw s4, RV_STK_S4(sp)
sw s5, RV_STK_S5(sp)
sw s6, RV_STK_S6(sp)
sw s7, RV_STK_S7(sp)
sw s8, RV_STK_S8(sp)
sw s9, RV_STK_S9(sp)
sw s10, RV_STK_S10(sp)
sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
.endm
.global _ns_sp_min
_ns_sp_min:
.word 0
.macro save_mepc
csrr t0, mepc
sw t0, RV_STK_MEPC(sp)
.endm
.macro save_mcsr
csrr t0, mstatus
sw t0, RV_STK_MSTATUS(sp)
csrr t0, mtvec
sw t0, RV_STK_MTVEC(sp)
csrr t0, mtval
sw t0, RV_STK_MTVAL(sp)
csrr t0, mhartid
sw t0, RV_STK_MHARTID(sp)
csrr t0, mcause
sw t0, RV_STK_MCAUSE(sp)
.endm
/* Restore the general purpose registers (excluding gp) from the context on
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
* but it can be overridden. */
.macro restore_general_regs cxt_size=CONTEXT_SIZE
lw ra, RV_STK_RA(sp)
lw tp, RV_STK_TP(sp)
lw t0, RV_STK_T0(sp)
lw t1, RV_STK_T1(sp)
lw t2, RV_STK_T2(sp)
lw s0, RV_STK_S0(sp)
lw s1, RV_STK_S1(sp)
lw a0, RV_STK_A0(sp)
lw a1, RV_STK_A1(sp)
lw a2, RV_STK_A2(sp)
lw a3, RV_STK_A3(sp)
lw a4, RV_STK_A4(sp)
lw a5, RV_STK_A5(sp)
lw a6, RV_STK_A6(sp)
lw a7, RV_STK_A7(sp)
lw s2, RV_STK_S2(sp)
lw s3, RV_STK_S3(sp)
lw s4, RV_STK_S4(sp)
lw s5, RV_STK_S5(sp)
lw s6, RV_STK_S6(sp)
lw s7, RV_STK_S7(sp)
lw s8, RV_STK_S8(sp)
lw s9, RV_STK_S9(sp)
lw s10, RV_STK_S10(sp)
lw s11, RV_STK_S11(sp)
lw t3, RV_STK_T3(sp)
lw t4, RV_STK_T4(sp)
lw t5, RV_STK_T5(sp)
lw t6, RV_STK_T6(sp)
addi sp,sp, \cxt_size
.endm
.macro restore_mepc
lw t0, RV_STK_MEPC(sp)
csrw mepc, t0
.endm
.macro store_magic_general_regs
lui ra, MAGIC
lui tp, MAGIC
lui t0, MAGIC
lui t1, MAGIC
lui t2, MAGIC
lui s0, MAGIC
lui s1, MAGIC
lui a0, MAGIC
lui a1, MAGIC
lui a2, MAGIC
lui a3, MAGIC
lui a4, MAGIC
lui a5, MAGIC
lui a6, MAGIC
lui a7, MAGIC
lui s2, MAGIC
lui s3, MAGIC
lui s4, MAGIC
lui s5, MAGIC
lui s6, MAGIC
lui s7, MAGIC
lui s8, MAGIC
lui s9, MAGIC
lui s10, MAGIC
lui s11, MAGIC
lui t3, MAGIC
lui t4, MAGIC
lui t5, MAGIC
lui t6, MAGIC
.endm
.global _ns_sp_max
_ns_sp_max:
.word 0
.section .exception_vectors.text, "ax"
@@ -311,6 +190,7 @@ _skip_thresh_restore:
* The A0 register contains the return value of the corresponding service.
* After restoring the entire register context, we assign A0 the value back to the return value. */
csrw mscratch, a0
restore_general_regs
csrrw a0, mscratch, zero
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -16,11 +16,10 @@
#include "esp_tee_intr_defs.h"
#include "sdkconfig.h"
.equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
#include "esp_tee_asm_utils.inc"
.equ panic_from_exception, tee_panic_from_exc
.equ panic_from_isr, tee_panic_from_isr
.equ MAGIC, 0x1f
.equ RTNVAL, 0xc0de
.equ ECALL_U_MODE, 0x8
.equ ECALL_M_MODE, 0xb
@@ -49,133 +48,13 @@ _s_sp:
_s_intr_thresh:
.word 0
/* Macro which first allocates space on the stack to save general
* purpose registers, and then save them. GP register is excluded.
* The default size allocated on the stack is CONTEXT_SIZE, but it
* can be overridden. */
.macro save_general_regs cxt_size=CONTEXT_SIZE
addi sp, sp, -\cxt_size
sw ra, RV_STK_RA(sp)
sw tp, RV_STK_TP(sp)
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp)
sw t2, RV_STK_T2(sp)
sw s0, RV_STK_S0(sp)
sw s1, RV_STK_S1(sp)
sw a0, RV_STK_A0(sp)
sw a1, RV_STK_A1(sp)
sw a2, RV_STK_A2(sp)
sw a3, RV_STK_A3(sp)
sw a4, RV_STK_A4(sp)
sw a5, RV_STK_A5(sp)
sw a6, RV_STK_A6(sp)
sw a7, RV_STK_A7(sp)
sw s2, RV_STK_S2(sp)
sw s3, RV_STK_S3(sp)
sw s4, RV_STK_S4(sp)
sw s5, RV_STK_S5(sp)
sw s6, RV_STK_S6(sp)
sw s7, RV_STK_S7(sp)
sw s8, RV_STK_S8(sp)
sw s9, RV_STK_S9(sp)
sw s10, RV_STK_S10(sp)
sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
.endm
.global _ns_sp_min
_ns_sp_min:
.word 0
.macro save_mepc
csrr t0, mepc
sw t0, RV_STK_MEPC(sp)
.endm
.macro save_mcsr
csrr t0, mstatus
sw t0, RV_STK_MSTATUS(sp)
csrr t0, mtvec
sw t0, RV_STK_MTVEC(sp)
csrr t0, mtval
sw t0, RV_STK_MTVAL(sp)
csrr t0, mhartid
sw t0, RV_STK_MHARTID(sp)
csrr t0, mcause
sw t0, RV_STK_MCAUSE(sp)
.endm
/* Restore the general purpose registers (excluding gp) from the context on
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
* but it can be overridden. */
.macro restore_general_regs cxt_size=CONTEXT_SIZE
lw ra, RV_STK_RA(sp)
lw tp, RV_STK_TP(sp)
lw t0, RV_STK_T0(sp)
lw t1, RV_STK_T1(sp)
lw t2, RV_STK_T2(sp)
lw s0, RV_STK_S0(sp)
lw s1, RV_STK_S1(sp)
lw a0, RV_STK_A0(sp)
lw a1, RV_STK_A1(sp)
lw a2, RV_STK_A2(sp)
lw a3, RV_STK_A3(sp)
lw a4, RV_STK_A4(sp)
lw a5, RV_STK_A5(sp)
lw a6, RV_STK_A6(sp)
lw a7, RV_STK_A7(sp)
lw s2, RV_STK_S2(sp)
lw s3, RV_STK_S3(sp)
lw s4, RV_STK_S4(sp)
lw s5, RV_STK_S5(sp)
lw s6, RV_STK_S6(sp)
lw s7, RV_STK_S7(sp)
lw s8, RV_STK_S8(sp)
lw s9, RV_STK_S9(sp)
lw s10, RV_STK_S10(sp)
lw s11, RV_STK_S11(sp)
lw t3, RV_STK_T3(sp)
lw t4, RV_STK_T4(sp)
lw t5, RV_STK_T5(sp)
lw t6, RV_STK_T6(sp)
addi sp,sp, \cxt_size
.endm
.macro restore_mepc
lw t0, RV_STK_MEPC(sp)
csrw mepc, t0
.endm
.macro store_magic_general_regs
lui ra, MAGIC
lui tp, MAGIC
lui t0, MAGIC
lui t1, MAGIC
lui t2, MAGIC
lui s0, MAGIC
lui s1, MAGIC
lui a0, MAGIC
lui a1, MAGIC
lui a2, MAGIC
lui a3, MAGIC
lui a4, MAGIC
lui a5, MAGIC
lui a6, MAGIC
lui a7, MAGIC
lui s2, MAGIC
lui s3, MAGIC
lui s4, MAGIC
lui s5, MAGIC
lui s6, MAGIC
lui s7, MAGIC
lui s8, MAGIC
lui s9, MAGIC
lui s10, MAGIC
lui s11, MAGIC
lui t3, MAGIC
lui t4, MAGIC
lui t5, MAGIC
lui t6, MAGIC
.endm
.global _ns_sp_max
_ns_sp_max:
.word 0
.section .exception_vectors.text, "ax"
@@ -299,6 +178,7 @@ _skip_thresh_restore:
* The A0 register contains the return value of the corresponding service.
* After restoring the entire register context, we assign A0 the value back to the return value. */
csrw mscratch, a0
restore_general_regs
csrrw a0, mscratch, zero
@@ -1,6 +1,6 @@
# Reducing TEE IRAM size
# 29.5KB
CONFIG_SECURE_TEE_IRAM_SIZE=0x7600
# 30KB
CONFIG_SECURE_TEE_IRAM_SIZE=0x7800
# TEE Secure Storage: Release mode
CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y
@@ -242,6 +242,7 @@ static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char
unsigned char *output_buf = NULL;
const unsigned char *dma_input;
chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len);
const size_t alloc_chunk_len = chunk_len;
size_t input_alignment = 1;
size_t output_alignment = 1;
@@ -309,10 +310,12 @@ static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char
cleanup:
if (realloc_input) {
if (realloc_input && input_buf) {
mbedtls_platform_zeroize(input_buf, alloc_chunk_len);
free(input_buf);
}
if (realloc_output) {
if (realloc_output && output_buf) {
mbedtls_platform_zeroize(output_buf, alloc_chunk_len);
free(output_buf);
}
@@ -455,7 +458,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le
dma_descriptors = (crypto_dma_desc_t *) aes_dma_calloc(dma_descs_needed, sizeof(crypto_dma_desc_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, NULL);
if (dma_descriptors == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for the array of DMA descriptors");
return ESP_FAIL;
goto err;
}
size_t populated_dma_descs = 0;
@@ -464,7 +467,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le
start_alignment_stream_buffer = aes_dma_calloc(alignment_buffer_size, sizeof(uint8_t), AES_DMA_ALLOC_CAPS | (esp_ptr_external_ram(buffer) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL) , NULL);
if (start_alignment_stream_buffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for start alignment buffer");
return ESP_FAIL;
goto err;
}
memset(start_alignment_stream_buffer, 0, unaligned_start_bytes);
@@ -486,7 +489,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le
end_alignment_stream_buffer = aes_dma_calloc(alignment_buffer_size, sizeof(uint8_t), AES_DMA_ALLOC_CAPS | (esp_ptr_external_ram(buffer) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL), NULL);
if (end_alignment_stream_buffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for end alignment buffer");
return ESP_FAIL;
goto err;
}
memset(end_alignment_stream_buffer, 0, unaligned_end_bytes);
@@ -500,7 +503,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le
if (dma_desc_link(dma_descriptors, dma_descs_needed, cache_line_size) != ESP_OK) {
ESP_LOGE(TAG, "DMA descriptors cache sync C2M failed");
return ESP_FAIL;
goto err;
}
ret:
@@ -521,6 +524,18 @@ ret:
*end_alignment_buffer = end_alignment_stream_buffer;
return ESP_OK;
err:
if (start_alignment_stream_buffer) {
mbedtls_platform_zeroize(start_alignment_stream_buffer, alignment_buffer_size);
free(start_alignment_stream_buffer);
}
if (end_alignment_stream_buffer) {
mbedtls_platform_zeroize(end_alignment_stream_buffer, alignment_buffer_size);
free(end_alignment_stream_buffer);
}
free(dma_descriptors);
return ESP_FAIL;
}
int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out)
@@ -585,19 +600,12 @@ int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsign
}
size_t input_alignment_buffer_size = MAX(2 * input_cache_line_size, AES_BLOCK_BYTES);
size_t output_alignment_buffer_size = MAX(2 * output_cache_line_size, AES_BLOCK_BYTES);
crypto_dma_desc_t *input_desc = NULL;
uint8_t *input_start_stream_buffer = NULL;
uint8_t *input_end_stream_buffer = NULL;
if (generate_descriptor_list(input, len, &input_start_stream_buffer, &input_end_stream_buffer, input_alignment_buffer_size, input_cache_line_size, NULL, NULL, &input_desc, NULL, false) != ESP_OK) {
mbedtls_platform_zeroize(output, len);
ESP_LOGE(TAG, "Generating input DMA descriptors failed");
return -1;
}
size_t output_alignment_buffer_size = MAX(2 * output_cache_line_size, AES_BLOCK_BYTES);
crypto_dma_desc_t *output_desc = NULL;
uint8_t *output_start_stream_buffer = NULL;
uint8_t *output_end_stream_buffer = NULL;
@@ -605,10 +613,16 @@ int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsign
size_t output_end_alignment = 0;
size_t output_dma_desc_num = 0;
if (generate_descriptor_list(input, len, &input_start_stream_buffer, &input_end_stream_buffer, input_alignment_buffer_size, input_cache_line_size, NULL, NULL, &input_desc, NULL, false) != ESP_OK) {
ESP_LOGE(TAG, "Generating input DMA descriptors failed");
ret = -1;
goto cleanup;
}
if (generate_descriptor_list(output, len, &output_start_stream_buffer, &output_end_stream_buffer, output_alignment_buffer_size, output_cache_line_size, &output_start_alignment, &output_end_alignment, &output_desc, &output_dma_desc_num, true) != ESP_OK) {
mbedtls_platform_zeroize(output, len);
ESP_LOGE(TAG, "Generating output DMA descriptors failed");
return -1;
ret = -1;
goto cleanup;
}
crypto_dma_desc_t *out_desc_tail = &output_desc[output_dma_desc_num - 1];
@@ -701,11 +715,23 @@ cleanup:
mbedtls_platform_zeroize(output, len);
}
free(input_start_stream_buffer);
free(input_end_stream_buffer);
if (input_start_stream_buffer) {
mbedtls_platform_zeroize(input_start_stream_buffer, input_alignment_buffer_size);
free(input_start_stream_buffer);
}
if (input_end_stream_buffer) {
mbedtls_platform_zeroize(input_end_stream_buffer, input_alignment_buffer_size);
free(input_end_stream_buffer);
}
free(output_start_stream_buffer);
free(output_end_stream_buffer);
if (output_start_stream_buffer) {
mbedtls_platform_zeroize(output_start_stream_buffer, output_alignment_buffer_size);
free(output_start_stream_buffer);
}
if (output_end_stream_buffer) {
mbedtls_platform_zeroize(output_end_stream_buffer, output_alignment_buffer_size);
free(output_end_stream_buffer);
}
free(input_desc);
free(output_desc);
@@ -914,12 +940,24 @@ cleanup:
free(aad_end_stream_buffer);
free(aad_desc);
free(input_start_stream_buffer);
free(input_end_stream_buffer);
if (input_start_stream_buffer) {
mbedtls_platform_zeroize(input_start_stream_buffer, input_alignment_buffer_size);
free(input_start_stream_buffer);
}
if (input_end_stream_buffer) {
mbedtls_platform_zeroize(input_end_stream_buffer, input_alignment_buffer_size);
free(input_end_stream_buffer);
}
free(input_desc);
free(output_start_stream_buffer);
free(output_end_stream_buffer);
if (output_start_stream_buffer) {
mbedtls_platform_zeroize(output_start_stream_buffer, output_alignment_buffer_size);
free(output_start_stream_buffer);
}
if (output_end_stream_buffer) {
mbedtls_platform_zeroize(output_end_stream_buffer, output_alignment_buffer_size);
free(output_end_stream_buffer);
}
free(output_desc);
free(len_buf);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,7 @@
#include "esp_ds.h"
#include "rsa_dec_alt.h"
#include "mbedtls/rsa.h"
#include "mbedtls/platform_util.h"
#include "esp_ds_common.h"
#include "esp_log.h"
@@ -214,6 +215,7 @@ int esp_ds_rsa_decrypt(void *ctx, size_t *olen,
esp_ds_data_t *s_ds_data = esp_ds_get_data_ctx();
if (s_ds_data == NULL) {
ESP_LOGE(TAG, "s_ds_data is NULL, cannot perform decryption");
memset(input_tmp, 0, data_len * sizeof(uint32_t));
free(input_tmp);
return -1;
}
@@ -275,15 +277,19 @@ int esp_ds_rsa_decrypt(void *ctx, size_t *olen,
}
memcpy(output, output_tmp, *olen);
mbedtls_platform_zeroize(output_tmp, data_len * sizeof(uint32_t));
free(output_tmp);
mbedtls_platform_zeroize(input_tmp, data_len * sizeof(uint32_t));
free(input_tmp);
return 0;
exit:
esp_ds_release_ds_lock();
if (input_tmp) {
mbedtls_platform_zeroize(input_tmp, data_len * sizeof(uint32_t));
free(input_tmp);
}
if (output_tmp) {
mbedtls_platform_zeroize(output_tmp, data_len * sizeof(uint32_t));
free(output_tmp);
}
if (olen) {
@@ -311,6 +311,7 @@ int esp_ds_rsa_sign( void *ctx,
&esp_ds_ctx);
if (ds_r != ESP_OK) {
ESP_LOGE(TAG, "Error in esp_ds_start_sign, returned %d ", ds_r);
memset(signature, 0, sig_len);
heap_caps_free(signature);
return -1;
}
@@ -322,6 +323,7 @@ int esp_ds_rsa_sign( void *ctx,
} else {
ESP_LOGE(TAG, "Error in esp_ds_finish_sign, returned %d ", ds_r);
}
memset(signature, 0, sig_len);
heap_caps_free(signature);
return -1;
}
@@ -329,6 +331,7 @@ int esp_ds_rsa_sign( void *ctx,
for (unsigned int i = 0; i < (data_len); i++) {
((uint32_t *)sig)[i] = SWAP_INT32(((uint32_t *)signature)[(data_len) - (i + 1)]);
}
memset(signature, 0, sig_len);
heap_caps_free(signature);
return 0;
}
+14 -2
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -27,6 +27,7 @@
#include "esp_crypto_dma.h"
#include "esp_heap_caps.h"
#include "hal/dma_types.h"
#include "mbedtls/platform_util.h"
#include "soc/ext_mem_defs.h"
#include "soc/periph_defs.h"
@@ -186,6 +187,10 @@ static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *inpu
buf_copy = heap_caps_aligned_alloc(SOC_GDMA_EXT_MEM_ENC_ALIGNMENT, buf_len, heap_caps);
if (buf_copy == NULL) {
ESP_LOGE(TAG, "Failed to allocate aligned internal memory");
if (input_copy) {
mbedtls_platform_zeroize(input_copy, ilen);
free(input_copy);
}
return ret;
}
memcpy(buf_copy, buf, buf_len);
@@ -197,10 +202,12 @@ static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *inpu
ret = esp_sha_dma_process(sha_type, dma_input, ilen, dma_buf, buf_len, is_first_block);
if (realloc_input) {
mbedtls_platform_zeroize(input_copy, ilen);
free(input_copy);
}
if (realloc_buf) {
mbedtls_platform_zeroize(buf_copy, buf_len);
free(buf_copy);
}
@@ -318,6 +325,7 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
{
int ret = 0;
unsigned char *dma_cap_buf = NULL;
uint32_t dma_cap_buf_len = 0;
if (buf_len > block_length(sha_type)) {
ESP_LOGE(TAG, "SHA DMA buf_len cannot exceed max size for a single block");
@@ -339,6 +347,7 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
goto cleanup;
}
memcpy(dma_cap_buf, buf, buf_len);
dma_cap_buf_len = buf_len;
buf = dma_cap_buf;
}
@@ -375,7 +384,10 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
}
cleanup:
free(dma_cap_buf);
if (dma_cap_buf) {
mbedtls_platform_zeroize(dma_cap_buf, dma_cap_buf_len);
free(dma_cap_buf);
}
return ret;
}
#endif /* SOC_SHA_SUPPORT_DMA */