Merge branch 'feature/esp_tee_c5' into 'master'

feat(esp_tee): Initial support for ESP32-C5

Closes IDF-10426, IDF-10427, IDF-10428, IDF-10429, and IDF-10430

See merge request espressif/esp-idf!38807
This commit is contained in:
Mahavir Jain
2025-08-14 17:44:12 +05:30
79 changed files with 3286 additions and 694 deletions

View File

@@ -271,15 +271,33 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_mtvt_addr(const void *mtvt_addr)
{
rv_utils_set_mtvt((uint32_t)mtvt_addr);
}
/**
* @brief Set the base address of the current CPU's Interrupt Vector Table (XTVT), based
* on the current privilege level
*
* @param xtvt_addr Interrupt Vector Table's base address
*
* @note The XTVT table is only applicable when CLIC is supported
*/
FORCE_INLINE_ATTR void esp_cpu_intr_set_xtvt_addr(const void *xtvt_addr)
{
rv_utils_set_xtvt((uint32_t)xtvt_addr);
}
#endif //#if SOC_INT_CLIC_SUPPORTED
#if SOC_CPU_SUPPORT_WFE
/**
* @brief Disable the WFE (wait for event) feature for CPU.
*/
FORCE_INLINE_ATTR void rv_utils_disable_wfe_mode(void)
FORCE_INLINE_ATTR void esp_cpu_disable_wfe_mode(void)
{
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb;
esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_WFE_MODE_ENABLE, false);
#else
rv_utils_wfe_mode_enable(false);
#endif
}
#endif
@@ -450,9 +468,14 @@ FORCE_INLINE_ATTR uint32_t esp_cpu_intr_get_enabled_mask(void)
{
#ifdef __XTENSA__
return xt_utils_intr_get_enabled_mask();
#else
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD && CONFIG_IDF_TARGET_ESP32C5
extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb;
return esp_tee_intr_sec_srv_cb(1, SS_RV_UTILS_INTR_GET_ENABLED_MASK);
#else
return rv_utils_intr_get_enabled_mask();
#endif
#endif
}
/**

View File

@@ -28,7 +28,10 @@
#define MSPI_TIMING_FLASH_MODULE_CLOCK 120
#endif
//------------------------------------FLASH Needs Tuning or not-------------------------------------//
#if MSPI_TIMING_FLASH_STR_MODE
/* TODO: [ESP-TEE | IDF-10425] The SPI1 controller is protected by APM when ESP-TEE is enabled.
* MSPI tuning requires access to this controller, so it is currently disabled.
*/
#if MSPI_TIMING_FLASH_STR_MODE && !CONFIG_SECURE_ENABLE_TEE
#define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 40)
#endif
@@ -45,7 +48,8 @@
#define MSPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz
#endif
//------------------------------------PSRAM Needs Tuning or not-------------------------------------//
#if MSPI_TIMING_PSRAM_STR_MODE
/* TODO: [ESP-TEE | IDF-10425] */
#if MSPI_TIMING_PSRAM_STR_MODE && !CONFIG_SECURE_ENABLE_TEE
#define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 40)
#endif

View File

@@ -1,3 +1,5 @@
idf_build_get_property(non_os_build NON_OS_BUILD)
set(srcs "rtc_clk_init.c"
"rtc_time.c"
"rtc_clk.c"
@@ -8,7 +10,7 @@ set(srcs "rtc_clk_init.c"
"ocode_init.c"
)
if(NOT BOOTLOADER_BUILD)
if(NOT non_os_build)
list(APPEND srcs "sar_periph_ctrl.c")
endif()

View File

@@ -126,6 +126,14 @@ void esp_cpu_configure_region_protection(void)
//
esp_cpu_configure_invalid_regions();
/* NOTE: When ESP-TEE is active, only configure invalid memory regions in bootloader
* to prevent errors before TEE initialization. TEE will handle all other
* memory protection.
*/
#if CONFIG_SECURE_ENABLE_TEE && BOOTLOADER_BUILD
return;
#endif
//
// Configure all the valid address regions using PMP
//

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,7 +15,20 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_
* Reserve interrupt line 1 for the Wifi controller.
* Reserve interrupt line 6 since it is used for disabling interrupts in the interrupt allocator (INT_MUX_DISABLED_INTNO)
*/
const uint32_t rsvd_mask = BIT(1) | BIT(6);
const uint32_t base_rsvd_mask = BIT(1) | BIT(6);
/* On the ESP32-C5, interrupt 31 is reserved for ESP-TEE
* for operations related to secure peripherals under its control
* (e.g. AES, SHA, APM)
*
* Interrupt 30 is reserved for handling REE interrupts occurring in TEE.
*/
#if CONFIG_SECURE_ENABLE_TEE
const uint32_t rsvd_mask = base_rsvd_mask | BIT(30) | BIT(31);
#else
const uint32_t rsvd_mask = base_rsvd_mask;
#endif
intr_desc_ret->priority = 1;
intr_desc_ret->type = ESP_CPU_INTR_TYPE_NA;
intr_desc_ret->flags = esp_riscv_intr_num_flags(intr_num, rsvd_mask);

View File

@@ -19,12 +19,12 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_
// [TODO: IDF-2465]
const uint32_t base_rsvd_mask = BIT(1) | BIT(3) | BIT(4) | BIT(6) | BIT(7);
/* On the ESP32-C6, interrupt 14 is reserved for ESP-TEE
/* On the ESP32-C6, interrupt 31 is reserved for ESP-TEE
* for operations related to secure peripherals under its control
* (e.g. AES, SHA, APM)
*/
#if CONFIG_SECURE_ENABLE_TEE
const uint32_t rsvd_mask = base_rsvd_mask | BIT(14);
const uint32_t rsvd_mask = base_rsvd_mask | BIT(31);
#else
const uint32_t rsvd_mask = base_rsvd_mask;
#endif

View File

@@ -62,6 +62,10 @@ static void esp_cpu_configure_invalid_regions(void)
// 7. End of address space
PMA_ENTRY_SET_TOR(11, SOC_PERIPHERAL_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(12, UINT32_MAX, PMA_TOR | PMA_NONE);
PMA_ENTRY_CFG_RESET(13);
PMA_ENTRY_CFG_RESET(14);
PMA_ENTRY_CFG_RESET(15);
}
void esp_cpu_configure_region_protection(void)

View File

@@ -18,12 +18,12 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_
// [TODO: IDF-2465]
const uint32_t base_rsvd_mask = BIT(3) | BIT(4) | BIT(6) | BIT(7);
/* On the ESP32-H2, interrupt 14 is reserved for ESP-TEE
/* On the ESP32-H2, interrupt 31 is reserved for ESP-TEE
* for operations related to secure peripherals under its control
* (e.g. AES, SHA, APM)
*/
#if CONFIG_SECURE_ENABLE_TEE
const uint32_t rsvd_mask = base_rsvd_mask | BIT(14);
const uint32_t rsvd_mask = base_rsvd_mask | BIT(31);
#else
const uint32_t rsvd_mask = base_rsvd_mask;
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,31 @@
#include "../ext_mem_layout.h"
#include "hal/mmu_types.h"
/* NOTE: With ESP-TEE enabled:
* - The start address is moved by the size of TEE IDROM segments since these
* segments are placed at the start of the linear address space
* - TEE IROM and DROM segments are both 64KB (CONFIG_SECURE_TEE_IROM_SIZE,
* CONFIG_SECURE_TEE_DROM_SIZE) for now. Thus, the number of reserved entries
* from the start would be (64KB + 64KB)/MMU_PAGE_SIZE
* - The last few MMU entries are reserved for TEE flash operations. The number
* of reserved entries matches the size of TEE IDROM segments (IROM + DROM)
* plus one additional entry, i.e. (64KB + 64KB)/MMU_PAGE_SIZE + 1
*/
#if CONFIG_SECURE_ENABLE_TEE
#define TEE_MMU_MEM_REG_START_OFFS (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE)
#define TEE_MMU_RESV_PAGES ((CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) / CONFIG_MMU_PAGE_SIZE)
#define TEE_MMU_MEM_REG_END_OFFS ((TEE_MMU_RESV_PAGES + 1) * CONFIG_MMU_PAGE_SIZE)
#define MMU_MEM_REG_START_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW + TEE_MMU_MEM_REG_START_OFFS)
#define MMU_MEM_REG_END_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH - TEE_MMU_MEM_REG_END_OFFS)
#define MMU_IRAM0_LINEAR_ADDRESS_LOW MMU_MEM_REG_START_ADDR_W_TEE
#define MMU_IRAM0_LINEAR_ADDRESS_HIGH MMU_MEM_REG_END_ADDR_W_TEE
#else
#define MMU_IRAM0_LINEAR_ADDRESS_LOW SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW
#define MMU_IRAM0_LINEAR_ADDRESS_HIGH SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH
#endif
/**
* The start addresses in this list should always be sorted from low to high, as MMU driver will need to
* coalesce adjacent regions
@@ -17,9 +42,9 @@
// TODO: [ESP32C5] IDF-8658
const mmu_mem_region_t g_mmu_mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM] = {
[0] = {
.start = SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW,
.end = SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH,
.size = SOC_BUS_SIZE(SOC_MMU_IRAM0_LINEAR),
.start = MMU_IRAM0_LINEAR_ADDRESS_LOW,
.end = MMU_IRAM0_LINEAR_ADDRESS_HIGH,
.size = MMU_IRAM0_LINEAR_ADDRESS_HIGH - MMU_IRAM0_LINEAR_ADDRESS_LOW,
.bus_id = CACHE_BUS_IBUS0 | CACHE_BUS_DBUS0,
.targets = MMU_TARGET_FLASH0 | MMU_TARGET_PSRAM0,
.caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_WRITE | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT,

View File

@@ -75,6 +75,10 @@ if(CONFIG_ESP_ROM_NO_USB_SERIAL_OUTPUT_API)
list(APPEND sources "patches/esp_rom_usb_serial.c")
endif()
if(CONFIG_SECURE_ENABLE_TEE AND CONFIG_IDF_TARGET_ESP32C5 AND NOT ESP_TEE_BUILD)
list(APPEND sources "patches/esp_rom_cache_esp32c5.c")
endif()
idf_component_register(SRCS ${sources}
INCLUDE_DIRS ${include_dirs}
PRIV_REQUIRES ${private_required_comp}
@@ -142,6 +146,9 @@ endif()
if(ESP_TEE_BUILD)
rom_linker_script("spiflash")
rom_linker_script("heap")
if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT)
rom_linker_script("newlib-nano")
endif()
endif()
if(BOOTLOADER_BUILD)
@@ -388,7 +395,7 @@ else() # Regular app build
endif()
endif()
if(CONFIG_ESP_ROM_DELAY_US_PATCH AND
if(CONFIG_ESP_ROM_DELAY_US_PATCH AND CONFIG_SECURE_ENABLE_TEE AND
(CONFIG_ESP32C5_REV_MIN_FULL LESS_EQUAL 100 OR CONFIG_ESP32C61_REV_MIN_FULL LESS_EQUAL 100))
# Force the linker to include esp_rom_sys.c for ets_ops_set_rom_patches constructor
target_link_libraries(${COMPONENT_LIB} PRIVATE "-u ets_ops_set_rom_patches")

View File

@@ -219,7 +219,7 @@ Cache_Suspend_Cache = 0x400006b4;
Cache_Resume_Cache = 0x400006b8;
Cache_Freeze_Enable = 0x400006bc;
Cache_Freeze_Disable = 0x400006c0;
Cache_Set_IDROM_MMU_Size = 0x400006c4;
PROVIDE ( Cache_Set_IDROM_MMU_Size = 0x400006c4 );
Cache_Get_IROM_MMU_End = 0x400006c8;
Cache_Get_DROM_MMU_End = 0x400006cc;
Cache_MMU_Init = 0x400006d0;

View File

@@ -6,6 +6,7 @@
#pragma once
#include <stddef.h>
#include <stdbool.h>
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
@@ -17,8 +18,17 @@ typedef void* tlsf_t;
typedef void* pool_t;
/* Create/destroy a memory pool. */
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
tlsf_t tlsf_create(void* mem);
tlsf_t tlsf_create_with_pool(void* mem, size_t bytes);
size_t tlsf_size(void);
#else
tlsf_t tlsf_create(void* mem, size_t max_bytes);
tlsf_t tlsf_create_with_pool(void* mem, size_t pool_bytes, size_t max_bytes);
size_t tlsf_size(tlsf_t tlsf);
#endif
void tlsf_destroy(tlsf_t tlsf);
pool_t tlsf_get_pool(tlsf_t tlsf);
/* Add/remove memory pools. */
@@ -36,7 +46,6 @@ void tlsf_free(tlsf_t tlsf, void* ptr);
size_t tlsf_block_size(void* ptr);
/* Overheads/limits of internal structures. */
size_t tlsf_size(void);
size_t tlsf_pool_overhead(void);
size_t tlsf_alloc_overhead(void);
@@ -47,7 +56,12 @@ size_t tlsf_alloc_overhead(void);
*/
size_t tlsf_align_size(void);
size_t tlsf_block_size_min(void);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
size_t tlsf_block_size_max(void);
#else
size_t tlsf_block_size_max(tlsf_t tlsf);
#endif
size_t tlsf_fit_size(tlsf_t tlsf, size_t size);
/* NOTE: The consumer of this callback function (tlsf_walk_pool) is patched
* in IDF builds to address issues in the ROM implementation. For TEE build,

View File

@@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp32c5/rom/cache.h"
/**
* @brief Dummy implementation of Cache_Set_IDROM_MMU_Size from ROM.
*
* NOTE: This ROM-provided API is intended to configure the Cache MMU size for
* instruction (irom) and rodata (drom) sections in flash.
*
* On ESP32-C5, it also sets the start pages for flash irom and drom sections,
* which involves accessing MMU registers directly. However, these MMU registers
* are protected by the APM and direct access from the REE results in a fault.
*
* To prevent this:
* - Mark this symbol with the `PROVIDE` attribute in the ROM linker script.
* - Define this dummy function as a stub implementation.
* - Wrap this function to be routed as a TEE service call
*
* @param irom_size Size of the instruction ROM region.
* @param drom_size Size of the data ROM region.
*/
void Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size)
{
(void)irom_size;
(void)drom_size;
}

View File

@@ -117,7 +117,7 @@ uint32_t esp_rom_get_bootloader_offset(void)
}
#endif // SOC_RECOVERY_BOOTLOADER_SUPPORTED
#if ESP_ROM_DELAY_US_PATCH && !NON_OS_BUILD
#if ESP_ROM_DELAY_US_PATCH && CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
#if CONFIG_ESP32C5_REV_MIN_FULL <= 100 || CONFIG_ESP32C61_REV_MIN_FULL <= 100
#include "riscv/rv_utils.h"

View File

@@ -15,7 +15,13 @@
#include "sdkconfig.h"
#include "ld.common"
#define SRAM_SEG_START 0x40800000
#if !CONFIG_SECURE_ENABLE_TEE
#define SRAM_SEG_START (0x40800000)
#else
#define SRAM_SEG_START (0x40800000 + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE)
#define FLASH_SEG_OFFSET (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE)
#endif // CONFIG_SECURE_ENABLE_TEE
#define SRAM_SEG_END 0x4084E5A0 /* 2nd stage bootloader iram_loader_seg start address */
#define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START
@@ -33,8 +39,14 @@ MEMORY
*/
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
#if CONFIG_SECURE_ENABLE_TEE
/* Flash mapped instruction data */
irom_seg (RX) : org = 0x42000020 + FLASH_SEG_OFFSET,
len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20
#else
/* Flash mapped instruction data */
irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20
#endif
/**
* (0x20 offset above is a convenience for the app binary image generation.
@@ -52,8 +64,14 @@ MEMORY
sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
#if CONFIG_SECURE_ENABLE_TEE
/* Flash mapped constant data */
drom_seg (R) : org = 0x42000020 + FLASH_SEG_OFFSET,
len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20
#else
/* Flash mapped instruction data */
drom_seg (R) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20
#endif
/* (See irom_seg for meaning of 0x20 offset in the above.) */
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS

View File

@@ -158,9 +158,22 @@ SECTIONS
_iram_start = ABSOLUTE(.);
/* Vectors go to start of IRAM */
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
_vector_table_start = ABSOLUTE(.);
KEEP(*(.exception_vectors_table.text));
KEEP(*(.exception_vectors.text));
ALIGNED_SYMBOL(4, _invalid_pc_placeholder)
/* esp_tee_config_t structure: used to share information between the TEE and REE
* (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.)
* This symbol is expected by the TEE at an offset of 0x2b0 from the vector table start.
*/
#if CONFIG_SECURE_ENABLE_TEE
ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg)
ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2b0, "esp_tee_app_cfg must be at an offset 0x2b0 from the vector table start");
*libesp_tee.a:(.esp_tee_app_cfg);
#endif
/* Code marked as running out of IRAM */
_iram_text_start = ABSOLUTE(.);

View File

@@ -172,8 +172,13 @@ static volatile bool s_resume_cores;
static void core_intr_matrix_clear(void)
{
uint32_t core_id = esp_cpu_get_core_id();
__attribute__((unused)) uint32_t core_id = esp_cpu_get_core_id();
/* NOTE: With ESP-TEE enabled, each iteration in this loop results in a service call.
* To accelerate the boot-up process, the interrupt configuration is pre-cleared in the TEE,
* allowing this step to be safely skipped here.
*/
#if !CONFIG_SECURE_ENABLE_TEE
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
#if SOC_INT_CLIC_SUPPORTED
interrupt_clic_ll_route(core_id, i, ETS_INVALID_INUM);
@@ -181,6 +186,7 @@ static void core_intr_matrix_clear(void)
esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM);
#endif // SOC_INT_CLIC_SUPPORTED
}
#endif // !CONFIG_SECURE_ENABLE_TEE
#if SOC_INT_CLIC_SUPPORTED
for (int i = 0; i < 32; i++) {
@@ -382,6 +388,15 @@ FORCE_INLINE_ATTR IRAM_ATTR void init_cpu(void)
);
#endif
/* NOTE: When ESP-TEE is enabled, this sets up the callback function
* which redirects all the interrupt management for the REE (user app)
* to the TEE by raising the appropriate service calls.
*/
#if CONFIG_SECURE_ENABLE_TEE
extern uint32_t esp_tee_service_call(int argc, ...);
esprv_int_setup_mgmt_cb((void *)esp_tee_service_call);
#endif
#if SOC_BRANCH_PREDICTOR_SUPPORTED
esp_cpu_branch_prediction_enable();
#endif
@@ -391,19 +406,12 @@ FORCE_INLINE_ATTR IRAM_ATTR void init_cpu(void)
/* When hardware vectored interrupts are enabled in CLIC,
* the CPU jumps to this base address + 4 * interrupt_id.
*/
esp_cpu_intr_set_mtvt_addr(&_mtvt_table);
/* NOTE: When ESP-TEE is enabled, this sets up the U-mode
* interrupt vector table (UTVT) */
esp_cpu_intr_set_xtvt_addr(&_mtvt_table);
#endif
#if SOC_CPU_SUPPORT_WFE
rv_utils_disable_wfe_mode();
#endif
/* NOTE: When ESP-TEE is enabled, this sets up the callback function
* which redirects all the interrupt management for the REE (user app)
* to the TEE by raising the appropriate service calls.
*/
#if CONFIG_SECURE_ENABLE_TEE
extern uint32_t esp_tee_service_call(int argc, ...);
esprv_int_setup_mgmt_cb((void *)esp_tee_service_call);
esp_cpu_disable_wfe_mode();
#endif
}

View File

@@ -305,6 +305,7 @@ __attribute__((weak)) void esp_perip_clk_init(void)
assist_debug_ll_enable_bus_clock(false);
#endif
mpi_ll_enable_bus_clock(false);
#if !CONFIG_SECURE_ENABLE_TEE
aes_ll_enable_bus_clock(false);
sha_ll_enable_bus_clock(false);
ecc_ll_enable_bus_clock(false);
@@ -312,9 +313,10 @@ __attribute__((weak)) void esp_perip_clk_init(void)
ds_ll_enable_bus_clock(false);
apm_ll_hp_tee_enable_clk_gating(true);
apm_ll_lp_tee_enable_clk_gating(true);
uhci_ll_enable_bus_clock(0, false);
apm_ll_hp_apm_enable_ctrl_clk_gating(true);
apm_ll_cpu_apm_enable_ctrl_clk_gating(true);
#endif
uhci_ll_enable_bus_clock(0, false);
// TODO: Replace with hal implementation
REG_CLR_BIT(PCR_TRACE_CONF_REG, PCR_TRACE_CLK_EN);
@@ -346,8 +348,10 @@ __attribute__((weak)) void esp_perip_clk_init(void)
_lp_clkrst_ll_enable_lp_ana_i2c_clock(false);
_lp_clkrst_ll_enable_lp_ext_i2c_clock(false);
#if !CONFIG_SECURE_ENABLE_TEE
apm_ll_lp_apm_enable_ctrl_clk_gating(true);
apm_ll_lp_apm0_enable_ctrl_clk_gating(true);
#endif
WRITE_PERI_REG(LP_CLKRST_LP_CLK_PO_EN_REG, 0);
}
}

View File

@@ -6,8 +6,10 @@ idf_build_get_property(target IDF_TARGET)
# headers & sources here are compiled into the app, not the esp_tee binary
# (see subproject/ for the esp_tee binary build files)
# ESP-TEE is currently supported only on the ESP32-C6 and ESP32-H2 SoCs
if(NOT ${target} STREQUAL "esp32c6" AND NOT ${target} STREQUAL "esp32h2")
# 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")
return()
endif()

View File

@@ -1,5 +1,5 @@
menu "ESP-TEE (Trusted Execution Environment)"
depends on IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2
depends on IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32C5
config SECURE_ENABLE_TEE
bool "Enable the ESP-TEE framework"

View File

