mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'fix/fix_esp_tee_iv_length_check_v5.5' into 'release/v5.5'
feat(esp_tee): ESP-TEE Security Audit fixes (v5.5) See merge request espressif/esp-idf!50970
This commit is contained in:
@@ -426,8 +426,8 @@ void bootloader_munmap(const void *mapping)
|
||||
mmu_hal_unmap_all();
|
||||
#else
|
||||
cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
|
||||
mmu_hal_unmap_region(0, FLASH_MMAP_VADDR, current_mapped_size);
|
||||
cache_hal_invalidate_addr(FLASH_MMAP_VADDR, current_mapped_size);
|
||||
mmu_hal_unmap_region(0, FLASH_MMAP_VADDR, current_mapped_size);
|
||||
cache_hal_resume(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@ idf_build_get_property(target IDF_TARGET)
|
||||
# ESP-TEE is currently supported only on the ESP32-C6, H2 and C5 SoCs
|
||||
set(SUPPORTED_TARGETS "esp32c6" "esp32h2" "esp32c5")
|
||||
if(NOT target IN_LIST SUPPORTED_TARGETS)
|
||||
message(STATUS "ESP-TEE is currently supported only on the ${SUPPORTED_TARGETS} SoCs")
|
||||
# ESP-TEE Kconfig is gated on the supported targets; nothing to register elsewhere.
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -48,6 +48,22 @@ extern "C" {
|
||||
#error "CONFIG_SECURE_TEE_INTR_STACK_SIZE must be 16-byte (0x10) aligned"
|
||||
#endif
|
||||
|
||||
#if ((CONFIG_SECURE_TEE_IROM_SIZE) % SOC_MMU_PAGE_SIZE)
|
||||
#error "CONFIG_SECURE_TEE_IROM_SIZE must be a multiple of SOC_MMU_PAGE_SIZE"
|
||||
#endif
|
||||
|
||||
#if ((CONFIG_SECURE_TEE_DROM_SIZE) % SOC_MMU_PAGE_SIZE)
|
||||
#error "CONFIG_SECURE_TEE_DROM_SIZE must be a multiple of SOC_MMU_PAGE_SIZE"
|
||||
#endif
|
||||
|
||||
/* With HAL assertions disabled (level 0), a failed HAL_ASSERT() expands to
|
||||
* __builtin_unreachable(): the compiler then optimizes assuming the asserted
|
||||
* preconditions always hold, turning any unvalidated HAL input into undefined
|
||||
* behavior. The TEE must never be built this way. */
|
||||
#if CONFIG_SECURE_ENABLE_TEE && (CONFIG_HAL_DEFAULT_ASSERTION_LEVEL < 1)
|
||||
#error "ESP-TEE requires HAL assertions (CONFIG_HAL_DEFAULT_ASSERTION_LEVEL >= 1)"
|
||||
#endif
|
||||
|
||||
/* TEE Secure Storage partition label and NVS namespace */
|
||||
#define ESP_TEE_SEC_STG_PART_LABEL "secure_storage"
|
||||
#define ESP_TEE_SEC_STG_NVS_NAMESPACE "tee_sec_stg_ns"
|
||||
|
||||
@@ -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_p192 -o ecdsa_p192_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
|
||||
|
||||
@@ -32,6 +32,7 @@ class KeyType(Enum):
|
||||
class Flags(IntFlag):
|
||||
NONE = 0x00000000
|
||||
WRITE_ONCE = 0x00000001
|
||||
TEE_ONLY = 0x00000002
|
||||
|
||||
|
||||
# === Key Generators ===
|
||||
@@ -113,6 +114,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()
|
||||
|
||||
|
||||
@@ -123,12 +129,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)
|
||||
|
||||
|
||||
@@ -46,6 +46,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);
|
||||
|
||||
+41
-8
@@ -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,12 +16,19 @@ extern "C" {
|
||||
#include "esp_err.h"
|
||||
#include "esp_bit_defs.h"
|
||||
|
||||
#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key */
|
||||
#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
|
||||
#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key (SECP256R1) */
|
||||
#endif /* CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN */
|
||||
#define MAX_AES_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the AES key */
|
||||
#define AES_GCM_SUPPORTED_IV_LEN 12 /*!< Supported IV length for AES-GCM operations */
|
||||
|
||||
#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
|
||||
@@ -94,6 +101,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
|
||||
|
||||
/**
|
||||
@@ -140,10 +162,16 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
|
||||
/**
|
||||
* @brief Perform encryption using AES256-GCM with the key from secure storage
|
||||
*
|
||||
* @param[in] ctx Pointer to the AEAD operation context
|
||||
* @param[out] tag Pointer to the authentication tag buffer
|
||||
* @param[in] tag_len Length of the authentication tag
|
||||
* @param[out] output Pointer to the output data buffer
|
||||
* @param[in,out] ctx Pointer to the AEAD operation context; the generated
|
||||
* initialization vector is written to @p ctx->iv
|
||||
* @param[out] tag Pointer to the authentication tag buffer
|
||||
* @param[in] tag_len Length of the authentication tag; must be 12 to 16 bytes (96- to 128-bit tag, per NIST SP 800-38D)
|
||||
* @param[out] output Pointer to the output data buffer
|
||||
*
|
||||
* @note The initialization vector is generated internally and is always
|
||||
* ::AES_GCM_SUPPORTED_IV_LEN bytes long (96-bit IV, per NIST SP 800-38D).
|
||||
* Read it from @p ctx->iv after the call and store it with the ciphertext.
|
||||
* @note Non-standard @p tag_len values are rejected with ESP_ERR_INVALID_SIZE.
|
||||
*
|
||||
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
|
||||
*/
|
||||
@@ -152,11 +180,16 @@ esp_err_t esp_tee_sec_storage_aead_encrypt(esp_tee_sec_storage_aead_ctx_t *ctx,
|
||||
/**
|
||||
* @brief Perform decryption using AES256-GCM with the key from secure storage
|
||||
*
|
||||
* @param[in] ctx Pointer to the AEAD operation context
|
||||
* @param[in] ctx Pointer to the AEAD operation context; @p ctx->iv must hold
|
||||
* the initialization vector used during encryption
|
||||
* @param[in] tag Pointer to the authentication tag buffer
|
||||
* @param[in] tag_len Length of the authentication tag
|
||||
* @param[in] tag_len Length of the authentication tag; must be 12 to 16 bytes (96- to 128-bit tag, per NIST SP 800-38D)
|
||||
* @param[out] output Pointer to the output data buffer
|
||||
*
|
||||
* @note The initialization vector is always ::AES_GCM_SUPPORTED_IV_LEN bytes long
|
||||
* (96-bit IV, per NIST SP 800-38D). Write it to @p ctx->iv before the call.
|
||||
* @note Non-standard @p tag_len values are rejected with ESP_ERR_INVALID_SIZE.
|
||||
*
|
||||
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
|
||||
*/
|
||||
esp_err_t esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output);
|
||||
|
||||
@@ -35,8 +35,9 @@
|
||||
|
||||
#define AES256_KEY_LEN 32
|
||||
#define AES256_KEY_BITS (AES256_KEY_LEN * 8)
|
||||
#define AES256_DEFAULT_IV_LEN 16
|
||||
#define AES256_GCM_IV_LEN (AES_GCM_SUPPORTED_IV_LEN)
|
||||
#define AES256_GCM_IV_LEN 12
|
||||
#define AES256_GCM_TAG_LEN_MIN 12 /* NIST SP800-38D general-use minimum (96-bit tag) */
|
||||
#define AES256_GCM_TAG_LEN_MAX 16 /* full GCM tag (128-bit) */
|
||||
#define ECDSA_SECP256R1_KEY_LEN 32
|
||||
#define ECDSA_SECP192R1_KEY_LEN 24
|
||||
|
||||
@@ -209,6 +210,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)
|
||||
@@ -558,8 +582,16 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (len == 0 || tag_len == 0 || iv_len != AES256_GCM_IV_LEN) {
|
||||
ESP_LOGE(TAG, "Invalid input/tag/iv length");
|
||||
if (len == 0) {
|
||||
ESP_LOGE(TAG, "Invalid input length");
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
/* Enforce standard AES-GCM parameters */
|
||||
if (iv_len != AES256_GCM_IV_LEN ||
|
||||
tag_len < AES256_GCM_TAG_LEN_MIN || tag_len > AES256_GCM_TAG_LEN_MAX) {
|
||||
ESP_LOGE(TAG, "Non-standard GCM iv_len(%u)/tag_len(%u) rejected",
|
||||
(unsigned)iv_len, (unsigned)tag_len);
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
|
||||
@@ -221,3 +221,35 @@
|
||||
1:
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/**
|
||||
* VALIDATE_REE_SP
|
||||
* Validate an REE-supplied sp before the TEE stores through it. The TEE region is
|
||||
* at the bottom of SRAM, so a valid REE frame [sp - framesz, sp) must lie in the
|
||||
* band above it and below the peripheral window: [SOC_S_DRAM_END, SOC_PERIPHERAL_LOW].
|
||||
* An out-of-bound sp will lead to a fault.
|
||||
*
|
||||
* With chk_priv (default) the check is skipped unless the trap came from U-mode;
|
||||
* pass chk_priv=0 where the U-mode origin is already guaranteed (ecall-from-U).
|
||||
*
|
||||
* TODO: Revisit these bounds for high-performance RISC-V SoCs (e.g. ESP32-P4,
|
||||
* ESP32-S31) with different memory maps than current ESP-TEE targets.
|
||||
*
|
||||
* Clobbers: \tx
|
||||
*/
|
||||
.macro VALIDATE_REE_SP framesz, tx, chk_priv=1
|
||||
.if \chk_priv
|
||||
/* Skip validation unless the previous privilege (mstatus.MPP) was U-mode */
|
||||
csrr \tx, mstatus
|
||||
srli \tx, \tx, MSTATUS_MPP_SHIFT
|
||||
andi \tx, \tx, (MSTATUS_MPP >> MSTATUS_MPP_SHIFT)
|
||||
bnez \tx, 1f
|
||||
.endif
|
||||
li \tx, (SOC_S_DRAM_END + \framesz)
|
||||
bltu sp, \tx, _tee_sp_reject /* frame would dip into the TEE (or sub-TEE) region */
|
||||
li \tx, SOC_PERIPHERAL_LOW
|
||||
bltu \tx, sp, _tee_sp_reject /* sp at/above the peripheral window */
|
||||
.if \chk_priv
|
||||
1:
|
||||
.endif
|
||||
.endm
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
.equ ECALL_M_MODE, 0xb
|
||||
.equ CSR_UINTTHRESH, 0x047
|
||||
.equ CSR_MINTTHRESH, 0x347
|
||||
.equ MCAUSE_EXCCODE_SHIFT, 20
|
||||
.equ MSTATUS_MPP_SHIFT, 11
|
||||
|
||||
.global esp_tee_global_interrupt_handler
|
||||
.global esp_tee_service_dispatcher
|
||||
@@ -55,34 +57,33 @@ _ns_sp_min:
|
||||
_ns_sp_max:
|
||||
.word 0
|
||||
|
||||
.global _ns_int_rtn
|
||||
_ns_int_rtn:
|
||||
.word 0
|
||||
|
||||
.section .exception_vectors.text, "ax"
|
||||
|
||||
/* Exception handler. */
|
||||
.global _tee_panic_handler
|
||||
.type _tee_panic_handler, @function
|
||||
_tee_panic_handler:
|
||||
/* Backup t0, t1 on the stack before using it */
|
||||
addi sp, sp, -16
|
||||
sw t0, 0(sp)
|
||||
sw t1, 4(sp)
|
||||
/* Backup t0 before using it */
|
||||
csrw mscratch, t0
|
||||
|
||||
/* Read mcause */
|
||||
/* Check whether the exception is an M-mode/U-mode ecall */
|
||||
csrr t0, mcause
|
||||
li t1, VECTORS_MCAUSE_REASON_MASK
|
||||
and t0, t0, t1
|
||||
slli t0, t0, MCAUSE_EXCCODE_SHIFT
|
||||
srli t0, t0, MCAUSE_EXCCODE_SHIFT
|
||||
addi t0, t0, -ECALL_M_MODE
|
||||
beqz t0, _machine_ecall /* M-mode ecall */
|
||||
addi t0, t0, (ECALL_M_MODE - ECALL_U_MODE)
|
||||
beqz t0, _user_ecall /* U-mode ecall */
|
||||
|
||||
/* Check whether the exception is an M-mode ecall */
|
||||
li t1, ECALL_M_MODE
|
||||
beq t0, t1, _machine_ecall
|
||||
/* Validate a U-mode-origin sp before the handler stores/dumps through it */
|
||||
VALIDATE_REE_SP RV_STK_FRMSZ, t0
|
||||
|
||||
/* Check whether the exception is an U-mode ecall */
|
||||
li t1, ECALL_U_MODE
|
||||
beq t0, t1, _user_ecall
|
||||
|
||||
/* Restore t0, t1 from the stack */
|
||||
lw t0, 0(sp)
|
||||
lw t1, 4(sp)
|
||||
addi sp, sp, 16
|
||||
/* Restore t0 */
|
||||
csrr t0, mscratch
|
||||
|
||||
_actual_panic:
|
||||
/* Not an ecall, proceed to the panic handler */
|
||||
@@ -146,6 +147,12 @@ _return_from_exception:
|
||||
restore_general_regs RV_STK_FRMSZ
|
||||
mret
|
||||
|
||||
/* Fault if the sp given by the REE is found to be out-of-bounds */
|
||||
_tee_sp_reject:
|
||||
csrr t0, mscratch
|
||||
la sp, _tee_stack
|
||||
j _actual_panic
|
||||
|
||||
.size _tee_panic_handler, .-_tee_panic_handler
|
||||
|
||||
/* ECALL handler. */
|
||||
@@ -204,14 +211,15 @@ _skip_ctx_restore:
|
||||
/* U-mode ecall handler */
|
||||
_user_ecall:
|
||||
/* Check whether we are returning after servicing an U-mode interrupt */
|
||||
lui t0, RTNVAL
|
||||
csrrw t1, mscratch, zero
|
||||
beq t0, t1, _rtn_from_ns_int
|
||||
la t0, _ns_int_rtn
|
||||
lw t0, 0(t0)
|
||||
bnez t0, _rtn_from_ns_int
|
||||
|
||||
/* Restore t0, t1 from the stack */
|
||||
lw t0, 0(sp)
|
||||
lw t1, 4(sp)
|
||||
addi sp, sp, 16
|
||||
/* Reject an sp whose frame would be out-of-bounds */
|
||||
VALIDATE_REE_SP CONTEXT_SIZE, t0, 0
|
||||
|
||||
/* Restore t0 */
|
||||
csrr t0, mscratch
|
||||
|
||||
/* This point is reached when a secure service call is issued from the REE */
|
||||
/* Save register context and mepc */
|
||||
@@ -259,6 +267,10 @@ _2:
|
||||
/* This point is reached after servicing a U-mode interrupt occurred
|
||||
* while executing a secure service */
|
||||
_rtn_from_ns_int:
|
||||
/* Consume the U-mode-interrupt-return sentinel (checked in _user_ecall). */
|
||||
la t0, _ns_int_rtn
|
||||
sw zero, 0(t0)
|
||||
|
||||
/* Disable the U-mode interrupt delegation */
|
||||
li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG
|
||||
li t1, TEE_PASS_INUM + CLIC_EXT_INTR_NUM_OFFSET
|
||||
@@ -392,8 +404,9 @@ _4:
|
||||
lw sp, 0(t1)
|
||||
|
||||
/* Set a flag to identify the next U2M switch would be after handling a U-mode interrupt */
|
||||
lui t0, RTNVAL
|
||||
csrw mscratch, t0
|
||||
la t0, _ns_int_rtn
|
||||
li t1, RTNVAL
|
||||
sw t1, 0(t0)
|
||||
|
||||
/* Place magic bytes in all the general registers */
|
||||
store_magic_general_regs
|
||||
@@ -408,6 +421,11 @@ _4:
|
||||
.global _tee_s_intr_handler
|
||||
.type _tee_s_intr_handler, @function
|
||||
_tee_s_intr_handler:
|
||||
/* Check sp if trapped from U-mode */
|
||||
csrw mscratch, t0
|
||||
VALIDATE_REE_SP RV_STK_FRMSZ, t0
|
||||
csrr t0, mscratch /* restore the preempted t0 */
|
||||
|
||||
/* Start by saving the general purpose registers and the PC value before
|
||||
* the interrupt happened. */
|
||||
save_general_regs RV_STK_FRMSZ
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
.equ RTNVAL, 0xc0de
|
||||
.equ ECALL_U_MODE, 0x8
|
||||
.equ ECALL_M_MODE, 0xb
|
||||
.equ MSTATUS_MPP_SHIFT, 11
|
||||
/* NOTE: INTWDT timeout and Cache error interrupts trigger the panic
|
||||
* handler before reset, so they don’t need to be delegated. */
|
||||
.equ TEE_INTR_DELEG_MASK, ~((1U << TEE_SECURE_INUM) | (1U << ETS_INT_WDT_INUM) | (1U << ETS_CACHEERR_INUM))
|
||||
@@ -56,34 +57,32 @@ _ns_sp_min:
|
||||
_ns_sp_max:
|
||||
.word 0
|
||||
|
||||
.global _ns_int_rtn
|
||||
_ns_int_rtn:
|
||||
.word 0
|
||||
|
||||
.section .exception_vectors.text, "ax"
|
||||
|
||||
/* Exception handler. */
|
||||
.global _tee_panic_handler
|
||||
.type _tee_panic_handler, @function
|
||||
_tee_panic_handler:
|
||||
/* Backup t0, t1 on the stack before using it */
|
||||
addi sp, sp, -16
|
||||
sw t0, 0(sp)
|
||||
sw t1, 4(sp)
|
||||
/* Backup t0 before using it */
|
||||
csrw mscratch, t0
|
||||
|
||||
/* Read mcause */
|
||||
/* Check whether the exception is an M-mode/U-mode ecall */
|
||||
csrr t0, mcause
|
||||
li t1, VECTORS_MCAUSE_REASON_MASK
|
||||
and t0, t0, t1
|
||||
andi t0, t0, VECTORS_MCAUSE_REASON_MASK
|
||||
addi t0, t0, -ECALL_M_MODE
|
||||
beqz t0, _machine_ecall /* M-mode ecall */
|
||||
addi t0, t0, (ECALL_M_MODE - ECALL_U_MODE)
|
||||
beqz t0, _user_ecall /* U-mode ecall */
|
||||
|
||||
/* Check whether the exception is an M-mode ecall */
|
||||
li t1, ECALL_M_MODE
|
||||
beq t0, t1, _machine_ecall
|
||||
/* Validate a U-mode-origin sp before the handler stores/dumps through it */
|
||||
VALIDATE_REE_SP RV_STK_FRMSZ, t0
|
||||
|
||||
/* Check whether the exception is an U-mode ecall */
|
||||
li t1, ECALL_U_MODE
|
||||
beq t0, t1, _user_ecall
|
||||
|
||||
/* Restore t0, t1 from the stack */
|
||||
lw t0, 0(sp)
|
||||
lw t1, 4(sp)
|
||||
addi sp, sp, 16
|
||||
/* Restore t0 */
|
||||
csrr t0, mscratch
|
||||
|
||||
_actual_panic:
|
||||
/* Not an ecall, proceed to the panic handler */
|
||||
@@ -138,6 +137,12 @@ _return_from_exception:
|
||||
restore_general_regs RV_STK_FRMSZ
|
||||
mret
|
||||
|
||||
/* Fault if the sp given by the REE is found to be out-of-bounds */
|
||||
_tee_sp_reject:
|
||||
csrr t0, mscratch
|
||||
la sp, _tee_stack
|
||||
j _actual_panic
|
||||
|
||||
.size _tee_panic_handler, .-_tee_panic_handler
|
||||
|
||||
/* ECALL handler. */
|
||||
@@ -192,14 +197,15 @@ _skip_ctx_restore:
|
||||
/* U-mode ecall handler */
|
||||
_user_ecall:
|
||||
/* Check whether we are returning after servicing an U-mode interrupt */
|
||||
lui t0, RTNVAL
|
||||
csrrw t1, mscratch, zero
|
||||
beq t0, t1, _rtn_from_ns_int
|
||||
la t0, _ns_int_rtn
|
||||
lw t0, 0(t0)
|
||||
bnez t0, _rtn_from_ns_int
|
||||
|
||||
/* Restore t0, t1 from the stack */
|
||||
lw t0, 0(sp)
|
||||
lw t1, 4(sp)
|
||||
addi sp, sp, 16
|
||||
/* Reject an sp whose frame would be out-of-bounds */
|
||||
VALIDATE_REE_SP CONTEXT_SIZE, t0, 0
|
||||
|
||||
/* Restore t0 */
|
||||
csrr t0, mscratch
|
||||
|
||||
/* This point is reached when a secure service call is issued from the REE */
|
||||
/* Save register context and mepc */
|
||||
@@ -244,6 +250,10 @@ _process_ecall:
|
||||
/* This point is reached after servicing a U-mode interrupt occurred
|
||||
* while executing a secure service */
|
||||
_rtn_from_ns_int:
|
||||
/* Consume the U-mode-interrupt-return sentinel (checked in _user_ecall). */
|
||||
la t0, _ns_int_rtn
|
||||
sw zero, 0(t0)
|
||||
|
||||
/* Disable the U-mode interrupt delegation */
|
||||
csrwi mideleg, 0
|
||||
|
||||
@@ -315,8 +325,9 @@ _tee_ns_intr_handler:
|
||||
lw sp, 0(t1)
|
||||
|
||||
/* Set a flag to identify the next U2M switch would be after handling a U-mode interrupt */
|
||||
lui t0, RTNVAL
|
||||
csrw mscratch, t0
|
||||
la t0, _ns_int_rtn
|
||||
li t1, RTNVAL
|
||||
sw t1, 0(t0)
|
||||
|
||||
/* Enable the U-mode interrupt delegation (except for the TEE secure interrupt) */
|
||||
li t0, TEE_INTR_DELEG_MASK
|
||||
@@ -335,6 +346,11 @@ _tee_ns_intr_handler:
|
||||
.global _tee_s_intr_handler
|
||||
.type _tee_s_intr_handler, @function
|
||||
_tee_s_intr_handler:
|
||||
/* Check sp if trapped from U-mode */
|
||||
csrw mscratch, t0
|
||||
VALIDATE_REE_SP RV_STK_FRMSZ, t0
|
||||
csrr t0, mscratch /* restore the preempted t0 */
|
||||
|
||||
/* Start by saving the general purpose registers and the PC value before
|
||||
* the interrupt happened. */
|
||||
save_general_regs RV_STK_FRMSZ
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "esp_rom_tlsf.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "tlsf_block_functions.h"
|
||||
@@ -63,6 +64,9 @@ esp_err_t esp_tee_heap_init(void *start_ptr, size_t size)
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
/* Zeroize the entire region before registering it as the TEE heap*/
|
||||
memset(start_ptr, 0, size);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
|
||||
void *heap = tlsf_create_with_pool(start_ptr + sizeof(heap_t), usable_size);
|
||||
size_t overhead = tlsf_size();
|
||||
@@ -229,7 +233,7 @@ void esp_tee_heap_dump_info(void)
|
||||
|
||||
/* Definitions for functions from the heap component, used in files shared with ESP-IDF */
|
||||
|
||||
void *heap_caps_malloc(size_t alignment, size_t size, uint32_t caps)
|
||||
void *heap_caps_malloc(size_t size, uint32_t caps)
|
||||
{
|
||||
(void) caps;
|
||||
return esp_tee_heap_malloc(size);
|
||||
|
||||
@@ -545,17 +545,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);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_macros.h"
|
||||
#include "esp_fault.h"
|
||||
|
||||
#include "hal/mmu_types.h"
|
||||
@@ -36,6 +37,9 @@
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "esp_tee_sec_srv_iram";
|
||||
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1))
|
||||
|
||||
/* ---------------------------------------------- Interrupts ------------------------------------------------- */
|
||||
|
||||
#if SOC_INT_CLIC_SUPPORTED
|
||||
@@ -189,67 +193,67 @@ void _ss_wdt_hal_deinit(wdt_hal_context_t *hal)
|
||||
*/
|
||||
esp_err_t _ss_esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_sign)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(hash, hlen) &&
|
||||
esp_tee_buf_in_ree(out_sign, sizeof(esp_tee_sec_storage_ecdsa_sign_t)));
|
||||
|
||||
if (!valid_addr) {
|
||||
bool valid_arg = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(hash, hlen) &&
|
||||
esp_tee_buf_in_ree(out_sign, sizeof(esp_tee_sec_storage_ecdsa_sign_t)) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id));
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_ecdsa_sign(cfg, hash, hlen, out_sign);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg_t *cfg, esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(out_pubkey, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)));
|
||||
|
||||
if (!valid_addr) {
|
||||
bool valid_arg = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(out_pubkey, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id));
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_ecdsa_get_pubkey(cfg, out_pubkey);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(ctx->iv, AES_GCM_SUPPORTED_IV_LEN) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len));
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx->key_id));
|
||||
|
||||
if (ctx->aad_len != 0) {
|
||||
valid_addr &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
}
|
||||
|
||||
if (!valid_addr) {
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_aead_encrypt(ctx, 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 *tag, size_t tag_len, uint8_t *output)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(ctx->iv, AES_GCM_SUPPORTED_IV_LEN) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len));
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx->key_id));
|
||||
|
||||
if (ctx->aad_len != 0) {
|
||||
valid_addr &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
}
|
||||
|
||||
if (!valid_addr) {
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_aead_decrypt(ctx, tag, tag_len, output);
|
||||
}
|
||||
@@ -272,11 +276,32 @@ esp_err_t _ss_esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pb
|
||||
|
||||
/* ---------------------------------------------- MMU HAL ------------------------------------------------- */
|
||||
|
||||
static bool tee_ree_ext_vaddr_ok(uint32_t mmu_id, uint32_t vaddr, uint32_t len)
|
||||
{
|
||||
uint32_t page = mmu_hal_pages_to_bytes(mmu_id, 1);
|
||||
uint32_t map_len = ALIGN_UP(len, page);
|
||||
|
||||
return (len != 0 && map_len >= len && (vaddr % page == 0) &&
|
||||
mmu_hal_check_valid_ext_vaddr_region(mmu_id, vaddr, map_len,
|
||||
MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION) &&
|
||||
!esp_tee_flash_check_vrange_in_tee_region(vaddr, map_len));
|
||||
}
|
||||
|
||||
static bool tee_ree_ext_paddr_ok(uint32_t mmu_id, uint32_t paddr, uint32_t len)
|
||||
{
|
||||
uint32_t page = mmu_hal_pages_to_bytes(mmu_id, 1);
|
||||
uint32_t map_len = ALIGN_UP(len, page);
|
||||
|
||||
return (len != 0 && map_len >= len && (paddr % page == 0) &&
|
||||
mmu_hal_check_valid_paddr_region(mmu_id, paddr, map_len) &&
|
||||
!esp_tee_flash_check_prange_in_tee_region(paddr, map_len));
|
||||
}
|
||||
|
||||
void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr,
|
||||
uint32_t paddr, uint32_t len, uint32_t *out_len)
|
||||
{
|
||||
bool valid_addr = (!esp_tee_flash_check_vrange_in_tee_region(vaddr, len) &&
|
||||
!esp_tee_flash_check_prange_in_tee_region(paddr, len) &&
|
||||
bool valid_addr = (tee_ree_ext_vaddr_ok(mmu_id, vaddr, len) &&
|
||||
tee_ree_ext_paddr_ok(mmu_id, paddr, len) &&
|
||||
esp_tee_buf_in_ree(out_len, sizeof(uint32_t)));
|
||||
|
||||
if (!valid_addr) {
|
||||
@@ -290,20 +315,21 @@ void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vad
|
||||
|
||||
void _ss_mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len)
|
||||
{
|
||||
bool vaddr_chk = esp_tee_flash_check_vrange_in_tee_region(vaddr, len);
|
||||
bool valid_addr = tee_ree_ext_vaddr_ok(mmu_id, vaddr, len);
|
||||
|
||||
if (vaddr_chk) {
|
||||
if (!valid_addr) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, vaddr);
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(!vaddr_chk);
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
mmu_hal_unmap_region(mmu_id, vaddr, len);
|
||||
}
|
||||
|
||||
bool _ss_mmu_hal_vaddr_to_paddr(uint32_t mmu_id, uint32_t vaddr, uint32_t *out_paddr, mmu_target_t *out_target)
|
||||
{
|
||||
bool valid_addr = (!esp_tee_flash_check_vaddr_in_tee_region(vaddr) &&
|
||||
uint32_t page = mmu_hal_pages_to_bytes(mmu_id, 1);
|
||||
bool valid_addr = (tee_ree_ext_vaddr_ok(mmu_id, ALIGN_DOWN(vaddr, page), 1) &&
|
||||
esp_tee_buf_in_ree(out_paddr, sizeof(uint32_t)) &&
|
||||
esp_tee_buf_in_ree(out_target, sizeof(mmu_target_t)));
|
||||
|
||||
@@ -317,7 +343,8 @@ bool _ss_mmu_hal_vaddr_to_paddr(uint32_t mmu_id, uint32_t vaddr, uint32_t *out_p
|
||||
|
||||
bool _ss_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t target, mmu_vaddr_t type, uint32_t *out_vaddr)
|
||||
{
|
||||
bool valid_addr = (!esp_tee_flash_check_paddr_in_tee_region(paddr) &&
|
||||
bool valid_addr = (mmu_hal_check_valid_paddr_region(mmu_id, paddr, 1) &&
|
||||
!esp_tee_flash_check_paddr_in_tee_region(paddr) &&
|
||||
esp_tee_buf_in_ree(out_vaddr, sizeof(uint32_t)));
|
||||
|
||||
if (!valid_addr) {
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -24,6 +24,9 @@
|
||||
|
||||
/* TEE symbols */
|
||||
extern uint32_t _tee_stack;
|
||||
extern uint32_t _tee_stack_bottom;
|
||||
extern uint32_t _tee_intr_stack;
|
||||
extern uint32_t _tee_intr_stack_bottom;
|
||||
extern uint32_t _tee_bss_start;
|
||||
extern uint32_t _tee_bss_end;
|
||||
extern uint32_t _tee_s_intr_handler;
|
||||
@@ -117,6 +120,9 @@ void __attribute__((noreturn)) esp_tee_init(uint32_t ree_entry_addr, uint32_t re
|
||||
{
|
||||
/* Clear BSS */
|
||||
memset(&_tee_bss_start, 0, (&_tee_bss_end - &_tee_bss_start) * sizeof(_tee_bss_start));
|
||||
/* Clear the TEE stack and interrupt stack */
|
||||
memset(&_tee_stack_bottom, 0, (&_tee_stack - &_tee_stack_bottom) * sizeof(_tee_stack_bottom));
|
||||
memset(&_tee_intr_stack_bottom, 0, (&_tee_intr_stack - &_tee_intr_stack_bottom) * sizeof(_tee_intr_stack_bottom));
|
||||
|
||||
static uint32_t btld_sp;
|
||||
|
||||
|
||||
@@ -16,19 +16,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FORCE_INLINE_ATTR bool esp_tee_ptr_in_ree(const void *p)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
return (
|
||||
(addr >= SOC_NS_IDRAM_START && addr < SOC_NS_IDRAM_END) ||
|
||||
(addr >= (uintptr_t)esp_tee_app_config.ns_drom_start &&
|
||||
addr < SOC_S_MMU_MMAP_RESV_START_VADDR)
|
||||
#if SOC_RTC_MEM_SUPPORTED
|
||||
|| (addr >= SOC_RTC_DATA_LOW && addr < SOC_RTC_DATA_HIGH)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
/* TODO: Revisit these bounds for high-performance RISC-V SoCs (e.g. ESP32-P4,
|
||||
* ESP32-S31) with different memory maps than current ESP-TEE targets.
|
||||
*/
|
||||
FORCE_INLINE_ATTR bool esp_tee_buf_in_ree(const void *p, size_t len)
|
||||
{
|
||||
uintptr_t start = (uintptr_t)p;
|
||||
@@ -40,13 +30,18 @@ FORCE_INLINE_ATTR bool esp_tee_buf_in_ree(const void *p, size_t len)
|
||||
|
||||
uintptr_t end = start + len;
|
||||
return ((start >= SOC_NS_IDRAM_START && end <= SOC_NS_IDRAM_END) ||
|
||||
(start >= (uintptr_t)esp_tee_app_config.ns_drom_start && end <= SOC_S_MMU_MMAP_RESV_START_VADDR)
|
||||
(start >= SOC_S_DROM_HIGH && end <= SOC_S_MMU_MMAP_RESV_START_VADDR)
|
||||
#if SOC_RTC_MEM_SUPPORTED
|
||||
|| (start >= SOC_RTC_DATA_LOW && end <= SOC_RTC_DATA_HIGH)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR bool esp_tee_ptr_in_ree(const void *p)
|
||||
{
|
||||
return esp_tee_buf_in_ree(p, 4);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -55,9 +55,9 @@ static void esp_tee_configure_invalid_regions(void)
|
||||
|
||||
// 7. Using PMA to configure the TEE text and data section access attribute. */
|
||||
PMA_ENTRY_CFG_RESET(12);
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(13));
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(14));
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(15));
|
||||
ESP_FAULT_ASSERT(IS_PMA_ENTRY_UNLOCKED(13) &&
|
||||
IS_PMA_ENTRY_UNLOCKED(14) &&
|
||||
IS_PMA_ENTRY_UNLOCKED(15));
|
||||
|
||||
extern int _tee_iram_end;
|
||||
PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_S_IRAM_START, PMA_NONE);
|
||||
@@ -122,6 +122,20 @@ void esp_tee_configure_region_protection(void)
|
||||
PMP_ENTRY_CFG_RESET(4);
|
||||
PMP_ENTRY_CFG_RESET(5);
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
/* Validate the REE-supplied (esp_tee_app_config) bounds before programming
|
||||
* the TOR-chained PMP entries below */
|
||||
const uint32_t ns_iram_end = (uint32_t)esp_tee_app_config.ns_iram_end;
|
||||
const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE;
|
||||
const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end);
|
||||
const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end);
|
||||
const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR);
|
||||
|
||||
ESP_FAULT_ASSERT(ns_iram_end >= SOC_NS_IRAM_START &&
|
||||
ns_iram_end <= SOC_DRAM_HIGH &&
|
||||
s_irom_resv_end <= ns_irom_resv_end &&
|
||||
ns_irom_resv_end <= ns_drom_resv_end &&
|
||||
ns_drom_resv_end <= ns_drom_mmap_end);
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
@@ -131,15 +145,10 @@ void esp_tee_configure_region_protection(void)
|
||||
} else {
|
||||
// REE SRAM (D/IRAM)
|
||||
PMP_ENTRY_SET(4, (int)SOC_NS_IRAM_START, NONE);
|
||||
PMP_ENTRY_SET(5, (int)esp_tee_app_config.ns_iram_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(5, (int)ns_iram_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(6, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
}
|
||||
|
||||
const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE;
|
||||
const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end);
|
||||
const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end);
|
||||
const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR);
|
||||
|
||||
// 4. I_Cache / D_Cache (flash) - REE
|
||||
PMP_ENTRY_CFG_RESET(7);
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -63,9 +63,9 @@ static void esp_tee_configure_invalid_regions(void)
|
||||
PMA_RESET_AND_ENTRY_SET_TOR(12, UINT32_MAX, PMA_TOR | PMA_NONE);
|
||||
|
||||
// 8. Using PMA to configure the TEE text and data section access attribute. */
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(13));
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(14));
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(15));
|
||||
ESP_FAULT_ASSERT(IS_PMA_ENTRY_UNLOCKED(13) &&
|
||||
IS_PMA_ENTRY_UNLOCKED(14) &&
|
||||
IS_PMA_ENTRY_UNLOCKED(15));
|
||||
|
||||
extern int _tee_iram_end;
|
||||
PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_S_IRAM_START, PMA_NONE);
|
||||
@@ -112,7 +112,20 @@ void esp_tee_configure_region_protection(void)
|
||||
PMP_ENTRY_SET(1, SOC_IROM_MASK_HIGH, PMP_TOR | RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
|
||||
/* TODO: Check whether changes are required here */
|
||||
/* Validate the REE-supplied (esp_tee_app_config) bounds before programming
|
||||
* the TOR-chained PMP entries below */
|
||||
const uint32_t ns_iram_end = (uint32_t)esp_tee_app_config.ns_iram_end;
|
||||
const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE;
|
||||
const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end);
|
||||
const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end);
|
||||
const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR);
|
||||
|
||||
ESP_FAULT_ASSERT(ns_iram_end >= SOC_NS_IRAM_START &&
|
||||
ns_iram_end <= SOC_DRAM_HIGH &&
|
||||
s_irom_resv_end <= ns_irom_resv_end &&
|
||||
ns_irom_resv_end <= ns_drom_resv_end &&
|
||||
ns_drom_resv_end <= ns_drom_mmap_end);
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
@@ -125,15 +138,10 @@ void esp_tee_configure_region_protection(void)
|
||||
// 2. IRAM and DRAM
|
||||
// Splitting the REE SRAM region into IRAM and DRAM
|
||||
PMP_ENTRY_SET(2, (int)SOC_NS_IRAM_START, NONE);
|
||||
PMP_ENTRY_SET(3, (int)esp_tee_app_config.ns_iram_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(3, (int)ns_iram_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(4, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
}
|
||||
|
||||
const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE;
|
||||
const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end);
|
||||
const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end);
|
||||
const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR);
|
||||
|
||||
// 4. I_Cache / D_Cache (flash) - REE
|
||||
PMP_ENTRY_CFG_RESET(5);
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -65,9 +65,9 @@ static void esp_tee_configure_invalid_regions(void)
|
||||
PMA_ENTRY_SET_TOR(12, UINT32_MAX, PMA_TOR | PMA_NONE);
|
||||
|
||||
/* 8. Using PMA to configure the TEE text and data section access attribute. */
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(13));
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(14));
|
||||
assert(IS_PMA_ENTRY_UNLOCKED(15));
|
||||
ESP_FAULT_ASSERT(IS_PMA_ENTRY_UNLOCKED(13) &&
|
||||
IS_PMA_ENTRY_UNLOCKED(14) &&
|
||||
IS_PMA_ENTRY_UNLOCKED(15));
|
||||
|
||||
extern int _tee_iram_end;
|
||||
PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_S_IRAM_START, PMA_NONE);
|
||||
@@ -108,7 +108,20 @@ void esp_tee_configure_region_protection(void)
|
||||
PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
|
||||
/* TODO: Check whether changes are required here */
|
||||
/* Validate the REE-supplied (esp_tee_app_config) bounds before programming
|
||||
* the TOR-chained PMP entries below */
|
||||
const uint32_t ns_iram_end = (uint32_t)esp_tee_app_config.ns_iram_end;
|
||||
const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE;
|
||||
const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end);
|
||||
const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end);
|
||||
const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR);
|
||||
|
||||
ESP_FAULT_ASSERT(ns_iram_end >= SOC_NS_IRAM_START &&
|
||||
ns_iram_end <= SOC_DRAM_HIGH &&
|
||||
s_irom_resv_end <= ns_irom_resv_end &&
|
||||
ns_irom_resv_end <= ns_drom_resv_end &&
|
||||
ns_drom_resv_end <= ns_drom_mmap_end);
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
@@ -121,15 +134,10 @@ void esp_tee_configure_region_protection(void)
|
||||
// 2. IRAM and DRAM
|
||||
// Splitting the REE SRAM region into IRAM and DRAM
|
||||
PMP_ENTRY_SET(1, (int)SOC_NS_IRAM_START, NONE);
|
||||
PMP_ENTRY_SET(2, (int)esp_tee_app_config.ns_iram_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(2, (int)ns_iram_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(3, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
}
|
||||
|
||||
const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE;
|
||||
const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end);
|
||||
const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end);
|
||||
const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR);
|
||||
|
||||
// 4. I_Cache / D_Cache (flash) - REE
|
||||
PMP_ENTRY_CFG_RESET(5);
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
|
||||
@@ -219,7 +219,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
|
||||
@@ -134,10 +134,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)
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
# Increasing TEE I/DRAM sizes
|
||||
# 38KB
|
||||
CONFIG_SECURE_TEE_IRAM_SIZE=0x9800
|
||||
# 18KB
|
||||
CONFIG_SECURE_TEE_DRAM_SIZE=0x4800
|
||||
# 18.5KB
|
||||
CONFIG_SECURE_TEE_DRAM_SIZE=0x4A00
|
||||
|
||||
# Security features - build-only configuration
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0xf000
|
||||
|
||||
@@ -289,6 +289,7 @@ class TEESerial(IdfSerial):
|
||||
'type': 'ecdsa_p256',
|
||||
'input': 'ecdsa_p256_key.pem',
|
||||
'write_once': True,
|
||||
'tee_only': True,
|
||||
'b64': (
|
||||
'LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUlNU1VpUktHaVZjSTIvbUZFekI3eXRIOVJj'
|
||||
'd0wyUThkNDhONHNFUHFYc0RvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkYxYXRZQUxrdnB4cCt4N3c1dmVPQ1Vj'
|
||||
@@ -349,6 +350,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
|
||||
]
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
|
||||
set(priv_requires bootloader_support esp_driver_gptimer esp_tee esp_timer mbedtls spi_flash)
|
||||
set(priv_requires bootloader_support esp_driver_gptimer esp_system esp_tee esp_timer mbedtls spi_flash)
|
||||
# Test FW related
|
||||
list(APPEND priv_requires json nvs_flash test_utils unity)
|
||||
# TEE related
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "unity.h"
|
||||
#include "esp_tee.h"
|
||||
#include "esp_private/hw_stack_guard.h"
|
||||
#include "secure_service_num.h"
|
||||
|
||||
#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ((addr) & ~((SOC_MMU_PAGE_SIZE) - 1))
|
||||
@@ -212,3 +213,22 @@ TEST_CASE("Test REE-TEE isolation: DROM-W1", "[exception]")
|
||||
*(uint32_t *)(test_addr - 0x04) = 0xbadc0de;
|
||||
TEST_FAIL_MESSAGE("Exception should have been generated");
|
||||
}
|
||||
|
||||
TEST_CASE("Test REE-TEE isolation: Corrupted SP", "[exception]")
|
||||
{
|
||||
uintptr_t atk_sp = (uintptr_t)&_iram_start - 0x100;
|
||||
|
||||
/* Disable U-mode interrupts so the tick cannot preempt before the ecall */
|
||||
__asm__ volatile("csrci ustatus, 0x1\n\t" : : : "memory");
|
||||
|
||||
/* Stop the REE-owned HW stack guard, as a malicious REE could */
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
esp_hw_stack_guard_monitor_stop();
|
||||
#endif
|
||||
|
||||
/* Cross into the TEE with the doctored sp; the handler rejects it and panics */
|
||||
__asm__ volatile("mv sp, %0\n\t"
|
||||
"ecall\n\t" : : "r"(atk_sp) : "memory");
|
||||
|
||||
TEST_FAIL_MESSAGE("Exception should have been generated");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -327,6 +327,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];
|
||||
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, tag, sizeof(tag), data));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_decrypt(&aead_ctx, tag, sizeof(tag), data));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("Test TEE Secure Storage - WRITE_ONCE keys", "[sec_storage]")
|
||||
{
|
||||
const char *key_id = "key_id_test_wo";
|
||||
@@ -346,6 +378,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);
|
||||
@@ -416,7 +464,7 @@ TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_ke
|
||||
|
||||
TEST_ESP_OK(esp_tee_sec_storage_clear_key(ecdsa_key_id0));
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(attest_key_id));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_clear_key(attest_key_id));
|
||||
|
||||
#if CONFIG_SECURE_TEE_ATTESTATION
|
||||
uint8_t *token_buf = heap_caps_calloc(ESP_ATT_TK_BUF_SIZE, sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
@@ -425,9 +473,19 @@ TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_ke
|
||||
uint32_t token_len = 0;
|
||||
TEST_ESP_OK(esp_tee_att_generate_token(0xA1B2C3D4, 0x0FACADE0, (const char *)ESP_ATT_TK_PSA_CERT_REF,
|
||||
token_buf, ESP_ATT_TK_BUF_SIZE, &token_len));
|
||||
|
||||
free(token_buf);
|
||||
#endif
|
||||
#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, msg_digest, 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
|
||||
|
||||
@@ -24,6 +24,7 @@ _BASE_CONFIG = {
|
||||
'DROM-R1': 'Load access fault',
|
||||
'DROM-W1': 'Store access fault',
|
||||
'MMU-spillover': 'Illegal instruction',
|
||||
'Corrupted SP': 'Environment call from U-mode',
|
||||
},
|
||||
'apm_violation': {
|
||||
'eFuse': 'APM - Space exception',
|
||||
|
||||
@@ -132,6 +132,18 @@ bool mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t target
|
||||
*/
|
||||
bool mmu_hal_check_valid_ext_vaddr_region(uint32_t mmu_id, uint32_t vaddr_start, uint32_t len, mmu_vaddr_t type);
|
||||
|
||||
/**
|
||||
* Check if the paddr region is valid
|
||||
*
|
||||
* @param mmu_id MMU ID
|
||||
* @param paddr_start start of the physical address
|
||||
* @param len length, in bytes
|
||||
*
|
||||
* @return
|
||||
* True for valid
|
||||
*/
|
||||
bool mmu_hal_check_valid_paddr_region(uint32_t mmu_id, uint32_t paddr_start, uint32_t len);
|
||||
|
||||
#if SOC_MMU_PER_EXT_MEM_TARGET
|
||||
/**
|
||||
* Get MMU ID from MMU target
|
||||
|
||||
@@ -186,6 +186,11 @@ bool mmu_hal_check_valid_ext_vaddr_region(uint32_t mmu_id, uint32_t vaddr_start,
|
||||
return mmu_ll_check_valid_ext_vaddr_region(mmu_id, vaddr_start, len, type);
|
||||
}
|
||||
|
||||
bool mmu_hal_check_valid_paddr_region(uint32_t mmu_id, uint32_t paddr_start, uint32_t len)
|
||||
{
|
||||
return mmu_ll_check_valid_paddr_region(mmu_id, paddr_start, len);
|
||||
}
|
||||
|
||||
#if SOC_MMU_PER_EXT_MEM_TARGET
|
||||
uint32_t mmu_hal_get_id_from_target(mmu_target_t target)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user