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

This commit is contained in:
Laukik Hase
2026-05-07 10:11:13 +05:30
parent 036fcf8e37
commit 281d219fac
11 changed files with 437 additions and 530 deletions

View File

@@ -183,6 +183,13 @@ esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge
}
esp_att_ecdsa_keypair_t keypair = {};
psa_hash_operation_t hash_op = PSA_HASH_OPERATION_INIT;
psa_status_t status;
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!");
@@ -206,10 +213,10 @@ esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge
memset(token_buf, 0x00, token_buf_size);
psa_hash_operation_t hash_op = PSA_HASH_OPERATION_INIT;
psa_status_t status = psa_hash_setup(&hash_op, PSA_ALG_SHA_256);
status = psa_hash_setup(&hash_op, PSA_ALG_SHA_256);
if (status != PSA_SUCCESS) {
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
json_gen_str_t jstr;
@@ -218,79 +225,84 @@ esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge
/* 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);
status = psa_hash_update(&hash_op, (const unsigned char *)hdr_json, hdr_len - 1);
if (status != PSA_SUCCESS) {
psa_hash_abort(&hash_op);
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);
status = psa_hash_update(&hash_op, (const unsigned char *)eat_json, eat_len - 1);
if (status != PSA_SUCCESS) {
psa_hash_abort(&hash_op);
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);
status = psa_hash_update(&hash_op, (const unsigned char *)pubkey_json, pubkey_len - 1);
if (status != PSA_SUCCESS) {
psa_hash_abort(&hash_op);
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
free(pubkey_json);
pubkey_json = NULL;
uint8_t digest[SHA256_DIGEST_SZ] = {0};
size_t digest_len = 0;
status = psa_hash_finish(&hash_op, digest, sizeof(digest), &digest_len);
if (status != PSA_SUCCESS) {
psa_hash_abort(&hash_op);
return ESP_FAIL;
err = ESP_FAIL;
goto exit;
}
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_size = json_gen_str_end(&jstr);
err = ESP_OK;
exit:
psa_hash_abort(&hash_op);
free(hdr_json);
free(eat_json);
free(pubkey_json);
free(sign_json);
free_sw_claim_list();
return err;
}

View File

@@ -22,6 +22,7 @@
#include "esp_hmac_pbkdf2.h"
#include "psa/crypto.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/psa_util.h"
#include "esp_rom_sys.h"
@@ -193,7 +194,7 @@ static esp_err_t compute_nvs_keys_with_hmac(esp_efuse_block_t key_blk, nvs_sec_c
psa_reset_key_attributes(&attributes);
// Zero out the key buffer after import
memset(key_buf, 0x00, sizeof(key_buf));
mbedtls_platform_zeroize(key_buf, sizeof(key_buf));
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to import HMAC key: %d", status);
@@ -208,7 +209,7 @@ static esp_err_t compute_nvs_keys_with_hmac(esp_efuse_block_t key_blk, nvs_sec_c
(uint8_t *)cfg->eky, SHA256_DIGEST_SZ, &mac_length);
if (status != PSA_SUCCESS) {
psa_destroy_key(psa_key_id);
memset(cfg, 0x00, sizeof(nvs_sec_cfg_t));
mbedtls_platform_zeroize(cfg, sizeof(nvs_sec_cfg_t));
return ESP_FAIL;
}
ESP_FAULT_ASSERT(status == PSA_SUCCESS);
@@ -221,7 +222,7 @@ static esp_err_t compute_nvs_keys_with_hmac(esp_efuse_block_t key_blk, nvs_sec_c
psa_destroy_key(psa_key_id);
if (status != PSA_SUCCESS) {
memset(cfg, 0x00, sizeof(nvs_sec_cfg_t));
mbedtls_platform_zeroize(cfg, sizeof(nvs_sec_cfg_t));
return ESP_FAIL;
}
ESP_FAULT_ASSERT(status == PSA_SUCCESS);
@@ -322,20 +323,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;
}
@@ -465,6 +470,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,
@@ -477,21 +483,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)
@@ -514,19 +527,21 @@ 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);
psa_key_id_t key_id = 0;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
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;
goto exit;
}
if (keyctx.type != cfg->type) {
ESP_LOGE(TAG, "Key type mismatch");
return ESP_ERR_INVALID_STATE;
err = ESP_ERR_INVALID_STATE;
goto exit;
}
psa_key_id_t key_id = 0;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH);
psa_algorithm_t ecdsa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
@@ -571,6 +586,7 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
exit:
psa_destroy_key(key_id);
psa_reset_key_attributes(&key_attributes);
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
return err;
}
@@ -594,12 +610,13 @@ 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;
}
/* Now determine the public key source and length based on key type */
@@ -619,13 +636,17 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
#endif
default:
ESP_LOGE(TAG, "Unsupported key-type");
return ESP_ERR_INVALID_ARG;
err = ESP_ERR_INVALID_ARG;
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,
@@ -648,17 +669,22 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
return err;
}
psa_key_id_t psa_key_id = 0;
uint8_t *aead_buf = NULL;
size_t aead_buf_len = 0;
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;
goto cleanup;
}
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 cleanup;
}
// Setup PSA key attributes
@@ -670,70 +696,66 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
// Import the AES key
psa_key_id_t key_id_psa = 0;
psa_status_t status = psa_import_key(&attributes, keyctx.aes256.key, AES256_KEY_LEN, &key_id_psa);
psa_status_t status = psa_import_key(&attributes, keyctx.aes256.key, AES256_KEY_LEN, &psa_key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
return ESP_FAIL;
err = ESP_FAIL;
goto cleanup;
}
/* PSA AEAD wants ciphertext+tag concatenated in a single buffer for both
* encrypt (output) and decrypt (input). */
aead_buf_len = len + tag_len;
aead_buf = malloc(aead_buf_len);
if (!aead_buf) {
err = ESP_ERR_NO_MEM;
goto cleanup;
}
if (is_encrypt) {
// PSA AEAD encrypt outputs ciphertext+tag concatenated
uint8_t *output_with_tag = malloc(len + tag_len);
if (!output_with_tag) {
psa_destroy_key(key_id_psa);
return ESP_ERR_NO_MEM;
}
esp_fill_random(iv, iv_len);
size_t output_length = 0;
status = psa_aead_encrypt(key_id_psa, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
status = psa_aead_encrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
iv, iv_len, aad, aad_len, input, len,
output_with_tag, len + tag_len, &output_length);
aead_buf, aead_buf_len, &output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in encrypting data: %d", status);
memset(output_with_tag, 0x00, len + tag_len);
free(output_with_tag);
psa_destroy_key(key_id_psa);
return ESP_FAIL;
err = ESP_FAIL;
goto cleanup;
}
// Separate ciphertext and tag
memcpy(output, output_with_tag, len);
memcpy(tag, output_with_tag + len, tag_len);
memset(output_with_tag, 0x00, len + tag_len);
free(output_with_tag);
memcpy(output, aead_buf, len);
memcpy(tag, aead_buf + len, tag_len);
} else {
// For decryption, PSA expects ciphertext + tag concatenated
uint8_t *input_with_tag = malloc(len + tag_len);
if (!input_with_tag) {
psa_destroy_key(key_id_psa);
return ESP_ERR_NO_MEM;
}
memcpy(input_with_tag, input, len);
memcpy(input_with_tag + len, tag, tag_len);
memcpy(aead_buf, input, len);
memcpy(aead_buf + len, tag, tag_len);
size_t output_length = 0;
status = psa_aead_decrypt(key_id_psa, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
iv, iv_len, aad, aad_len, input_with_tag, len + tag_len,
status = psa_aead_decrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
iv, iv_len, aad, aad_len, aead_buf, aead_buf_len,
output, len, &output_length);
memset(input_with_tag, 0x00, len + tag_len);
free(input_with_tag);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in decrypting data: %d", status);
psa_destroy_key(key_id_psa);
return ESP_FAIL;
err = ESP_FAIL;
goto cleanup;
}
}
psa_destroy_key(key_id_psa);
return ESP_OK;
err = ESP_OK;
cleanup:
if (aead_buf) {
mbedtls_platform_zeroize(aead_buf, aead_buf_len);
free(aead_buf);
}
if (psa_key_id != 0) {
psa_destroy_key(psa_key_id);
}
mbedtls_platform_zeroize(&keyctx, sizeof(keyctx));
return err;
}
esp_err_t 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)
@@ -819,24 +841,20 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2
}
// Sign the hash
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
size_t signature_length = 0;
status = psa_sign_hash(psa_key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256),
hash, hlen,
out_sign->signature, sizeof(out_sign->signature), &signature_length);
if (status != PSA_SUCCESS) {
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
err = ESP_FAIL;
goto exit;
}
// Export public key
memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t));
uint8_t public_key[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
size_t public_key_length = 0;
status = psa_export_public_key(psa_key_id, public_key, sizeof(public_key), &public_key_length);
if (status != PSA_SUCCESS) {
memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t));
err = ESP_FAIL;
goto exit;
}
@@ -844,7 +862,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2
// PSA exports public key in uncompressed format: 0x04 || X || Y
// Skip the first byte (0x04) and copy X and Y coordinates
if (public_key_length != (1 + 2 * key_len) || public_key[0] != 0x04) {
memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t));
err = ESP_FAIL;
goto exit;
}
@@ -859,7 +876,7 @@ exit:
psa_destroy_key(psa_key_id);
}
if (derived_key) {
memset(derived_key, 0x00, key_len);
mbedtls_platform_zeroize(derived_key, key_len);
free(derived_key);
}
return err;