@@ -10,13 +10,17 @@
extern "C" {
#endif
#include "soc/soc_caps.h"
#include "sdkconfig.h"
/* Declarations used inside TEE binary, only */
#define portNUM_PROCESSORS (1)
#define configNUM_CORES (portNUM_PROCESSORS)
#define TEE_SECURE_INUM (14)
#define TEE_SECURE_INUM (31)
#if SOC_INT_CLIC_SUPPORTED
#define TEE_PASS_INUM (30)
#endif
#define ESP_TEE_M2U_SWITCH_MAGIC 0xfedef

View File

@@ -0,0 +1,332 @@
secure_services:
- family: misc
entries:
- id: 0
type: custom
function: invalid_secure_service
args: 0
# ID: 1-4 (4) - External memory (Flash) protection [SPI0]
- family: flash_protection_spi0
entries:
- id: 1
type: IDF
function: mmu_hal_map_region
args: 6
- id: 2
type: IDF
function: mmu_hal_unmap_region
args: 3
- id: 3
type: IDF
function: mmu_hal_vaddr_to_paddr
args: 4
- id: 4
type: IDF
function: mmu_hal_paddr_to_vaddr
args: 5
- id: 5
type: IDF
function: Cache_Set_IDROM_MMU_Size
args: 2
# ID: 6-22 (17) - External memory (Flash) protection [SPI1]
- family: flash_protection_spi1
entries:
- id: 6
type: IDF
function: spi_flash_hal_check_status
args: 1
- id: 7
type: IDF
function: spi_flash_hal_common_command
args: 2
- id: 8
type: IDF
function: spi_flash_hal_device_config
args: 1
- id: 9
type: IDF
function: spi_flash_hal_erase_block
args: 2
- id: 10
type: IDF
function: spi_flash_hal_erase_chip
args: 1
- id: 11
type: IDF
function: spi_flash_hal_erase_sector
args: 2
- id: 12
type: IDF
function: spi_flash_hal_program_page
args: 4
- id: 13
type: IDF
function: spi_flash_hal_read
args: 4
- id: 14
type: IDF
function: spi_flash_hal_resume
args: 1
- id: 15
type: IDF
function: spi_flash_hal_set_write_protect
args: 2
- id: 16
type: IDF
function: spi_flash_hal_setup_read_suspend
args: 2
- id: 17
type: IDF
function: spi_flash_hal_supports_direct_read
args: 2
- id: 18
type: IDF
function: spi_flash_hal_supports_direct_write
args: 2
- id: 19
type: IDF
function: spi_flash_hal_suspend
args: 1
- id: 20
type: IDF
function: bootloader_flash_execute_command_common
args: 7
- id: 21
type: IDF
function: memspi_host_flush_cache
args: 3
- id: 22
type: IDF
function: spi_flash_chip_generic_config_host_io_mode
args: 2
# ID: 30-53 (24) - Interrupt Handling
- family: interrupt_handling
entries:
- id: 30
type: IDF
function: esp_rom_route_intr_matrix
args: 3
- id: 31
type: IDF
function: rv_utils_intr_enable
args: 1
- id: 32
type: IDF
function: rv_utils_intr_disable
args: 1
- id: 33
type: IDF
function: rv_utils_intr_set_priority
args: 2
- id: 34
type: IDF
function: rv_utils_intr_set_type
args: 2
- id: 35
type: IDF
function: rv_utils_intr_set_threshold
args: 1
- id: 36
type: IDF
function: rv_utils_intr_edge_ack
args: 1
- id: 37
type: IDF
function: rv_utils_intr_global_enable
args: 0
- id: 38
type: IDF
function: rv_utils_intr_get_enabled_mask
args: 0
- id: 39
type: IDF
function: rv_utils_set_cycle_count
args: 1
- id: 40
type: IDF
function: rv_utils_en_branch_predictor
args: 0
- id: 41
type: IDF
function: rv_utils_dis_branch_predictor
args: 0
- id: 42
type: IDF
function: rv_utils_wfe_mode_enable
args: 1
- id: 43
type: IDF
function: esprv_int_set_vectored
args: 2
# ID: 54-85 (32) - HAL
- family: hal
entries:
- id: 54
type: IDF
function: wdt_hal_init
args: 4
- id: 55
type: IDF
function: wdt_hal_deinit
args: 1
# ID: 86-133 (48) - Crypto
- family: crypto
entries:
- id: 86
type: IDF
function: esp_aes_intr_alloc
args: 0
- id: 87
type: IDF
function: esp_aes_crypt_cbc
args: 6
- id: 88
type: IDF
function: esp_aes_crypt_cfb8
args: 6
- id: 89
type: IDF
function: esp_aes_crypt_cfb128
args: 7
- id: 90
type: IDF
function: esp_aes_crypt_ctr
args: 7
- id: 91
type: IDF
function: esp_aes_crypt_ecb
args: 4
- id: 92
type: IDF
function: esp_aes_crypt_ofb
args: 6
- id: 93
type: IDF
function: esp_sha
args: 4
- id: 94
type: IDF
function: esp_sha_block
args: 3
- id: 95
type: IDF
function: esp_sha_dma
args: 6
- id: 96
type: IDF
function: esp_sha_read_digest_state
args: 2
- id: 97
type: IDF
function: esp_sha_write_digest_state
args: 2
- id: 98
type: IDF
function: esp_crypto_sha_enable_periph_clk
args: 1
- id: 99
type: IDF
function: esp_hmac_calculate
args: 4
- id: 100
type: IDF
function: esp_hmac_jtag_enable
args: 2
- id: 101
type: IDF
function: esp_hmac_jtag_disable
args: 0
- id: 102
type: IDF
function: esp_ds_sign
args: 4
- id: 103
type: IDF
function: esp_ds_start_sign
args: 4
- id: 104
type: IDF
function: esp_ds_is_busy
args: 0
- id: 105
type: IDF
function: esp_ds_finish_sign
args: 2
- id: 106
type: IDF
function: esp_ds_encrypt_params
args: 4
- id: 107
type: IDF
function: esp_crypto_mpi_enable_periph_clk
args: 1
- id: 108
type: IDF
function: esp_ecc_point_multiply
args: 4
- id: 109
type: IDF
function: esp_ecc_point_verify
args: 1
- id: 110
type: IDF
function: esp_crypto_ecc_enable_periph_clk
args: 1
- id: 111
type: IDF
function: esp_sha_set_mode
args: 1
- id: 112
type: IDF
function: esp_sha_512_t_init_hash
args: 1
# ID: 134-169 (36) - Reserved for future use
- family: attestation
entries:
- id: 170
type: custom
function: esp_tee_att_generate_token
args: 6
# ID: 175-194 (20) - Secure Storage
- family: secure_storage
entries:
- id: 175
type: custom
function: esp_tee_sec_storage_clear_key
args: 1
- id: 176
type: custom
function: esp_tee_sec_storage_gen_key
args: 1
- id: 177
type: custom
function: esp_tee_sec_storage_ecdsa_sign
args: 4
- id: 178
type: custom
function: esp_tee_sec_storage_ecdsa_get_pubkey
args: 2
- id: 179
type: custom
function: esp_tee_sec_storage_aead_encrypt
args: 4
- id: 180
type: custom
function: esp_tee_sec_storage_aead_decrypt
args: 4
# ID: 195-199 (5) - OTA
- family: ota
entries:
- id: 195
type: custom
function: esp_tee_ota_begin
args: 0
- id: 196
type: custom
function: esp_tee_ota_write
args: 3
- id: 197
type: custom
function: esp_tee_ota_end
args: 0
# ID: 200+ - User-defined

View File

@@ -20,6 +20,7 @@
#include "esp_flash.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#include "esp_tee.h"
#include "secure_service_num.h"
@@ -31,6 +32,13 @@ void IRAM_ATTR __wrap_esp_rom_route_intr_matrix(int cpu_no, uint32_t model_num,
esp_tee_service_call(4, SS_ESP_ROM_ROUTE_INTR_MATRIX, cpu_no, model_num, intr_num);
}
#if SOC_INT_CLIC_SUPPORTED
void IRAM_ATTR __wrap_esprv_int_set_vectored(int rv_int_num, bool vectored)
{
esp_tee_service_call(3, SS_ESPRV_INT_SET_VECTORED, rv_int_num, vectored);
}
#endif
/* ---------------------------------------------- RTC_WDT ------------------------------------------------- */
void __wrap_wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t prescaler, bool enable_intr)
@@ -222,6 +230,13 @@ void __wrap_esp_crypto_sha_enable_periph_clk(bool enable)
esp_tee_service_call(2, SS_ESP_CRYPTO_SHA_ENABLE_PERIPH_CLK, enable);
}
#if SOC_SHA_SUPPORT_SHA512_T
int __wrap_esp_sha_512_t_init_hash(uint16_t t)
{
return esp_tee_service_call(2, SS_ESP_SHA_512_T_INIT_HASH, t);
}
#endif
/* ---------------------------------------------- HMAC ------------------------------------------------- */
esp_err_t __wrap_esp_hmac_calculate(hmac_key_id_t key_id, const void *message, size_t message_len, uint8_t *hmac)
@@ -365,6 +380,25 @@ bool IRAM_ATTR __wrap_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mm
return esp_tee_service_call(6, SS_MMU_HAL_PADDR_TO_VADDR, mmu_id, paddr, target, type, out_vaddr);
}
/**
* NOTE: This ROM-provided API is intended to configure the Cache MMU size for
* instruction (irom) and rodata (drom) sections in flash.
*
* On ESP32-C5, it also sets the start pages for flash irom and drom sections,
* which involves accessing MMU registers directly.
*
* However, these MMU registers are protected by the APM and direct access
* from the REE results in a fault.
*
* To prevent this, we wrap this function to be routed as a TEE service call.
*/
#if CONFIG_IDF_TARGET_ESP32C5
void IRAM_ATTR __wrap_Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size)
{
esp_tee_service_call(3, SS_CACHE_SET_IDROM_MMU_SIZE, irom_size, drom_size);
}
#endif
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
/* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -100,7 +100,7 @@ esp_err_t get_flash_contents_sha256(uint32_t flash_offset, uint32_t len, uint8_t
uint32_t mmap_len = MIN(len, partial_image_len);
const void *image = esp_tee_flash_mmap(flash_offset, mmap_len);
if (image == NULL) {
mbedtls_sha256_finish(&ctx, NULL);
mbedtls_sha256_free(&ctx);
return ESP_FAIL;
}
mbedtls_sha256_update(&ctx, image, mmap_len);

View File

@@ -14,8 +14,13 @@ set(srcs "core/esp_tee_init.c"
"core/esp_secure_service_table.c")
# Arch specific implementation for TEE
list(APPEND srcs "arch/${arch}/esp_tee_vectors.S"
"arch/${arch}/esp_tee_vector_table.S")
if(CONFIG_SOC_INT_PLIC_SUPPORTED)
list(APPEND srcs "arch/${arch}/esp_tee_vectors_plic.S"
"arch/${arch}/esp_tee_vector_table_plic.S")
elseif(CONFIG_SOC_INT_CLIC_SUPPORTED)
list(APPEND srcs "arch/${arch}/esp_tee_vectors_clic.S"
"arch/${arch}/esp_tee_vector_table_clic.S")
endif()
# SoC specific implementation for TEE
list(APPEND srcs "soc/${target}/esp_tee_secure_sys_cfg.c"

View File

@@ -0,0 +1,107 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "soc/soc.h"
/* The system interrupts are not used for now, so trigger a panic every time one occurs. */
#define _system_int_handler _tee_panic_handler
/* Handlers defined in the `vector.S` file, common to all RISC-V targets */
.global _tee_ns_intr_handler
.global _tee_panic_handler
.section .exception_vectors_table.text
/* Prevent the compiler from generating 2-byte instruction in the vector tables */
.option push
.option norvc
/**
* Non-hardware vectored interrupt entry. MTVEC CSR points here.
*
* On targets that use CLIC as their interrupt controller, when an exception occurs, the CPU
* jumps to the address stored in MTVEC[31:6] << 6. The CPU will also jump to this location
* if an interrupt is configured as non-vectored (CLIC_INT_ATTR.shv = 0).
*
* Because of the left-shift `<< 6`, this entry must be aligned on 64.
*/
.global _vector_table
.type _vector_table, @function
.balign 0x40
_vector_table:
j _tee_panic_handler
.size _vector_table, .-_vector_table
/**
* Vectored interrupt table. MTVT CSR points here.
*
* If an interrupt occurs and is configured as (hardware) vectored, the CPU will jump to
* MTVT[31:0] + 4 * interrupt_id
*
* In the case of the ESP32P4, the interrupt matrix, between the CPU interrupt lines
* and the peripherals, offers 32 lines. As such, the interrupt_id between 0 and 31.
*
* Since the interrupts are initialized as vectored on CPU start, we can manage the special
* interrupts ETS_T1_WDT_INUM, ETS_CACHEERR_INUM and ETS_MEMPROT_ERR_INUM here.
*/
.balign 0x40
.global _mtvt_table
.type _mtvt_table, @function
_mtvt_table:
.word _system_int_handler /* 0: System interrupt number. Exceptions are non-vectored, won't load this. */
.word _system_int_handler /* 1: System interrupt number */
.word _system_int_handler /* 2: System interrupt number */
.word _system_int_handler /* 3: System interrupt number */
.word _system_int_handler /* 4: System interrupt number */
.word _system_int_handler /* 5: System interrupt number */
.word _system_int_handler /* 6: System interrupt number */
.word _system_int_handler /* 7: System interrupt number */
.word _system_int_handler /* 8: System interrupt number */
.word _system_int_handler /* 9: System interrupt number */
.word _system_int_handler /* 10: System interrupt number */
.word _system_int_handler /* 11: System interrupt number */
.word _system_int_handler /* 12: System interrupt number */
.word _system_int_handler /* 13: System interrupt number */
.word _system_int_handler /* 14: System interrupt number */
.word _system_int_handler /* 15: System interrupt number */
.word _tee_ns_intr_handler /* 16: Free interrupt number */
.word _tee_ns_intr_handler /* 17: Free interrupt number */
.word _tee_ns_intr_handler /* 18: Free interrupt number */
.word _tee_ns_intr_handler /* 19: Free interrupt number */
.word _tee_ns_intr_handler /* 20: Free interrupt number */
.word _tee_ns_intr_handler /* 21: Free interrupt number */
.word _tee_ns_intr_handler /* 22: Free interrupt number */
.word _tee_ns_intr_handler /* 23: Free interrupt number */
.word _tee_ns_intr_handler /* 24: Free interrupt number */
.word _tee_ns_intr_handler /* 25: Free interrupt number */
.word _tee_ns_intr_handler /* 26: Free interrupt number */
.word _tee_ns_intr_handler /* 27: Free interrupt number */
.word _tee_ns_intr_handler /* 28: Free interrupt number */
.word _tee_ns_intr_handler /* 29: Free interrupt number */
.word _tee_ns_intr_handler /* 30: Free interrupt number */
.word _tee_ns_intr_handler /* 31: Free interrupt number */
.word _tee_ns_intr_handler /* 32: Free interrupt number */
.word _tee_ns_intr_handler /* 33: Free interrupt number */
.word _tee_ns_intr_handler /* 34: Free interrupt number */
.word _tee_ns_intr_handler /* 35: Free interrupt number */
.word _tee_ns_intr_handler /* 36: Free interrupt number */
.word _tee_ns_intr_handler /* 37: Free interrupt number */
.word _tee_ns_intr_handler /* 38: Free interrupt number */
.word _tee_ns_intr_handler /* 39: Free interrupt number */
.word _tee_panic_handler /* 40: ETS_INT_WDT_INUM (+16) panic-interrupt (soc-level panic) */
.word _tee_panic_handler /* 41: ETS_CACHEERR_INUM (+16) panic-interrupt (soc-level panic) */
/* NOTE: Triggers panic irrespective of the Kconfig setting with ESP-TEE */
.word _tee_panic_handler /* 42: ETS_MEMPROT_ERR_INUM (+16) handler (soc-level panic) */
/* TODO: [IDF-10770] Not supported yet with ESP-TEE */
.word _tee_panic_handler /* 43: ETS_ASSIST_DEBUG_INUM (+16) handler (soc-level panic) */
.word _tee_ns_intr_handler /* 44: ETS_IPC_ISR_INUM (+16) handler*/
.word _tee_ns_intr_handler /* 45: Free interrupt number */
.word _tee_ns_intr_handler /* 46: ESP-TEE: U-mode interrupt delegation entry */
.word _tee_s_intr_handler /* 47: ESP-TEE: Secure interrupt handler entry */
.size _mtvt_table, .-_mtvt_table
.option pop

View File

@@ -51,7 +51,7 @@ _vector_table:
j _tee_ns_intr_handler /* 11: Free interrupt number */
j _tee_ns_intr_handler /* 12: Free interrupt number */
j _tee_ns_intr_handler /* 13: Free interrupt number */
j _tee_s_intr_handler /* 14: ESP-TEE: Secure interrupt handler entry */
j _tee_ns_intr_handler /* 14: Free interrupt number */
j _tee_ns_intr_handler /* 15: Free interrupt number */
j _tee_ns_intr_handler /* 16: Free interrupt number */
j _tee_ns_intr_handler /* 17: Free interrupt number */
@@ -70,7 +70,7 @@ _vector_table:
j _tee_ns_intr_handler /* 28: Free interrupt number */
j _tee_ns_intr_handler /* 29: Free interrupt number */
j _tee_ns_intr_handler /* 30: Free interrupt number */
j _tee_ns_intr_handler /* 31: Free interrupt number */
j _tee_s_intr_handler /* 31: ESP-TEE: Secure interrupt handler entry */
j _panic_handler /* exception handler, entry 0 */
.size _vector_table, .-_vector_table

View File

@@ -0,0 +1,628 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/clic_reg.h"
#include "riscv/encoding.h"
#include "riscv/rvruntime-frames.h"
#include "esp_private/vectors_const.h"
#include "esp_tee.h"
#include "esp_tee_intr_defs.h"
#include "sdkconfig.h"
.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
.equ CSR_UINTTHRESH, 0x047
.global esp_tee_global_interrupt_handler
.global esp_tee_service_dispatcher
.global _tee_s_entry
.section .data
.align 4
.global _ns_sp
_ns_sp:
.word 0
.align 4
.global _s_sp
_s_sp:
.word 0
/* Macro which first allocates space on the stack to save general
* purpose registers, and then save them. GP register is excluded.
* The default size allocated on the stack is CONTEXT_SIZE, but it
* can be overridden. */
.macro save_general_regs cxt_size=CONTEXT_SIZE
addi sp, sp, -\cxt_size
sw ra, RV_STK_RA(sp)
sw tp, RV_STK_TP(sp)
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp)
sw t2, RV_STK_T2(sp)
sw s0, RV_STK_S0(sp)
sw s1, RV_STK_S1(sp)
sw a0, RV_STK_A0(sp)
sw a1, RV_STK_A1(sp)
sw a2, RV_STK_A2(sp)
sw a3, RV_STK_A3(sp)
sw a4, RV_STK_A4(sp)
sw a5, RV_STK_A5(sp)
sw a6, RV_STK_A6(sp)
sw a7, RV_STK_A7(sp)
sw s2, RV_STK_S2(sp)
sw s3, RV_STK_S3(sp)
sw s4, RV_STK_S4(sp)
sw s5, RV_STK_S5(sp)
sw s6, RV_STK_S6(sp)
sw s7, RV_STK_S7(sp)
sw s8, RV_STK_S8(sp)
sw s9, RV_STK_S9(sp)
sw s10, RV_STK_S10(sp)
sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
.endm
.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. */
.global _tee_panic_handler
.type _tee_panic_handler, @function
_tee_panic_handler:
/* Exception handler. */
.global _panic_handler
.type _panic_handler, @function
_panic_handler:
/* Backup t0, t1 on the stack before using it */
addi sp, sp, -16
sw t0, 0(sp)
sw t1, 4(sp)
/* Read mcause */
csrr t0, mcause
li t1, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK
and t0, t0, t1
/* Check whether the exception is an M-mode ecall */
li t1, ECALL_M_MODE
beq t0, t1, _machine_ecall
/* 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
_actual_panic:
/* Not an ecall, proceed to the panic handler */
/* Allocate space on the stack and store general purpose registers */
save_general_regs RV_STK_FRMSZ
/* As gp register is not saved by the macro, save it here */
sw gp, RV_STK_GP(sp)
/* Same goes for the SP value before trapping */
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
/* Save CSRs */
sw t0, RV_STK_SP(sp)
save_mepc
save_mcsr
/* Keep mcause in s0, only the exception code and interrupt bit are relevant */
csrr s0, mcause
li t1, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK
and s0, s0, t1
/* Call panic_from_exception(sp) or panic_from_isr(sp)
* depending on whether we have a pseudo excause or not.
* If mcause's highest bit is 1, then an interrupt called this routine,
* so we have a pseudo excause. Else, it is due to a exception, we don't
* have an pseudo excause */
mv a0, sp
mv a1, s0
/* Branches instructions don't accept immediates values, so use t1 to
* store our comparator */
li t0, 0x80000000
bgeu a1, t0, _call_panic_handler
sw a1, RV_STK_MCAUSE(sp)
/* exception_from_panic never returns */
jal panic_from_exception
/* We arrive here if the exception handler has returned. */
j _return_from_exception
_call_panic_handler:
/* Remove highest bit from mcause (a1) register and save it in the
* structure */
not t0, t0
and a1, a1, t0
#if CONFIG_SOC_INT_CLIC_SUPPORTED
/* When CLIC is supported, external interrupts are shifted by 16, deduct this difference from mcause */
add a1, a1, -16
#endif // CONFIG_SOC_INT_CLIC_SUPPORTED
sw a1, RV_STK_MCAUSE(sp)
jal panic_from_isr
/* We arrive here if the exception handler has returned. This means that
* the exception was handled, and the execution flow should resume.
* Restore the registers and return from the exception.
*/
_return_from_exception:
restore_mepc
/* MTVEC and SP are assumed to be unmodified.
* MSTATUS, MHARTID, MTVAL are read-only and not restored. */
lw gp, RV_STK_GP(sp)
restore_general_regs RV_STK_FRMSZ
mret
.size _panic_handler, .-_panic_handler
/* ECALL handler. */
.type _ecall_handler, @function
_ecall_handler:
/* M-mode ecall handler */
_machine_ecall:
/* Enable the U-mode delegation of all interrupts */
li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG
li t1, 0x00
sw t1, 0(t0)
fence
/* Verify the above */
_1:
lw t2, 0(t0)
bne t2, t1, _2
/* Set the privilege mode to transition to after mret to U-mode */
li t0, MSTATUS_MPP
csrc mstatus, t0
/* Check whether this is the first M-mode ecall (see esp_tee_init) and skip context restoration */
lui t0, ESP_TEE_M2U_SWITCH_MAGIC
beq a1, t0, _skip_ctx_restore
/* Switching back to the saved REE stack */
la t0, _ns_sp
lw sp, 0(t0)
fence
/* 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
restore_general_regs
csrrw a0, mscratch, zero
_skip_ctx_restore:
/* Copy the ra register to mepc which contains the user app entry point (i.e. call_start_cpu0) */
csrw mepc, ra
/* Jump to the REE */
mret
/* 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
/* Restore t0, t1 from the stack */
lw t0, 0(sp)
lw t1, 4(sp)
addi sp, sp, 16
/* This point is reached when a secure service call is issued from the REE */
/* Save register context and mepc */
save_general_regs
save_mepc
/* Save the U-mode (i.e. REE) stack pointer */
la t0, _ns_sp
sw sp, 0(t0)
/* Switch to the M-mode (i.e. TEE) stack */
la sp, _tee_stack
/* Load the TEE entry point (see _tee_s_entry) in the mepc */
la t0, _tee_s_entry
csrw mepc, t0
/* Disable the U-mode delegation of all interrupts */
li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG
li t1, TEE_PASS_INUM + CLIC_EXT_INTR_NUM_OFFSET
sw t1, 0(t0)
fence
/* Verify the above */
_2:
lw t2, 0(t0)
bne t2, t1, _2
/* Set the privilege mode to transition to after mret to M-mode */
li t0, MSTATUS_MPP
csrs mstatus, t0
mret
/* This point is reached after servicing a U-mode interrupt occurred
* while executing a secure service */
_rtn_from_ns_int:
/* 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
sw t1, 0(t0)
fence
/* Verify the above */
_3:
lw t2, 0(t0)
bne t2, t1, _2
/* Restore the secure stack pointer */
la t0, _s_sp
lw sp, 0(t0)
/* Set the privilege mode to transition to after mret to M-mode */
li t0, MSTATUS_MPP
csrs mstatus, t0
/* Restore register context and resume the secure service */
restore_mepc
restore_general_regs
mret
.size _ecall_handler, .-_ecall_handler
/* This is the interrupt handler for the U-mode interrupts.
* It saves the registers on the stack, re-enables the interrupt delegation,
* then jumps to the U-mode global interrupt handler, */
.global _tee_ns_intr_handler
.type _tee_ns_intr_handler, @function
_tee_ns_intr_handler:
/* Start by saving the general purpose registers and the PC value before
* the interrupt happened. */
save_general_regs
save_mepc
/* Though it is not necessary we save GP and SP here.
* SP is necessary to help GDB to properly unwind
* the backtrace of threads preempted by interrupts (OS tick etc.).
* GP is saved just to have its proper value in GDB. */
/* As gp register is not saved by the macro, save it here */
sw gp, RV_STK_GP(sp)
/* Same goes for the SP value before trapping */
addi t0, sp, CONTEXT_SIZE /* restore sp with the value when interrupt happened */
/* Save SP */
sw t0, RV_STK_SP(sp)
/*
* NOTE: Since this is a delegated U-mode interrupt routed through M-mode, the U-mode CSRs
* (like ucause, uintstatus, and uintthresh) are not automatically populated by hardware.
*
* To correctly simulate the U-mode interrupt context, we must explicitly update:
* - ucause: to reflect the interrupt source (including EXCCODE, INTBIT, and PIE).
* - uintthresh: to the level of the interrupt being serviced.
*
* uintstatus is read-only and will be zero in this scenario.
* However, CLIC uses max(uintstatus.uil, uintthresh.th) to determine active interrupt level.
* So, setting uintthresh to the current interrupt level ensures that only higher-priority
* U-mode interrupts can preempt while this one is being handled.
*/
/* Pass the interrupt ID to be serviced to U-mode */
li t2, INTMTX_SEC_STATUS_REG
lw t0, 0(t2)
li t1, 0
_find_intr_loop:
and t2, t0, 1
bnez t2, _found_intr
srai t0, t0, 1
addi t1, t1, 1
bnez t0, _find_intr_loop
/* should not reach here */
li t1, -1
unimp
_found_intr:
addi t6, t1, CLIC_EXT_INTR_NUM_OFFSET
/* Update ucause */
csrr t0, ucause
li t1, VECTORS_MCAUSE_REASON_MASK
not t1, t1
and t0, t0, t1
or t0, t0, t6
li t1, VECTORS_MCAUSE_INTBIT_MASK
or t0, t0, t1
csrw ucause, t0
/* Update the new the U-mode interrupt threshold */
li t1, DR_REG_CLIC_CTRL_BASE
slli t2, t6, 2
add t1, t1, t2
lw t2, 0(t1)
fence
srli t2, t2, CLIC_INT_CTL_S
csrw CSR_UINTTHRESH, t2
/* Enable the U-mode interrupt delegation */
li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG
li t1, 0x00
sw t1, 0(t0)
fence
/* Verify the above */
_4:
lw t2, 0(t0)
bne t2, t1, _2
/* For U-mode interrupts, we use mret to switch to U-mode after executing the below steps - */
/* Disable the U-mode global interrupts */
csrci ustatus, USTATUS_UIE
/* Configure `uepc` with the U-mode ecall handler (see u2m_switch) so that we can
* return to M-mode after handling the interrupt */
la t0, esp_tee_app_config
lw t1, ESP_TEE_CFG_OFFS_NS_ENTRY_ADDR(t0)
csrw uepc, t1
/* Set the program counter to the U-mode global interrupt handler (see _interrupt_handler) */
lw t1, ESP_TEE_CFG_OFFS_NS_INTR_HANDLER(t0)
csrw mepc, t1
/* Set the privilege mode to transition to after mret to U-mode */
li t1, MSTATUS_MPP
csrc mstatus, t1
/* Save the current secure stack pointer and switch to the U-mode interrupt stack
* saved while entering the secure service call routine (see `sec_world_entry`) */
la t0, _s_sp
sw sp, 0(t0)
la t1, _ns_sp
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
/* Place magic bytes in all the general registers */
store_magic_general_regs
mret
.size _tee_ns_intr_handler, .-_tee_ns_intr_handler
/* This is the interrupt handler for the M-mode interrupts.
* It saves the registers on the stack, prepares for interrupt nesting,
* re-enables the interrupts, then jumps to the C dispatcher in esp_tee_intr.c. */
.global _tee_s_intr_handler
.type _tee_s_intr_handler, @function
_tee_s_intr_handler:
/* Start by saving the general purpose registers and the PC value before
* the interrupt happened. */
save_general_regs RV_STK_FRMSZ
save_mepc
/* Though it is not necessary we save GP and SP here.
* SP is necessary to help GDB to properly unwind
* the backtrace of threads preempted by interrupts (OS tick etc.).
* GP is saved just to have its proper value in GDB. */
/* As gp register is not saved by the macro, save it here */
sw gp, RV_STK_GP(sp)
/* Same goes for the SP value before trapping */
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when interrupt happened */
/* Save SP */
sw t0, RV_STK_SP(sp)
/* Check if the interrupt source is related to an APM exception */
/* Define the addresses of the registers */
li t0, INTMTX_STATUS_REG_0
/* Load the values from the registers */
lw t1, 0(t0)
/* Define the masks */
li t2, TEE_SECURE_INT_APM_MASK_0
/* Apply the masks */
and t1, t1, t2
/* Check if any of the masked bits are set */
bnez t1, _save_reg_ctx
/* Repeat for the other status register */
li t0, INTMTX_STATUS_REG_1
lw t1, 0(t0)
li t2, TEE_SECURE_INT_APM_MASK_1
and t1, t1, t2
bnez t1, _save_reg_ctx
/* Continue normal execution */
j _continue
_save_reg_ctx:
/* Save CSR context here */
save_mcsr
/* NOTE: With ESP-TEE, since APM violations trigger a panic, it's safe to use the mscratch
* register to pass on the stack pointer to the APM violation handler */
csrw mscratch, sp
j _intr_hdlr_exec
_continue:
/* Before doing anything preserve the stack pointer */
mv s11, sp
/* Switch to the TEE interrupt stack */
la sp, _tee_intr_stack
/* If this is a non-nested interrupt, SP now points to the interrupt stack */
/* Before dispatch c handler, restore interrupt to enable nested intr */
csrr s1, mcause
csrr s2, mstatus
/* TODO: [IDF-9972] Nested interrupts are not supported yet */
# csrsi mstatus, MSTATUS_MIE
# /* MIE set. Nested interrupts can now occur */
#ifdef CONFIG_PM_TRACE
li a0, 0 /* = ESP_PM_TRACE_IDLE */
#if SOC_CPU_CORES_NUM == 1
li a1, 0 /* No need to check core ID on single core hardware */
#else
csrr a1, mhartid
#endif
la t0, esp_pm_trace_exit
jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
#endif
#ifdef CONFIG_PM_ENABLE
la t0, esp_pm_impl_isr_hook
jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
#endif
_intr_hdlr_exec:
/* call the C dispatcher */
mv a0, sp /* argument 1, stack pointer */
mv a1, s1 /* argument 2, interrupt number (mcause) */
/* mask off the interrupt flag of mcause */
li t0, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK
and a1, a1, t0
jal esp_tee_global_interrupt_handler
/* TODO: [IDF-9972] Nested interrupts are not supported yet */
# csrci mstatus, MSTATUS_MIE
# /* MIE cleared. Nested interrupts are disabled */
/* restore the rest of the registers */
csrw mcause, s1
csrw mstatus, s2
/* Restoring the stack pointer */
mv sp, s11
restore_mepc
restore_general_regs RV_STK_FRMSZ
/* exit, this will also re-enable the interrupts */
mret
.size _tee_s_intr_handler, .-_tee_s_intr_handler
.section .text, "ax"
.align 4
.type _tee_s_entry, @function
_tee_s_entry:
/* Jump to the secure service dispatcher */
jal esp_tee_service_dispatcher
/* Fire an M-ecall */
mv a1, zero
ecall
fence
.size _tee_s_entry, .-_tee_s_entry

