diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index c235ab098e..9904fbbc3f 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -136,7 +136,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) #if ESP_TEE_BUILD #include "esp_fault.h" #include "esp_flash_partitions.h" -#include "esp32c6/rom/spi_flash.h" +#include "rom/spi_flash.h" extern bool esp_tee_flash_check_paddr_in_active_tee_part(size_t paddr); #endif diff --git a/components/esp_hw_support/port/esp32h2/CMakeLists.txt b/components/esp_hw_support/port/esp32h2/CMakeLists.txt index 408601655e..0be7eb5dd9 100644 --- a/components/esp_hw_support/port/esp32h2/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h2/CMakeLists.txt @@ -1,3 +1,5 @@ +idf_build_get_property(non_os_build NON_OS_BUILD) + set(srcs "rtc_clk_init.c" "rtc_clk.c" "pmu_param.c" @@ -7,7 +9,7 @@ set(srcs "rtc_clk_init.c" "chip_info.c" ) -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) list(APPEND srcs "sar_periph_ctrl.c") endif() diff --git a/components/esp_hw_support/port/esp32h2/cpu_region_protect.c b/components/esp_hw_support/port/esp32h2/cpu_region_protect.c index b60dc95d4a..338f421378 100644 --- a/components/esp_hw_support/port/esp32h2/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32h2/cpu_region_protect.c @@ -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 */ @@ -112,6 +112,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 // diff --git a/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c b/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c index ca63df5141..bace035293 100644 --- a/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c +++ b/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c @@ -6,6 +6,7 @@ #include "esp_cpu.h" #include "esp_riscv_intr.h" +#include "sdkconfig.h" void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_desc_ret) { @@ -15,7 +16,18 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_ * Interrupts 3, 4 and 7 are unavailable for PULP CPU as they are bound to Core-Local Interrupts (CLINT) */ // [TODO: IDF-2465] - const uint32_t rsvd_mask = BIT(3) | BIT(4) | BIT(6) | BIT(7); + 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 + * 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); +#else + const uint32_t rsvd_mask = base_rsvd_mask; +#endif + intr_desc_ret->priority = 1; intr_desc_ret->type = ESP_CPU_INTR_TYPE_NA; diff --git a/components/esp_mm/port/esp32h2/ext_mem_layout.c b/components/esp_mm/port/esp32h2/ext_mem_layout.c index 9c0004bfdd..64f38a2a4a 100644 --- a/components/esp_mm/port/esp32h2/ext_mem_layout.c +++ b/components/esp_mm/port/esp32h2/ext_mem_layout.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,15 +10,40 @@ #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 */ 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, .caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT, diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index ad638e1b1c..1d8c7f1612 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -131,10 +131,8 @@ if(CONFIG_ESP_ROM_HAS_VERSION) endif() if(ESP_TEE_BUILD) - if(target STREQUAL "esp32c6") - rom_linker_script("spiflash") - rom_linker_script("heap") - endif() + rom_linker_script("spiflash") + rom_linker_script("heap") endif() if(BOOTLOADER_BUILD) diff --git a/components/esp_system/ld/esp32h2/memory.ld.in b/components/esp_system/ld/esp32h2/memory.ld.in index 27bb9091cf..ba1e5d9960 100644 --- a/components/esp_system/ld/esp32h2/memory.ld.in +++ b/components/esp_system/ld/esp32h2/memory.ld.in @@ -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 0x4083EFD0 /* 2nd stage bootloader iram_loader_seg start address */ #define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START @@ -35,8 +41,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. @@ -54,8 +66,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 diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index 34fa0ea8cf..be973ed63c 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -173,9 +173,22 @@ SECTIONS /* 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 0x300 from the vector table start. + */ +#if CONFIG_SECURE_ENABLE_TEE + ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg) + ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2e0, "esp_tee_app_cfg must be at an offset 0x2e0 from the vector table start"); + *libesp_tee.a:(.esp_tee_app_cfg); +#endif + /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); diff --git a/components/esp_system/port/soc/esp32h2/clk.c b/components/esp_system/port/soc/esp32h2/clk.c index ac7760a223..4289dbeb3f 100644 --- a/components/esp_system/port/soc/esp32h2/clk.c +++ b/components/esp_system/port/soc/esp32h2/clk.c @@ -277,11 +277,14 @@ __attribute__((weak)) void esp_perip_clk_init(void) periph_ll_disable_clk_set_rst(PERIPH_ASSIST_DEBUG_MODULE); #endif periph_ll_disable_clk_set_rst(PERIPH_RSA_MODULE); +#if !CONFIG_SECURE_ENABLE_TEE + // NOTE: [ESP-TEE] The TEE is responsible for the AES and SHA peripherals periph_ll_disable_clk_set_rst(PERIPH_AES_MODULE); periph_ll_disable_clk_set_rst(PERIPH_SHA_MODULE); periph_ll_disable_clk_set_rst(PERIPH_ECC_MODULE); periph_ll_disable_clk_set_rst(PERIPH_HMAC_MODULE); periph_ll_disable_clk_set_rst(PERIPH_DS_MODULE); +#endif periph_ll_disable_clk_set_rst(PERIPH_ECDSA_MODULE); // TODO: Replace with hal implementation diff --git a/components/esp_tee/CMakeLists.txt b/components/esp_tee/CMakeLists.txt index 2da9c5904f..21a70d6b8c 100644 --- a/components/esp_tee/CMakeLists.txt +++ b/components/esp_tee/CMakeLists.txt @@ -6,8 +6,8 @@ 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 SoC -if(NOT ${target} STREQUAL "esp32c6") +# ESP-TEE is currently supported only on the ESP32-C6 and ESP32-H2 SoCs +if(NOT ${target} STREQUAL "esp32c6" AND NOT ${target} STREQUAL "esp32h2") return() endif() diff --git a/components/esp_tee/Kconfig.projbuild b/components/esp_tee/Kconfig.projbuild index 155333f9bd..d443156412 100644 --- a/components/esp_tee/Kconfig.projbuild +++ b/components/esp_tee/Kconfig.projbuild @@ -1,9 +1,8 @@ menu "ESP-TEE (Trusted Execution Environment)" - depends on IDF_TARGET_ESP32C6 + depends on IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 config SECURE_ENABLE_TEE bool "Enable the ESP-TEE framework" - depends on IDF_TARGET_ESP32C6 select ESP_SYSTEM_MEMPROT_FEATURE_VIA_TEE help This configuration enables the Trusted Execution Environment (TEE) feature. @@ -75,7 +74,6 @@ menu "ESP-TEE (Trusted Execution Environment)" Secure storage will be encrypted by a constant key embedded in the TEE firmware config SECURE_TEE_SEC_STG_MODE_RELEASE - depends on IDF_TARGET_ESP32C6 bool "Release" help Secure storage will be encrypted by the data stored in eFuse block diff --git a/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml new file mode 100644 index 0000000000..f70e9b1434 --- /dev/null +++ b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml @@ -0,0 +1,296 @@ +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-21 (17) - External memory (Flash) protection [SPI1] + - family: flash_protection_spi1 + entries: + - id: 5 + type: IDF + function: spi_flash_hal_check_status + args: 1 + - id: 6 + type: IDF + function: spi_flash_hal_common_command + args: 2 + - id: 7 + type: IDF + function: spi_flash_hal_device_config + args: 1 + - id: 8 + type: IDF + function: spi_flash_hal_erase_block + args: 2 + - id: 9 + type: IDF + function: spi_flash_hal_erase_chip + args: 1 + - id: 10 + type: IDF + function: spi_flash_hal_erase_sector + args: 2 + - id: 11 + type: IDF + function: spi_flash_hal_program_page + args: 4 + - id: 12 + type: IDF + function: spi_flash_hal_read + args: 4 + - id: 13 + type: IDF + function: spi_flash_hal_resume + args: 1 + - id: 14 + type: IDF + function: spi_flash_hal_set_write_protect + args: 2 + - id: 15 + type: IDF + function: spi_flash_hal_setup_read_suspend + args: 2 + - id: 16 + type: IDF + function: spi_flash_hal_supports_direct_read + args: 2 + - id: 17 + type: IDF + function: spi_flash_hal_supports_direct_write + args: 2 + - id: 18 + type: IDF + function: spi_flash_hal_suspend + args: 1 + - id: 19 + type: IDF + function: bootloader_flash_execute_command_common + args: 7 + - id: 20 + type: IDF + function: memspi_host_flush_cache + args: 3 + - id: 21 + 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: 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: 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 diff --git a/components/esp_tee/src/esp_secure_service_wrapper.c b/components/esp_tee/src/esp_secure_service_wrapper.c index 35039c7134..89ae362d5f 100644 --- a/components/esp_tee/src/esp_secure_service_wrapper.c +++ b/components/esp_tee/src/esp_secure_service_wrapper.c @@ -331,6 +331,13 @@ int __wrap_esp_ecc_point_verify(const ecc_point_t *point) return err; } +#if SOC_ECDSA_SUPPORTED +void __wrap_esp_crypto_ecc_enable_periph_clk(bool enable) +{ + esp_tee_service_call(2, SS_ESP_CRYPTO_ECC_ENABLE_PERIPH_CLK, enable); +} +#endif + /* ---------------------------------------------- MMU HAL ------------------------------------------------- */ void IRAM_ATTR __wrap_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr, uint32_t paddr, uint32_t len, uint32_t *out_len) diff --git a/components/esp_tee/subproject/main/CMakeLists.txt b/components/esp_tee/subproject/main/CMakeLists.txt index 3d6ad4399f..9127646233 100644 --- a/components/esp_tee/subproject/main/CMakeLists.txt +++ b/components/esp_tee/subproject/main/CMakeLists.txt @@ -20,9 +20,10 @@ list(APPEND srcs "arch/${arch}/esp_tee_vectors.S" # SoC specific implementation for TEE list(APPEND srcs "soc/${target}/esp_tee_secure_sys_cfg.c" "soc/${target}/esp_tee_pmp_pma_prot_cfg.c" - "soc/${target}/esp_tee_apm_prot_cfg.c" - "soc/${target}/esp_tee_apm_intr.c" - "soc/${target}/esp_tee_aes_intr.c") + "soc/${target}/esp_tee_apm_prot_cfg.c") + +list(APPEND srcs "soc/common/esp_tee_apm_intr.c" + "soc/common/esp_tee_aes_intr.c") # Common module implementation for TEE @@ -35,6 +36,7 @@ list(APPEND srcs "common/brownout.c") list(APPEND include "include" "common" + "soc/common/include" "soc/${target}/include") # Heap @@ -52,6 +54,12 @@ list(APPEND srcs "common/syscall_stubs.c") idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${include}) +# NOTE: The ESP32-H2 ROM does not have sprintf/snprintf implementation, +# thus newlib-nano implementation from the toolchain has been used. +if(CONFIG_IDF_TARGET_ESP32H2) + target_link_libraries(${COMPONENT_LIB} INTERFACE "--specs=nano.specs") +endif() + # TODO: Currently only -Og optimization level works correctly at runtime set_source_files_properties("core/esp_secure_dispatcher.c" PROPERTIES COMPILE_FLAGS "-Og") diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S index 2028bec395..bc797366a6 100644 --- a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S @@ -7,14 +7,12 @@ #include "soc/soc.h" #include "soc/soc_caps.h" -#include "soc/interrupt_reg.h" -#include "soc/interrupt_matrix_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 @@ -25,13 +23,10 @@ .equ RTNVAL, 0xc0de .equ ECALL_U_MODE, 0x8 .equ ECALL_M_MODE, 0xb - .equ TEE_APM_INTR_MASK_0, 0x00300000 - .equ TEE_APM_INTR_MASK_1, 0x000000f8 .equ TEE_INTR_DELEG_MASK, 0xffffbfff .global esp_tee_global_interrupt_handler - .global esp_tee_service_dispatcher - + .global esp_tee_service_dispatcher .section .data .align 4 @@ -441,22 +436,24 @@ _tee_s_intr_handler: /* Check if the interrupt source is related to an APM exception */ /* Define the addresses of the registers */ - li t0, INTMTX_CORE0_INT_STATUS_REG_0_REG + li t0, INTMTX_STATUS_REG_0 /* Load the values from the registers */ lw t1, 0(t0) /* Define the masks */ - li t2, TEE_APM_INTR_MASK_0 + 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 +#if CONFIG_IDF_TARGET_ESP32C6 /* Repeat for the other status register */ - li t0, INTMTX_CORE0_INT_STATUS_REG_1_REG + li t0, INTMTX_STATUS_REG_1 lw t1, 0(t0) - li t2, TEE_APM_INTR_MASK_1 + li t2, TEE_SECURE_INT_APM_MASK_1 and t1, t1, t2 bnez t1, _save_reg_ctx +#endif /* Continue normal execution */ j _continue @@ -464,6 +461,11 @@ _tee_s_intr_handler: _save_reg_ctx: /* Save CSR context here */ save_mcsr + csrr t0, mcause + sw t0, RV_STK_MCAUSE(sp) + /* 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: diff --git a/components/esp_tee/subproject/main/common/multi_heap.c b/components/esp_tee/subproject/main/common/multi_heap.c index 7e45c6f617..985bbfde47 100644 --- a/components/esp_tee/subproject/main/common/multi_heap.c +++ b/components/esp_tee/subproject/main/common/multi_heap.c @@ -6,6 +6,7 @@ #include #include #include "esp_rom_tlsf.h" +#include "esp_rom_sys.h" #include "tlsf_block_functions.h" #include "multi_heap.h" @@ -153,15 +154,15 @@ size_t esp_tee_heap_get_min_free_size(void) static void heap_dump_tlsf(void* ptr, size_t size, int used, void* user) { (void)user; - printf("Block %p data, size: %d bytes, Free: %s\n", - (void *)ptr, - size, - used ? "No" : "Yes"); + esp_rom_printf("Block %p data, size: %d bytes, Free: %s\n", + (void *)ptr, + size, + used ? "No" : "Yes"); } void esp_tee_heap_dump_info(void) { - printf("Showing data for TEE heap: %p (%uB)\n", (void *)tee_heap, tee_heap->pool_size); + esp_rom_printf("Showing data for TEE heap: %p (%uB)\n", (void *)tee_heap, tee_heap->pool_size); tlsf_walk_pool(tlsf_get_pool(tee_heap->heap_data), heap_dump_tlsf, NULL); } diff --git a/components/esp_tee/subproject/main/common/syscall_stubs.c b/components/esp_tee/subproject/main/common/syscall_stubs.c index 76e79f6e68..ee810a1aac 100644 --- a/components/esp_tee/subproject/main/common/syscall_stubs.c +++ b/components/esp_tee/subproject/main/common/syscall_stubs.c @@ -130,6 +130,13 @@ int __cxa_thread_atexit(void (*func)(void *), void *arg, void *dso) return 0; } +#if CONFIG_IDF_TARGET_ESP32H2 +void *_sbrk(ptrdiff_t incr) +{ + return (void *) -1; +} +#endif + void esp_tee_include_syscalls_impl(void) { diff --git a/components/esp_tee/subproject/main/core/esp_secure_services.c b/components/esp_tee/subproject/main/core/esp_secure_services.c index cf1a9cd542..0595c3d318 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.c @@ -345,6 +345,11 @@ int _ss_esp_ecc_point_verify(const ecc_point_t *point) return esp_ecc_point_verify(point); } +void _ss_esp_crypto_ecc_enable_periph_clk(bool enable) +{ + esp_crypto_ecc_enable_periph_clk(enable); +} + /* ---------------------------------------------- OTA ------------------------------------------------- */ int _ss_esp_tee_ota_begin(void) diff --git a/components/esp_tee/subproject/main/core/esp_tee_intr.c b/components/esp_tee/subproject/main/core/esp_tee_intr.c index 2b64871348..ef0cb14e3d 100644 --- a/components/esp_tee/subproject/main/core/esp_tee_intr.c +++ b/components/esp_tee/subproject/main/core/esp_tee_intr.c @@ -1,24 +1,25 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include "esp_log.h" +#include "esp_cpu.h" + +#include "hal/cpu_ll.h" + +#include "soc/periph_defs.h" +#include "soc/interrupts.h" +#include "soc/interrupt_reg.h" + #include "esp_tee.h" #include "esp_tee_intr.h" +#include "esp_tee_intr_defs.h" #include "esp_tee_rv_utils.h" -#include "soc/periph_defs.h" -#include "soc/interrupt_reg.h" -#include "hal/cpu_ll.h" -#include "esp_cpu.h" -#include "esp_log.h" - -/* For ESP32-C6 */ -#define INTR_MAX_SOURCE (77) #define INTR_SET_SIZE (32) -#define INTR_SET_COUNT ((((INTR_MAX_SOURCE) + ((INTR_SET_SIZE) - 1)) & ~((INTR_SET_SIZE) - 1)) / INTR_SET_SIZE) -#define INTR_DISABLED_INUM (6) +#define INTR_SET_COUNT ((((ETS_MAX_INTR_SOURCE) + ((INTR_SET_SIZE) - 1)) & ~((INTR_SET_SIZE) - 1)) / INTR_SET_SIZE) static const char *TAG = "esp_tee_intr"; @@ -27,7 +28,7 @@ typedef struct tee_handler_table_entry { void *arg; } tee_handler_table_entry; -static tee_handler_table_entry tee_interrupt_table[INTR_MAX_SOURCE * portNUM_PROCESSORS]; +static tee_handler_table_entry tee_interrupt_table[ETS_MAX_INTR_SOURCE * portNUM_PROCESSORS]; static uint32_t protected_sources[INTR_SET_COUNT]; @@ -60,14 +61,6 @@ void esp_tee_route_intr_matrix(int cpu_no, uint32_t model_num, uint32_t intr_num return; } - if (intr_num != ETS_INVALID_INUM) { - if (intr_num == INTR_DISABLED_INUM) { - rv_utils_tee_intr_disable(BIT(intr_num)); - } else { - rv_utils_tee_intr_enable(BIT(intr_num)); - } - } - esp_rom_route_intr_matrix(cpu_no, model_num, intr_num); } @@ -126,60 +119,45 @@ 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, INTR_DISABLED_INUM); + esp_rom_route_intr_matrix(cpu, vd->source, 0); return 0; } #define FIND_MSB_SET(n) (31 - __builtin_clz((uint32_t)(n))) -// LP_APM_M0_INTR, LP_APM_M1_INTR -#define TEE_SECURE_INT_APM_MASK_0 (0x00300000) -// EFUSE_INTR, LP_RTC_TIMER_INTR -#define TEE_SECURE_INT_MASK_0 (TEE_SECURE_INT_APM_MASK_0 | 0x0000C000) -// HP_APM_M0_INTR, HP_APM_M1_INTR, HP_APM_M2_INTR, HP_APM_M3_INTR, LP_APM0_INTR -#define TEE_SECURE_INT_APM_MASK_1 (0x000000F8) -#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 | 0x00080000) -#endif -// AES_INTR, SHA_INTR, RSA_INTR, ECC_INTR -#define TEE_SECURE_INT_MASK_2 (0x00001E00) /* called from esp_tee_vectors.S */ void esp_tee_global_interrupt_handler(intptr_t sp, int mcause) { uint32_t status, source; - while (1) { - if ((status = TEE_SECURE_INT_MASK_0 & - REG_READ(INTMTX_CORE0_INT_STATUS_REG_0_REG))) { + do { + status = REG_READ(INTMTX_STATUS_REG_0) & TEE_SECURE_INT_MASK_0; + if (status) { source = FIND_MSB_SET(status); - /* 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 */ - if (status & TEE_SECURE_INT_APM_MASK_0) { - RV_WRITE_CSR(mscratch, sp); - } - } else if ((status = TEE_SECURE_INT_MASK_1 & - REG_READ(INTMTX_CORE0_INT_STATUS_REG_1_REG))) { - source = FIND_MSB_SET(status) + 32; - if (status & TEE_SECURE_INT_APM_MASK_1) { - RV_WRITE_CSR(mscratch, sp); - } - } else if ((status = TEE_SECURE_INT_MASK_2 & - REG_READ(INTMTX_CORE0_INT_STATUS_REG_2_REG))) { - source = FIND_MSB_SET(status) + 64; - } - - if (!status) { break; } - ESP_LOGV(TAG, "Found intr src: %d", source); - tee_handler_table_entry ih = tee_interrupt_table[source]; - if (ih.handler) { - (*ih.handler)(ih.arg); + status = REG_READ(INTMTX_STATUS_REG_1) & TEE_SECURE_INT_MASK_1; + if (status) { + source = FIND_MSB_SET(status) + 32; + break; } + + status = REG_READ(INTMTX_STATUS_REG_2) & TEE_SECURE_INT_MASK_2; + if (status) { + source = FIND_MSB_SET(status) + 64; + break; + } + + /* No valid interrupt found */ + ESP_LOGV(TAG, "No valid interrupt found"); + return; + } while (0); + + ESP_LOGV(TAG, "Found intr src: %d", source); + tee_handler_table_entry ih = tee_interrupt_table[source]; + if (ih.handler) { + (*ih.handler)(ih.arg); } } diff --git a/components/esp_tee/subproject/main/idf_component.yml b/components/esp_tee/subproject/main/idf_component.yml index d2a3d2d24d..4f7ce5ca99 100644 --- a/components/esp_tee/subproject/main/idf_component.yml +++ b/components/esp_tee/subproject/main/idf_component.yml @@ -3,4 +3,4 @@ dependencies: espressif/json_generator: version: "^1.1.2" rules: - - if: "target in [esp32c6]" + - if: "target in [esp32c6, esp32h2]" diff --git a/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in new file mode 100644 index 0000000000..c68ba06763 --- /dev/null +++ b/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in @@ -0,0 +1,304 @@ +/* + * 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 + 0x22e0 ); +#else +PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x2e0 ); +#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.*) + /* snprintf-related functions */ + *libc_nano.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!"); diff --git a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_aes_intr.c b/components/esp_tee/subproject/main/soc/common/esp_tee_aes_intr.c similarity index 95% rename from components/esp_tee/subproject/main/soc/esp32c6/esp_tee_aes_intr.c rename to components/esp_tee/subproject/main/soc/common/esp_tee_aes_intr.c index 9c23c53924..68796beabb 100644 --- a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_aes_intr.c +++ b/components/esp_tee/subproject/main/soc/common/esp_tee_aes_intr.c @@ -8,10 +8,9 @@ #include "hal/aes_hal.h" #include "soc/interrupts.h" -#include "esp_attr.h" +#include "esp_attr.h" #include "esp_tee_intr.h" -#include "esp_tee_aes_intr.h" volatile DRAM_ATTR bool intr_flag; diff --git a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_apm_intr.c b/components/esp_tee/subproject/main/soc/common/esp_tee_apm_intr.c similarity index 93% rename from components/esp_tee/subproject/main/soc/esp32c6/esp_tee_apm_intr.c rename to components/esp_tee/subproject/main/soc/common/esp_tee_apm_intr.c index 5843137eb1..d6c4dea1db 100644 --- a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_apm_intr.c +++ b/components/esp_tee/subproject/main/soc/common/esp_tee_apm_intr.c @@ -4,13 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include -#include "hal/apm_ll.h" +#include "soc/soc_caps.h" +#include "esp_bit_defs.h" + #include "hal/apm_hal.h" - -#include "esp_tee.h" -#include "esp_tee_apm_intr.h" +#include "hal/apm_ll.h" static const char *const excp_mid_strs[] = { [APM_LL_MASTER_HPCORE] = "HPCORE", @@ -41,9 +40,9 @@ const char *esp_tee_apm_excp_type_to_str(uint8_t type) { char *excp_type = "APM - Unknown exception"; - if (type & 0x01) { + if (type & BIT(0)) { excp_type = "APM - Authority exception"; - } else if (type & 0x02) { + } else if (type & BIT(1)) { excp_type = "APM - Space exception"; } @@ -55,9 +54,11 @@ const char *esp_tee_apm_excp_ctrl_to_str(apm_ll_apm_ctrl_t apm_ctrl) char *excp_ctrl = NULL; switch (apm_ctrl) { +#if SOC_APM_LP_APM0_SUPPORTED case LP_APM0_CTRL: excp_ctrl = "LP_APM0"; break; +#endif case HP_APM_CTRL: excp_ctrl = "HP_APM"; break; diff --git a/components/esp_tee/subproject/main/soc/esp32c6/include/esp_tee_aes_intr.h b/components/esp_tee/subproject/main/soc/common/include/esp_tee_aes_intr.h similarity index 100% rename from components/esp_tee/subproject/main/soc/esp32c6/include/esp_tee_aes_intr.h rename to components/esp_tee/subproject/main/soc/common/include/esp_tee_aes_intr.h diff --git a/components/esp_tee/subproject/main/soc/esp32c6/include/esp_tee_apm_intr.h b/components/esp_tee/subproject/main/soc/common/include/esp_tee_apm_intr.h similarity index 100% rename from components/esp_tee/subproject/main/soc/esp32c6/include/esp_tee_apm_intr.h rename to components/esp_tee/subproject/main/soc/common/include/esp_tee_apm_intr.h diff --git a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c index a3efc665a2..6d10ba9f56 100644 --- a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c @@ -8,6 +8,7 @@ #include "riscv/rv_utils.h" #include "riscv/encoding.h" +#include "esp_private/interrupt_plic.h" #include "esp_cpu.h" #include "esp_log.h" @@ -28,9 +29,6 @@ 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; @@ -58,9 +56,8 @@ void esp_tee_soc_secure_sys_init(void) RV_WRITE_CSR(uie, 0x00); /* All interrupts except the TEE secure interrupt are delegated to the U-mode */ - uint32_t mideleg_val = UINT32_MAX; - CLR_BIT(mideleg_val, TEE_SECURE_INUM); - RV_WRITE_CSR(mideleg, mideleg_val); + RV_WRITE_CSR(mideleg, UINT32_MAX); + RV_CLEAR_CSR(mideleg, TEE_SECURE_INUM); /* TODO: IDF-8958 * The values for the secure interrupt number and priority and @@ -71,7 +68,7 @@ void esp_tee_soc_secure_sys_init(void) /* 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(1); + esprv_int_set_threshold(RVHAL_INTR_ENABLE_THRESH); esprv_int_enable(BIT(TEE_SECURE_INUM)); #endif @@ -93,7 +90,6 @@ void esp_tee_soc_secure_sys_init(void) 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_LP_APM0_INTR_SOURCE); // LP_APM0 - esp_tee_protect_intr_src(ETS_EFUSE_INTR_SOURCE); // eFuse 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 diff --git a/components/esp_tee/subproject/main/soc/esp32c6/include/esp_tee_intr_defs.h b/components/esp_tee/subproject/main/soc/esp32c6/include/esp_tee_intr_defs.h new file mode 100644 index 0000000000..921b8b37bc --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32c6/include/esp_tee_intr_defs.h @@ -0,0 +1,36 @@ +/* + * 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, LP_APM0_INTR +#define TEE_SECURE_INT_APM_MASK_1 (0x000000F8) + +// 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 | 0x00080000) +#endif +// AES_INTR, SHA_INTR, ECC_INTR +#define TEE_SECURE_INT_MASK_2 (0x00001600) + +#define INTMTX_STATUS_REG_0 (INTMTX_CORE0_INT_STATUS_REG_0_REG) +#define INTMTX_STATUS_REG_1 (INTMTX_CORE0_INT_STATUS_REG_1_REG) +#define INTMTX_STATUS_REG_2 (INTMTX_CORE0_INT_STATUS_REG_2_REG) + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_apm_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_apm_prot_cfg.c new file mode 100644 index 0000000000..af5472b4b5 --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_apm_prot_cfg.c @@ -0,0 +1,303 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_log.h" +#include "esp_tee.h" +#include "esp_tee_intr.h" + +#include "hal/apm_hal.h" +#include "soc/soc.h" +#include "soc/spi_mem_reg.h" +#include "soc/efuse_reg.h" +#include "soc/pcr_reg.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_SPI1_BASE +#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 +#define HP_APM_SPI1_REG_END DR_REG_I2C_EXT0_BASE +#else +#define HP_APM_SPI1_REG_END HP_APM_SPI1_REG_START +#endif + +/*----------------------- HP APM range and filter configuration -----------------------*/ + +/* HP_APM: TEE mode accessible regions */ +apm_ctrl_region_config_data_t hp_apm_pms_data_tee[] = { + /* Region 0: Entire memory region (RWX)*/ + { + .regn_num = 0, + .regn_start_addr = 0x0, + .regn_end_addr = ~0x0, + .regn_pms = 0x7, + .filter_enable = 1, + }, +}; + +/* HP_APM: REE0 mode accessible regions */ +apm_ctrl_region_config_data_t hp_apm_pms_data[] = { + /* NOTE: Without this entry, the REE SRAM region becomes inaccessible to + * the MODEM master, resulting in an APM violation during Wi-Fi initialization. + */ + /* Region 1: REE SRAM region (RW) */ + { + .regn_num = 1, + .regn_start_addr = SOC_NS_IRAM_START, + .regn_end_addr = SOC_IRAM_HIGH, + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 2: RTC memory (RWX) */ + { + .regn_num = 2, + .regn_start_addr = SOC_RTC_IRAM_LOW, + .regn_end_addr = SOC_RTC_IRAM_HIGH, + .regn_pms = 0x7, + .filter_enable = 1, + }, + /* Region 3: Peripherals [Start - MMU] (RW) */ + /* Protected: MMU */ + { + .regn_num = 3, + .regn_start_addr = SOC_PERIPHERAL_LOW, + .regn_end_addr = (SPI_MEM_MMU_ITEM_CONTENT_REG(0) - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 4: Peripherals [MMU - SPI1] (RW) */ + /* Protected: SPI1 */ + { + .regn_num = 4, + .regn_start_addr = SPI_MEM_MMU_POWER_CTRL_REG(0), + .regn_end_addr = (HP_APM_SPI1_REG_START - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 5: Peripherals [SPI1 - Interrupt Matrix] (RW) */ + /* Protected: Interrupt Matrix */ + { + .regn_num = 5, + .regn_start_addr = HP_APM_SPI1_REG_END, + .regn_end_addr = (DR_REG_INTMTX_BASE - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 6/7: Peripherals [H/W Lock - HMAC] (RW) */ + /* Protected: AES, SHA, ECC, DS, HMAC */ + { + .regn_num = 6, + .regn_start_addr = DR_REG_PCNT_BASE, + .regn_end_addr = (DR_REG_AES_BASE - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + { + .regn_num = 7, + .regn_start_addr = DR_REG_RSA_BASE, + .regn_end_addr = (DR_REG_ECC_MULT_BASE - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 8/9/10: Peripherals [IO_MUX - TEE Controller & APM] (RW) */ + /* Protected: AES, SHA, ECC, DS and HMAC PCRs, APM, TEE Controller */ + { + .regn_num = 8, + .regn_start_addr = DR_REG_ECDSA_BASE, + .regn_end_addr = (PCR_AES_CONF_REG - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + { + .regn_num = 9, + .regn_start_addr = PCR_RSA_CONF_REG, + .regn_end_addr = (PCR_ECC_CONF_REG - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + { + .regn_num = 10, + .regn_start_addr = PCR_ECDSA_CONF_REG, + .regn_end_addr = (DR_REG_TEE_BASE - 0x4), + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 11: Peripherals [Miscellaneous - PMU] (RW) */ + { + .regn_num = 11, + .regn_start_addr = DR_REG_MISC_BASE, + .regn_end_addr = (DR_REG_PMU_BASE - 0x04), + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 12: Peripherals [DEBUG - PWDET] (RW) */ + { + .regn_num = 12, + .regn_start_addr = DR_REG_TRACE_BASE, + .regn_end_addr = 0x600D0000, + .regn_pms = 0x6, + .filter_enable = 1, + }, +}; + +/* 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 | + * +---------+-------------+ + */ + +/* HP_APM: TEE mode masters' configuration */ +apm_ctrl_secure_mode_config_t hp_apm_sec_mode_data_tee = { + .apm_ctrl = HP_APM_CTRL, + .apm_m_cnt = HP_APM_MAX_ACCESS_PATH, + .sec_mode = APM_LL_SECURE_MODE_TEE, + /* Crypto DMA (AES/SHA) and HP_CPU */ + .master_ids = 0xC00001, + .pms_data = hp_apm_pms_data_tee, +}; + +/* HP_APM: REE0 mode masters' configuration */ +apm_ctrl_secure_mode_config_t hp_apm_sec_mode_data = { + .apm_ctrl = HP_APM_CTRL, + .apm_m_cnt = HP_APM_MAX_ACCESS_PATH, + .sec_mode = APM_LL_SECURE_MODE_REE0, + /* All masters except crypto DMA (AES/SHA) and HP CPU */ + .master_ids = 0xFF3FFFFE, + .pms_data = hp_apm_pms_data, +}; + +/*----------------------- LP_APM range and filter configuration -----------------------*/ + +/* NOTE: Due to ESP32-H2's limited LP_APM module regions, neither TEE nor REE can directly + * access the protected eFuse region. However, since the HMAC peripheral can access the + * key stored in eFuse for TEE secure storage, this access restriction does not impact + * functionality. + */ +/* LP_APM: REE0 mode accessible regions */ +apm_ctrl_region_config_data_t lp_apm_pms_data[] = { + /* Region 0: LP Peripherals [PMU - eFuse BLK x] (RW) */ + /* Protected: eFuse BLK x */ + { + .regn_num = 0, + .regn_start_addr = DR_REG_PMU_BASE, + .regn_end_addr = (LP_APM_EFUSE_REG_START - 0x04), + .regn_pms = 0x6, + .filter_enable = 1, + }, + /* Region 1: LP Peripherals [eFuse - END] (RW) */ + { + .regn_num = 1, + .regn_start_addr = LP_APM_EFUSE_REG_END, + .regn_end_addr = (DR_REG_TRACE_BASE - 0x04), + .regn_pms = 0x6, + .filter_enable = 1, + }, +}; + +/* LP_APM: REE0 mode masters' configuration */ +apm_ctrl_secure_mode_config_t lp_apm_sec_mode_data = { + .apm_ctrl = LP_APM_CTRL, + .apm_m_cnt = LP_APM_MAX_ACCESS_PATH, + .sec_mode = APM_LL_SECURE_MODE_REE0, + /* HP_CPU */ + .master_ids = 0x1, + .pms_data = lp_apm_pms_data, +}; + +/*---------------- TEE APM API-----------------------*/ + +void esp_tee_apm_int_enable(apm_ctrl_secure_mode_config_t *sec_mode_data) +{ + for (int i = 0; i < sec_mode_data->apm_m_cnt; i++) { + apm_ctrl_path_t *apm_excp_data = calloc(1, sizeof(apm_ctrl_path_t)); + assert(apm_excp_data != NULL); + + apm_excp_data->apm_ctrl = sec_mode_data->apm_ctrl; + apm_excp_data->apm_m_path = i; + + int intr_src_num = apm_hal_apm_ctrl_get_int_src_num(apm_excp_data); + + struct vector_desc_t apm_vd = {0}; + apm_vd.source = intr_src_num; + apm_vd.isr = tee_apm_violation_isr; + apm_vd.arg = (void *)apm_excp_data; + + /* Register interrupt handler with TEE. */ + esp_tee_intr_register((void *)&apm_vd); + + /* Enable APM Ctrl intewrrupt for access path(M[0:n]) */ + apm_hal_apm_ctrl_exception_clear(apm_excp_data); + apm_hal_apm_ctrl_interrupt_enable(apm_excp_data, true); + } +} + +void esp_tee_configure_apm_protection(void) +{ + /* Disable all control filter first to have full access of address rage. */ + apm_hal_apm_ctrl_filter_enable_all(false); + + /* Switch HP_CPU to TEE mode */ + apm_tee_hal_set_master_secure_mode(HP_APM_CTRL, APM_LL_MASTER_HPCORE, APM_LL_SECURE_MODE_TEE); + + /* LP APM TEE configuration. */ + lp_apm_sec_mode_data.regn_count = sizeof(lp_apm_pms_data) / sizeof(apm_ctrl_region_config_data_t); + apm_hal_apm_ctrl_master_sec_mode_config(&lp_apm_sec_mode_data); + /* LP APM interrupt configuration. */ + esp_tee_apm_int_enable(&lp_apm_sec_mode_data); + ESP_LOGD(TAG, "[REE0] LP_APM configured"); + + /* HP APM TEE configuration. */ + hp_apm_sec_mode_data_tee.regn_count = sizeof(hp_apm_pms_data_tee) / sizeof(apm_ctrl_region_config_data_t); + apm_hal_apm_ctrl_master_sec_mode_config(&hp_apm_sec_mode_data_tee); + ESP_LOGD(TAG, "[TEE] HP_APM configured"); + + /* HP APM configuration. */ + hp_apm_sec_mode_data.regn_count = sizeof(hp_apm_pms_data) / sizeof(apm_ctrl_region_config_data_t); + apm_hal_apm_ctrl_master_sec_mode_config(&hp_apm_sec_mode_data); + /* HP APM interrupt configuration. */ + esp_tee_apm_int_enable(&hp_apm_sec_mode_data); + ESP_LOGD(TAG, "[REE0] HP_APM configured"); +} diff --git a/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_pmp_pma_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_pmp_pma_prot_cfg.c new file mode 100644 index 0000000000..ed21a9267a --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_pmp_pma_prot_cfg.c @@ -0,0 +1,174 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "soc/ext_mem_defs.h" +#include "soc/lp_analog_peri_reg.h" +#include "soc/lp_wdt_reg.h" +#include "soc/plic_reg.h" +#include "soc/clint_reg.h" +#include "riscv/csr.h" +#include "esp_cpu.h" +#include "esp_fault.h" +#include "esp_tee.h" + +#define CONDITIONAL_NONE 0x0 +#define CONDITIONAL_R PMP_R +#define CONDITIONAL_RX PMP_R | PMP_X +#define CONDITIONAL_RW PMP_R | PMP_W +#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X + +#define IS_PMA_ENTRY_UNLOCKED(ENTRY) \ + ((RV_READ_CSR((CSR_PMACFG0) + (ENTRY)) & PMA_L) == 0) + +#define SWD_PROT_REG_START (LP_WDT_SWD_CONFIG_REG) +#define SWD_PROT_REG_END (LP_WDT_INT_CLR_REG) +#define BOD_PROT_REG_START (DR_REG_LP_ANALOG_PERI_BASE) +#define BOD_PROT_REG_END (DR_REG_LP_ANALOG_PERI_BASE + 0x40) + +static void esp_tee_configure_invalid_regions(void) +{ + const unsigned PMA_NONE = PMA_L | PMA_EN; + __attribute__((unused)) const unsigned PMA_RW = PMA_L | PMA_EN | PMA_R | PMA_W; + __attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X; + __attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X; + + // 1. Gap at bottom of address space + PMA_ENTRY_SET_TOR(0, SOC_CPU_SUBSYSTEM_LOW, PMA_TOR | PMA_NONE); + + // 2. Gap between CPU subsystem region & IROM + PMA_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE); + + // 3. Gap between ROM & RAM + PMA_ENTRY_SET_TOR(3, SOC_DROM_MASK_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(4, SOC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 4. Gap between DRAM and I_Cache + PMA_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE); + + // 5. Gap between D_Cache & LP_RAM + PMA_ENTRY_SET_TOR(7, SOC_DROM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(8, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 6. Gap between LP memory & peripheral addresses + PMA_ENTRY_SET_TOR(9, SOC_RTC_IRAM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(10, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE); + + // 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); + + /* 8. Using PMA to configure the TEE text and data section access attribute. */ + assert(IS_PMA_ENTRY_UNLOCKED(13)); + assert(IS_PMA_ENTRY_UNLOCKED(14)); + assert(IS_PMA_ENTRY_UNLOCKED(15)); + PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_S_IRAM_START, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(14, SOC_S_IRAM_END, PMA_TOR | PMA_RX); + PMA_RESET_AND_ENTRY_SET_TOR(15, SOC_S_DRAM_END, PMA_TOR | PMA_RW); +} + +void esp_tee_configure_region_protection(void) +{ + /* Notes on implementation: + * + * 1) Note: ESP32-C6 CPU doesn't support overlapping PMP regions + * + * 2) ESP32-C6 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 invalid address regions using PMA + // + // We lock the PMA entries since they mark the invalid regions and is applicable to both the privilege modes + // + esp_tee_configure_invalid_regions(); + + // 1.1 I/D-ROM + const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); + PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RX); + _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); + + /* TODO: Check whether changes are required here */ + if (esp_cpu_dbgr_is_attached()) { + // Anti-FI check that cpu is really in ocd mode + ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached()); + + // 2. IRAM and DRAM + PMP_ENTRY_SET(1, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(2, SOC_IRAM_HIGH, PMP_TOR | RWX); + _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); + } else { + // 2. IRAM and DRAM + // Splitting the REE SRAM region into IRAM and DRAM + PMP_ENTRY_SET(1, (int)SOC_NS_IRAM_START, NONE); + PMP_ENTRY_SET(2, (int)esp_tee_app_config.ns_iram_end, PMP_TOR | RX); + PMP_ENTRY_SET(3, SOC_DRAM_HIGH, PMP_TOR | RW); + } + + const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE; + const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end); + const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end); + const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR); + + // 4. I_Cache / D_Cache (flash) - REE + PMP_ENTRY_CFG_RESET(5); + PMP_ENTRY_CFG_RESET(6); + PMP_ENTRY_CFG_RESET(7); + PMP_ENTRY_SET(4, s_irom_resv_end, NONE); + PMP_ENTRY_SET(5, ns_irom_resv_end, PMP_TOR | RX); + PMP_ENTRY_SET(6, ns_drom_resv_end, PMP_TOR | R); + PMP_ENTRY_SET(7, ns_drom_mmap_end, PMP_TOR | RX); + + // 5. LP memory + /* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits + * Bootloader might have given extra permissions and those won't be cleared + */ + const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH); + PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | RWX); + _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region"); + + // 6. Super WDT and Brownout detector + PMP_ENTRY_SET(9, SWD_PROT_REG_START, CONDITIONAL_NONE); + PMP_ENTRY_SET(10, SWD_PROT_REG_END, PMP_TOR | CONDITIONAL_NONE); + _Static_assert(SWD_PROT_REG_START < SWD_PROT_REG_END, "Invalid peripheral region"); + + /* NOTE: Due to the limited number of PMP entries, NAPOT address matching had to be + * utilized here. To meet the requirements of NAPOT, the adjacent 20 bytes have also + * been protected along with the intended region. + */ + const uint32_t pmpaddr11 = PMPADDR_NAPOT(BOD_PROT_REG_START, BOD_PROT_REG_END); + PMP_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | CONDITIONAL_NONE); + _Static_assert(BOD_PROT_REG_START < BOD_PROT_REG_END, "Invalid peripheral region"); + + // 7. Peripheral addresses + 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"); + + // 8. User-mode interrupt controller registers + const uint32_t pmpaddr13 = PMPADDR_NAPOT(DR_REG_PLIC_UX_BASE, DR_REG_PLIC_UX_END); + PMP_ENTRY_SET(13, pmpaddr13, PMP_NAPOT | RW); + _Static_assert(DR_REG_PLIC_UX_BASE < DR_REG_PLIC_UX_END, "Invalid User mode PLIC region"); + + const uint32_t pmpaddr14 = PMPADDR_NAPOT(DR_REG_CLINT_U_BASE, DR_REG_CLINT_U_END); + PMP_ENTRY_SET(14, pmpaddr14, PMP_NAPOT | RW); + _Static_assert(DR_REG_CLINT_U_BASE < DR_REG_CLINT_U_END, "Invalid User mode CLINT region"); +} diff --git a/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c new file mode 100644 index 0000000000..3efc9e81d9 --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "riscv/rv_utils.h" +#include "riscv/encoding.h" +#include "esp_private/interrupt_plic.h" + +#include "esp_cpu.h" +#include "esp_log.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 "esp_tee.h" +#include "esp_tee_intr.h" + +#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) : ); \ + }) + +static const char *TAG = "esp_tee_secure_sys_cfg"; + +extern uint32_t _vector_table; + +void esp_tee_soc_secure_sys_init(void) +{ + ESP_LOGI(TAG, "Current privilege level - %d", esp_cpu_get_curr_privilege_level()); + + /* NOTE: M/U-mode PLIC Special Configuration Register + * Bit 0: Use the external PLIC registers (legacy) from the SoC (default) + * Bit 1: Use the internal PLIC registers as per the new SoC address map + */ + REG_SET_BIT(PLIC_MXINT_CONF_REG, BIT(0)); + REG_SET_BIT(PLIC_UXINT_CONF_REG, BIT(0)); + + /* Setting the M-mode vector table */ + rv_utils_set_mtvec((uint32_t)&_vector_table); + + /* Disable global interrupts */ + RV_CLEAR_CSR(mstatus, MSTATUS_UIE); + RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + + /* Clear all interrupts */ + RV_WRITE_CSR(mie, 0x00); + RV_WRITE_CSR(uie, 0x00); + + /* 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); + + /* 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)); + ESP_LOGD(TAG, "mie: 0x%08x | uie: 0x%08x", RV_READ_CSR(mie), RV_READ_CSR(uie)); + ESP_LOGD(TAG, "mstatus: 0x%08x | ustatus: 0x%08x", RV_READ_CSR(mstatus), RV_READ_CSR(ustatus)); + ESP_LOGD(TAG, "[PLIC] MX: 0x%08x | UX: 0x%08x", REG_READ(PLIC_MXINT_ENABLE_REG), REG_READ(PLIC_UXINT_ENABLE_REG)); + + /* 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_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_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 ree_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(ree_entry_addr, ESP_TEE_M2U_SWITCH_MAGIC << 12); +} diff --git a/components/esp_tee/subproject/main/soc/esp32h2/include/esp_tee_intr_defs.h b/components/esp_tee/subproject/main/soc/esp32h2/include/esp_tee_intr_defs.h new file mode 100644 index 0000000000..da96fba4c6 --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32h2/include/esp_tee_intr_defs.h @@ -0,0 +1,34 @@ +/* + * 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, HP_APM_M0_INTR, HP_APM_M1_INTR, HP_APM_M2_INTR, HP_APM_M3_INTR +#define TEE_SECURE_INT_APM_MASK_0 (0x3C000040) + +// LP_RTC_TIMER_INTR +#define TEE_SECURE_INT_MASK_0 (TEE_SECURE_INT_APM_MASK_0 | 0x00000004) +// AES_INTR, SHA_INTR, ECC_INTR +#if !CONFIG_SECURE_TEE_TEST_MODE +#define TEE_SECURE_INT_MASK_1 (0xB0000000) +#else +// + TG0_T0_INTR (only for test mode) +#define TEE_SECURE_INT_MASK_1 (0xB0000200) +#endif +#define TEE_SECURE_INT_MASK_2 (0U) + +#define INTMTX_STATUS_REG_0 (INTMTX_CORE0_INT_STATUS_REG_0_REG) +#define INTMTX_STATUS_REG_1 (INTMTX_CORE0_INT_STATUS_REG_1_REG) +#define INTMTX_STATUS_REG_2 (INTMTX_CORE0_INT_STATUS_REG_2_REG) + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_tee/subproject/main/soc/esp32h2/include/esp_tee_rv_utils.h b/components/esp_tee/subproject/main/soc/esp32h2/include/esp_tee_rv_utils.h new file mode 100644 index 0000000000..c961a35623 --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32h2/include/esp_tee_rv_utils.h @@ -0,0 +1,132 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include + +#include "riscv/csr.h" +#include "riscv/interrupt.h" + +#include "soc/interrupt_reg.h" +#include "soc/plic_reg.h" + +#include "esp_attr.h" +#include "esp_tee.h" + +#ifdef __cplusplus +extern "C" { +#endif + +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) +{ + unsigned old_xstatus; + + // Machine mode + // Disable all interrupts to make updating of the interrupt mask atomic. + old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + REG_SET_BIT(PLIC_MXINT_ENABLE_REG, intr_mask); + RV_SET_CSR(mie, intr_mask); + RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE); + + // User mode + // Disable all interrupts to make updating of the interrupt mask atomic. + old_xstatus = RV_CLEAR_CSR(ustatus, USTATUS_UIE); + REG_SET_BIT(PLIC_UXINT_ENABLE_REG, intr_mask); + RV_SET_CSR(uie, intr_mask); + RV_SET_CSR(ustatus, old_xstatus & USTATUS_UIE); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_disable(uint32_t intr_mask) +{ + unsigned old_xstatus; + + // Machine mode + // Disable all interrupts to make updating of the interrupt mask atomic. + old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + REG_CLR_BIT(PLIC_MXINT_ENABLE_REG, intr_mask); + RV_CLEAR_CSR(mie, intr_mask); + RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE); + + // User mode + // Disable all interrupts to make updating of the interrupt mask atomic. + old_xstatus = RV_CLEAR_CSR(ustatus, USTATUS_UIE); + REG_CLR_BIT(PLIC_UXINT_ENABLE_REG, intr_mask); + RV_CLEAR_CSR(uie, intr_mask); + RV_SET_CSR(ustatus, old_xstatus & USTATUS_UIE); +} + +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); + + if (type == INTR_TYPE_LEVEL) { + REG_CLR_BIT(PLIC_MXINT_TYPE_REG, BIT(intr_num)); + REG_CLR_BIT(PLIC_UXINT_TYPE_REG, BIT(intr_num)); + } else { + REG_SET_BIT(PLIC_MXINT_TYPE_REG, BIT(intr_num)); + REG_SET_BIT(PLIC_UXINT_TYPE_REG, BIT(intr_num)); + } +} + +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); + + REG_WRITE(PLIC_MXINT_PRI_REG(rv_int_num), priority); + REG_WRITE(PLIC_UXINT_PRI_REG(rv_int_num), priority); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_set_threshold(int priority_threshold) +{ + REG_WRITE(PLIC_MXINT_THRESH_REG, priority_threshold); + REG_WRITE(PLIC_UXINT_THRESH_REG, priority_threshold); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_edge_ack(int intr_num) +{ + assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM); + + REG_SET_BIT(PLIC_MXINT_CLEAR_REG, intr_num); + REG_SET_BIT(PLIC_UXINT_CLEAR_REG, intr_num); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_tee/test_apps/.build-test-rules.yml b/components/esp_tee/test_apps/.build-test-rules.yml index 4f0f92041d..04999bc2f9 100644 --- a/components/esp_tee/test_apps/.build-test-rules.yml +++ b/components/esp_tee/test_apps/.build-test-rules.yml @@ -7,5 +7,5 @@ components/esp_tee/test_apps/tee_cli_app: components/esp_tee/test_apps/tee_test_fw: disable: - - if: IDF_TARGET not in ["esp32c6"] - reason: only supported with esp32c6 for now + - if: IDF_TARGET not in ["esp32c6", "esp32h2"] + reason: only supported with esp32c6 and esp32h2 for now diff --git a/components/esp_tee/test_apps/tee_test_fw/README.md b/components/esp_tee/test_apps/tee_test_fw/README.md index 8259fa367e..a4ee87e6ce 100644 --- a/components/esp_tee/test_apps/tee_test_fw/README.md +++ b/components/esp_tee/test_apps/tee_test_fw/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | -| ----------------- | -------- | +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | ## ESP-TEE: Test Suite diff --git a/components/esp_tee/test_apps/tee_test_fw/conftest.py b/components/esp_tee/test_apps/tee_test_fw/conftest.py index bf076ee6d6..d344c193f0 100644 --- a/components/esp_tee/test_apps/tee_test_fw/conftest.py +++ b/components/esp_tee/test_apps/tee_test_fw/conftest.py @@ -63,6 +63,47 @@ esp_tee_empty_bin = { 0xF4, 0xA4, 0xCF, 0x06, 0xAE, 0x94, 0x75, 0x47, 0xBC, 0x88, 0xA2, 0xCA, 0x52, 0x97, 0x7A, 0x5C, 0x55, 0x43, 0xD9, 0xF5, 0xD3, 0x45, 0xD1, 0x34, 0xFC, 0x74, 0xB2, 0xB9, 0x34, 0x72, 0xC3, 0x00 + ], + 'esp32h2': [ + 0xE9, 0x04, 0x02, 0x1F, 0x00, 0x00, 0x80, 0x40, 0xEE, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x78, 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 + 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 ] } # fmt: on diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c index 4f979a0e95..ef2ac6dbe1 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c @@ -119,7 +119,7 @@ TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp256r1)", "[sec_stora } } -#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN +#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN && !TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2) TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp192r1)", "[sec_storage]") { const size_t buf_sz = 16 * 1024 + 6; // NOTE: Not an exact multiple of SHA block size @@ -507,7 +507,7 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid) TEST_CASE("Test TEE Secure Storage - mbedtls ECDSA signing", "[mbedtls]") { test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1); -#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN +#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN && !TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2) test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1); #endif } diff --git a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py index 2dd5eae1fe..6b4654e79e 100644 --- a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py +++ b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py @@ -1,42 +1,57 @@ # SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 from enum import Enum -from typing import Any from typing import Dict +from typing import Tuple import pytest from pytest_embedded_idf import IdfDut from pytest_embedded_idf.utils import idf_parametrize -CONFIGS_DEFAULT = [pytest.param('default', marks=[pytest.mark.esp32c6])] +# ---------------- Pytest build parameters ---------------- -CONFIGS_OTA = [pytest.param('ota', marks=[pytest.mark.esp32c6])] +SUPPORTED_TARGETS = ['esp32c6', 'esp32h2'] -CONFIGS_ALL = [pytest.param('default', marks=[pytest.mark.esp32c6]), pytest.param('ota', marks=[pytest.mark.esp32c6])] +CONFIG_DEFAULT = [ + # 'config, target, markers', + ('default', target, (pytest.mark.generic,)) + for target in SUPPORTED_TARGETS +] -TEE_VIOLATION_TEST_EXC_RSN: Dict[str, Any] = { - 'esp32c6': { - ('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', - } +CONFIG_OTA = [ + # 'config, target, skip_autoflash, markers', + ('ota', target, 'y', (pytest.mark.generic,)) + for target in SUPPORTED_TARGETS +] + +CONFIG_ALL = [ + # 'config, target, markers', + (config, target, (pytest.mark.generic,)) + for config in ['default', 'ota'] + for target in SUPPORTED_TARGETS +] + +# ---------------- 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', } -REE_ISOLATION_TEST_EXC_RSN: Dict[str, Any] = { - 'esp32c6': { - ('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[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', } TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR'] @@ -44,34 +59,42 @@ TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'EC # ---------------- TEE default tests ---------------- -@pytest.mark.generic -@idf_parametrize('config', ['default'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_DEFAULT, + indirect=['config', 'target'], +) def test_esp_tee(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='basic') dut.run_all_single_board_cases(group='heap') -@pytest.mark.generic -@idf_parametrize('config', ['default', 'ota'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_ALL, + indirect=['config', 'target'], +) def test_esp_tee_crypto_aes(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='aes') dut.run_all_single_board_cases(group='aes-gcm') -@pytest.mark.generic -@idf_parametrize('config', ['default', 'ota'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_ALL, + indirect=['config', 'target'], +) def test_esp_tee_crypto_sha(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='mbedtls') dut.run_all_single_board_cases(group='hw_crypto') # NOTE: Stress testing the AES performance case for interrupt-related edge-cases -@pytest.mark.generic -@idf_parametrize('config', ['default', 'ota'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_ALL, + indirect=['config', 'target'], +) def test_esp_tee_aes_perf(dut: IdfDut) -> None: # start test for i in range(24): @@ -86,21 +109,29 @@ def test_esp_tee_aes_perf(dut: IdfDut) -> None: # ---------------- TEE Exceptions generation Tests ---------------- -@pytest.mark.generic -@idf_parametrize('config', ['default'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_DEFAULT, + indirect=['config', 'target'], +) 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}"') exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() - if exc != 'APM - Authority exception': + if dut.target == 'esp32h2' and check == 'eFuse': + exp_str = 'APM - Space exception' + else: + exp_str = 'APM - Authority exception' + if exc != exp_str: raise RuntimeError('Incorrect exception received!') -@pytest.mark.generic -@idf_parametrize('config', ['default'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_DEFAULT, + indirect=['config', 'target'], +) def test_esp_tee_illegal_instruction(dut: IdfDut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"Test TEE-TEE violation: Illegal Instruction"') @@ -109,11 +140,13 @@ def test_esp_tee_illegal_instruction(dut: IdfDut) -> None: raise RuntimeError('Incorrect exception received!') -@pytest.mark.generic -@idf_parametrize('config', ['default'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_DEFAULT, + indirect=['config', 'target'], +) def test_esp_tee_violation_checks(dut: IdfDut) -> None: - checks_list = TEE_VIOLATION_TEST_EXC_RSN[dut.target] + checks_list = TEE_VIOLATION_TEST_EXC_RSN for test in checks_list: memory, access_type = test expected_exc = checks_list[test] @@ -126,11 +159,13 @@ def test_esp_tee_violation_checks(dut: IdfDut) -> None: raise RuntimeError('Incorrect exception received!') -@pytest.mark.generic -@idf_parametrize('config', ['default'], indirect=['config']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_DEFAULT, + indirect=['config', 'target'], +) def test_esp_tee_isolation_checks(dut: IdfDut) -> None: - checks_list = REE_ISOLATION_TEST_EXC_RSN[dut.target] + checks_list = REE_ISOLATION_TEST_EXC_RSN for test in checks_list: memory, access_type = test expected_exc = checks_list[test] @@ -199,10 +234,11 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl dut.expect_exact('Press ENTER to see the list of tests.') -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -216,10 +252,11 @@ def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: continue -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -233,10 +270,11 @@ def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: continue -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_flash_prot_esp_rom_spiflash(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -250,10 +288,11 @@ def test_esp_tee_flash_prot_esp_rom_spiflash(dut: IdfDut) -> None: continue -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_flash_prot_esp_partition(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -267,10 +306,11 @@ def test_esp_tee_flash_prot_esp_partition(dut: IdfDut) -> None: continue -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: # Flash the bootloader, TEE and REE firmware dut.serial.custom_flash() @@ -289,7 +329,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'], indirect=['target']) +@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) def test_esp_tee_ota_negative(dut: IdfDut) -> None: # start test dut.expect_exact('Press ENTER to see the list of tests') @@ -300,10 +340,11 @@ def test_esp_tee_ota_negative(dut: IdfDut) -> None: dut.serial.erase_partition('tee_otadata') -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_ota_corrupted_img(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_gen() @@ -338,10 +379,11 @@ def tee_ota_stage_checks(dut: IdfDut, stage: TeeOtaStage, offset: str) -> None: raise ValueError('Undefined stage!') -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_gen() @@ -363,10 +405,11 @@ def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None: dut.serial.erase_partition('tee_otadata') -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_ota_valid_img(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_gen() @@ -396,10 +439,11 @@ def test_esp_tee_ota_valid_img(dut: IdfDut) -> None: dut.serial.erase_partition('tee_otadata') -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_ota_rollback(dut: IdfDut) -> None: # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_rb() @@ -434,10 +478,11 @@ def test_esp_tee_ota_rollback(dut: IdfDut) -> None: # ---------------- TEE Secure Storage tests ---------------- -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_secure_storage(dut: IdfDut) -> None: # Flash image and erase the secure_storage partition dut.serial.custom_flash_with_empty_sec_stg() @@ -445,10 +490,11 @@ def test_esp_tee_secure_storage(dut: IdfDut) -> None: dut.run_all_single_board_cases(group='sec_storage') -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_secure_storage_with_host_img(dut: IdfDut) -> None: # Flash image and write the secure_storage partition with host-generated keys dut.serial.custom_flash_with_host_gen_sec_stg_img() @@ -459,10 +505,11 @@ def test_esp_tee_secure_storage_with_host_img(dut: IdfDut) -> None: # ---------------- TEE Attestation tests ---------------- -@pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA, + indirect=['config', 'target', 'skip_autoflash'], +) def test_esp_tee_attestation(dut: IdfDut) -> None: # Flash image and erase the secure_storage partition dut.serial.custom_flash_with_empty_sec_stg() diff --git a/components/heap/port/esp32h2/memory_layout.c b/components/heap/port/esp32h2/memory_layout.c index 224e2ec454..05071759e9 100644 --- a/components/heap/port/esp32h2/memory_layout.c +++ b/components/heap/port/esp32h2/memory_layout.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-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. @@ -94,6 +99,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 diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index fe61d2468f..6f3b849273 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -22,15 +22,18 @@ #if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN #include "esp_tee_sec_storage.h" -#else -#include "hal/ecc_ll.h" +#endif +#if SOC_ECDSA_SUPPORTED #include "hal/ecdsa_ll.h" #include "hal/ecdsa_hal.h" +#include "esp_efuse.h" +#endif +#if SOC_ECC_SUPPORTED +#include "hal/ecc_ll.h" +#endif #if SOC_MPI_SUPPORTED #include "hal/mpi_ll.h" #endif -#include "esp_efuse.h" -#endif #define ECDSA_KEY_MAGIC (short) 0xECD5A #define ECDSA_KEY_MAGIC_TEE (short) 0xA5DCE diff --git a/components/soc/esp32h2/include/soc/interrupt_reg.h b/components/soc/esp32h2/include/soc/interrupt_reg.h index 7e870b5410..3cbbecdbf0 100644 --- a/components/soc/esp32h2/include/soc/interrupt_reg.h +++ b/components/soc/esp32h2/include/soc/interrupt_reg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,16 +9,36 @@ #include "soc/plic_reg.h" #include "soc/soc_caps.h" +#ifdef __has_include +# if __has_include("sdkconfig.h") +# include "sdkconfig.h" +# endif +#endif + +#if CONFIG_SECURE_ENABLE_TEE +#define INTERRUPT_PRIO_REG(n) (PLIC_UXINT0_PRI_REG + (n)*4) +#define INTERRUPT_CURRENT_CORE_INT_THRESH_REG PLIC_UXINT_THRESH_REG +#else #define INTERRUPT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4) #define INTERRUPT_CURRENT_CORE_INT_THRESH_REG PLIC_MXINT_THRESH_REG +#endif /** * ESP32H2 should use the PLIC controller as the interrupt controller instead of INTC (SOC_INT_PLIC_SUPPORTED = y) * Keep the following macros for backward compatibility reasons */ +#if CONFIG_SECURE_ENABLE_TEE +#define INTERRUPT_CORE0_CPU_INT_ENABLE_REG PLIC_UXINT_ENABLE_REG +#define INTERRUPT_CORE0_CPU_INT_THRESH_REG PLIC_UXINT_THRESH_REG +#define INTERRUPT_CORE0_CPU_INT_CLEAR_REG PLIC_UXINT_CLEAR_REG +#define INTERRUPT_CORE0_CPU_INT_TYPE_REG PLIC_UXINT_TYPE_REG +#define INTC_INT_PRIO_REG(n) (PLIC_UXINT0_PRI_REG + (n)*4) +#else #define INTERRUPT_CORE0_CPU_INT_ENABLE_REG PLIC_MXINT_ENABLE_REG #define INTERRUPT_CORE0_CPU_INT_THRESH_REG PLIC_MXINT_THRESH_REG #define INTERRUPT_CORE0_CPU_INT_CLEAR_REG PLIC_MXINT_CLEAR_REG #define INTERRUPT_CORE0_CPU_INT_TYPE_REG PLIC_MXINT_TYPE_REG #define INTC_INT_PRIO_REG(n) (PLIC_MXINT0_PRI_REG + (n)*4) +#endif + #define DR_REG_INTERRUPT_BASE DR_REG_INTMTX_BASE diff --git a/components/soc/esp32h2/register/soc/clint_reg.h b/components/soc/esp32h2/register/soc/clint_reg.h index 828ff818b7..7677ed68cf 100644 --- a/components/soc/esp32h2/register/soc/clint_reg.h +++ b/components/soc/esp32h2/register/soc/clint_reg.h @@ -11,6 +11,7 @@ extern "C" { #define DR_REG_CLINT_M_BASE ( 0x20001800) #define DR_REG_CLINT_U_BASE ( 0x20001C00) +#define DR_REG_CLINT_U_END ( 0x20002000) /*CLINT MINT*/ #define CLINT_MINT_SIP_REG (DR_REG_CLINT_M_BASE + 0x0) diff --git a/components/soc/esp32h2/register/soc/plic_reg.h b/components/soc/esp32h2/register/soc/plic_reg.h index b744601310..8f1944e63f 100644 --- a/components/soc/esp32h2/register/soc/plic_reg.h +++ b/components/soc/esp32h2/register/soc/plic_reg.h @@ -12,6 +12,7 @@ extern "C" { #define DR_REG_PLIC_MX_BASE ( 0x20001000 ) #define DR_REG_PLIC_UX_BASE ( 0x20001400 ) +#define DR_REG_PLIC_UX_END ( 0x20001800 ) #define PLIC_MXINT_CONF_REG ( 0x200013FC ) #define PLIC_UXINT_CONF_REG ( 0x200017FC )