View File

@@ -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

View File

@@ -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,15 +16,10 @@
#include "esp_tee_intr_defs.h"
#include "sdkconfig.h"
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
#include "esp_private/hw_stack_guard.h"
#endif
#include "esp_tee_asm_utils.inc"
.equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
.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
@@ -60,205 +55,6 @@ _ns_sp_min:
_ns_sp_max:
.word 0
/**
* 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
/* 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
.section .exception_vectors.text, "ax"
/* Exception handler. */
@@ -394,13 +190,14 @@ _skip_thresh_restore:
STACK_GUARD_POST_SWITCH t3 1 _ns_sp_min _ns_sp_max
fence
call syscall_exit_tee
/* Backup the A0 register
* This point is reached after an ecall is triggered after executing the secure service.
* 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
call syscall_exit_tee
restore_general_regs
csrrw a0, mscratch, zero

View File

@@ -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,15 +16,10 @@
#include "esp_tee_intr_defs.h"
#include "sdkconfig.h"
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
#include "esp_private/hw_stack_guard.h"
#endif
#include "esp_tee_asm_utils.inc"
.equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
.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
@@ -65,205 +60,6 @@ _ns_sp_min:
_ns_sp_max:
.word 0
/**
* 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
/* 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
.section .exception_vectors.text, "ax"
/* Exception handler. */
@@ -386,13 +182,14 @@ _skip_thresh_restore:
STACK_GUARD_POST_SWITCH t3 1 _ns_sp_min _ns_sp_max
fence
call syscall_exit_tee
/* Backup the A0 register
* This point is reached after an ecall is triggered after executing the secure service.
* 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
call syscall_exit_tee
restore_general_regs
csrrw a0, mscratch, zero

View File

@@ -244,6 +244,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;
@@ -313,10 +314,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);
}
@@ -459,7 +462,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;
@@ -468,7 +471,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);
@@ -490,7 +493,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);
@@ -504,7 +507,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:
@@ -525,6 +528,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)
@@ -589,19 +604,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;
@@ -609,10 +617,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];
@@ -705,11 +719,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);
@@ -918,12 +944,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);

View File

@@ -50,6 +50,7 @@ static psa_status_t esp_crypto_aes_gcm_setup(
status = mbedtls_to_psa_error(esp_aes_gcm_setkey(ctx, 2, key_buffer, key_buffer_size * 8));
if (status != PSA_SUCCESS) {
esp_aes_gcm_free(ctx);
free(ctx);
goto exit;
}

View File

@@ -215,6 +215,7 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_start(
error:
if (em) {
memset(em, 0, rsa_len_bytes);
heap_caps_free(em);
em = NULL;
}
@@ -471,6 +472,7 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
err = esp_key_mgr_activate_key(km_key_recovery_info);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to activate key: 0x%x", err);
memset(em_words, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
esp_rsa_ds_release_ds_lock();
return PSA_ERROR_INVALID_HANDLE;
@@ -485,6 +487,7 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
hmac_key_id,
&operation.esp_rsa_ds_ctx);
if (err != ESP_OK) {
memset(em_words, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
#if SOC_KEY_MANAGER_SUPPORTED
if (km_key_recovery_info && operation.is_km_key_active) {
@@ -506,6 +509,7 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
#endif /* SOC_KEY_MANAGER_SUPPORTED */
if (err != ESP_OK) {
memset(em_words, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
esp_rsa_ds_release_ds_lock();
return PSA_ERROR_GENERIC_ERROR;

View File

@@ -12,6 +12,7 @@
#include "include/psa_crypto_driver_esp_sha512.h"
#include "psa/crypto.h"
#include "psa/crypto_sizes.h"
#include "mbedtls/platform_util.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
@@ -229,6 +230,7 @@ psa_status_t esp_sha_hash_finish(
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
esp_sha1_context *ctx = (esp_sha1_context *)operation->sha_ctx;
int ret = esp_sha1_driver_finish(ctx, hash, hash_size, hash_length);
mbedtls_platform_zeroize(ctx, sizeof(esp_sha1_context));
free(ctx); // Free the context after use
operation->sha_ctx = NULL;
return ret;
@@ -239,6 +241,7 @@ psa_status_t esp_sha_hash_finish(
operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
esp_sha256_context *ctx = (esp_sha256_context *)operation->sha_ctx;
int ret = esp_sha256_driver_finish(ctx, hash, hash_size, hash_length, operation->sha_type);
mbedtls_platform_zeroize(ctx, sizeof(esp_sha256_context));
free(ctx); // Free the context after use
operation->sha_ctx = NULL;
return ret;
@@ -249,6 +252,7 @@ psa_status_t esp_sha_hash_finish(
operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA512) {
esp_sha512_context *ctx = (esp_sha512_context *)operation->sha_ctx;
int ret = esp_sha512_driver_finish(ctx, hash, hash_size, hash_length, operation->sha_type);
mbedtls_platform_zeroize(ctx, sizeof(esp_sha512_context));
free(ctx); // Free the context after use
operation->sha_ctx = NULL;
return ret;

View File

@@ -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 */

View File

@@ -156,6 +156,8 @@ components_not_formatted_permanent:
- /components/esp_system/openocd_stub_bins/*.inc
- /components/esp_system/openocd_stub_bins/esp32c6/*.inc
- /components/esp_system/openocd_stub_bins/esp32h2/*.inc
# TEE ASM helper macros — .inc file, not C include files
- /components/esp_tee/subproject/main/arch/riscv/*.inc
docs:
# Docs directory contains some .inc files, which are not C include files