View File

@@ -23,7 +23,7 @@
.equ RTNVAL, 0xc0de
.equ ECALL_U_MODE, 0x8
.equ ECALL_M_MODE, 0xb
.equ TEE_INTR_DELEG_MASK, 0xffffbfff
.equ TEE_INTR_DELEG_MASK, ~(1U << TEE_SECURE_INUM)
.global esp_tee_global_interrupt_handler
.global esp_tee_service_dispatcher

View File

@@ -39,22 +39,37 @@ static void assert_valid_block(const heap_t *heap, const block_header_t *block)
esp_err_t esp_tee_heap_init(void *start_ptr, size_t size)
{
assert(start_ptr);
if (size < (tlsf_size() + tlsf_block_size_min() + sizeof(heap_t))) {
// Region too small to be a heap.
heap_t *result = (heap_t *)start_ptr;
size_t usable_size = size - sizeof(heap_t);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
bool too_small = (usable_size < tlsf_size() + tlsf_block_size_min());
#else
bool too_small = (size < sizeof(heap_t));
#endif
if (too_small) {
return ESP_ERR_INVALID_SIZE;
}
heap_t *result = (heap_t *)start_ptr;
size -= sizeof(heap_t);
#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();
#else
size_t max_bytes = 0;
void *heap = tlsf_create_with_pool(start_ptr + sizeof(heap_t), usable_size, max_bytes);
size_t overhead = tlsf_size(heap);
#endif
result->heap_data = tlsf_create_with_pool(start_ptr + sizeof(heap_t), size);
if (result->heap_data == NULL) {
if (heap == NULL) {
return ESP_FAIL;
}
result->heap_data = heap;
result->lock = NULL;
result->free_bytes = size - tlsf_size();
result->pool_size = size;
result->free_bytes = usable_size - overhead;
result->pool_size = usable_size;
result->minimum_free_bytes = result->free_bytes;
tee_heap = (multi_heap_handle_t)result;

View File

@@ -10,13 +10,21 @@
#include "esp_macros.h"
#include "esp_rom_sys.h"
#include "esp_rom_serial_output.h"
#include "rom/cache.h"
#include "riscv/rv_utils.h"
#include "riscv/rvruntime-frames.h"
#include "hal/cache_types.h"
#include "hal/cache_ll.h"
#include "hal/cache_hal.h"
#include "hal/apm_hal.h"
#if SOC_INT_PLIC_SUPPORTED
#include "soc/plic_reg.h"
#elif SOC_INT_CLIC_SUPPORTED
#include "soc/clic_reg.h"
#endif
#include "esp_tee.h"
#include "esp_tee_apm_intr.h"
#include "esp_tee_rv_utils.h"
@@ -32,11 +40,16 @@ static void tee_panic_end(void)
rv_utils_tee_intr_global_disable();
// Disable the cache
Cache_Disable_ICache();
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
// Clear the interrupt controller configurations
#if SOC_INT_PLIC_SUPPORTED
memset((void *)DR_REG_PLIC_MX_BASE, 0x00, (PLIC_MXINT_CLAIM_REG + 4 - DR_REG_PLIC_MX_BASE));
memset((void *)DR_REG_PLIC_UX_BASE, 0x00, (PLIC_UXINT_CLAIM_REG + 4 - DR_REG_PLIC_UX_BASE));
#elif SOC_INT_CLIC_SUPPORTED
memset((void *)DR_REG_CLIC_CTRL_BASE, 0x00, (REG_GET_FIELD(CLIC_INT_INFO_REG, CLIC_INT_INFO_NUM_INT)) * 4);
REG_WRITE(CLIC_INT_THRESH_REG, 0x00);
#endif
// Make sure all the panic handler output is sent from UART FIFO
if (CONFIG_ESP_CONSOLE_UART_NUM >= 0) {

View File

@@ -7,11 +7,12 @@
#include "esp_attr.h"
#include "esp_rom_sys.h"
#include "esp_private/panic_reason.h"
#include "esp_private/vectors_const.h"
#include "riscv/csr.h"
#include "riscv/encoding.h"
#include "riscv/rvruntime-frames.h"
#include "soc/tee_reg.h"
#include "esp_tee.h"
#include "panic_helper.h"
#include "sdkconfig.h"
@@ -60,16 +61,26 @@ void panic_print_registers(const void *f, int core)
const char *name;
uint32_t value;
} csr_regs[] = {
{ "MIE ", RV_READ_CSR(mie) },
{ "MIP ", RV_READ_CSR(mip) },
{ "MSCRATCH ", RV_READ_CSR(mscratch) },
{ "UEPC ", RV_READ_CSR(uepc) },
{ "USTATUS ", RV_READ_CSR(ustatus) },
{ "UTVEC ", RV_READ_CSR(utvec) },
{ "UCAUSE ", RV_READ_CSR(ucause) },
#if CONFIG_IDF_TARGET_ESP32C6
{ "MIE ", RV_READ_CSR(mie) },
{ "MIP ", RV_READ_CSR(mip) },
{ "UTVAL ", RV_READ_CSR(utval) },
{ "UIE ", RV_READ_CSR(uie) },
{ "UIP ", RV_READ_CSR(uip) },
#endif
#if CONFIG_IDF_TARGET_ESP32C5
{ "USCRATCH ", RV_READ_CSR(0x040) },
{ "MEXSTATUS ", RV_READ_CSR(0x7E1) },
{ "MINTSTATUS", RV_READ_CSR(0xFB1) },
{ "MINTTHRESH", RV_READ_CSR(0x347) },
{ "UINTSTATUS", RV_READ_CSR(0xCB1) },
{ "UINTTHRESH", RV_READ_CSR(0x047) },
#endif
};
tee_panic_print("\n\n");
@@ -116,9 +127,10 @@ void panic_print_exccause(const void *f, int core)
};
const char *rsn = NULL;
if (regs->mcause < (sizeof(reason) / sizeof(reason[0]))) {
if (reason[regs->mcause] != NULL) {
rsn = (reason[regs->mcause]);
uint32_t mcause = regs->mcause & (VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK);
if (mcause < (sizeof(reason) / sizeof(reason[0]))) {
if (reason[mcause] != NULL) {
rsn = (reason[mcause]);
}
}

View File

@@ -203,6 +203,13 @@ void _ss_esp_crypto_sha_enable_periph_clk(bool enable)
esp_crypto_sha_enable_periph_clk(enable);
}
#if SOC_SHA_SUPPORT_SHA512_T
int _ss_esp_sha_512_t_init_hash(uint16_t t)
{
return esp_sha_512_t_init_hash(t);
}
#endif
/* ---------------------------------------------- HMAC ------------------------------------------------- */
esp_err_t _ss_esp_hmac_calculate(hmac_key_id_t key_id, const void *message, size_t message_len, uint8_t *hmac)

View File

@@ -12,12 +12,14 @@
#include "hal/mmu_types.h"
#include "hal/mmu_hal.h"
#include "hal/wdt_hal.h"
#include "rom/cache.h"
#include "hal/spi_flash_hal.h"
#include "hal/spi_flash_types.h"
#include "spi_flash_chip_generic.h"
#include "memspi_host_driver.h"
#include "esp_flash.h"
#include "riscv/rv_utils.h"
#include "esp_tee.h"
#include "esp_tee_memory_utils.h"
@@ -63,7 +65,7 @@ void _ss_rv_utils_intr_set_threshold(int priority_threshold)
void _ss_rv_utils_intr_edge_ack(uint32_t intr_num)
{
rv_utils_tee_intr_edge_ack(intr_num);
rv_utils_intr_edge_ack(intr_num);
}
void _ss_rv_utils_intr_global_enable(void)
@@ -71,6 +73,42 @@ void _ss_rv_utils_intr_global_enable(void)
rv_utils_tee_intr_global_enable();
}
uint32_t _ss_rv_utils_intr_get_enabled_mask(void)
{
return rv_utils_intr_get_enabled_mask();
}
void _ss_rv_utils_set_cycle_count(uint32_t ccount)
{
rv_utils_set_cycle_count(ccount);
}
#if SOC_BRANCH_PREDICTOR_SUPPORTED
void _ss_rv_utils_en_branch_predictor(void)
{
rv_utils_en_branch_predictor();
}
void _ss_rv_utils_dis_branch_predictor(void)
{
rv_utils_dis_branch_predictor();
}
#endif
#if SOC_CPU_SUPPORT_WFE
void _ss_rv_utils_wfe_mode_enable(bool en)
{
rv_utils_wfe_mode_enable(en);
}
#endif
#if SOC_INT_CLIC_SUPPORTED
void _ss_esprv_int_set_vectored(int rv_int_num, bool vectored)
{
esprv_int_set_vectored(rv_int_num, vectored);
}
#endif
/* ---------------------------------------------- RTC_WDT ------------------------------------------------- */
void _ss_wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t prescaler, bool enable_intr)
@@ -164,6 +202,7 @@ void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vad
bool vaddr_chk = esp_tee_flash_check_vaddr_in_tee_region(vaddr);
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(paddr);
if (vaddr_chk || paddr_chk) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x | 0x%08x", __func__, vaddr, paddr);
return;
}
ESP_FAULT_ASSERT(!vaddr_chk && !paddr_chk);
@@ -175,6 +214,7 @@ void _ss_mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len)
{
bool vaddr_chk = esp_tee_flash_check_vaddr_in_tee_region(vaddr);
if (vaddr_chk) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, vaddr);
return;
}
ESP_FAULT_ASSERT(!vaddr_chk);
@@ -202,6 +242,13 @@ bool _ss_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t ta
return mmu_hal_paddr_to_vaddr(mmu_id, paddr, target, type, out_vaddr);
}
#if CONFIG_IDF_TARGET_ESP32C5
void _ss_Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size)
{
Cache_Set_IDROM_MMU_Size(irom_size, drom_size);
}
#endif
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
/* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */

View File

@@ -60,8 +60,23 @@ void esp_tee_route_intr_matrix(int cpu_no, uint32_t model_num, uint32_t intr_num
if (esp_tee_is_intr_src_protected(model_num) || intr_num == TEE_SECURE_INUM) {
return;
}
#if SOC_INT_CLIC_SUPPORTED
if (intr_num == TEE_PASS_INUM) {
return;
}
#endif
esp_rom_route_intr_matrix(cpu_no, model_num, intr_num);
ESP_LOGV(TAG, "Connected src %d to int %d (cpu %d)", model_num, intr_num, cpu_no);
#if SOC_INT_CLIC_SUPPORTED
if (intr_num != ETS_T1_WDT_INUM && intr_num != ETS_CACHEERR_INUM) {
/* Configure interrupts to be visible in the TEE (M-mode) */
REG_SET_BIT(DR_REG_INTMTX_BASE + 4 * model_num, BIT(8));
/* Configure interrupts to be serviced in the REE (U-mode) */
rv_utils_tee_intr_set_mode(intr_num, PRV_U);
}
#endif
}
/**
@@ -119,7 +134,7 @@ int esp_tee_intr_deregister(void *arg)
tee_set_interrupt_handler(vd);
// Setting back the default value for interrupt pin.
esp_rom_route_intr_matrix(cpu, vd->source, 0);
esp_rom_route_intr_matrix(cpu, vd->source, ETS_INVALID_INUM);
return 0;
}

View File

@@ -3,4 +3,4 @@ dependencies:
espressif/json_generator:
version: "^1.1.2"
rules:
- if: "target in [esp32c6, esp32h2]"
- if: "target in [esp32c6, esp32h2, esp32c5]"

View File

@@ -0,0 +1,302 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#define SRAM_IRAM_START (0x40800000)
#define SRAM_IRAM_TEE_ORG (SRAM_IRAM_START)
#define SRAM_DRAM_TEE_ORG (SRAM_IRAM_START)
#define SRAM_IRAM_ORG (SRAM_IRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE)
#define SRAM_DRAM_TEE_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE)
#define SRAM_DRAM_TEE_END (SRAM_DRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE)
#define I_D_SRAM_TEE_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE)
/* TEE interrupt stack is placed at the end of the TEE DRAM segment.
* The top of the TEE stack is before the end of interrupt stack
* and the bottom of the stack is at _heap_end.
*/
#define SRAM_STACK_TEE_ORG (SRAM_DRAM_TEE_END)
#define SRAM_INTR_STACK_TEE_ORG (SRAM_DRAM_TEE_END + CONFIG_SECURE_TEE_STACK_SIZE)
#define FLASH_IROM_TEE_ORG (0x42000000)
#define FLASH_DROM_TEE_ORG (0x42000000)
#define I_D_FLASH_TEE_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE)
/**
* These values are the same in every app binary for the same chip target.
*
* Values that may change when the app is rebuilt, or in a new ESP-IDF version,
* should be stored via esp_app_tee_config structure
*/
#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS
PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x22b0 );
#else
PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x2b0 );
#endif
PROVIDE ( GDMA = 0x60080000 );
/* Default entry point: */
ENTRY(esp_tee_init);
MEMORY
{
/* IRAM Configuration */
iram_tee_seg (RX) : org = SRAM_IRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE
/* DRAM Configuration */
dram_tee_seg (RW) : org = SRAM_DRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE
/* TEE Stack Configuration */
stack_tee_seg (RW) : org = SRAM_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_STACK_SIZE
/* TEE Interrupt Stack Configuration */
intr_stack_tee_seg (RW) : org = SRAM_INTR_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE
/* TEE flash data section */
flash_data_seg (R) : org = FLASH_DROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20
/* TEE flash text section */
flash_text_seg (RX): org = FLASH_IROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20
}
SECTIONS
{
/**
* This section is required to skip .iram.tee_text area because iram_tee_seg and
* dram_tee_seg reflect the same address space on different buses.
*/
.dram.tee_dummy (NOLOAD):
{
. = ORIGIN(dram_tee_seg) + CONFIG_SECURE_TEE_IRAM_SIZE;
} > dram_tee_seg
.dram.tee.bss (NOLOAD) :
{
. = ALIGN (8);
_tee_dram_start = ABSOLUTE(.);
_tee_bss_start = ABSOLUTE(.);
*(.bss .bss.*)
*(.sbss .sbss.*)
. = ALIGN (8);
_tee_bss_end = ABSOLUTE(.);
} > dram_tee_seg
.dram.tee.data :
{
_data_start = ABSOLUTE(.);
*(.data .data.*)
*(.sdata .sdata.*)
*(.dram1 .dram1.*)
. = ALIGN(4);
_data_end = ABSOLUTE(.);
} > dram_tee_seg
.dram.tee.rodata :
{
_rodata_start = ABSOLUTE(.);
/* TEE flash manager */
*libtee_flash_mgr.a:*(.rodata .srodata .rodata.* .srodata.*)
*libbootloader_support.a:bootloader_flash.*(.rodata .srodata .rodata.* .srodata.*)
/* Secure services */
*libmain.a:esp_secure_services_iram.c.*(.rodata .srodata .rodata.* .srodata.*)
*libmain.a:esp_secure_dispatcher.c.*(.rodata .srodata .rodata.* .srodata.*)
/* Panic handler */
*libmain.a:panic_helper_riscv.*(.rodata .srodata .rodata.* .srodata.*)
*libmain.a:esp_tee_apm_intr.c.*(.rodata .srodata .rodata.* .srodata.*)
/* HAL (noflash) */
*libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*)
*libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*)
_rodata_end = ABSOLUTE(.);
_tee_dram_end = ABSOLUTE(.);
} > dram_tee_seg
.dram.tee.heap :
{
. = ALIGN (16);
_tee_heap_start = ABSOLUTE(.);
. = ORIGIN(dram_tee_seg) + LENGTH(dram_tee_seg);
_tee_heap_end = ABSOLUTE(.);
} > dram_tee_seg
.dram.tee.stack :
{
. = ALIGN (16);
_tee_stack_bottom = ABSOLUTE(.);
. = ORIGIN(stack_tee_seg) + LENGTH(stack_tee_seg);
_tee_stack = ABSOLUTE(.);
} > stack_tee_seg
.dram.tee.intr_stack :
{
. = ALIGN (16);
_tee_intr_stack_bottom = ABSOLUTE(.);
. = ORIGIN(intr_stack_tee_seg) + LENGTH(intr_stack_tee_seg);
_tee_intr_stack = ABSOLUTE(.);
} > intr_stack_tee_seg
.flash.rodata :
{
_tee_xip_data_start = ABSOLUTE(.);
*(.rodata_desc .rodata_desc.*) /* Should be the first. TEE App version info. DO NOT PUT ANYTHING BEFORE IT! */
*(.rodata .rodata.*)
*(.srodata .srodata.*)
*(.gcc_except_table .gcc_except_table.*)
_tee_xip_data_end = ABSOLUTE(.);
} > flash_data_seg
.flash.text_dummy (NOLOAD):
{
. = ALIGN(ALIGNOF(.flash.rodata));
/* Create an empty gap as big as .flash.rodata section */
. = . + SIZEOF(.flash.rodata);
/* Prepare the alignment of the section above. Few bytes (0x20) must be
* added for the mapping header. */
. = ALIGN(CONFIG_MMU_PAGE_SIZE) + 0x20;
} > flash_text_seg
/* HAL modules and their memory placement:
*
* +-----------+---------------+--------+
* | Module | Section | Memory |
* +-----------+---------------+--------+
* | MMU | text+rodata | SRAM |
* | CACHE | text+rodata | SRAM |
* | WDT | text | SRAM |
* | APM | text | Flash* |
* | AES | text | Flash |
* | SHA | text | Flash |
* | HMAC | text | Flash |
* | DS | text | Flash |
* | ECC | text | Flash |
* | BROWNOUT | text | Flash |
* | EFUSE | text | Flash |
* | LPTIMER | text | Flash |
* | SPI_FLASH | text | Flash |
* +-----------+---------------+--------+
*
* By default, for ESP-TEE, text sections are placed in SRAM while rodata sections go to the flash.
* Therefore, only HAL modules that require SRAM placement for proper functionality are located there,
* while the remaining modules are placed in flash memory.
*/
.flash.text :
{
_tee_xip_text_start = ABSOLUTE(.);
/* Secure Services */
*libmain.a:esp_secure_services.c*(.literal .text .literal.* .text.*)
/* HAL */
*libhal.a:aes_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:sha_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:hmac_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:ds_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:ecc_hal.c*(.literal .text .literal.* .text.*)
/* NOTE: There is a possibility of APM violations (SPI1 flash protection)
* being triggered with the flash cache disabled */
#if !CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
*libhal.a:apm_hal.c*(.literal .text .literal.* .text.*)
#endif
*libhal.a:brownout_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:spi_flash_hal.c*(.literal .text .literal.* .text.*)
/* These HAL modules have functions marked with the IRAM_ATTR attribute which get placed in the SRAM */
*libhal.a:efuse_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:lp_timer_hal.c*(.literal .text .literal.* .text.*)
/* Mbedtls for TEE */
*libmbedtls.a:*(.literal .text .literal.* .text.*)
*libmbedcrypto.a:*(.literal .text .literal.* .text.*)
/* HMAC-DS layer */
*libesp_security.a:*(.literal .text .literal.* .text.*)
/* NVS flash and related modules */
*libnvs_flash.a:*(.literal .text .literal.* .text.*)
*libstdc++.a:*(.literal .text .literal.* .text.*)
*libgcc.a:*(.literal .text .literal.* .text.*)
/* esp_partition API */
*libesp_partition.a:*(.literal .text .literal.* .text.*)
/* TEE attestation module */
*libattestation.a:*(.literal .text .literal.* .text.*)
*json_generator.a:*(.literal .text .literal.* .text.*)
/* TEE test module */
*libtest_sec_srv.a:*(.literal .text .literal.* .text.*)
_tee_xip_text_end = ABSOLUTE(.);
_tee_xip_end = ABSOLUTE(.);
} > flash_text_seg
.iram.tee.text :
{
/* Vectors go to start of IRAM */
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
_tee_vec_start = ABSOLUTE(.);
KEEP(*(.exception_vectors_table.text));
KEEP(*(.exception_vectors.text));
. = ALIGN(4);
_invalid_pc_placeholder = ABSOLUTE(.);
_tee_vec_end = ABSOLUTE(.);
_tee_iram_start = ABSOLUTE(.);
*(.literal .text .iram1 .literal.* .text.* .iram1.*)
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
_tee_iram_end = ABSOLUTE(.);
} > iram_tee_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
}
ASSERT ((_tee_iram_end < _tee_dram_start), "Error: TEE IRAM segment overflowed into the DRAM segment!");

View File

@@ -0,0 +1,266 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/spi_mem_c_reg.h"
#include "soc/efuse_reg.h"
#include "soc/pcr_reg.h"
#include "soc/lp_analog_peri_reg.h"
#include "soc/lp_wdt_reg.h"
#include "soc/apm_defs.h"
#include "hal/apm_types.h"
#include "hal/apm_hal.h"
#include "esp_log.h"
#include "esp_bit_defs.h"
#include "esp_tee.h"
#include "esp_tee_intr.h"
extern void tee_apm_violation_isr(void *arg);
static const char *TAG = "esp_tee_apm_prot_cfg";
/* NOTE: Figuring out the eFuse protection range based on where the TEE secure storage key is stored */
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
#if CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID < 0
#error "TEE: eFuse protection region for APM out of range! (see CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID)"
#endif
#define LP_APM_EFUSE_REG_START \
(EFUSE_RD_KEY0_DATA0_REG + (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID * 0x20))
#define LP_APM_EFUSE_REG_END \
(EFUSE_RD_KEY1_DATA0_REG + (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID * 0x20))
#elif CONFIG_SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
#define LP_APM_EFUSE_REG_START EFUSE_RD_KEY5_DATA0_REG
#if CONFIG_SECURE_TEE_TEST_MODE
#define LP_APM_EFUSE_REG_END EFUSE_RD_SYS_PART2_DATA0_REG
#else
#define LP_APM_EFUSE_REG_END LP_APM_EFUSE_REG_START
#endif
#endif
/* NOTE: Flash protection over the SPI1 controller */
#define HP_APM_SPI1_REG_START DR_REG_SPIMEM1_BASE
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
#define HP_APM_SPI1_REG_END DR_REG_I2C_BASE
#else
#define HP_APM_SPI1_REG_END HP_APM_SPI1_REG_START
#endif
/* NOTE: Super-Watchdog and Brownout Detector protection */
#define LP_APM_SWD_REG_START (LP_WDT_SWD_CONFIG_REG)
#define LP_APM_SWD_REG_END (LP_WDT_INT_CLR_REG + 4U)
#define LP_APM_BOD_REG_START (LP_ANA_BOD_MODE0_CNTL_REG)
#define LP_APM_BOD_REG_END (LP_ANA_LP_INT_CLR_REG + 4U)
/* NOTE: Following are the master IDs for setting the security mode and access through APM:
* +---------+-------------+
* | Bit | Source |
* +---------+-------------+
* | 0 | HP CPU |
* | 1 | LP CPU |
* | 2 | reserved |
* | 3 | SDIO_SLV |
* | 4 | reserved |
* | 5 | MEM_MONITOR |
* | 6 | TRACE |
* | 7~15 | reserved |
* | 16 | SPI2 |
* | 17 | Dummy-1 |
* | 18 | UHCI |
* | 19 | I2S |
* | 20 | Dummy-4 |
* | 21 | Dummy-5 |
* | 22 | AES |
* | 23 | SHA |
* | 24 | ADC |
* | 25 | PARLIO |
* | 26~31 | Dummy-10~15 |
* +---------+-------------+
*/
#define APM_MASTERS_ALL (UINT32_MAX)
#define APM_MASTERS_HP_CPU (BIT(APM_MASTER_HPCORE))
#define APM_MASTERS_LP_CPU (BIT(APM_MASTER_LPCORE))
#define APM_MASTERS_GDMA_CRYPTO (BIT(APM_MASTER_GDMA_AES) | BIT(APM_MASTER_GDMA_SHA))
#define APM_MASTERS_TEE (APM_MASTERS_HP_CPU | APM_MASTERS_GDMA_CRYPTO)
#define APM_MASTERS_REE (APM_MASTERS_ALL & ~(APM_MASTERS_TEE))
#define APM_PERIPH_ALL (UINT64_MAX)
#define APM_PERIPH_HP_PMS (BIT64(APM_TEE_HP_PERIPH_HP_APM) | BIT64(APM_TEE_HP_PERIPH_CPU_APM) | BIT64(APM_TEE_HP_PERIPH_TEE))
#define APM_PERIPH_LP_PMS (BIT64(APM_TEE_LP_PERIPH_LP_TEE) | BIT64(APM_TEE_LP_PERIPH_LP_APM))
#define APM_PERIPH_HP_REE (APM_PERIPH_ALL & ~(APM_PERIPH_HP_PMS))
#define APM_PERIPH_LP_REE (APM_PERIPH_ALL & ~(APM_PERIPH_LP_PMS))
/*----------------------- REE0 mode configuration -----------------------*/
/*----------------------- HP_APM configuration -----------------------*/
/* HP_APM: REE0 mode accessible regions */
static apm_hal_ctrl_region_cfg_t hp_apm_regn_cfg_ree0[] = {
/* Region 0: CPU peripherals (RW) */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, DR_REG_TRACE_BASE, 0x600D0000, APM_PERM_R | APM_PERM_W, true),
/* NOTE: Without this entry, the REE D/IRAM region becomes inaccessible to
* the MODEM master, resulting in an APM violation during Wi-Fi initialization.
*/
/* Region 1: REE SRAM region (RW) - for all other masters except LP_CORE */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 1, SOC_NS_IRAM_START, SOC_IRAM_HIGH, APM_PERM_R | APM_PERM_W, true),
/* Region 1: REE SRAM region (RW) - for all LP_CORE */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M2, 1, SOC_NS_IRAM_START, SOC_IRAM_HIGH, APM_PERM_R | APM_PERM_W, true),
/* Region 2: Peripherals [Start - MMU] (RW) */
/* Protected: MMU */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 2, SOC_PERIPHERAL_LOW, SPI_MEM_MMU_ITEM_CONTENT_REG(0), APM_PERM_R | APM_PERM_W, true),
/* Region 3: Peripherals [MMU - SPI1] (RW) */
/* Protected: SPI1 */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 3, SPI_MEM_MMU_POWER_CTRL_REG(0), HP_APM_SPI1_REG_START, APM_PERM_R | APM_PERM_W, true),
/* Region 4: Peripherals [SPI1 - Interrupt Matrix] (RW) */
/* Protected: Interrupt Matrix */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 4, HP_APM_SPI1_REG_END, DR_REG_INTMTX_BASE, APM_PERM_R | APM_PERM_W, true),
/* Region 5/6: Peripherals [H/W Lock - HMAC] (RW) */
/* Protected: AES, SHA, ECC, DS, HMAC */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 5, DR_REG_PCNT_BASE, DR_REG_AES_BASE, APM_PERM_R | APM_PERM_W, true),
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 6, DR_REG_RSA_BASE, DR_REG_ECC_MULT_BASE, APM_PERM_R | APM_PERM_W, true),
/* Region 7/8/9: Peripherals [ECDSA - PMU] (RW) */
/* Protected: AES, SHA, ECC, DS and HMAC PCRs */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 7, DR_REG_ECDSA_BASE, PCR_AES_CONF_REG, APM_PERM_R | APM_PERM_W, true),
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 8, PCR_RSA_CONF_REG, PCR_ECC_CONF_REG, APM_PERM_R | APM_PERM_W, true),
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 9, PCR_ECDSA_CONF_REG, DR_REG_PMU_BASE, APM_PERM_R | APM_PERM_W, true),
/* Region 10: EXT_MEM region (RW) */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M4, 10, SOC_S_DROM_HIGH, SOC_EXTRAM_DATA_HIGH, APM_PERM_R | APM_PERM_W, true),
};
/* HP_APM: REE0 mode masters' configuration */
static apm_hal_ctrl_sec_mode_cfg_t hp_apm_ctrl_sec_mode_cfg_ree0 =
APM_HAL_SEC_MODE_CFG(APM_CTRL_HP_APM, APM_SEC_MODE_REE0, hp_apm_regn_cfg_ree0);
/*----------------------- LP_APM configuration -----------------------*/
static apm_hal_ctrl_region_cfg_t lp_apm_regn_cfg_ree0[] = {
/* Region 0: RTC memory (RWX) */
/* NOTE: LP_MEM gets automatically remapped to an offset of 0x20000000
* when accessed in low-speed mode */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, SOC_RTC_IRAM_LOW + 0x20000000, SOC_RTC_IRAM_HIGH + 0x20000000, APM_PERM_ALL, true),
/* Region 1: LP Peripherals [PMU - SWDT] (RW) */
/* Protected: SWDT */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 1, DR_REG_PMU_BASE, LP_APM_SWD_REG_START, APM_PERM_R | APM_PERM_W, true),
/* Region 2: LP Peripherals [SWDT - BOD] (RW) */
/* Protected: BOD */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 2, LP_APM_SWD_REG_END, LP_APM_BOD_REG_START, APM_PERM_R | APM_PERM_W, true),
/* Region 3: LP Peripherals [BOD - eFuse BLK x] (RW) */
/* Protected: eFuse BLK x */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 3, LP_APM_BOD_REG_END, LP_APM_EFUSE_REG_START, APM_PERM_R | APM_PERM_W, true),
/* Region 4: LP Peripherals [eFuse - END] (RW) */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 4, LP_APM_EFUSE_REG_END, DR_REG_TRACE_BASE, APM_PERM_R | APM_PERM_W, true),
};
/* LP_APM: REE0 mode masters' configuration */
static apm_hal_ctrl_sec_mode_cfg_t lp_apm_ctrl_sec_mode_cfg_ree0 =
APM_HAL_SEC_MODE_CFG(APM_CTRL_LP_APM, APM_SEC_MODE_REE0, lp_apm_regn_cfg_ree0);
/*----------------------- LP_APM0 configuration -----------------------*/
/* LP_APM0: REE0 mode accessible regions */
static apm_hal_ctrl_region_cfg_t lp_apm0_regn_cfg_ree0[] = {
/* Region 0: RTC memory (RWX) */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH, APM_PERM_ALL, true),
};
/* LP_APM0: REE0 mode masters' configuration */
static apm_hal_ctrl_sec_mode_cfg_t lp_apm0_ctrl_sec_mode_cfg_ree0 =
APM_HAL_SEC_MODE_CFG(APM_CTRL_LP_APM0, APM_SEC_MODE_REE0, lp_apm0_regn_cfg_ree0);
/*----------------------- CPU_APM configuration -----------------------*/
/* CPU_APM: REE0 mode accessible regions */
static apm_hal_ctrl_region_cfg_t cpu_apm_regn_cfg_ree0[] = {
/* Region 0: All SRAM access (RWX) */
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, SOC_IRAM_LOW, SOC_DRAM_HIGH, APM_PERM_ALL, true),
APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 0, SOC_IRAM_LOW, SOC_DRAM_HIGH, APM_PERM_ALL, true),
};
/* CPU_APM: REE0 mode masters' configuration */
static apm_hal_ctrl_sec_mode_cfg_t cpu_apm_ctrl_sec_mode_cfg_ree0 =
APM_HAL_SEC_MODE_CFG(APM_CTRL_CPU_APM, APM_SEC_MODE_REE0, cpu_apm_regn_cfg_ree0);
/*---------------- TEE APM Setup -----------------------*/
static void enable_apm_intr(apm_ctrl_module_t ctrl_mod, uint32_t path_count)
{
for (uint32_t i = 0; i < path_count; i++) {
apm_hal_ctrl_info_t *ctrl_info = calloc(1, sizeof(apm_hal_ctrl_info_t));
assert(ctrl_info != NULL);
ctrl_info->ctrl_mod = ctrl_mod;
ctrl_info->path = i;
int intr_src_num = apm_hal_get_intr_src_num(ctrl_info);
struct vector_desc_t apm_vd = {0};
apm_vd.source = intr_src_num;
apm_vd.isr = tee_apm_violation_isr;
apm_vd.arg = (void *)ctrl_info;
/* Register interrupt handler with TEE. */
esp_tee_intr_register((void *)&apm_vd);
/* Enable APM Ctrl interrupt for access path(M[0:n]) */
apm_hal_clear_exception_status(ctrl_info);
apm_hal_enable_intr(ctrl_info, true);
}
}
void esp_tee_configure_apm_protection(void)
{
/* Disable all control filter first to have full access of address rage. */
apm_hal_enable_ctrl_filter_all(false);
/* HP_APM REE0 configuration. */
apm_hal_set_ctrl_sec_mode_cfg(&hp_apm_ctrl_sec_mode_cfg_ree0);
/* HP_APM interrupt configuration. */
enable_apm_intr(APM_CTRL_HP_APM, APM_CTRL_HP_APM_PATH_NUM);
ESP_LOGD(TAG, "[HP_APM] Configured for REE0");
/* LP_APM REE0 configuration. */
apm_hal_set_ctrl_sec_mode_cfg(&lp_apm_ctrl_sec_mode_cfg_ree0);
/* LP_APM interrupt configuration. */
enable_apm_intr(APM_CTRL_LP_APM, APM_CTRL_LP_APM_PATH_NUM);
ESP_LOGD(TAG, "[LP_APM] Configured for REE0");
/* LP_APM0 REE0 configuration. */
apm_hal_set_ctrl_sec_mode_cfg(&lp_apm0_ctrl_sec_mode_cfg_ree0);
/* LP_APM0 interrupt configuration. */
enable_apm_intr(APM_CTRL_LP_APM0, APM_CTRL_LP_APM0_PATH_NUM);
ESP_LOGD(TAG, "[LP_APM0] Configured for REE0");
/* CPU_APM REE0 configuration. */
apm_hal_set_ctrl_sec_mode_cfg(&cpu_apm_ctrl_sec_mode_cfg_ree0);
/* CPU_APM interrupt configuration. */
enable_apm_intr(APM_CTRL_CPU_APM, APM_CTRL_CPU_APM_PATH_NUM);
ESP_LOGD(TAG, "[CPU_APM] Configured for REE0");
/* Switch HP_CPU to TEE mode and rest of the masters to REE0 mode */
apm_hal_set_master_sec_mode(APM_MASTERS_TEE, APM_SEC_MODE_TEE);
apm_hal_set_master_sec_mode(APM_MASTERS_REE, APM_SEC_MODE_REE0);
apm_hal_lock_master_sec_mode(APM_MASTERS_ALL);
/* Open up all peripherals to REE0 mode*/
apm_hal_tee_set_peri_access(APM_TEE_CTRL_HP, APM_PERIPH_HP_REE, APM_SEC_MODE_REE0, APM_PERM_R | APM_PERM_W);
apm_hal_tee_set_peri_access(APM_TEE_CTRL_LP, APM_PERIPH_LP_REE, APM_SEC_MODE_REE0, APM_PERM_R | APM_PERM_W);
}

View File

@@ -0,0 +1,108 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "sdkconfig.h"
#include "soc/soc.h"
#include "soc/ext_mem_defs.h"
#include "esp_cpu.h"
#include "esp_fault.h"
#include "esp32c5/rom/rom_layout.h"
#include "esp_tee.h"
void esp_tee_configure_region_protection(void)
{
/* Notes on implementation:
*
* 1) Note: ESP32-C5 CPU support overlapping PMP regions
*
* 2) ESP32-C5 supports 16 PMA regions so we use this feature to block all the invalid address ranges
*
* 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range)
* entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries
* which can be used to provide more granular access
*
* 4) Entries are grouped in order with some static asserts to try and verify everything is
* correct.
*/
const unsigned NONE = PMP_L;
const unsigned R = PMP_L | PMP_R;
const unsigned RW = PMP_L | PMP_R | PMP_W;
const unsigned RX = PMP_L | PMP_R | PMP_X;
const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
//
// Configure all the valid address regions using PMP
//
// 1. CPU Subsystem region - contains interrupt config registers
PMP_ENTRY_CFG_RESET(0);
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH);
PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RWX);
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
// 2. I/D-ROM
PMP_ENTRY_CFG_RESET(1);
PMP_ENTRY_CFG_RESET(2);
PMP_ENTRY_CFG_RESET(3);
const uint32_t drom_start = (uint32_t)(ets_rom_layout_p->drom_start);
if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) {
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX);
PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | R);
} else {
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX);
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
}
// 3. IRAM and DRAM
PMP_ENTRY_CFG_RESET(4);
PMP_ENTRY_CFG_RESET(5);
PMP_ENTRY_CFG_RESET(6);
if (esp_cpu_dbgr_is_attached()) {
// Anti-FI check that cpu is really in ocd mode
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
PMP_ENTRY_SET(4, SOC_IRAM_LOW, NONE);
PMP_ENTRY_SET(5, SOC_IRAM_HIGH, PMP_TOR | RWX);
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
} else {
// TODO: [IDF-13827] TEE SRAM region to be partitioned into text and data sections using APM
// 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(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);
PMP_ENTRY_CFG_RESET(9);
PMP_ENTRY_CFG_RESET(10);
PMP_ENTRY_SET(7, s_irom_resv_end, NONE);
PMP_ENTRY_SET(8, ns_irom_resv_end, PMP_TOR | RX);
PMP_ENTRY_SET(9, ns_drom_resv_end, PMP_TOR | R);
PMP_ENTRY_SET(10, ns_drom_mmap_end, PMP_TOR | RX);
// 5. LP memory
// TODO: LP memory to be further partitioned into text and data regions using APM
PMP_ENTRY_CFG_RESET(11);
const uint32_t pmpaddr11 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
PMP_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | RWX);
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
// 6. Peripheral addresses
PMP_ENTRY_CFG_RESET(12);
const uint32_t pmpaddr12 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
PMP_ENTRY_SET(12, pmpaddr12, PMP_NAPOT | RW);
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
//TODO: Add protection for SPIRAM
}

View File

@@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdarg.h>
#include <stdint.h>
#include "riscv/rv_utils.h"
#include "riscv/encoding.h"
#include "hal/apm_hal.h"
#include "hal/aes_ll.h"
#include "hal/sha_ll.h"
#include "hal/hmac_ll.h"
#include "hal/ds_ll.h"
#include "hal/ecc_ll.h"
#include "soc/clic_reg.h"
#include "soc/interrupts.h"
#include "esp_tee.h"
#include "esp_tee_intr.h"
#include "esp_tee_rv_utils.h"
#include "esp_cpu.h"
#include "esp_log.h"
#define CSR_MCOUNTEREN 0x306
#define _m2u_switch(arg0, arg1) \
({ \
register uintptr_t ra asm("ra") = (uintptr_t)(arg0); \
register uintptr_t a1 asm("a1") = (uintptr_t)(arg1); \
asm volatile("ecall" : :"r"(ra), "r"(a1) : ); \
})
#define SET_BIT(t, n) (t |= (1UL << (n)))
#define CLR_BIT(t, n) (t &= ~(1UL << (n)))
static const char *TAG = "esp_tee_secure_sys_cfg";
extern uint32_t _vector_table;
extern uint32_t _mtvt_table;
void esp_tee_soc_secure_sys_init(void)
{
ESP_LOGI(TAG, "Current privilege level - 0x%x", esp_cpu_get_curr_privilege_level());
/* Setting the M-mode vector table */
rv_utils_set_mtvec((uint32_t)&_vector_table);
rv_utils_set_mtvt((uint32_t)&_mtvt_table);
/* Disable global interrupts */
RV_CLEAR_CSR(mstatus, MSTATUS_UIE);
RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
/* Enabled support for U-mode interrupts */
REG_SET_FIELD(CLIC_INT_CONFIG_REG, CLIC_INT_CONFIG_NMBITS, 0x01);
REG_SET_FIELD(CLIC_INT_CONFIG_REG, CLIC_INT_CONFIG_UNLBITS, NLBITS);
REG_SET_FIELD(CLIC_INT_CONFIG_REG, CLIC_INT_CONFIG_MNLBITS, NLBITS);
/* Allow reading the cycle counter CSRs from U-mode */
RV_WRITE_CSR(CSR_MCOUNTEREN, 0x07);
/* Clearing all interrupt configurations */
uint32_t core_id = esp_cpu_get_core_id();
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
interrupt_clic_ll_route(core_id, i, ETS_INVALID_INUM);
REG_CLR_BIT(DR_REG_INTMTX_BASE + 4 * i, BIT(8));
}
/* TODO: IDF-8958
* The values for the secure interrupt number and priority and
* the interrupt priority threshold (for both M and U mode) need
* to be investigated further
*/
esprv_int_set_threshold(0);
esprv_int_set_priority(TEE_SECURE_INUM, 7);
esprv_int_set_type(TEE_SECURE_INUM, ESP_CPU_INTR_TYPE_LEVEL);
esprv_int_enable(BIT(TEE_SECURE_INUM));
esprv_int_set_vectored(TEE_SECURE_INUM, true);
rv_utils_tee_intr_set_mode(TEE_SECURE_INUM, PRV_M);
esprv_int_set_priority(TEE_PASS_INUM, 1);
esprv_int_set_type(TEE_PASS_INUM, ESP_CPU_INTR_TYPE_LEVEL);
esprv_int_enable(BIT(TEE_PASS_INUM));
esprv_int_set_vectored(TEE_PASS_INUM, true);
rv_utils_tee_intr_set_mode(TEE_PASS_INUM, PRV_M);
ESP_LOGD(TAG, "Initial interrupt config -");
ESP_LOGD(TAG, "mtvec: 0x%08x", RV_READ_CSR(mtvec));
ESP_LOGD(TAG, "mtvt: 0x%08x", RV_READ_CSR(MTVT_CSR));
ESP_LOGD(TAG, "mstatus: 0x%08x", RV_READ_CSR(mstatus));
ESP_LOGD(TAG, "mcounteren: 0x%08x", RV_READ_CSR(CSR_MCOUNTEREN));
/* PMP, PMA and APM configuration to isolate the resources between TEE and REE. */
esp_tee_configure_region_protection();
esp_tee_configure_apm_protection();
/* Protect secure interrupt sources */
esp_tee_protect_intr_src(ETS_LP_APM_M0_INTR_SOURCE); // LP_APM_M0
esp_tee_protect_intr_src(ETS_LP_APM_M1_INTR_SOURCE); // LP_APM_M1
esp_tee_protect_intr_src(ETS_HP_APM_M0_INTR_SOURCE); // HP_APM_M0
esp_tee_protect_intr_src(ETS_HP_APM_M1_INTR_SOURCE); // HP_APM_M1
esp_tee_protect_intr_src(ETS_HP_APM_M2_INTR_SOURCE); // HP_APM_M2
esp_tee_protect_intr_src(ETS_HP_APM_M3_INTR_SOURCE); // HP_APM_M3
esp_tee_protect_intr_src(ETS_HP_APM_M4_INTR_SOURCE); // HP_APM_M4
esp_tee_protect_intr_src(ETS_LP_APM0_INTR_SOURCE); // LP_APM0
esp_tee_protect_intr_src(ETS_CPU_APM_M0_INTR_SOURCE); // CPU_APM_M0
esp_tee_protect_intr_src(ETS_CPU_APM_M1_INTR_SOURCE); // CPU_APM_M1
esp_tee_protect_intr_src(ETS_AES_INTR_SOURCE); // AES
esp_tee_protect_intr_src(ETS_SHA_INTR_SOURCE); // SHA
esp_tee_protect_intr_src(ETS_ECC_INTR_SOURCE); // ECC
/* Disable protected crypto peripheral clocks; they will be toggled as needed when the peripheral is in use */
aes_ll_enable_bus_clock(false);
sha_ll_enable_bus_clock(false);
hmac_ll_enable_bus_clock(false);
ds_ll_enable_bus_clock(false);
ecc_ll_enable_bus_clock(false);
}
IRAM_ATTR inline void esp_tee_switch_to_ree(uint32_t ns_entry_addr)
{
/* 2nd argument is used as magic value to detect very first M2U switch */
/* TBD: clean this up and use proper temporary register instead of a1 */
/* Switch to non-secure world and launch App. */
_m2u_switch(ns_entry_addr, ESP_TEE_M2U_SWITCH_MAGIC << 12);
}

View File

@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/interrupt_matrix_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
// LP_APM_M0_INTR, LP_APM_M1_INTR
#define TEE_SECURE_INT_APM_MASK_0 (0x00300000)
// HP_APM_M0_INTR, HP_APM_M1_INTR, HP_APM_M2_INTR, HP_APM_M3_INTR,
// HP_APM_M4_INTR, LP_APM0_INTR, CPU_APM_M0_INTR, CPU_APM_M1_INTR
#define TEE_SECURE_INT_APM_MASK_1 (0x00000FF0)
// LP_RTC_TIMER_INTR
#define TEE_SECURE_INT_MASK_0 (TEE_SECURE_INT_APM_MASK_0 | 0x00008000)
#if !CONFIG_SECURE_TEE_TEST_MODE
#define TEE_SECURE_INT_MASK_1 (TEE_SECURE_INT_APM_MASK_1)
#else
// + TG0_T0_INTR (only for test mode)
#define TEE_SECURE_INT_MASK_1 (TEE_SECURE_INT_APM_MASK_1 | 0x02000000)
#endif
// AES_INTR, SHA_INTR, ECC_INTR
#define TEE_SECURE_INT_MASK_2 (0x0002C000)
#define INTMTX_STATUS_REG_0 (INTERRUPT_CORE0_INT_STATUS_REG_0_REG)
#define INTMTX_STATUS_REG_1 (INTERRUPT_CORE0_INT_STATUS_REG_1_REG)
#define INTMTX_STATUS_REG_2 (INTERRUPT_CORE0_INT_STATUS_REG_2_REG)
#define INTMTX_SEC_STATUS_REG (INTERRUPT_CORE0_SECURE_STATUS_REG)
#define INTMTX_SIG_IDX_ASSERT_IN_SEC_REG (INTERRUPT_CORE0_SIG_IDX_ASSERT_IN_SEC_REG)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <assert.h>
#include "riscv/csr.h"
#include "riscv/interrupt.h"
#include "hal/interrupt_clic_ll.h"
#include "soc/interrupt_reg.h"
#include "soc/clic_reg.h"
#include "esp_attr.h"
#include "esp_tee.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MCOUNTEREN_CSR 0x306
#define MTVT_CSR 0x307
#define MINTSTATUS_CSR 0xFB1
#define MINTTHRESH_CSR 0x347
#define UINTTHRESH_CSR 0x047
FORCE_INLINE_ATTR void rv_utils_tee_intr_global_enable(void)
{
/*
* Set the the U-mode previous enable global interrupts state
*
* NOTE: The TICK interrupt is setup before this service call and thus,
* it occurs in the return path of this call.
*
* Before entering the U-mode interrupt handler routine, USTATUS:UIE is
* cleared to disable U-mode interrupts temporarily.
*
* While exiting the above routine, URET is executed, setting USTATUS:UIE
* to the value of USTATUS:UPIE. However, since no interrupts were enabled
* previously, USTATUS:UPIE and thus, USTATUS:UIE is cleared.
*
* The service call completes and returns to U-mode with USTATUS:UIE disabled,
* preventing any further interrupts in U-mode.
*
*/
RV_SET_CSR(ustatus, USTATUS_UPIE);
/* Enabling the global M-mode and U-mode interrupts */
RV_SET_CSR(ustatus, USTATUS_UIE);
RV_SET_CSR(mstatus, MSTATUS_UIE);
RV_SET_CSR(mstatus, MSTATUS_MIE);
}
FORCE_INLINE_ATTR void rv_utils_tee_intr_global_disable(void)
{
RV_CLEAR_CSR(ustatus, USTATUS_UIE);
RV_CLEAR_CSR(mstatus, MSTATUS_UIE);
RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
}
FORCE_INLINE_ATTR void rv_utils_tee_intr_enable(uint32_t intr_mask)
{
// Machine mode
// Disable all interrupts to make updating of the interrupt mask atomic.
unsigned old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
while (intr_mask != 0) {
// __builtin_ffs returns one plus the index of the lsb 1-bit of x. If x is zero, returns zero
uint32_t intr_num = __builtin_ffs(intr_mask) - 1;
*(uint8_t volatile *)(BYTE_CLIC_INT_IE_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET)) = BYTE_CLIC_INT_IE;
intr_mask &= (intr_mask - 1);
}
RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE);
}
FORCE_INLINE_ATTR void rv_utils_tee_intr_disable(uint32_t intr_mask)
{
// Machine mode
// Disable all interrupts to make updating of the interrupt mask atomic.
unsigned old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
while (intr_mask != 0) {
// __builtin_ffs returns one plus the index of the lsb 1-bit of x. If x is zero, returns zero
uint32_t intr_num = __builtin_ffs(intr_mask) - 1;
*(uint8_t volatile *)(BYTE_CLIC_INT_IE_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET)) = 0;
intr_mask &= (intr_mask - 1);
}
RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE);
}
FORCE_INLINE_ATTR void rv_utils_tee_intr_set_type(int intr_num, enum intr_type type)
{
assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM);
/* TODO: CLIC supports both rising and falling edge triggered interrupts.
* Currently only rising edge is implemented.
*/
volatile uint8_t *attr_reg = (volatile uint8_t *)BYTE_CLIC_INT_ATTR_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET);
uint8_t attr = *attr_reg;
attr &= ~BYTE_CLIC_INT_ATTR_TRIG_M;
if (type == INTR_TYPE_EDGE) {
attr |= (INTR_TYPE_EDGE << BYTE_CLIC_INT_ATTR_TRIG_S);
}
*attr_reg = attr;
}
FORCE_INLINE_ATTR void rv_utils_tee_intr_set_priority(int rv_int_num, int priority)
{
assert(rv_int_num >= 0 && rv_int_num < SOC_CPU_INTR_NUM);
*(uint8_t volatile *)(BYTE_CLIC_INT_CTL_REG(rv_int_num + CLIC_EXT_INTR_NUM_OFFSET)) = (priority << BYTE_CLIC_INT_CTL_S);
}
FORCE_INLINE_ATTR void rv_utils_tee_intr_set_threshold(int priority_threshold)
{
uint32_t adj_threshold = ((priority_threshold << (8 - NLBITS)) | 0x1f);
REG_SET_FIELD(CLIC_INT_THRESH_REG, CLIC_CPU_INT_THRESH, adj_threshold);
RV_WRITE_CSR(MINTTHRESH_CSR, adj_threshold);
RV_WRITE_CSR(UINTTHRESH_CSR, adj_threshold);
}
FORCE_INLINE_ATTR void rv_utils_tee_intr_set_mode(int rv_int_num, int mode)
{
assert(rv_int_num >= 0 && rv_int_num < SOC_CPU_INTR_NUM);
REG_SET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + CLIC_EXT_INTR_NUM_OFFSET), CLIC_INT_ATTR_MODE, mode);
}
#ifdef __cplusplus
}
#endif

View File

@@ -10,6 +10,9 @@
#include "riscv/encoding.h"
#include "esp_private/interrupt_plic.h"
#include "soc/plic_reg.h"
#include "soc/interrupts.h"
#include "esp_cpu.h"
#include "esp_log.h"
#include "hal/apm_hal.h"
@@ -57,20 +60,24 @@ void esp_tee_soc_secure_sys_init(void)
/* All interrupts except the TEE secure interrupt are delegated to the U-mode */
RV_WRITE_CSR(mideleg, UINT32_MAX);
RV_CLEAR_CSR(mideleg, TEE_SECURE_INUM);
RV_CLEAR_CSR(mideleg, BIT(TEE_SECURE_INUM));
/* Clearing all interrupt configurations */
uint32_t core_id = esp_cpu_get_core_id();
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM);
}
/* TODO: IDF-8958
* The values for the secure interrupt number and priority and
* the interrupt priority threshold (for both M and U mode) need
* to be investigated further
*/
#ifdef SOC_CPU_HAS_FLEXIBLE_INTC
/* TODO: Currently, we do not allow interrupts to be set up with a priority greater than 7, see intr_alloc.c */
esprv_int_set_priority(TEE_SECURE_INUM, 7);
esprv_int_set_type(TEE_SECURE_INUM, ESP_CPU_INTR_TYPE_LEVEL);
esprv_int_set_threshold(RVHAL_INTR_ENABLE_THRESH);
esprv_int_enable(BIT(TEE_SECURE_INUM));
#endif
ESP_LOGD(TAG, "Initial interrupt config -");
ESP_LOGD(TAG, "mideleg: 0x%08x", RV_READ_CSR(mideleg));

View File

@@ -10,6 +10,9 @@
#include "riscv/encoding.h"
#include "esp_private/interrupt_plic.h"
#include "soc/plic_reg.h"
#include "soc/interrupts.h"
#include "esp_cpu.h"
#include "esp_log.h"
#include "hal/apm_hal.h"
@@ -57,7 +60,13 @@ void esp_tee_soc_secure_sys_init(void)
/* All interrupts except the TEE secure interrupt are delegated to the U-mode */
RV_WRITE_CSR(mideleg, UINT32_MAX);
RV_CLEAR_CSR(mideleg, TEE_SECURE_INUM);
RV_CLEAR_CSR(mideleg, BIT(TEE_SECURE_INUM));
/* Clearing all interrupt configurations */
uint32_t core_id = esp_cpu_get_core_id();
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM);
}
/* TODO: IDF-8958
* The values for the secure interrupt number and priority and

View File

@@ -2,10 +2,10 @@
components/esp_tee/test_apps/tee_cli_app:
disable:
- if: IDF_TARGET not in ["esp32c6"]
reason: only supported with esp32c6 for now
- if: IDF_TARGET not in ["esp32c6", "esp32c5"]
reason: only supported with c6 and c5
components/esp_tee/test_apps/tee_test_fw:
disable:
- if: IDF_TARGET not in ["esp32c6", "esp32h2"]
reason: only supported with esp32c6 and esp32h2 for now
- if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5"]
reason: only supported with c6, h2 and c5

View File

@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C6 |
| ----------------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-C6 |
| ----------------- | -------- | -------- |
# TEE CLI Application: Secure Services Demonstration

View File

@@ -111,7 +111,6 @@ static void tee_ota_task(void *pvParameter)
task_fatal_error();
} else if (data_read > 0) {
if (image_header_was_checked == false) {
/* TODO: TEE image header is missing the `esp_app_desc_t` configuration structure */
if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)) {
esp_image_header_t img_hdr;
memcpy(&img_hdr, ota_write_data, sizeof(esp_image_header_t));

View File

@@ -6,11 +6,9 @@ import json
import logging
import multiprocessing
import os
import socket
import ssl
import time
from typing import Any
from typing import Callable
import pexpect
import pytest
@@ -22,7 +20,6 @@ from ecdsa.keys import VerifyingKey
from ecdsa.util import sigdecode_der
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
from RangeHTTPServer import RangeRequestHandler
TEST_MSG = 'hello world'
@@ -36,12 +33,12 @@ key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/
@pytest.mark.generic
@idf_parametrize('target', ['esp32c6'], indirect=['target'])
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_tee_cli_secure_storage(dut: Dut) -> None:
# Dumping the REE binary size
binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin')
bin_size = os.path.getsize(binary_file)
logging.info('tee_cli_bin_size : {}KB'.format(bin_size // 1024))
logging.info(f'tee_cli_bin_size : {bin_size // 1024}KB')
# Starting the test
dut.expect('ESP-TEE: Secure services demonstration', timeout=30)
@@ -122,12 +119,12 @@ def verify_att_token_signature(att_tk: str) -> Any:
@pytest.mark.generic
@idf_parametrize('target', ['esp32c6'], indirect=['target'])
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_tee_cli_attestation(dut: Dut) -> None:
# Dumping the REE binary size
binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin')
bin_size = os.path.getsize(binary_file)
logging.info('tee_cli_bin_size : {}KB'.format(bin_size // 1024))
logging.info(f'tee_cli_bin_size : {bin_size // 1024}KB')
# Starting the test
dut.expect('ESP-TEE: Secure services demonstration', timeout=30)
@@ -149,41 +146,22 @@ def test_tee_cli_attestation(dut: Dut) -> None:
#######################################
def https_request_handler() -> Callable[..., http.server.BaseHTTPRequestHandler]:
"""
Returns a request handler class that handles broken pipe exception
"""
class RequestHandler(RangeRequestHandler):
def finish(self) -> None:
try:
if not self.wfile.closed:
self.wfile.flush()
self.wfile.close()
except socket.error:
pass
self.rfile.close()
def handle(self) -> None:
try:
RangeRequestHandler.handle(self)
except socket.error:
pass
return RequestHandler
def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> None:
os.chdir(ota_image_dir)
requestHandler = https_request_handler()
httpd = http.server.HTTPServer((server_ip, server_port), requestHandler)
server_address = (server_ip, server_port)
httpd.socket = ssl.wrap_socket(httpd.socket, keyfile=key_file, certfile=server_file, server_side=True)
Handler = http.server.SimpleHTTPRequestHandler
httpd = http.server.HTTPServer(server_address, Handler)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile=server_file, keyfile=key_file)
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()
@pytest.mark.wifi_high_traffic
@idf_parametrize('target', ['esp32c6'], indirect=['target'])
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_tee_cli_secure_ota_wifi(dut: Dut) -> None:
"""
This is a positive test case, which downloads complete binary file multiple number of times.
@@ -214,7 +192,7 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None:
# Starting the test
dut.expect('ESP-TEE: Secure services demonstration', timeout=30)
time.sleep(1)
time.sleep(2)
# Connecting to Wi-Fi
env_name = 'wifi_high_traffic'
@@ -225,7 +203,7 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None:
# Fetch the DUT IP address
try:
ip_address = dut.expect(r'got ip:(\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
print(f'Connected to AP/Ethernet with IP: {ip_address}')
except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')

View File

@@ -14,7 +14,7 @@ CONFIG_FREERTOS_UNICORE=y
# TEE: OTA-related
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y
CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y
CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=45000
CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=30000
# Custom certificates for testing
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y

View File

@@ -1,20 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIDWDCCAkACCQCbF4+gVh/MLjANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJJ
TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD
VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j
b20wHhcNMjEwNzEyMTIzNjI3WhcNNDEwNzA3MTIzNjI3WjBuMQswCQYDVQQGEwJJ
TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD
VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhxF/y7bygndxPwiWL
SwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQuc32W
ukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2mKRbQ
S5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO2fEz
YaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnvL6Oz
3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdOAoap
rFTRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAItw24y565k3C/zENZlxyzto44ud
IYPQXN8Fa2pBlLe1zlSIyuaA/rWQ+i1daS8nPotkCbWZyf5N8DYaTE4B0OfvoUPk
B5uGDmbuk6akvlB5BGiYLfQjWHRsK9/4xjtIqN1H58yf3QNROuKsPAeywWS3Fn32
3//OpbWaClQePx6udRYMqAitKR+QxL7/BKZQsX+UyShuq8hjphvXvk0BW8ONzuw9
RcoORxM0FzySYjeQvm4LhzC/P3ZBhEq0xs55aL2a76SJhq5hJy7T/Xz6NFByvlrN
lFJJey33KFrAf5vnV9qcyWFIo7PYy2VsaaEjFeefr7q3sTFSMlJeadexW2Y=
MIIEmzCCAwOgAwIBAgIUCjRtb8JpjaUnUr1g2JJK8WxzXAkwDQYJKoZIhvcNAQEL
BQAwTDELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAk1IMQswCQYDVQQHDAJQTjEMMAoG
A1UECgwDZXNwMRUwEwYDVQQDDAwxOTIuMTY4LjEuMzYwHhcNMjUwNzI0MTI0OTQw
WhcNMzUwNzIyMTI0OTQwWjBMMQswCQYDVQQGEwJJTjELMAkGA1UECAwCTUgxCzAJ
BgNVBAcMAlBOMQwwCgYDVQQKDANlc3AxFTATBgNVBAMMDDE5Mi4xNjguMS4zNjCC
AaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAK4nnofpHHPvvF4IuF1OhZvp
cTtScOV/h0eTFCpm+eq9NcsIUpEad1DMmKPGN9y1dp//qNZUJomZBnhG+NoHBLPX
Xu62fQ+n1EsJ8QtmEaNo+3fElM2joN6Vfi5/Pz6JyrYq5FYkZnI5agMlLPbrldZa
G3ZHh1vCAhbVrD6S0hLKNrTRt/PbKWfohz8swkl4DqOk0DQDKdkIB/WVLmFo3sMZ
wfTm04lfH9VMJXUrmxFI+WUycTqlpdupMPHdVAr4v85RsC8kRcIneJnc1lKDDHlX
ou0Loxjz3oLCtFNfiqARx7UQ0voAdLJlk7+NHM8D/ArcfMcKWE+aj/e8S6USf/9F
fkvqKJzdCQieEnI4uISAeHgj1Cy52nafD+eQRXcjjPCe3WZxYyD9kpeindoy0suM
EPgIMCTXKY/0iQxYNO9CxGqw5O3ROVPq/vWbRr/yOfJ8SRGnklztxrQiLB0kRtpO
hVCYmfk84l+98c9CPu1CY9VjlYqUOREjKc4edBeR9QIDAQABo3UwczAdBgNVHQ4E
FgQUAL1glrdORLboiLujugzLmArsLXowHwYDVR0jBBgwFoAUAL1glrdORLboiLuj
ugzLmArsLXowDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCBaAwEwYDVR0lBAww
CgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggGBAFiQgcPxNLK2Tan6Kw4Xyb2q
LdpEQXvxiF0f+tLAFJx1mc8aExaM0WinNehGZSwZl1DnH6sJlOiuitAewSjiaFVF
QXxS+8nkBGn0C0tAV4kc3/TxOpbNpTPZUDb3PNMhlGH1LJqZBpWrzbzHL8YSwXmT
aoiXV6/ubWk1yYjTLPChmavWaOAVhYK3GqRbDGDERXC8uXe7de5UuD8R+oaFS1oh
nC6x1wspGQbILjDwmqRE5GvPlTWSBAHw4bbWD4GnXMXAAkDj5Fjom+CzC5D7Q3wQ
C/JlVN1cHNLF6VlOlLDZyLDeWPOVkpm3OB5+IxPEW+8XtNfGrpB5cI/zf2Ba7kZU
jmZNrMqXXd3r7fYLTGjWfMMQb/XLTT2/qE/iOc/tCVLVkDu2hd5gtsIasnlwaBZ7
dn1nRwrKaXwZnPql+Fx3KjuY6nA2+SDz9t57bIxkWhjE+Nn/zFZk7l84foyo3RhO
TAlCEC81uG9vZqL2fShbrTqpXs59KP3wlPVKuWro5Q==
-----END CERTIFICATE-----

View File

@@ -1,28 +1,40 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP
wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu
c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m
KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO
2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv
L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO
AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH
fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj
z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF
gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z
Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q
jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz
i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw
8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N
JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq
gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv
kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN
P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al
pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG
1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU
10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ
hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O
rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G
rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ
YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG
vSXnRLaxQhooWm+IuX9SuBQ=
MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCuJ56H6Rxz77xe
CLhdToWb6XE7UnDlf4dHkxQqZvnqvTXLCFKRGndQzJijxjfctXaf/6jWVCaJmQZ4
RvjaBwSz117utn0Pp9RLCfELZhGjaPt3xJTNo6DelX4ufz8+icq2KuRWJGZyOWoD
JSz265XWWht2R4dbwgIW1aw+ktISyja00bfz2yln6Ic/LMJJeA6jpNA0AynZCAf1
lS5haN7DGcH05tOJXx/VTCV1K5sRSPllMnE6paXbqTDx3VQK+L/OUbAvJEXCJ3iZ
3NZSgwx5V6LtC6MY896CwrRTX4qgEce1ENL6AHSyZZO/jRzPA/wK3HzHClhPmo/3
vEulEn//RX5L6iic3QkInhJyOLiEgHh4I9Qsudp2nw/nkEV3I4zwnt1mcWMg/ZKX
op3aMtLLjBD4CDAk1ymP9IkMWDTvQsRqsOTt0TlT6v71m0a/8jnyfEkRp5Jc7ca0
IiwdJEbaToVQmJn5POJfvfHPQj7tQmPVY5WKlDkRIynOHnQXkfUCAwEAAQKCAYA4
VJxUfbQ0U+Dr0YpAs/tHePSlKX9W3C8XmZ02MeS4ZscVivWZ9aOOQP9GSgEbpJ5g
FkO4P7PPYe3TzbEEZKzCtvD/6Yr+G1zxgJ+0/ijKYFSmYrF26mxIUrZjt8jvI4ar
8ae1rURtweBmcAnhPEZU9QRY973ykgg29pomCztj1IBpcEQ93i/AalgEuSeGuAyU
JeUqTbOlfZGFf+FmpJMZLCWuX1Mg5eHYDi83fQlFSANTFkPFonrJWCp6sQpUGiz2
hFgGkH3jqLbA1KE5x/SwuQmWMbBHRPYhET2Py5mhkS5zddJS5YG3WSO/dv6o7tGP
Ek0G0RQzfKqraJRBM0ePb4texi5umIE+G3XpQApE8ZELJjVpEAQkKCH189np7oxv
tcWCQwPq5addMTPqVzaNjhC4JADhUeSiXYGlTmvSuSV/ZIXI7fffI1qDwrBVIX7N
T6ie4JQU+lc+hv8gPZqNdglHYUMj6i3bPPzQ8p/Tu5MdNcAoh455aXUilflJjukC
gcEA8EtvDE9k1zHgZFmcXkl+c+PgpGcp0nwoJ+uH2BCd5PI962IcDhQcKxCPNPa2
GxV/6J/y6cLk99v3novIlZmEnIvMf/g2gYdW0XNKEljwtB6ms/Oq/OMMuGMP+Ix4
0H9uW6LpYzYBuyKOt6RfYrgWsNsL2caojcu92aX4ug4kkf97OnsslrAqkp1hGJiN
okuiss63UVROalcNSWFLqkz7zcKy67eItuIBOEY+tKkdUt1b3/DURHFL4e5ZCdWo
UnjrAoHBALmJi3f9VGqsn2mFnetSeablRnvOyNMMblRgBLBVsc6hEl3Vxd0ejY8N
APWZ+W8/AXwpHj+Oqoap6wYiuXr1xcHBRNZu2gRB0evZUEzdu7m6dj28dc9ICymj
9CuFW+HVxidmBPfAum1+PU0WHkB4CwDpm5DtPymlNHJKKvDILawo4j2jh9K5YeCK
6/YdjmQVaBeHoB2v59UkEPZCcFarZa1Z6ZBlkNKCeCrKYB081RsEjYpwZUVd8eHw
49jl131onwKBwFHFec64ndpVUMUVcY7sd6m8XE/WA3drZMbg8eNnFDQ68zNMubtY
wJUvF2ywoBvrXxGsjJ9cAUsPgd5kNyghi+0x7a+GqhW+Fp9EGmrP9Wl2HMiUHRXd
thBxNZghRWO+WbG5aK6oTEKAagy4VPVlK+OXRxse7XEDamHMhy3Zbjx4slieXfgR
jwtBny8diuU10/IBQoTcqaqqYQ0dnQAhHndQ0E5CsLV7h2q9DM2x1xbB2WgFrlZ0
L5x83bPpD1SxbQKBwQCjuKr4o/Qk+dTlwcGbkTjGPFWZFN0D11lYXS5mCAiSBHJ3
mRczyy0xSVFKaKfCMf/2dzY48YSqtjAtRuETjuMF2a0L59+8l/RMwYPpgFSSTObg
DXiMA8/N296vtMtimkh0JcNGeKxJyHcBmf3x97wF/x6GocP11NFV9Pq1ZH9hBua1
a6OEIJAtG4misWwgBv/Gm6h/6eSSoXPSSshkwnRDpy7Ce81y5Sxy3gg4ZKDMaZUY
z5udvYufS/lTQWaJRJMCgcEAzxLRrGW3Gz4ch1V+ZCNTNQJqUwHeIQF4mVNkeEk5
wXE2NsW/DqStQiNkNDSMHiTXPfVoHDGhxxKhSYPe2O7JXkJL8EyzwMwEZJ4ypjuV
5/DadZh6cGu6UWVNAzzvcOMnEH8rHFfQlAd7MnFdJafXnEAX9UCfNFHOoNJhBbUj
kQPYVUEkEws0Feu0yUgyDRfDZcxeEC+ubvO0mGZEdGAuvu29AHnnGLhBTTdFb05H
Q4QjfIE8PkLbVa1oC3niOWdo
-----END PRIVATE KEY-----

View File

@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C6 | ESP32-H2 |
| ----------------- | -------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 |
| ----------------- | -------- | -------- | -------- |
## ESP-TEE: Test Suite

View File

@@ -9,36 +9,11 @@
extern "C" {
#endif
#include <stdint.h>
#include "esp_attr.h"
#define TEE_TEST_INT_COUNT 3
#define ESP_TEE_TEST_INTR_ITER (4)
uint32_t NOINLINE_ATTR esp_tee_service_add(uint32_t a, uint32_t b);
uint32_t NOINLINE_ATTR esp_tee_service_sub(uint32_t a, uint32_t b);
uint32_t NOINLINE_ATTR esp_tee_service_mul(uint32_t a, uint32_t b);
uint32_t NOINLINE_ATTR esp_tee_service_div(uint32_t a, uint32_t b);
int esp_tee_secure_int_test(void);
int esp_tee_non_secure_int_test(volatile uint32_t* volatile ns_int_count);
int esp_tee_test_int_count(uint32_t *secure_int_count);
int esp_tee_test_store_prohibited(uint32_t type);
int esp_tee_test_illegal_instr(void);
int esp_tee_test_instr_fetch_prohibited(uint32_t type);
void NOINLINE_ATTR dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i);
uint32_t add_in_loop(uint32_t a, uint32_t b, uint32_t iter);
int _ss_esp_tee_test_heap_malloc_write_free(void);
void NOINLINE_ATTR esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i);
#ifdef __cplusplus
}

View File

@@ -3,73 +3,69 @@ secure_services:
entries:
- id: 200
type: custom
function: esp_tee_service_add
function: esp_tee_test_service_add
args: 2
- id: 201
type: custom
function: esp_tee_service_sub
function: esp_tee_test_service_sub
args: 2
- id: 202
type: custom
function: esp_tee_service_mul
function: esp_tee_test_service_mul
args: 2
- id: 203
type: custom
function: esp_tee_service_div
function: esp_tee_test_service_div
args: 2
- id: 204
type: custom
function: esp_tee_test_timer_init
args: 1
function: esp_tee_test_tee_intr_in_tee
args: 0
- id: 205
type: custom
function: esp_tee_secure_int_test
args: 0
function: esp_tee_test_ree_intr_in_tee
args: 1
- id: 206
type: custom
function: esp_tee_non_secure_int_test
args: 1
function: esp_tee_test_tee_intr_in_ree
args: 2
- id: 207
type: custom
function: esp_tee_test_int_count
args: 1
- id: 208
type: custom
function: esp_tee_test_resv_reg1_write_violation
args: 0
- id: 209
- id: 208
type: custom
function: esp_tee_test_resv_reg1_exec_violation
args: 0
- id: 210
- id: 209
type: custom
function: esp_tee_test_iram_reg1_write_violation
args: 0
- id: 211
- id: 210
type: custom
function: esp_tee_test_iram_reg2_write_violation
args: 0
- id: 212
- id: 211
type: custom
function: esp_tee_test_dram_reg1_exec_violation
args: 0
- id: 213
- id: 212
type: custom
function: esp_tee_test_dram_reg2_exec_violation
args: 0
- id: 214
- id: 213
type: custom
function: esp_tee_test_illegal_instruction
args: 0
- id: 214
type: custom
function: esp_tee_test_dummy_sec_srv
args: 9
- id: 215
type: custom
function: dummy_secure_service
args: 9
function: esp_tee_test_priv_mode_switch
args: 2
- id: 216
type: custom
function: add_in_loop
args: 3
- id: 217
type: custom
function: esp_tee_test_heap_malloc_write_free
args: 0

View File

@@ -9,7 +9,7 @@
#include "multi_heap.h"
void NOINLINE_ATTR _ss_dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i)
void NOINLINE_ATTR _ss_esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i)
{
esp_rom_printf("Dummy secure service\n");
*i = a + b + c + d + e + f + g + h;

View File

@@ -1,14 +1,14 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdarg.h>
#include "secure_service_num.h"
#include "esp_tee.h"
#include "esp_err.h"
#include "esp_attr.h"
void dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i)
void NOINLINE_ATTR esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i)
{
esp_tee_service_call(10, SS_DUMMY_SECURE_SERVICE, a, b, c, d, e, f, g, h, i);
esp_tee_service_call(10, SS_ESP_TEE_TEST_DUMMY_SEC_SRV, a, b, c, d, e, f, g, h, i);
}

View File

@@ -4,174 +4,168 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <assert.h>
#include "esp_cpu.h"
#include "esp_log.h"
#include "riscv/csr.h"
#include "esp_rom_sys.h"
#include "hal/timer_ll.h"
#include "hal/clk_gate_ll.h"
#include "soc/timer_group_reg.h"
#include "soc/soc.h"
#include "soc/interrupts.h"
#include "soc/interrupt_matrix_reg.h"
#include "soc/pcr_reg.h"
#include "hal/timer_ll.h"
#include "esp_tee.h"
#include "esp_tee_intr.h"
#include "esp_tee_test.h"
#define TIMER_DIVIDER 80 // Hardware timer clock divider
#define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution
#define TIMER_ALARM_PERIOD_S 0.10 // sample test interval for the first timer
static const char *TAG __attribute__((unused)) = "esp_tee_intr_test";
/* TEE uses Group0 Timer0 */
#define TEE_SECURE_GROUP 0
#define TEE_SECURE_TIMER 0
/* ---------------------------------------------------- Utility functions ---------------------------------------------------- */
static const char *TAG = "esp_tee_intr_test";
#define TEST_TIMER_GROUP (0)
#define TEST_TIMER_ID (0)
#define TEST_TIMER_DIVIDER (80)
static timg_dev_t *timg_hw = (&TIMERG0);
#define TEST_TIMER_RESOLUTION_HZ (1000000ULL) // 1MHz, 1 tick = 1us
#define TIMER_ALARM_PERIOD_S (0.25f) // 250ms @ resolution 1MHz
uint32_t *psecure_int_count = NULL;
static timg_dev_t *timg_dev = TIMER_LL_GET_HW(TEST_TIMER_GROUP);
static void IRAM_ATTR timer_group0_isr(void *arg)
static void IRAM_ATTR test_timer_isr(void *arg)
{
ESP_LOGI(TAG, "Timer ISR Handler from World %d!", esp_cpu_get_curr_privilege_level());
uint32_t *intr_count = (uint32_t *)arg;
*intr_count = *intr_count + 1;
esp_rom_printf("[mode: %d] Interrupt triggered (%d)\n", esp_cpu_get_curr_privilege_level(), *intr_count);
/* For interrupt test. */
*psecure_int_count = *psecure_int_count + 1;
/* Clear interrupt */
timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER));
/* Re-enable the alarm. */
timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, true);
/* Clear interrupt and re-enable the alarm */
timer_ll_clear_intr_status(timg_dev, TIMER_LL_EVENT_ALARM(TEST_TIMER_ID));
timer_ll_enable_alarm(timg_dev, TEST_TIMER_ID, true);
}
static void tee_timer_enable(void)
static void test_timer_deinit(void)
{
struct vector_desc_t timer_vd = { 0, NULL, NULL, NULL };
const uint32_t timer_id = TEST_TIMER_ID;
// init timer_vc
timer_vd.source = ETS_TG0_T0_LEVEL_INTR_SOURCE;
timer_vd.isr = timer_group0_isr;
// Disable and clear timer state
timer_ll_enable_counter(timg_dev, timer_id, false);
timer_ll_enable_auto_reload(timg_dev, timer_id, false);
timer_ll_enable_alarm(timg_dev, timer_id, false);
ESP_LOGI(TAG, "Enabling test timer from secure world");
timer_ll_enable_intr(timg_dev, TIMER_LL_EVENT_ALARM(timer_id), false);
timer_ll_clear_intr_status(timg_dev, TIMER_LL_EVENT_ALARM(timer_id));
/* Enable TG0 peripheral module */
_timer_ll_enable_bus_clock(TEE_SECURE_GROUP, true);
_timer_ll_reset_register(TEE_SECURE_GROUP);
/* Stop counter, alarm, auto-reload at first place */
timer_ll_enable_clock(TEE_SECURE_GROUP, TEE_SECURE_TIMER, true);
timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, false);
timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, false);
timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, false);
// Set clock source
timer_ll_set_clock_source(TEE_SECURE_GROUP, TEE_SECURE_TIMER, GPTIMER_CLK_SRC_DEFAULT);
timer_ll_set_clock_prescale(timg_hw, TEE_SECURE_TIMER, TIMER_DIVIDER);
// Initialize counter value to zero
timer_ll_set_reload_value(timg_hw, TEE_SECURE_TIMER, 0);
timer_ll_trigger_soft_reload(timg_hw, TEE_SECURE_TIMER);
// set counting direction
timer_ll_set_count_direction(timg_hw, TEE_SECURE_TIMER, GPTIMER_COUNT_UP);
// disable interrupt
timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), false);
// clear pending interrupt event
timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER));
esp_tee_intr_register((void *)&timer_vd);
timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), true);
timer_ll_set_reload_value(timg_hw, TEE_SECURE_TIMER, 0);
// enable timer interrupt
timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), true);
// set timer alarm
uint64_t alarm_value = (TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ);
timer_ll_set_alarm_value(timg_hw, TEE_SECURE_TIMER, alarm_value);
timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, true);
timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, true);
timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, true);
}
static void tee_timer_disable(void)
{
ESP_LOGI(TAG, "Disabling test timer from secure world");
/* Init timer interrupt vector descriptor */
struct vector_desc_t timer_vd = { 0, NULL, NULL, NULL };
timer_vd.source = ETS_TG0_T0_LEVEL_INTR_SOURCE;
timer_vd.isr = timer_group0_isr;
// Reset the counter
uint64_t prev_val = timer_ll_get_reload_value(timg_dev, timer_id);
timer_ll_set_reload_value(timg_dev, timer_id, 0);
timer_ll_trigger_soft_reload(timg_dev, timer_id);
timer_ll_set_reload_value(timg_dev, timer_id, prev_val);
// Deregister ISR
struct vector_desc_t timer_vd = {
.source = ETS_TG0_T0_LEVEL_INTR_SOURCE,
};
esp_tee_intr_deregister((void *)&timer_vd);
/* Disable timer */
timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, false);
timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, false);
timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, false);
/* Disable and clear interrupt */
timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), false);
timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER));
/* Disable TG0 peripheral module */
// periph_ll_disable_clk_set_rst(PERIPH_TIMG0_MODULE);
timer_ll_enable_clock(TEST_TIMER_GROUP, timer_id, false);
}
void _ss_esp_tee_test_timer_init(bool enable)
static void test_timer_init(volatile uint32_t *arg)
{
if (enable) {
tee_timer_enable();
} else {
tee_timer_disable();
}
const uint32_t group_id = TEST_TIMER_GROUP;
const uint32_t timer_id = TEST_TIMER_ID;
test_timer_deinit();
// Enable peripheral clock and reset hardware
_timer_ll_enable_bus_clock(group_id, true);
_timer_ll_reset_register(group_id);
// Select clock source and enable module clock
// Enable the default clock source PLL_F80M
REG_SET_BIT(PCR_PLL_DIV_CLK_EN_REG, PCR_PLL_80M_CLK_EN);
timer_ll_set_clock_source(group_id, timer_id, GPTIMER_CLK_SRC_DEFAULT);
timer_ll_enable_clock(group_id, timer_id, true);
timer_ll_set_clock_prescale(timg_dev, timer_id, TEST_TIMER_DIVIDER);
timer_ll_set_count_direction(timg_dev, timer_id, GPTIMER_COUNT_UP);
// Register ISR
struct vector_desc_t timer_vd = {
.source = ETS_TG0_T0_LEVEL_INTR_SOURCE,
.isr = test_timer_isr,
.arg = (void *)arg,
};
esp_tee_intr_register((void *)&timer_vd);
timer_ll_enable_intr(timg_dev, TIMER_LL_EVENT_ALARM(timer_id), true);
// Configure and enable timer alarm
timer_ll_set_alarm_value(timg_dev, timer_id, TIMER_ALARM_PERIOD_S * TEST_TIMER_RESOLUTION_HZ);
timer_ll_enable_auto_reload(timg_dev, timer_id, true);
timer_ll_enable_alarm(timg_dev, timer_id, true);
timer_ll_enable_counter(timg_dev, timer_id, true);
}
/**
* Secure interrupt in secure world test.
*/
int _ss_esp_tee_secure_int_test(void)
/* ---------------------------------------------------- Test cases ---------------------------------------------------- */
uint32_t _ss_esp_tee_test_tee_intr_in_tee(void)
{
ESP_LOGD(TAG, "In WORLD %d", esp_cpu_get_curr_privilege_level());
volatile uint32_t secure_int_count = 0;
psecure_int_count = (uint32_t *)&secure_int_count;
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
_ss_esp_tee_test_timer_init(true);
while (secure_int_count < TEE_TEST_INT_COUNT);
_ss_esp_tee_test_timer_init(false);
volatile uint32_t tee_intr_count = 0;
test_timer_init(&tee_intr_count);
ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level());
return secure_int_count;
while (tee_intr_count < ESP_TEE_TEST_INTR_ITER) {
esp_rom_delay_us(10 * 1000U);
}
/**
* Non-Secure interrupt in secure world test.
*/
int _ss_esp_tee_non_secure_int_test(volatile uint32_t *volatile ns_int_count)
test_timer_deinit();
mode = esp_cpu_get_curr_privilege_level();
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
return tee_intr_count;
}
uint32_t _ss_esp_tee_test_tee_intr_in_ree(int stage, volatile uint32_t *volatile intr_count)
{
ESP_LOGD(TAG, "In WORLD %d", esp_cpu_get_curr_privilege_level());
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
uint32_t count = 0;
count = *ns_int_count;
while ((*ns_int_count < TEE_TEST_INT_COUNT)) {
if (*ns_int_count > count) {
count = *ns_int_count;
ESP_LOGI(TAG, "Interrupt count %d", count);
}
switch (stage) {
case 0:
test_timer_init(intr_count);
break;
case 1:
test_timer_deinit();
break;
default:
assert(false && "Invalid stage!");
break;
}
ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level());
mode = esp_cpu_get_curr_privilege_level();
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
return 0;
}
int _ss_esp_tee_test_int_count(uint32_t *secure_int_count)
uint32_t _ss_esp_tee_test_ree_intr_in_tee(volatile uint32_t *volatile intr_count)
{
psecure_int_count = secure_int_count;
return (*psecure_int_count);
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
uint32_t prev_count = 0;
while (true) {
uint32_t curr_count = *intr_count;
if (curr_count > prev_count) {
prev_count = curr_count;
esp_rom_printf("[mode: %d] Interrupt received (%d)\n", esp_cpu_get_curr_privilege_level(), curr_count);
}
if (curr_count >= ESP_TEE_TEST_INTR_ITER) {
break;
}
esp_rom_delay_us(1000U);
}
mode = esp_cpu_get_curr_privilege_level();
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
return 0;
}

View File

@@ -12,37 +12,45 @@ static const char *TAG = "test_sec_srv";
/* Sample Trusted App */
uint32_t NOINLINE_ATTR _ss_esp_tee_service_add(uint32_t a, uint32_t b)
uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_add(uint32_t a, uint32_t b)
{
ESP_LOGD(TAG, "SS: %s", __func__);
return (a + b);
}
uint32_t NOINLINE_ATTR _ss_esp_tee_service_sub(uint32_t a, uint32_t b)
uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_sub(uint32_t a, uint32_t b)
{
ESP_LOGD(TAG, "SS: %s", __func__);
return (a - b);
}
uint32_t NOINLINE_ATTR _ss_esp_tee_service_mul(uint32_t a, uint32_t b)
uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_mul(uint32_t a, uint32_t b)
{
ESP_LOGD(TAG, "SS: %s", __func__);
return (a * b);
}
uint32_t NOINLINE_ATTR _ss_esp_tee_service_div(uint32_t a, uint32_t b)
uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_div(uint32_t a, uint32_t b)
{
ESP_LOGD(TAG, "SS: %s", __func__);
return (a / b);
}
uint32_t _ss_add_in_loop(uint32_t a, uint32_t b, uint32_t iter)
uint32_t _ss_esp_tee_test_priv_mode_switch(uint32_t *a, uint32_t *b)
{
ESP_LOGD(TAG, "SS: %s", __func__);
for (int i = 0; i < iter; i++) {
a += b;
esp_rom_delay_us(1000000);
esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), a);
*a = 1;
*b = 1;
uint32_t c = 0;
while (c < ESP_TEE_TEST_INTR_ITER * 2) {
c = *a + *b;
esp_rom_delay_us(500 * 1000U);
esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), c);
*a += 1;
*b += 1;
}
return a;
return c;
}

View File

@@ -10,8 +10,6 @@ import sys
import tempfile
from pathlib import Path
from typing import Any
from typing import Dict
from typing import List
import espsecure
import esptool
@@ -104,7 +102,48 @@ esp_tee_empty_bin = {
0xDC, 0x60, 0x86, 0x6C, 0x37, 0x76, 0xAA, 0x30, 0x1F, 0x61, 0x48, 0x23,
0xEA, 0x34, 0xAA, 0x19, 0xE8, 0xDE, 0x04, 0x7D, 0x2A, 0x30, 0xC1, 0xDD,
0x61, 0x38, 0x9D, 0xB5, 0xCA, 0x13, 0x5A, 0x79
]
],
'esp32c5': [
0xE9, 0x04, 0x02, 0x1F, 0x00, 0x00, 0x80, 0x40, 0xEE, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x64, 0x00, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
# DROM segment
0x20, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00,
# esp_app_desc structure
0x32, 0x54, 0xCD, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0x35, 0x2E, 0x35, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x65, 0x73, 0x70, 0x5F, 0x74, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x30, 0x3A, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x76, 0x20, 0x31, 0x31, 0x20, 0x32,
0x30, 0x32, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x35, 0x2E, 0x35,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2D, 0x63, 0x66, 0x8B, 0x75, 0xFA, 0x59, 0x05,
0x53, 0x34, 0x91, 0x71, 0x51, 0x33, 0x91, 0xDD, 0xF8, 0xB1, 0xFE, 0x83,
0x06, 0xEB, 0x03, 0x80, 0x45, 0xC9, 0x18, 0x20, 0x83, 0x7E, 0x2E, 0x43,
*([0x00] * 0x58),
# Padding
*([0x00] * 0x100),
# IRAM segment
0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x00, 0x00,
*([0x00] * 0x20),
# PADDING segment
0x00, 0x00, 0x00, 0x00, 0xC8, 0x7D, 0x00, 0x00,
*([0x00] * 0x7DC8),
# IROM segment
0x20, 0x80, 0x00, 0x42, 0x00, 0x01, 0x00, 0x00,
*([0x00] * 0x100),
# Padding
*([0x00] * 0x0F),
# CRC8 checksum
0x56,
# Image SHA256
0xCD, 0xCC, 0xF2, 0xE3, 0x52, 0x76, 0xE5, 0x6D, 0xF6, 0x32, 0x95, 0x27,
0x5F, 0xF3, 0xD8, 0x90, 0xD7, 0x95, 0xA0, 0x95, 0xD5, 0xDA, 0xE7, 0xA4,
0x58, 0x08, 0x84, 0xBB, 0x8F, 0x29, 0xAB, 0xE4
],
}
# fmt: on
@@ -233,7 +272,7 @@ class TEESerial(IdfSerial):
self.flash()
self.custom_erase_partition('secure_storage')
KEY_DEFS: List[Dict[str, Any]] = [
KEY_DEFS: list[dict[str, Any]] = [
{'key': 'aes256_key0', 'type': 'aes256', 'input': None, 'write_once': True},
{
'key': 'aes256_key1',
@@ -264,7 +303,7 @@ class TEESerial(IdfSerial):
NVS_CSV_PATH = TMP_DIR / 'tee_sec_stg_val.csv'
NVS_BIN_PATH = TMP_DIR / 'tee_sec_stg_nvs.bin'
def run_command(self, command: List[str]) -> None:
def run_command(self, command: list[str]) -> None:
try:
subprocess.check_call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
@@ -276,7 +315,7 @@ class TEESerial(IdfSerial):
def create_tee_sec_stg_csv(self, tmp_dir: Path) -> Path:
csv_path = self.NVS_CSV_PATH
rows: List[List[str]] = [
rows: list[list[str]] = [
['key', 'type', 'encoding', 'value'],
['tee_sec_stg_ns', 'namespace', '', ''],
]

View File

@@ -4,32 +4,46 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "esp_tee.h"
#include "secure_service_num.h"
#include "esp_tee_test.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_cpu.h"
#include "esp_tee.h"
#include "esp_tee_test.h"
#include "secure_service_num.h"
#include "unity.h"
#include "sdkconfig.h"
#define TEST_TASK_1_DONE_BIT (BIT0)
#define TEST_TASK_2_DONE_BIT (BIT1)
typedef struct {
uint32_t id;
uint32_t *val;
EventBits_t done_bit;
} test_task_args_t;
static EventGroupHandle_t test_task_eg;
static void test_op(int sec_srv_num, uint32_t a, uint32_t b)
{
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
uint32_t lval = 0;
switch (sec_srv_num) {
case SS_ESP_TEE_SERVICE_ADD:
case SS_ESP_TEE_TEST_SERVICE_ADD:
lval = (a + b);
break;
case SS_ESP_TEE_SERVICE_SUB:
case SS_ESP_TEE_TEST_SERVICE_SUB:
lval = (a - b);
break;
case SS_ESP_TEE_SERVICE_MUL:
case SS_ESP_TEE_TEST_SERVICE_MUL:
lval = (a * b);
break;
case SS_ESP_TEE_SERVICE_DIV:
case SS_ESP_TEE_TEST_SERVICE_DIV:
lval = (a / b);
break;
default:
@@ -40,60 +54,94 @@ static void test_op(int sec_srv_num, uint32_t a, uint32_t b)
uint32_t val = esp_tee_service_call(3, sec_srv_num, a, b);
TEST_ASSERT_EQUAL_UINT32(lval, val);
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed");
mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
}
TEST_CASE("Test single calls to sample app (basic services)", "[basic]")
{
const uint32_t a = 200, b = 100;
test_op(SS_ESP_TEE_SERVICE_ADD, a, b);
test_op(SS_ESP_TEE_SERVICE_SUB, a, b);
test_op(SS_ESP_TEE_SERVICE_MUL, a, b);
test_op(SS_ESP_TEE_SERVICE_DIV, a, b);
test_op(SS_ESP_TEE_TEST_SERVICE_ADD, a, b);
test_op(SS_ESP_TEE_TEST_SERVICE_SUB, a, b);
test_op(SS_ESP_TEE_TEST_SERVICE_MUL, a, b);
test_op(SS_ESP_TEE_TEST_SERVICE_DIV, a, b);
}
TEST_CASE("Test multiple calls to sample app (basic services)", "[basic]")
{
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
for (int i = 0; i < 1024; i++) {
uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_SERVICE_ADD, i, i + 1);
uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_TEST_SERVICE_ADD, i, i + 1);
TEST_ASSERT_EQUAL_UINT32((2 * i + 1), val);
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed");
mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
}
}
TEST_CASE("Custom secure service call", "[basic]")
TEST_CASE("Test custom secure service call", "[basic]")
{
int res = -1;
dummy_secure_service(1, 2, 3, 4, 5, 6, 7, 8, &res);
esp_tee_test_dummy_sec_srv(1, 2, 3, 4, 5, 6, 7, 8, &res);
TEST_ASSERT_EQUAL_UINT32(36, res);
}
void test_task(void *pvParameters)
static void test_task(void *pvParameters)
{
for (int i = 0; i < 8; i++) {
esp_rom_printf("[mode: %d] test_task - %d\n", esp_cpu_get_curr_privilege_level(), i);
vTaskDelay(pdMS_TO_TICKS(1000));
test_task_args_t *args = (test_task_args_t *)pvParameters;
uint32_t *val = args->val;
uint32_t id = args->id;
uint32_t prev_val = *val;
while (*val <= ESP_TEE_TEST_INTR_ITER) {
uint32_t curr_val = *val;
if (curr_val != prev_val) {
esp_rom_printf("[mode: %d] test_task - %d | val - %d\n", esp_cpu_get_curr_privilege_level(), id, curr_val);
prev_val = curr_val;
}
vTaskDelay(pdMS_TO_TICKS(100));
}
xEventGroupSetBits(test_task_eg, args->done_bit);
vTaskDelete(NULL);
}
TEST_CASE("Task switching during secure service calls", "[basic]")
TEST_CASE("Test task switching during secure service calls", "[basic]")
{
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
xTaskCreate(test_task, "test_task", 4096, NULL, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL);
test_task_eg = xEventGroupCreate();
TEST_ASSERT_NOT_NULL(test_task_eg);
const uint32_t a = 100, b = 200, iter = 8;
TEST_ASSERT_EQUAL_UINT32(a + b * iter, esp_tee_service_call(4, SS_ADD_IN_LOOP, a, b, iter));
uint32_t a = 0, b = 0;
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
test_task_args_t task_args_1 = {
.id = 1,
.val = &a,
.done_bit = TEST_TASK_1_DONE_BIT
};
test_task_args_t task_args_2 = {
.id = 2,
.val = &b,
.done_bit = TEST_TASK_2_DONE_BIT
};
xTaskCreate(test_task, "test_task_1", 4096, (void *)&task_args_1, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL);
xTaskCreate(test_task, "test_task_2", 4096, (void *)&task_args_2, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL);
uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_TEST_PRIV_MODE_SWITCH, &a, &b);
TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER * 2, val);
EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_1_DONE_BIT | TEST_TASK_2_DONE_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
TEST_ASSERT_MESSAGE((bits & TEST_TASK_1_DONE_BIT), "Task 1 did not complete");
TEST_ASSERT_MESSAGE((bits & TEST_TASK_2_DONE_BIT), "Task 2 did not complete");
vEventGroupDelete(test_task_eg);
mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
}
TEST_CASE("Test TEE Heap: Malloc-write-free cycles", "[heap]")

View File

@@ -22,6 +22,7 @@
#include "unity.h"
#include "ccomp_timer.h"
#include "sdkconfig.h"
#define BOOT_COUNT_NAMESPACE "boot_count"
#define TEST_PART_LABEL "custom"
@@ -29,6 +30,30 @@
#define ESP_TEE_SEC_STG_PART_LABEL "secure_storage"
__attribute__((unused)) static const uint32_t mmu_op_fail_seq[8] = {[0 ... 7] = 0x0addbad0};
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
#define SOC_TEE_FLASH_OP_FAIL_FAULT 1
#else
#define SOC_TEE_FLASH_OP_FAIL_FAULT 0
#endif
#if SOC_TEE_FLASH_OP_FAIL_FAULT
#define CHECK_MMU_OP_FAIL(ptr_) do {} while (0)
#else
#define CHECK_MMU_OP_FAIL(ptr_) \
do { \
TEST_ASSERT_EQUAL_HEX8_ARRAY(mmu_op_fail_seq, (ptr_), 0x20); \
esp_restart(); \
} while (0)
#endif
#if SOC_TEE_FLASH_OP_FAIL_FAULT
#define CHECK_FLASH_OP_FAIL(err) TEST_ESP_ERR(ESP_FAIL, err)
#else
#define CHECK_FLASH_OP_FAIL(err) do { (void)(err); esp_restart(); } while (0)
#endif
static const char *TAG = "test_esp_tee_flash_prot";
static void set_boot_count_in_nvs(uint8_t boot_count)
@@ -77,6 +102,7 @@ static void test_esp_partition_mmap_api(void)
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_0, NULL);
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle));
CHECK_MMU_OP_FAIL(outptr);
ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO);
TEST_FAIL_MESSAGE("System fault should have been generated");
break;
@@ -84,6 +110,7 @@ static void test_esp_partition_mmap_api(void)
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_1, NULL);
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_INST, &outptr, &out_handle));
CHECK_MMU_OP_FAIL(outptr);
ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO);
TEST_FAIL_MESSAGE("System fault should have been generated");
break;
@@ -91,6 +118,7 @@ static void test_esp_partition_mmap_api(void)
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL);
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle));
CHECK_MMU_OP_FAIL(outptr);
ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO);
TEST_FAIL_MESSAGE("System fault should have been generated");
break;
@@ -98,6 +126,7 @@ static void test_esp_partition_mmap_api(void)
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, ESP_TEE_SEC_STG_PART_LABEL);
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle));
CHECK_MMU_OP_FAIL(outptr);
ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO);
TEST_FAIL_MESSAGE("System fault should have been generated");
break;
@@ -117,7 +146,8 @@ static void test_esp_partition_api_r(const esp_partition_t *part)
TEST_ASSERT_NOT_NULL(part);
uint8_t buf_r[128];
memset(buf_r, 0x00, sizeof(buf_r));
TEST_ESP_ERR(ESP_FAIL, esp_partition_read(part, 0x00, buf_r, sizeof(buf_r)));
esp_err_t err = esp_partition_read(part, 0x00, buf_r, sizeof(buf_r));
CHECK_FLASH_OP_FAIL(err);
}
static void test_esp_partition_api_w(const esp_partition_t *part)
@@ -125,13 +155,15 @@ static void test_esp_partition_api_w(const esp_partition_t *part)
TEST_ASSERT_NOT_NULL(part);
uint8_t buf_w[128];
memset(buf_w, 0xA5, sizeof(buf_w));
TEST_ESP_ERR(ESP_FAIL, esp_partition_write(part, 0x00, buf_w, sizeof(buf_w)));
esp_err_t err = esp_partition_write(part, 0x00, buf_w, sizeof(buf_w));
CHECK_FLASH_OP_FAIL(err);
}
static void test_esp_partition_api_e(const esp_partition_t *part)
{
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_ERR(ESP_FAIL, esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE));
esp_err_t err = esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE);
CHECK_FLASH_OP_FAIL(err);
}
static void test_esp_partition_api(void)
@@ -188,6 +220,7 @@ static void test_spi_flash_mmap_api(void)
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_0, NULL);
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_DATA, &ptr, &handle));
CHECK_MMU_OP_FAIL(ptr);
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO);
TEST_FAIL_MESSAGE("System fault should have been generated");
break;
@@ -195,6 +228,7 @@ static void test_spi_flash_mmap_api(void)
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_1, NULL);
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_INST, &ptr, &handle));
CHECK_MMU_OP_FAIL(ptr);
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO);
TEST_FAIL_MESSAGE("System fault should have been generated");
break;
@@ -202,6 +236,7 @@ static void test_spi_flash_mmap_api(void)
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL);
TEST_ASSERT_NOT_NULL(part);
TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_DATA, &ptr, &handle));
CHECK_MMU_OP_FAIL(ptr);
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO);
TEST_FAIL_MESSAGE("System fault should have been generated");
break;
@@ -222,19 +257,22 @@ static void test_esp_flash_api_r(uint32_t paddr)
{
uint8_t buf_r[128];
memset(buf_r, 0x00, sizeof(buf_r));
TEST_ESP_ERR(ESP_FAIL, esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r)));
esp_err_t err = esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r));
CHECK_FLASH_OP_FAIL(err);
}
static void test_esp_flash_api_w(uint32_t paddr)
{
uint8_t buf_w[128];
memset(buf_w, 0xA5, sizeof(buf_w));
TEST_ESP_ERR(ESP_FAIL, esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w)));
esp_err_t err = esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w));
CHECK_FLASH_OP_FAIL(err);
}
static void test_esp_flash_api_e(uint32_t paddr)
{
TEST_ESP_ERR(ESP_FAIL, esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE));
esp_err_t err = esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE);
CHECK_FLASH_OP_FAIL(err);
}
static void test_esp_flash_api(void)

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,90 +17,47 @@
#include "unity.h"
static const char *TAG = "test_esp_tee_intr";
#define TEST_TIMER_RESOLUTION_HZ (1000000ULL) // 1MHz, 1 tick = 1us
#define TIMER_ALARM_PERIOD_S (0.25f) // 250ms @ resolution 1MHz
static const char __attribute__((unused)) *TAG = "test_esp_tee_intr";
/* ---------------------------------------------------- Utility functions ---------------------------------------------------- */
typedef struct {
uint64_t event_count;
} test_queue_element_t;
static QueueHandle_t s_timer_queue;
static gptimer_handle_t gptimer = NULL;
static volatile uint32_t ns_int_count;
static bool IRAM_ATTR test_timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
{
ESP_EARLY_LOGI(TAG, "Timer ISR Handler from World %d!", esp_cpu_get_curr_privilege_level());
BaseType_t high_task_awoken = pdFALSE;
QueueHandle_t queue = (QueueHandle_t)user_data;
// Retrieve count value and send to queue
test_queue_element_t ele = {
.event_count = edata->count_value
};
ns_int_count += 1;
xQueueSendFromISR(queue, &ele, &high_task_awoken);
// return whether we need to yield at the end of ISR
return (high_task_awoken == pdTRUE);
uint32_t *intr_count = (uint32_t *)user_data;
*intr_count = *intr_count + 1;
esp_rom_printf("[mode: %d] Interrupt triggered (%d)\n", esp_cpu_get_curr_privilege_level(), *intr_count);
return true;
}
static void IRAM_ATTR timer_evt_task(void *arg)
static void test_timer_init(volatile uint32_t *arg)
{
int record = 3;
while (1) {
test_queue_element_t ele;
if (xQueueReceive(s_timer_queue, &ele, pdMS_TO_TICKS(2000))) {
ESP_LOGI(TAG, "Timer reloaded, count=%llu", ele.event_count);
record--;
} else {
ESP_LOGW(TAG, "Missed one count event");
}
if (!record) {
break;
}
}
}
static void test_timer_init(bool for_ns_world)
{
s_timer_queue = xQueueCreate(10, sizeof(test_queue_element_t));
if (!s_timer_queue) {
ESP_LOGE(TAG, "Creating queue failed");
return;
}
ns_int_count = 0;
/* Select and initialize basic parameters of the timer */
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // 1MHz, 1 tick=1us
.resolution_hz = TEST_TIMER_RESOLUTION_HZ,
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
gptimer_event_callbacks_t cbs = {
.on_alarm = test_timer_on_alarm_cb,
};
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, s_timer_queue));
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, (void *)arg));
ESP_ERROR_CHECK(gptimer_enable(gptimer));
gptimer_alarm_config_t alarm_config2 = {
.reload_count = 0,
.alarm_count = 250000, // Alarm target = 250ms @ resolution 1MHz
.alarm_count = TIMER_ALARM_PERIOD_S * TEST_TIMER_RESOLUTION_HZ,
.flags.auto_reload_on_alarm = true,
};
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config2));
ESP_ERROR_CHECK(gptimer_start(gptimer));
if (for_ns_world) {
timer_evt_task(NULL);
}
}
static void test_timer_deinit(void)
@@ -108,109 +65,80 @@ static void test_timer_deinit(void)
ESP_ERROR_CHECK(gptimer_stop(gptimer));
ESP_ERROR_CHECK(gptimer_disable(gptimer));
ESP_ERROR_CHECK(gptimer_del_timer(gptimer));
if (s_timer_queue != NULL) {
vQueueDelete(s_timer_queue);
s_timer_queue = NULL;
}
}
/* ---------------------------------------------------- Test cases ---------------------------------------------------- */
TEST_CASE("Test Secure interrupt in Non-Secure World", "[basic]")
TEST_CASE("Test TEE interrupt in TEE", "[basic]")
{
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
volatile uint32_t lsecure_int_count = 0;
uint32_t val = esp_tee_service_call(1, SS_ESP_TEE_TEST_TEE_INTR_IN_TEE);
TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER, val);
/* Pass the variable to secure world to record the interrupt count. */
esp_tee_service_call(2, SS_ESP_TEE_TEST_INT_COUNT, &lsecure_int_count);
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed");
esp_tee_service_call(2, SS_ESP_TEE_TEST_TIMER_INIT, true);
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed");
/* Secure timer initialized.
* As secure timer interrupt will fire; CPU will switch to secure world.
* Secure world ISR handler will be called, Secure ISR log can be observed on console.
* After handling the secure interrupt, CPU will return to non-secure world
* and resume this loop and wait for the next secure timer interrupt.
* CPU will wait for TEE_TEST_INT_COUNT number of secure interrupts.
*/
while (lsecure_int_count < TEE_TEST_INT_COUNT);
/* After waiting for TEE_TEST_INT_COUNT secure interrupt,
* disable the secure timer and assert the test status.
*/
esp_tee_service_call(2, SS_ESP_TEE_TEST_TIMER_INIT, false);
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed");
/* Assert the number of secure interrupt occurred again. */
TEST_ASSERT_EQUAL_UINT32(TEE_TEST_INT_COUNT, lsecure_int_count);
mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
}
TEST_CASE("Test Secure interrupt in Secure World", "[basic]")
TEST_CASE("Test REE interrupt in REE", "[basic]")
{
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
uint32_t cnt = esp_tee_service_call(1, SS_ESP_TEE_SECURE_INT_TEST);
TEST_ASSERT_EQUAL_UINT32(TEE_TEST_INT_COUNT, cnt);
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed");
volatile uint32_t ree_intr_count = 0;
test_timer_init(&ree_intr_count);
while (ree_intr_count < ESP_TEE_TEST_INTR_ITER) {
vTaskDelay(pdMS_TO_TICKS(250));
}
test_timer_deinit();
}
static volatile uint32_t *get_ns_int_count(void)
TEST_CASE("Test REE interrupt in TEE", "[basic]")
{
return &ns_int_count;
}
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
TEST_CASE("Test Non-secure interrupt in Secure World", "[basic]")
{
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not W1");
volatile uint32_t ree_intr_count = 0;
volatile uint32_t *volatile ree_intr_count_ptr = &ree_intr_count;
/* Non-secure world timer initialization. */
ESP_LOGI(TAG, "Enabling test timer from non-secure world");
test_timer_init(false);
test_timer_init(ree_intr_count_ptr);
volatile uint32_t *volatile lns_int_count;
lns_int_count = get_ns_int_count();
/* After non-secure timer initialization,
* CPU will switch to secure world by using a service call to test API.
* CPU will wait in finite loop in secure world.
* And as non-secure timer interrupt fires, CPU will switch to non-secure world.
* Non-secure world ISR handler will be called, non-secure ISR log can be obsereved on console.
* After handling the interrupt in non-secure world, CPU will switch back to secure world
* and wait for the next timer interrupt.
* In secure world CPU will wait for TEE_TEST_INT_COUNT non-secure interrupts.
*/
uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_NON_SECURE_INT_TEST, lns_int_count);
uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_TEST_REE_INTR_IN_TEE, ree_intr_count_ptr);
TEST_ASSERT_EQUAL_UINT32(0, val);
world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed");
ESP_LOGI(TAG, "Disabling test timer from non-secure world");
test_timer_deinit();
mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
}
TEST_CASE("Test Non-secure interrupt in Non-Secure World", "[basic]")
TEST_CASE("Test TEE interrupt in REE", "[basic]")
{
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
ESP_LOGI(TAG, "Enabling test timer from non-secure world");
test_timer_init(true);
volatile uint32_t tee_intr_count = 0;
volatile uint32_t *volatile tee_intr_count_ptr = &tee_intr_count;
esp_tee_service_call(3, SS_ESP_TEE_TEST_TEE_INTR_IN_REE, 0, tee_intr_count_ptr);
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_LOGI(TAG, "Disabling test timer from non-secure world");
test_timer_deinit();
uint32_t prev_count = 0;
while (true) {
uint32_t curr_count = *tee_intr_count_ptr;
if (curr_count > prev_count) {
prev_count = curr_count;
esp_rom_printf("[mode: %d] Interrupt received (%d)\n", esp_cpu_get_curr_privilege_level(), curr_count);
}
if (curr_count >= ESP_TEE_TEST_INTR_ITER) {
break;
}
vTaskDelay(pdMS_TO_TICKS(1));
}
esp_tee_service_call(3, SS_ESP_TEE_TEST_TEE_INTR_IN_REE, 1, NULL);
TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER, tee_intr_count);
mode = esp_cpu_get_curr_privilege_level();
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
}

View File

@@ -35,102 +35,117 @@ extern uint32_t _instruction_reserved_start;
#define TEST_APM_EFUSE_PROT_REG EFUSE_RD_KEY5_DATA0_REG
#endif
TEST_CASE("Test APM violation interrupt: eFuse", "[apm_violation]")
TEST_CASE("Test APM violation: eFuse", "[apm_violation]")
{
uint32_t val = UINT32_MAX;
val = REG_READ(TEST_APM_EFUSE_PROT_REG);
TEST_ASSERT_EQUAL(0, val);
TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
TEST_FAIL_MESSAGE("APM violation should have been generated");
}
TEST_CASE("Test APM violation interrupt: MMU", "[apm_violation]")
TEST_CASE("Test APM violation: MMU", "[apm_violation]")
{
uint32_t val = UINT32_MAX;
REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), SOC_MMU_ENTRY_NUM - 2);
val = REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0));
TEST_ASSERT_EQUAL(0, val);
TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
TEST_FAIL_MESSAGE("APM violation should have been generated");
}
TEST_CASE("Test APM violation interrupt: AES", "[apm_violation]")
TEST_CASE("Test APM violation: AES", "[apm_violation]")
{
uint32_t val = UINT32_MAX;
val = REG_READ(AES_KEY_2_REG);
TEST_ASSERT_EQUAL(0, val);
TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
TEST_FAIL_MESSAGE("APM violation should have been generated");
}
TEST_CASE("Test APM violation interrupt: HMAC", "[apm_violation]")
TEST_CASE("Test APM violation: HMAC", "[apm_violation]")
{
uint32_t val = UINT32_MAX;
val = REG_READ(HMAC_SET_PARA_KEY_REG);
TEST_ASSERT_EQUAL(0, val);
TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
TEST_FAIL_MESSAGE("APM violation should have been generated");
}
TEST_CASE("Test APM violation interrupt: DS", "[apm_violation]")
TEST_CASE("Test APM violation: DS", "[apm_violation]")
{
uint32_t val = UINT32_MAX;
val = REG_READ(DS_Z_MEM);
TEST_ASSERT_EQUAL(0, val);
TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
TEST_FAIL_MESSAGE("APM violation should have been generated");
}
TEST_CASE("Test APM violation interrupt: SHA PCR", "[apm_violation]")
TEST_CASE("Test APM violation: SHA PCR", "[apm_violation]")
{
uint32_t val = 0;
REG_WRITE(PCR_SHA_CONF_REG, val);
TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
TEST_FAIL_MESSAGE("APM violation should have been generated");
}
TEST_CASE("Test APM violation interrupt: ECC PCR", "[apm_violation]")
TEST_CASE("Test APM violation: ECC PCR", "[apm_violation]")
{
uint32_t val = 0;
REG_WRITE(PCR_ECC_CONF_REG, val);
TEST_FAIL_MESSAGE("APM violation interrupt should have been generated");
TEST_FAIL_MESSAGE("APM violation should have been generated");
}
/* TEE IRAM: Reserved/Vector-table boundary */
TEST_CASE("Test TEE-TEE violation: IRAM (W1)", "[exception]")
// NOTE: For C6/H2, SWDT and BOD are protected using PMP, thus this test
// generates a store access fault instead of APM violation
TEST_CASE("Test APM violation: SWDT/BOD", "[exception]")
{
esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG1_WRITE_VIOLATION);
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
REG_WRITE(LP_ANALOG_PERI_LP_ANA_FIB_ENABLE_REG, 0);
#else
REG_WRITE(LP_ANA_FIB_ENABLE_REG, 0);
#endif
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* Illegal memory space: Write */
TEST_CASE("Test TEE-TEE violation: Reserved (W1)", "[exception]")
TEST_CASE("Test TEE-TEE violation: Reserved-W1", "[exception]")
{
esp_tee_service_call(1, SS_ESP_TEE_TEST_RESV_REG1_WRITE_VIOLATION);
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* Illegal memory space: Execution */
TEST_CASE("Test TEE-TEE violation: Reserved (X1)", "[exception]")
TEST_CASE("Test TEE-TEE violation: Reserved-X1", "[exception]")
{
esp_tee_service_call(1, SS_ESP_TEE_TEST_RESV_REG1_EXEC_VIOLATION);
TEST_FAIL_MESSAGE("Exception should have been generated");
}
// TODO: [IDF-13827] Enable when TEE SRAM is partitioned as IRAM (RX) and DRAM (RW)
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5)
/* TEE IRAM: Reserved/Vector-table boundary */
TEST_CASE("Test TEE-TEE violation: IRAM-W1", "[exception]")
{
esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG1_WRITE_VIOLATION);
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* TEE IRAM: Vector table region */
TEST_CASE("Test TEE-TEE violation: IRAM (W2)", "[exception]")
TEST_CASE("Test TEE-TEE violation: IRAM-W2", "[exception]")
{
esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG2_WRITE_VIOLATION);
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* TEE DRAM: Stack region */
TEST_CASE("Test TEE-TEE violation: DRAM (X1)", "[exception]")
TEST_CASE("Test TEE-TEE violation: DRAM-X1", "[exception]")
{
esp_tee_service_call(1, SS_ESP_TEE_TEST_DRAM_REG1_EXEC_VIOLATION);
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* TEE DRAM: Heap region */
TEST_CASE("Test TEE-TEE violation: DRAM (X2)", "[exception]")
TEST_CASE("Test TEE-TEE violation: DRAM-X2", "[exception]")
{
esp_tee_service_call(1, SS_ESP_TEE_TEST_DRAM_REG2_EXEC_VIOLATION);
TEST_FAIL_MESSAGE("Exception should have been generated");
}
#endif
/* Illegal Instruction */
TEST_CASE("Test TEE-TEE violation: Illegal Instruction", "[exception]")
@@ -140,7 +155,7 @@ TEST_CASE("Test TEE-TEE violation: Illegal Instruction", "[exception]")
}
/* TEE DRAM -REE IRAM Boundary */
TEST_CASE("Test REE-TEE isolation: DRAM (R1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: DRAM-R1", "[exception]")
{
uint32_t* val = (uint32_t *)(&_iram_start - 0x04);
TEST_ASSERT_EQUAL(0, *val);
@@ -148,14 +163,14 @@ TEST_CASE("Test REE-TEE isolation: DRAM (R1)", "[exception]")
}
/* TEE DRAM -REE IRAM Boundary */
TEST_CASE("Test REE-TEE isolation: DRAM (W1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: DRAM-W1", "[exception]")
{
*(uint32_t *)(&_iram_start - 0x04) = 0xbadc0de;
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* TEE IRAM region */
TEST_CASE("Test REE-TEE isolation: IRAM (R1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: IRAM-R1", "[exception]")
{
uint32_t *val = (uint32_t *)(&_iram_start - (CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) + 0x04);
TEST_ASSERT_EQUAL(0, *val);
@@ -163,14 +178,14 @@ TEST_CASE("Test REE-TEE isolation: IRAM (R1)", "[exception]")
}
/* TEE IRAM region */
TEST_CASE("Test REE-TEE isolation: IRAM (W1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: IRAM-W1", "[exception]")
{
*(uint32_t *)(&_iram_start - (CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) + 0x04) = 0xbadc0de;
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* TEE IROM region */
TEST_CASE("Test REE-TEE isolation: IROM (R1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: IROM-R1", "[exception]")
{
uint32_t *val = (uint32_t *)(SOC_IROM_LOW + 0x04);
TEST_ASSERT_EQUAL(0, *val);
@@ -178,14 +193,14 @@ TEST_CASE("Test REE-TEE isolation: IROM (R1)", "[exception]")
}
/* TEE IROM region */
TEST_CASE("Test REE-TEE isolation: IROM (W1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: IROM-W1", "[exception]")
{
*(uint32_t *)(SOC_IROM_LOW + 0x04) = 0xbadc0de;
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* TEE DROM - REE IROM boundary */
TEST_CASE("Test REE-TEE isolation: DROM (R1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: DROM-R1", "[exception]")
{
const uint32_t test_addr = ALIGN_DOWN_TO_MMU_PAGE_SIZE((uint32_t)&_instruction_reserved_start);
uint32_t *val = (uint32_t *)(test_addr - 0x04);
@@ -194,16 +209,9 @@ TEST_CASE("Test REE-TEE isolation: DROM (R1)", "[exception]")
}
/* TEE DROM - REE IROM boundary */
TEST_CASE("Test REE-TEE isolation: DROM (W1)", "[exception]")
TEST_CASE("Test REE-TEE isolation: DROM-W1", "[exception]")
{
const uint32_t test_addr = ALIGN_DOWN_TO_MMU_PAGE_SIZE((uint32_t)&_instruction_reserved_start);
*(uint32_t *)(test_addr - 0x04) = 0xbadc0de;
TEST_FAIL_MESSAGE("Exception should have been generated");
}
/* SWDT/BOD Reset register */
TEST_CASE("Test REE-TEE isolation: SWDT/BOD (W)", "[exception]")
{
REG_WRITE(LP_ANALOG_PERI_LP_ANA_FIB_ENABLE_REG, 0);
TEST_FAIL_MESSAGE("Exception should have been generated");
}

View File

@@ -2,8 +2,6 @@
# SPDX-License-Identifier: Apache-2.0
import re
from enum import Enum
from typing import Dict
from typing import Tuple
import pytest
from pytest_embedded_idf import IdfDut
@@ -11,7 +9,7 @@ from pytest_embedded_idf.utils import idf_parametrize
# ---------------- Pytest build parameters ----------------
SUPPORTED_TARGETS = ['esp32c6', 'esp32h2']
SUPPORTED_TARGETS = ['esp32c6', 'esp32h2', 'esp32c5']
CONFIG_DEFAULT = [
# 'config, target, markers',
@@ -34,28 +32,27 @@ CONFIG_ALL = [
# ---------------- Exception test-cases reasons ----------------
TEE_VIOLATION_TEST_EXC_RSN: Dict[Tuple[str, str], str] = {
('Reserved', 'W1'): 'Store access fault',
('Reserved', 'X1'): 'Instruction access fault',
('IRAM', 'W1'): 'Store access fault',
('IRAM', 'W2'): 'Store access fault',
('DRAM', 'X1'): 'Instruction access fault',
('DRAM', 'X2'): 'Instruction access fault',
TEE_VIOLATION_TEST_EXC_RSN: dict[str, str] = {
('Reserved-W1'): 'Store access fault',
('Reserved-X1'): 'Instruction access fault',
('IRAM-W1'): 'Store access fault',
('IRAM-W2'): 'Store access fault',
('DRAM-X1'): 'Instruction access fault',
('DRAM-X2'): 'Instruction access fault',
}
REE_ISOLATION_TEST_EXC_RSN: Dict[Tuple[str, str], str] = {
('DRAM', 'R1'): 'Load access fault',
('DRAM', 'W1'): 'Store access fault',
('IRAM', 'R1'): 'Load access fault',
('IRAM', 'W1'): 'Store access fault',
('IROM', 'R1'): 'Load access fault',
('IROM', 'W1'): 'Store access fault',
('DROM', 'R1'): 'Load access fault',
('DROM', 'W1'): 'Store access fault',
('SWDT/BOD', 'W'): 'Store access fault',
REE_ISOLATION_TEST_EXC_RSN: dict[str, str] = {
('DRAM-R1'): 'Load access fault',
('DRAM-W1'): 'Store access fault',
('IRAM-R1'): 'Load access fault',
('IRAM-W1'): 'Store access fault',
('IROM-R1'): 'Load access fault',
('IROM-W1'): 'Store access fault',
('DROM-R1'): 'Load access fault',
('DROM-W1'): 'Store access fault',
}
TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR']
TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR', 'SWDT/BOD']
# ---------------- TEE default tests ----------------
@@ -118,10 +115,12 @@ def test_esp_tee_aes_perf(dut: IdfDut) -> None:
def test_esp_tee_apm_violation(dut: IdfDut) -> None:
for check in TEE_APM_VIOLATION_EXC_CHK:
dut.expect_exact('Press ENTER to see the list of tests')
dut.write(f'"Test APM violation interrupt: {check}"')
dut.write(f'"Test APM violation: {check}"')
exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode()
if dut.target == 'esp32h2' and check == 'eFuse':
if dut.target == 'esp32c5' or (dut.target == 'esp32h2' and check == 'eFuse'):
exp_str = 'APM - Space exception'
elif check == 'SWDT/BOD':
exp_str = 'Store access fault'
else:
exp_str = 'APM - Authority exception'
if exc != exp_str:
@@ -148,13 +147,12 @@ def test_esp_tee_illegal_instruction(dut: IdfDut) -> None:
)
def test_esp_tee_violation_checks(dut: IdfDut) -> None:
checks_list = TEE_VIOLATION_TEST_EXC_RSN
for test in checks_list:
memory, access_type = test
expected_exc = checks_list[test]
if expected_exc is None:
for test, expected_exc in checks_list.items():
if expected_exc is None or dut.target == 'esp32c5':
# TODO: Enable when TEE SRAM is partitioned as IRAM (RX) and DRAM (RW)
continue
dut.expect_exact('Press ENTER to see the list of tests')
dut.write(f'"Test TEE-TEE violation: {memory} ({access_type})"')
dut.write(f'"Test TEE-TEE violation: {test}"')
actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode()
if actual_exc != expected_exc:
raise RuntimeError('Incorrect exception received!')
@@ -167,13 +165,11 @@ def test_esp_tee_violation_checks(dut: IdfDut) -> None:
)
def test_esp_tee_isolation_checks(dut: IdfDut) -> None:
checks_list = REE_ISOLATION_TEST_EXC_RSN
for test in checks_list:
memory, access_type = test
expected_exc = checks_list[test]
for test, expected_exc in checks_list.items():
if expected_exc is None:
continue
dut.expect_exact('Press ENTER to see the list of tests')
dut.write(f'"Test REE-TEE isolation: {memory} ({access_type})"')
dut.write(f'"Test REE-TEE isolation: {test}"')
actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode()
if actual_exc != expected_exc:
raise RuntimeError('Incorrect exception received!')
@@ -215,6 +211,8 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl
flash_enc_enabled = dut.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True)
SOC_TEE_FLASH_OP_FAIL_FAULT = ['esp32c6', 'esp32h2']
for stage in range(1, stages + 1):
dut.write(str(test_case_num))
dut.expect(r'\s+\((\d+)\)\s+"([^"]+)"\r?\n', timeout=30)
@@ -222,7 +220,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl
if stage > 1:
if api in {TeeFlashAccessApi.ESP_PARTITION_MMAP, TeeFlashAccessApi.SPI_FLASH_MMAP}:
if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT:
expect_panic_rsn(dut, 'Cache error')
else:
dut.expect(r'\[_ss_mmu_hal_map_region] Illegal flash access at\s+\S+\s*\|\s*\S+', timeout=10)
elif api in {TeeFlashAccessApi.ESP_PARTITION, TeeFlashAccessApi.ESP_FLASH}:
op_index = stage - 2
curr_op = expected_ops[api][op_index]
@@ -230,7 +231,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl
# NOTE: The esp_partition_read API handles both decrypted
# and plaintext reads. When flash encryption is enabled,
# it uses the MMU HAL instead of the SPI flash HAL.
if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT:
expect_panic_rsn(dut, 'Cache error')
else:
dut.expect(r'\[_ss_mmu_hal_map_region] Illegal flash access at\s+\S+\s*\|\s*\S+', timeout=10)
else:
match = dut.expect(
r'\[_ss_spi_flash_hal_(\w+)\] Illegal flash access at \s*(0x[0-9a-fA-F]+)', timeout=10
@@ -239,7 +243,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl
if not re.fullmatch(curr_op, actual_op):
raise RuntimeError(f'Unexpected flash operation: {actual_op} (expected: {curr_op})')
elif api == TeeFlashAccessApi.ESP_ROM_SPIFLASH:
if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT:
expect_panic_rsn(dut, 'APM - Authority exception')
else:
expect_panic_rsn(dut, 'APM - Space exception')
if stage != stages:
dut.expect_exact('Press ENTER to see the list of tests.')
@@ -340,7 +347,7 @@ def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None:
@pytest.mark.generic
@idf_parametrize('config', ['ota'], indirect=['config'])
@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target'])
@idf_parametrize('target', SUPPORTED_TARGETS, indirect=['target'])
def test_esp_tee_ota_negative(dut: IdfDut) -> None:
# start test
dut.expect_exact('Press ENTER to see the list of tests')
@@ -474,8 +481,8 @@ def test_esp_tee_ota_rollback(dut: IdfDut) -> None:
dut.expect('TEE otadata - Current image state: NEW', timeout=10)
dut.expect('Loaded TEE app from partition at offset 0x40000', timeout=10)
rst_rsn = dut.expect(r'rst:(0x[0-9A-Fa-f]+) \(([^)]+)\)', timeout=30).group(2).decode()
# NOTE: LP_WDT_SYS is for ESP32-C6 case as bootloader fails to load the dummy TEE app
if rst_rsn != 'LP_WDT_SYS':
# NOTE: LP_WDT_SYS (C6/H2) and RTC_WDT_SYS (C5) are expected as bootloader fails to load the dummy TEE app
if rst_rsn not in {'LP_WDT_SYS', 'RTC_WDT_SYS'}:
raise RuntimeError('Incorrect reset reason observed after TEE image failure!')
# after rollback

View File

@@ -9,6 +9,7 @@ CONFIG_SECURE_TEE_TEST_MODE=y
# Setting partition table
CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y
CONFIG_PARTITION_TABLE_OFFSET=0xF000
# TEE IRAM size
CONFIG_SECURE_TEE_IRAM_SIZE=0x8400

View File

@@ -131,7 +131,15 @@ esp_err_t spi_flash_hal_configure_host_io_mode(
addr_bitlen += SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS;
#endif
spi_flash_ll_set_extra_address(dev, 0);
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
// TODO: [IDF-13582]
// Currently, REE and TEE use different sets of APIs for flash operations -
// REE uses the IDF SPI flash driver while TEE call the ROM APIs. This inconsistency
// leads to compatibility issues on ESP32-C5.
// One specific issue arises when esp_flash_read() is used in REE, which internally
// calls spi_flash_ll_wb_mode_enable(). This function enables the WB mode bit in
// the flash write operation. However, the ROM API does not support this
// feature, resulting in failures when TEE attempts to access flash after this call.
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE
spi_flash_ll_wb_mode_enable(dev, true);
#endif
}
@@ -208,7 +216,8 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr
if (trans->miso_len > 0) {
spi_flash_ll_get_buffer_data(dev, trans->miso_data, trans->miso_len);
}
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
// TODO: [IDF-13582]
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE
spi_flash_ll_wb_mode_enable(dev, false);
#endif
return ESP_OK;

View File

@@ -22,10 +22,6 @@
#include "sdkconfig.h"
#define UTVT_CSR (0x007)
#define UINTSTATUS_CSR (0xCB1)
#define UINTTHRESH_CSR (0x047)
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -22,10 +22,6 @@
#include "sdkconfig.h"
#define UTVT_CSR (0x007)
#define UINTSTATUS_CSR (0xCB1)
#define UINTTHRESH_CSR (0x047)
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,6 +12,11 @@
#include "heap_memory_layout.h"
#include "esp_heap_caps.h"
#if CONFIG_SECURE_ENABLE_TEE
#define SRAM_DIRAM_TEE_ORG (SOC_DIRAM_IRAM_LOW)
#define SRAM_DIRAM_TEE_END (SRAM_DIRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE)
#endif
/**
* @brief Memory type descriptors. These describe the capabilities of a type of memory in the SoC.
* Each type of memory map consists of one or more regions in the address space.
@@ -97,6 +102,14 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_d
// Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips
SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);
/* NOTE: When ESP-TEE is enabled, the start of the internal SRAM
* is used by the TEE and is protected from any REE access using
* memory protection mechanisms employed by ESP-TEE.
*/
#if CONFIG_SECURE_ENABLE_TEE
SOC_RESERVE_MEMORY_REGION((intptr_t)SRAM_DIRAM_TEE_ORG, (intptr_t)(SRAM_DIRAM_TEE_END), tee_diram);
#endif
#ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data);
#endif

View File

@@ -10,15 +10,10 @@
#include "mbedtls/aes.h"
#include "esp_crypto_dma.h"
#include "hal/clk_gate_ll.h"
#include "hal/gdma_ll.h"
#include "hal/gdma_types.h"
#include "hal/aes_hal.h"
#include "soc/lldesc.h"
#include "soc/periph_defs.h"
#include "soc/gdma_channel.h"
#include "soc/gdma_struct.h"
#include "soc/soc_caps.h"
#include "esp_tee_crypto_shared_gdma.h"
@@ -27,6 +22,38 @@
#define TEE_CRYPTO_GDMA_CH (0)
#if SOC_AHB_GDMA_VERSION == 2
#include "hal/ahb_dma_ll.h"
#include "soc/ahb_dma_struct.h"
#define DMA_DEV (AHB_DMA)
#define DMA_LL_FUNC(func) ahb_dma_ll_##func
#elif SOC_AHB_GDMA_VERSION == 1
#include "hal/gdma_ll.h"
#include "soc/gdma_struct.h"
#define DMA_DEV (GDMA)
#define DMA_LL_FUNC(func) gdma_ll_##func
#endif
#define dma_ll_force_enable_reg_clock DMA_LL_FUNC(force_enable_reg_clock)
#define dma_ll_tx_enable_data_burst DMA_LL_FUNC(tx_enable_data_burst)
#define dma_ll_tx_enable_descriptor_burst DMA_LL_FUNC(tx_enable_descriptor_burst)
#define dma_ll_rx_enable_data_burst DMA_LL_FUNC(rx_enable_data_burst)
#define dma_ll_rx_enable_descriptor_burst DMA_LL_FUNC(rx_enable_descriptor_burst)
#define dma_ll_tx_reset_channel DMA_LL_FUNC(tx_reset_channel)
#define dma_ll_tx_connect_to_periph DMA_LL_FUNC(tx_connect_to_periph)
#define dma_ll_rx_reset_channel DMA_LL_FUNC(rx_reset_channel)
#define dma_ll_rx_connect_to_periph DMA_LL_FUNC(rx_connect_to_periph)
#define dma_ll_tx_disconnect_from_periph DMA_LL_FUNC(tx_disconnect_from_periph)
#define dma_ll_rx_disconnect_from_periph DMA_LL_FUNC(rx_disconnect_from_periph)
#define dma_ll_tx_set_desc_addr DMA_LL_FUNC(tx_set_desc_addr)
#define dma_ll_tx_start DMA_LL_FUNC(tx_start)
#define dma_ll_rx_set_desc_addr DMA_LL_FUNC(rx_set_desc_addr)
#define dma_ll_rx_start DMA_LL_FUNC(rx_start)
#define dma_ll_tx_stop DMA_LL_FUNC(tx_stop)
#define dma_ll_rx_stop DMA_LL_FUNC(rx_stop)
#define dma_ll_tx_set_priority DMA_LL_FUNC(tx_set_priority)
#define dma_ll_rx_set_priority DMA_LL_FUNC(rx_set_priority)
/*
* NOTE: [ESP-TEE] This is a low-level (LL), non-OS version of
* port/crypto_shared_gdma/esp_crypto_shared_gdma.c that defines
@@ -37,30 +64,23 @@
static void crypto_shared_gdma_init(void)
{
// enable APB to access GDMA registers
periph_ll_enable_clk_clear_rst(PERIPH_GDMA_MODULE);
// enable gdma clock
gdma_ll_force_enable_reg_clock(&GDMA, true);
gdma_ll_enable_bus_clock(0, true);
gdma_ll_reset_register(0);
dma_ll_force_enable_reg_clock(&DMA_DEV, true);
// setting the transfer ability
gdma_ll_tx_enable_data_burst(&GDMA, TEE_CRYPTO_GDMA_CH, true);
gdma_ll_tx_enable_descriptor_burst(&GDMA, TEE_CRYPTO_GDMA_CH, true);
dma_ll_tx_enable_data_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, true);
dma_ll_tx_enable_descriptor_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, true);
gdma_ll_rx_enable_data_burst(&GDMA, TEE_CRYPTO_GDMA_CH, false);
gdma_ll_rx_enable_descriptor_burst(&GDMA, TEE_CRYPTO_GDMA_CH, true);
dma_ll_rx_enable_data_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, false);
dma_ll_rx_enable_descriptor_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, true);
#if SOC_GDMA_SUPPORT_PSRAM
gdma_ll_tx_set_block_size_psram(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_LL_EXT_MEM_BK_SIZE_16B);
gdma_ll_rx_set_block_size_psram(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_LL_EXT_MEM_BK_SIZE_16B);
#endif // SOC_GDMA_SUPPORT_PSRAM
gdma_ll_tx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH);
gdma_ll_tx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0);
gdma_ll_rx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH);
gdma_ll_rx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0);
dma_ll_tx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
dma_ll_tx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0);
dma_ll_rx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
dma_ll_rx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0);
}
esp_err_t esp_tee_crypto_shared_gdma_start(const crypto_dma_desc_t *input, const crypto_dma_desc_t *output, gdma_trigger_peripheral_t periph)
@@ -76,40 +96,39 @@ esp_err_t esp_tee_crypto_shared_gdma_start(const crypto_dma_desc_t *input, const
crypto_shared_gdma_init();
gdma_ll_tx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH);
gdma_ll_rx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH);
dma_ll_tx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
dma_ll_rx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
gdma_ll_tx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH);
gdma_ll_tx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id);
dma_ll_tx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
dma_ll_tx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id);
gdma_ll_rx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH);
gdma_ll_rx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id);
dma_ll_rx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
dma_ll_rx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id);
gdma_ll_tx_set_desc_addr(&GDMA, TEE_CRYPTO_GDMA_CH, (intptr_t)input);
gdma_ll_tx_start(&GDMA, TEE_CRYPTO_GDMA_CH);
dma_ll_tx_set_desc_addr(&DMA_DEV, TEE_CRYPTO_GDMA_CH, (intptr_t)input);
dma_ll_tx_start(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
gdma_ll_rx_set_desc_addr(&GDMA, TEE_CRYPTO_GDMA_CH, (intptr_t)output);
gdma_ll_rx_start(&GDMA, TEE_CRYPTO_GDMA_CH);
dma_ll_rx_set_desc_addr(&DMA_DEV, TEE_CRYPTO_GDMA_CH, (intptr_t)output);
dma_ll_rx_start(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
return ESP_OK;
}
void esp_tee_crypto_shared_gdma_free(void)
{
gdma_ll_tx_stop(&GDMA, TEE_CRYPTO_GDMA_CH);
gdma_ll_rx_stop(&GDMA, TEE_CRYPTO_GDMA_CH);
dma_ll_tx_stop(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
dma_ll_rx_stop(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
gdma_ll_tx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH);
gdma_ll_rx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH);
dma_ll_tx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
dma_ll_rx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH);
gdma_ll_tx_set_priority(&GDMA, TEE_CRYPTO_GDMA_CH, 0);
gdma_ll_rx_set_priority(&GDMA, TEE_CRYPTO_GDMA_CH, 0);
dma_ll_tx_set_priority(&DMA_DEV, TEE_CRYPTO_GDMA_CH, 0);
dma_ll_rx_set_priority(&DMA_DEV, TEE_CRYPTO_GDMA_CH, 0);
// disable gdma clock
gdma_ll_force_enable_reg_clock(&GDMA, false);
// disable APB for GDMA registers
periph_ll_disable_clk_set_rst(PERIPH_GDMA_MODULE);
gdma_ll_enable_bus_clock(0, false);
gdma_ll_reset_register(0);
dma_ll_force_enable_reg_clock(&DMA_DEV, false);
}
/* ---------------------------------------------- DMA Implementations: AES ------------------------------------------------- */

View File

@@ -22,6 +22,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#ifndef ESP_TEE_MBEDTLS_CONFIG_H
@@ -50,13 +51,24 @@
#define MBEDTLS_ECP_C
#define MBEDTLS_ECDSA_C
#if CONFIG_MBEDTLS_SHA1_C
#define MBEDTLS_SHA1_C
#endif
#define MBEDTLS_SHA224_C
#define MBEDTLS_SHA256_C
#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C
#define MBEDTLS_SHA384_C
#define MBEDTLS_SHA512_C
#endif
#if CONFIG_MBEDTLS_HARDWARE_SHA
#if CONFIG_MBEDTLS_SHA1_C
#define MBEDTLS_SHA1_ALT
#endif
#define MBEDTLS_SHA256_ALT
#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C
#define MBEDTLS_SHA512_ALT
#endif
#endif
#ifdef CONFIG_MBEDTLS_HARDWARE_ECC

View File

@@ -15,6 +15,8 @@ elseif(esp_tee_build)
set(srcs "rv_utils.c")
if(CONFIG_SOC_INT_PLIC_SUPPORTED)
list(APPEND srcs "interrupt_plic.c")
elseif(CONFIG_SOC_INT_CLIC_SUPPORTED)
list(APPEND srcs "interrupt_clic.c")
endif()
else()
set(priv_requires soc hal)

View File

@@ -44,6 +44,7 @@ extern "C" {
* @brief CSR to set the interrupt jump table address is MTVT.
*/
#define MTVT_CSR 0x307
#define UTVT_CSR 0x007
#if CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V2
@@ -61,7 +62,9 @@ extern "C" {
/* The ESP32-C5 (MP), C61, H4 and P4 (since REV2) use the standard CLIC specification, for example, it defines the mintthresh CSR */
#define INTTHRESH_STANDARD 1
#define MINTSTATUS_CSR 0xFB1
#define UINTSTATUS_CSR 0xCB1
#define MINTTHRESH_CSR 0x347
#define UINTTHRESH_CSR 0x047
#else
#error "Check the implementation of the CLIC on this target."
@@ -114,7 +117,11 @@ extern "C" {
#define RVHAL_INTR_ENABLE_THRESH_CLIC (CLIC_INT_THRESH(RVHAL_INTR_ENABLE_THRESH))
#if CONFIG_SECURE_ENABLE_TEE
#define IS_PRV_M_MODE() (RV_READ_CSR(CSR_PRV_MODE) == PRV_M)
#else
#define IS_PRV_M_MODE() (1UL)
#endif
FORCE_INLINE_ATTR void assert_valid_rv_int_num(int rv_int_num)
@@ -132,7 +139,12 @@ FORCE_INLINE_ATTR void assert_valid_rv_int_num(int rv_int_num)
FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_threshold(void)
{
#if INTTHRESH_STANDARD
uint32_t threshold = RV_READ_CSR(MINTTHRESH_CSR);
uint32_t threshold;
if (IS_PRV_M_MODE()) {
threshold = RV_READ_CSR(MINTTHRESH_CSR);
} else {
threshold = RV_READ_CSR(UINTTHRESH_CSR);
}
#else
uint32_t threshold = REG_READ(CLIC_INT_THRESH_REG);
#endif
@@ -148,6 +160,19 @@ FORCE_INLINE_ATTR void rv_utils_set_mtvt(uint32_t mtvt_val)
RV_WRITE_CSR(MTVT_CSR, mtvt_val);
}
/**
* @brief Set the XTVT CSR value (based on the current privilege mode),
* used as a base address for the interrupt jump table
*/
FORCE_INLINE_ATTR void rv_utils_set_xtvt(uint32_t xtvt_val)
{
if (IS_PRV_M_MODE()) {
RV_WRITE_CSR(MTVT_CSR, xtvt_val);
} else {
RV_WRITE_CSR(UTVT_CSR, xtvt_val);
}
}
#if SOC_CPU_SUPPORT_WFE
/**
* @brief Set the MEXSTATUS_WFFEN value, used to enable/disable wait for event mode.
@@ -167,7 +192,11 @@ FORCE_INLINE_ATTR void rv_utils_wfe_mode_enable(bool en)
*/
FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level_regval(void)
{
if (IS_PRV_M_MODE()) {
return RV_READ_CSR(MINTSTATUS_CSR);
} else {
return RV_READ_CSR(UINTSTATUS_CSR);
}
}
/**
@@ -175,9 +204,14 @@ FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level_regval(void)
*/
FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level(void)
{
const uint32_t mintstatus = RV_READ_CSR(MINTSTATUS_CSR);
uint32_t xintstatus;
if (IS_PRV_M_MODE()) {
xintstatus = RV_READ_CSR(MINTSTATUS_CSR);
} else {
xintstatus = RV_READ_CSR(UINTSTATUS_CSR);
}
/* Extract the level from this field */
return CLIC_STATUS_TO_INT(mintstatus);
return CLIC_STATUS_TO_INT(xintstatus);
}
/**
@@ -190,7 +224,11 @@ FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level(void)
FORCE_INLINE_ATTR void rv_utils_restore_intlevel_regval(uint32_t restoreval)
{
#if INTTHRESH_STANDARD
if (IS_PRV_M_MODE()) {
RV_WRITE_CSR(MINTTHRESH_CSR, restoreval);
} else {
RV_WRITE_CSR(UINTTHRESH_CSR, restoreval);
}
#else
REG_WRITE(CLIC_INT_THRESH_REG, restoreval);
/**
@@ -224,7 +262,11 @@ FORCE_INLINE_ATTR void rv_utils_restore_intlevel(uint32_t restoreval)
FORCE_INLINE_ATTR uint32_t rv_utils_set_intlevel_regval(uint32_t intlevel)
{
#if INTTHRESH_STANDARD
if (IS_PRV_M_MODE()) {
return RV_SWAP_CSR(MINTTHRESH_CSR, intlevel);
} else {
return RV_SWAP_CSR(UINTTHRESH_CSR, intlevel);
}
#else // !INTTHRESH_STANDARD
uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
uint32_t old_thresh = REG_READ(CLIC_INT_THRESH_REG);

View File

@@ -149,7 +149,7 @@ void esprv_int_set_vectored(int rv_int_num, bool vectored);
/*************************** ESP-TEE specific ***************************/
/** Function prototype executing interrupt configuration APIs as service calls */
typedef void (*esprv_int_mgmt_t)(int argc, ...);
typedef uint32_t (*esprv_int_mgmt_t)(int argc, ...);
/**
* @brief Setup the callback function which executes the interrupt

View File

@@ -118,7 +118,11 @@ FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_get_cycle_cou
FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_set_cycle_count(uint32_t ccount)
{
#if !SOC_CPU_HAS_CSR_PC
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_SET_CYCLE_COUNT, ccount);
#else
RV_WRITE_CSR(mcycle, ccount);
#endif
#else
if (IS_PRV_M_MODE()) {
RV_WRITE_CSR(CSR_PCCR_MACHINE, ccount);
@@ -481,12 +485,20 @@ FORCE_INLINE_ATTR bool rv_utils_compare_and_set(volatile uint32_t *addr, uint32_
#if SOC_BRANCH_PREDICTOR_SUPPORTED
FORCE_INLINE_ATTR void rv_utils_en_branch_predictor(void)
{
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(1, SS_RV_UTILS_EN_BRANCH_PREDICTOR);
#else
RV_SET_CSR(MHCR, MHCR_RS|MHCR_BFE|MHCR_BTB);
#endif
}
FORCE_INLINE_ATTR void rv_utils_dis_branch_predictor(void)
{
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(1, SS_RV_UTILS_DIS_BRANCH_PREDICTOR);
#else
RV_CLEAR_CSR(MHCR, MHCR_RS|MHCR_BFE|MHCR_BTB);
#endif
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -40,3 +40,44 @@ void esprv_int_set_vectored(int rv_int_num, bool vectored)
{
interrupt_clic_ll_set_vectored(rv_int_num + RV_EXTERNAL_INT_OFFSET, vectored);
}
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
DRAM_ATTR esprv_int_mgmt_t esp_tee_intr_sec_srv_cb = NULL;
void esprv_int_setup_mgmt_cb(void *fptr)
{
esp_tee_intr_sec_srv_cb = (esprv_int_mgmt_t)fptr;
}
/* NOTE: Overriding ROM-based interrupt configuration symbols */
void esprv_int_enable(uint32_t unmask)
{
rv_utils_intr_enable(unmask);
}
void esprv_int_disable(uint32_t mask)
{
rv_utils_intr_disable(mask);
}
void esprv_int_set_type(int intr_num, enum intr_type type)
{
rv_utils_intr_set_type(intr_num, type);
}
void esprv_int_set_priority(int rv_int_num, int priority)
{
rv_utils_intr_set_priority(rv_int_num, priority);
}
void esprv_int_set_threshold(int priority_threshold)
{
rv_utils_intr_set_threshold(priority_threshold);
}
#endif

View File

@@ -17,6 +17,8 @@
.equ EXC_ILLEGAL_INSTRUCTION, 0x2
.equ panic_from_exception, xt_unhandled_exception
.equ panic_from_isr, panicHandler
.equ CSR_UINTSTATUS, 0xCB1
.equ CSR_UINTTHRESH, 0x047
#if ( SOC_CPU_COPROC_NUM > 0 )
/* Targets with coprocessors present a special CSR to get Illegal Instruction exception reason */
@@ -90,8 +92,11 @@
sw t0, RV_STK_MSTATUS(sp)
csrr t0, utvec
sw t0, RV_STK_MTVEC(sp)
/* NOTE: C6 and H2 possess the utval CSR, but rest of the SoCs don't */
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
csrr t0, utval
sw t0, RV_STK_MTVAL(sp)
#endif
#else
csrr t0, mstatus
sw t0, RV_STK_MSTATUS(sp)
@@ -467,6 +472,24 @@ _tee_interrupt_handler:
li t0, INTERRUPT_CURRENT_CORE_INT_THRESH_REG
sw s3, 0(t0)
fence
#elif CONFIG_SECURE_ENABLE_TEE
/* Restore the U-mode interrupt threshold level.
*
* If uintstatus == 0, it means we have returned here after servicing a
* U-mode interrupt that was delegated via M-mode. In this case, we should
* reset the threshold to the minimum valid level.
*
* If uintstatus != 0, we are currently handling a U-mode interrupt that
* either originated directly in U-mode or is a nested U-mode interrupt.
* In this case, the threshold must be retained, so we skip the reset.
*/
csrr t0, CSR_UINTSTATUS
bnez t0, _skip_thresh_reset
csrr t0, CSR_UINTTHRESH
li t1, (1 << (8 - NLBITS) - 1)
beq t0, t1, _skip_thresh_reset
csrw CSR_UINTTHRESH, t1
_skip_thresh_reset:
#endif // !SOC_INT_HW_NESTED_SUPPORTED
/* The RTOS will restore the current TCB stack pointer. This routine will preserve s1 and s2.

View File

@@ -5,7 +5,6 @@
*/
#pragma once
#include <stdint.h>
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {