From b471faf803e117314f00ee977a918efdaa9c4b5e Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Tue, 19 May 2026 19:41:32 +0530 Subject: [PATCH] fix(esp_tee): Harden the TEE secure services against REE manipulation - `bootloader_flash_execute_command_common`: whitelist the flash command opcodes the REE actually uses; reject the rest - `spi_flash_hal_* services`: a forged `host->driver` could hijack TEE control flow since the HAL dispatches through it, so swap `host->driver` to a TEE-rodata vtable around each HAL call - Deny partition table and bootloader writes by default and permit bootloader writes only when explicitly enabled via `CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED` option - Protect the TEE-assigned interrupt pin configuration against REE - Validate nested DS context pointers in start/finish_sign and bound the result copy to the SoC max signature size - Fix the stack usage in service dispatcher argument parsing --- .../esp_tee/include/private/esp_tee_binary.h | 7 +- .../components/tee_flash_mgr/esp_tee_flash.c | 36 +++- .../tee_flash_mgr/include/esp_tee_flash.h | 14 +- .../main/core/esp_secure_dispatcher.c | 16 +- .../main/core/esp_secure_services.c | 24 ++- .../main/core/esp_secure_services_iram.c | 180 +++++++++++++++--- .../main/include/esp_tee_memory_utils.h | 9 +- .../main/soc/esp32c5/esp_tee_secure_sys_cfg.c | 9 +- .../main/soc/esp32c6/esp_tee_secure_sys_cfg.c | 10 +- .../main/soc/esp32h2/esp_tee_secure_sys_cfg.c | 12 +- 10 files changed, 251 insertions(+), 66 deletions(-) diff --git a/components/esp_tee/include/private/esp_tee_binary.h b/components/esp_tee/include/private/esp_tee_binary.h index c66f3ad617d..62287abd312 100644 --- a/components/esp_tee/include/private/esp_tee_binary.h +++ b/components/esp_tee/include/private/esp_tee_binary.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,11 @@ extern "C" { #define TEE_SECURE_INUM (31) #if SOC_INT_CLIC_SUPPORTED #define TEE_PASS_INUM (30) +/* CLIC: 3 effective priority bits (NLBITS=3), max priority = 7 */ +#define TEE_SECURE_INUM_PRIO (7) +#else +/* PLIC: 4-bit priority field, max priority = 15 */ +#define TEE_SECURE_INUM_PRIO (15) #endif #define ESP_TEE_M2U_SWITCH_MAGIC 0xfedef diff --git a/components/esp_tee/subproject/components/tee_flash_mgr/esp_tee_flash.c b/components/esp_tee/subproject/components/tee_flash_mgr/esp_tee_flash.c index 0f979de7011..f6badae0c1b 100644 --- a/components/esp_tee/subproject/components/tee_flash_mgr/esp_tee_flash.c +++ b/components/esp_tee/subproject/components/tee_flash_mgr/esp_tee_flash.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "esp_err.h" #include "esp_log.h" +#include "bootloader_flash_priv.h" #include "bootloader_utility_tee.h" #include "esp_tee_ota_utils.h" @@ -17,6 +18,8 @@ #include "esp_tee_flash.h" #include "sdkconfig.h" +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + static const char *TAG = "esp_tee_flash"; // Structure containing the valid flash address range for flash operations through TEE @@ -169,8 +172,8 @@ esp_err_t esp_tee_flash_setup_prot_ctx(uint8_t tee_boot_part) if (subtype == PART_SUBTYPE_DATA_TEE_OTA) { needs_protection = true; } else if (subtype == PART_SUBTYPE_DATA_WIFI) { - size_t label_len = strlen(ESP_TEE_SEC_STG_PART_LABEL); - if (memcmp(partition_entry->partition.label, ESP_TEE_SEC_STG_PART_LABEL, label_len) == 0) { + if (strncmp((const char *)partition_entry->partition.label, ESP_TEE_SEC_STG_PART_LABEL, + sizeof(partition_entry->partition.label)) == 0) { needs_protection = true; } } @@ -241,3 +244,30 @@ bool esp_tee_flash_check_prange_in_active_tee_part(const size_t paddr, const siz return ((paddr < tee_prot_ctx.active_part_end_paddr) && (paddr_end > tee_prot_ctx.active_part_start_paddr)); } + +bool esp_tee_flash_check_prange_write_protected(const size_t paddr, const size_t len) +{ + size_t paddr_start = paddr; + if (len == FLASH_SECTOR_SIZE || len == FLASH_BLOCK_SIZE) { + paddr_start &= ~(len - 1); + } + + size_t paddr_end = paddr_start + len; + if (paddr_end < paddr_start) { + return true; + } + + const size_t ptb_start = CONFIG_PARTITION_TABLE_OFFSET; + const size_t ptb_end = ALIGN_UP(CONFIG_PARTITION_TABLE_OFFSET + ESP_PARTITION_TABLE_MAX_LEN, FLASH_SECTOR_SIZE); + bool ptb_overlap = (paddr_start < ptb_end) && (paddr_end > ptb_start); + + /* Bootloader: write-protected unless dangerous writes are explicitly allowed. */ + bool btl_overlap = false; +#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED + const size_t btl_start = CONFIG_BOOTLOADER_OFFSET_IN_FLASH; + const size_t btl_end = CONFIG_PARTITION_TABLE_OFFSET; + btl_overlap = (paddr_start < btl_end) && (paddr_end > btl_start); +#endif + + return (ptb_overlap || btl_overlap); +} diff --git a/components/esp_tee/subproject/components/tee_flash_mgr/include/esp_tee_flash.h b/components/esp_tee/subproject/components/tee_flash_mgr/include/esp_tee_flash.h index 631cc3d6cb3..decf09702a9 100644 --- a/components/esp_tee/subproject/components/tee_flash_mgr/include/esp_tee_flash.h +++ b/components/esp_tee/subproject/components/tee_flash_mgr/include/esp_tee_flash.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -133,3 +133,15 @@ bool esp_tee_flash_check_prange_in_tee_region(const size_t paddr, const size_t l * @return bool true if any part of the range overlaps with active TEE partition, false otherwise */ bool esp_tee_flash_check_prange_in_active_tee_part(const size_t paddr, const size_t len); + +/** + * @brief Check if the given physical address range overlaps a write-protected flash region. + * The partition table is always protected; the bootloader is protected unless + * CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is set. Use only for write/erase operations. + * + * @param paddr Starting physical address of the range to check + * @param len Length of the address range in bytes + * + * @return bool true if the range overlaps the write-protected region, false otherwise + */ +bool esp_tee_flash_check_prange_write_protected(const size_t paddr, const size_t len); diff --git a/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c b/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c index 2b77e1fa7f5..43fe6117f10 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c +++ b/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,7 +53,7 @@ int esp_tee_service_dispatcher(int argc, va_list ap) argc--; const secure_service_entry_t *service = find_service_by_id(sid); - if (service == NULL) { + if (service == NULL || service->func == NULL) { ESP_LOGE(TAG, "Invalid service ID!"); return ret; } @@ -71,13 +71,16 @@ int esp_tee_service_dispatcher(int argc, va_list ap) uint32_t *argp = &argv[0]; asm volatile( + // Reserve outgoing-argument area for stack args 9+ + "addi sp, sp, -16 \n" + "mv t0, %1 \n" // t0 = argc "mv t1, %3 \n" // t1 = argp "li t2, 8 \n" // t2 = 8 (max register args) "ble t0, t2, load_regs \n" // If argc <= 8 (a0-a7), skip stack routine - // Store extra args (argc > 8) on stack + // Store extra args (argc > 8) on the reserved area "mv t3, sp \n" "addi t1, t1, 32 \n" @@ -87,7 +90,7 @@ int esp_tee_service_dispatcher(int argc, va_list ap) "addi t1, t1, 4 \n" "addi t3, t3, 4 \n" "addi t0, t0, -1 \n" - "bge t0, t2, stack_loop \n" + "bgt t0, t2, stack_loop \n" // Load the first 8 arguments into a0-a7 "load_regs: \n" @@ -104,10 +107,13 @@ int esp_tee_service_dispatcher(int argc, va_list ap) "mv t1, %2 \n" // Load function pointer "jalr 0(t1) \n" // Call function "mv %0, a0 \n" // Store return value + + // Restore the outgoing-argument area + "addi sp, sp, 16 \n" : "=r"(ret) : "r"(argc), "r"(fp_secure_service), "r"(argp) : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", - "t0", "t1", "t2", "t3", "t4" + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "ra", "memory" ); return ret; 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 a044b9a3574..616ea50ae8e 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -358,10 +358,15 @@ esp_err_t _ss_esp_hmac_jtag_disable(void) static size_t get_ds_msg_sign_len(esp_digital_signature_length_t rsa_length) { - if (rsa_length != ESP_DS_RSA_1024 && rsa_length != ESP_DS_RSA_2048 && - rsa_length != ESP_DS_RSA_3072 && rsa_length != ESP_DS_RSA_4096) { + + if (rsa_length != ESP_DS_RSA_1024 && rsa_length != ESP_DS_RSA_2048 && rsa_length != ESP_DS_RSA_3072 +#if SOC_DS_SIGNATURE_MAX_BIT_LEN == 4096 + && rsa_length != ESP_DS_RSA_4096 +#endif + ) { return 0; } + return (size_t)(rsa_length + 1) * 4; } @@ -397,6 +402,7 @@ esp_err_t _ss_esp_ds_start_sign(const void *message, esp_ds_context_t **esp_ds_ctx) { bool valid_addr = (esp_tee_buf_in_ree(esp_ds_ctx, sizeof(esp_ds_context_t *)) && + esp_tee_buf_in_ree(*esp_ds_ctx, sizeof(esp_ds_context_t)) && esp_tee_buf_in_ree(data, sizeof(esp_ds_data_t))); if (!valid_addr) { return ESP_ERR_INVALID_ARG; @@ -425,8 +431,16 @@ bool _ss_esp_ds_is_busy(void) esp_err_t _ss_esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx) { - const size_t max_sign = get_ds_msg_sign_len(ESP_DS_RSA_4096); - bool valid_addr = esp_tee_buf_in_ree(signature, max_sign); + const size_t max_sign = SOC_DS_SIGNATURE_MAX_BIT_LEN / 8; + bool valid_addr = (esp_tee_buf_in_ree(signature, max_sign) && + esp_tee_buf_in_ree(esp_ds_ctx, sizeof(esp_ds_context_t))); + if (!valid_addr) { + return ESP_ERR_INVALID_ARG; + } + + const esp_ds_data_t *data = (const esp_ds_data_t *)esp_ds_ctx->data; + valid_addr &= esp_tee_buf_in_ree(data, sizeof(esp_ds_data_t)) && + (get_ds_msg_sign_len(data->rsa_length) > 0); if (!valid_addr) { return ESP_ERR_INVALID_ARG; diff --git a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c index b3881531f5c..a076d8c3391 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_err.h" #include "esp_log.h" @@ -17,10 +18,12 @@ #include "hal/spi_flash_hal.h" #include "hal/spi_flash_types.h" #include "spi_flash_chip_generic.h" +#include "spi_flash/spi_flash_defs.h" #include "memspi_host_driver.h" #include "esp_private/mspi_timing_tuning.h" #include "esp_flash.h" #include "riscv/rv_utils.h" +#include "soc/soc.h" #include "esp_tee.h" #include "esp_tee_memory_utils.h" @@ -35,28 +38,49 @@ static __attribute__((unused)) const char *TAG = "esp_tee_sec_srv_iram"; /* ---------------------------------------------- Interrupts ------------------------------------------------- */ +#if SOC_INT_CLIC_SUPPORTED +#define TEE_RESERVED_INTR_MASK ((1U << TEE_SECURE_INUM) | (1U << TEE_PASS_INUM)) +#else +#define TEE_RESERVED_INTR_MASK ((1U << TEE_SECURE_INUM)) +#endif + +static inline bool is_intr_num_invalid(uint32_t intr_num) +{ + return (intr_num >= (uint32_t)SOC_CPU_INTR_NUM) || + (((1U << intr_num) & TEE_RESERVED_INTR_MASK) != 0U); +} + void _ss_esp_rom_route_intr_matrix(int cpu_no, uint32_t model_num, uint32_t intr_num) { + if (is_intr_num_invalid(intr_num)) { + return; + } return esp_tee_route_intr_matrix(cpu_no, model_num, intr_num); } void _ss_rv_utils_intr_enable(uint32_t intr_mask) { - rv_utils_tee_intr_enable(intr_mask); + rv_utils_tee_intr_enable(intr_mask & ~TEE_RESERVED_INTR_MASK); } void _ss_rv_utils_intr_disable(uint32_t intr_mask) { - rv_utils_tee_intr_disable(intr_mask); + rv_utils_tee_intr_disable(intr_mask & ~TEE_RESERVED_INTR_MASK); } void _ss_rv_utils_intr_set_priority(int rv_int_num, int priority) { + if (is_intr_num_invalid((uint32_t)rv_int_num)) { + return; + } rv_utils_tee_intr_set_priority(rv_int_num, priority); } void _ss_rv_utils_intr_set_type(int intr_num, enum intr_type type) { + if (is_intr_num_invalid((uint32_t)intr_num)) { + return; + } rv_utils_tee_intr_set_type(intr_num, type); } @@ -67,6 +91,9 @@ void _ss_rv_utils_intr_set_threshold(int priority_threshold) void _ss_rv_utils_intr_edge_ack(uint32_t intr_num) { + if (is_intr_num_invalid(intr_num)) { + return; + } rv_utils_intr_edge_ack(intr_num); } @@ -107,6 +134,9 @@ void _ss_rv_utils_wfe_mode_enable(bool en) #if SOC_INT_CLIC_SUPPORTED void _ss_esprv_int_set_vectored(int rv_int_num, bool vectored) { + if (is_intr_num_invalid((uint32_t)rv_int_num)) { + return; + } esprv_int_set_vectored(rv_int_num, vectored); } #endif @@ -290,16 +320,31 @@ void _ss_Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size) #if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 /* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */ +#define FLASH_ADDR_MAX_24BIT (0xFFFFFFU) + +static bool is_flash_addr_writable(uint32_t paddr, uint32_t len) +{ + return !esp_tee_flash_check_prange_in_tee_region(paddr, len) && + !esp_tee_flash_check_prange_write_protected(paddr, len); +} + +static bool is_flash_addr_readable(uint32_t paddr, uint32_t len) +{ + return !esp_tee_flash_check_prange_in_tee_region(paddr, len); +} + static bool is_spi_host_in_ree(spi_flash_host_inst_t *host) { - return esp_tee_buf_in_ree(host, sizeof(spi_flash_host_inst_t)); + return esp_tee_buf_in_ree(host, sizeof(spi_flash_hal_context_t)); } static bool is_spi_trans_valid(spi_flash_host_inst_t *host, spi_flash_trans_t *trans) { - bool valid_addr = (is_spi_host_in_ree(host) && - esp_tee_buf_in_ree(trans, sizeof(spi_flash_trans_t))); + if (!is_spi_host_in_ree(host) || !esp_tee_buf_in_ree(trans, sizeof(spi_flash_trans_t))) { + return false; + } + bool valid_addr = true; if (trans->mosi_len != 0) { valid_addr &= esp_tee_buf_in_ree(trans->mosi_data, trans->mosi_len); } @@ -309,6 +354,37 @@ static bool is_spi_trans_valid(spi_flash_host_inst_t *host, spi_flash_trans_t *t return valid_addr; } +static bool is_spi_cmd_addr_ok(uint32_t addr_bitlen, uint32_t address, uint32_t mosi_len, uint32_t miso_len) +{ + if (addr_bitlen == 0) { + return true; + } + + if (addr_bitlen < 32U && address > ((1U << addr_bitlen) - 1U)) { + return false; + } + + uint32_t data_len = MAX(1, MAX(mosi_len, miso_len)); + return is_flash_addr_writable(address, data_len); +} + +extern void spi_flash_hal_poll_cmd_done(spi_flash_host_inst_t *host); +extern esp_err_t spi_flash_hal_configure_host_io_mode(spi_flash_host_inst_t *host, uint32_t command, + uint32_t addr_bitlen, int dummy_cyclelen_base, + esp_flash_io_mode_t io_mode); + +static const spi_flash_host_driver_t tee_host_driver = { + .poll_cmd_done = spi_flash_hal_poll_cmd_done, + .configure_host_io_mode = spi_flash_hal_configure_host_io_mode, +}; + +static inline const spi_flash_host_driver_t *tee_substitute_host_driver(spi_flash_host_inst_t *host) +{ + const spi_flash_host_driver_t *orig = host->driver; + host->driver = &tee_host_driver; + return orig; +} + uint32_t _ss_spi_flash_hal_check_status(spi_flash_host_inst_t *host) { bool valid_addr = is_spi_host_in_ree(host); @@ -323,17 +399,23 @@ uint32_t _ss_spi_flash_hal_check_status(spi_flash_host_inst_t *host) esp_err_t _ss_spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans) { - bool valid_addr = (is_spi_trans_valid(host, trans) && - !esp_tee_flash_check_prange_in_tee_region(trans->address, trans->mosi_len) && - !esp_tee_flash_check_prange_in_tee_region(trans->address, trans->miso_len)); + bool trans_valid = is_spi_trans_valid(host, trans); + if (!trans_valid) { + return ESP_ERR_INVALID_ARG; + } + ESP_FAULT_ASSERT(trans_valid); - if (!valid_addr) { + bool addr_ok = is_spi_cmd_addr_ok(trans->address_bitlen, trans->address, trans->mosi_len, trans->miso_len); + if (!addr_ok) { ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, trans->address); return ESP_ERR_INVALID_ARG; } - ESP_FAULT_ASSERT(valid_addr); + ESP_FAULT_ASSERT(addr_ok); - return spi_flash_hal_common_command(host, trans); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); + esp_err_t r = spi_flash_hal_common_command(host, trans); + host->driver = orig; + return r; } esp_err_t _ss_spi_flash_hal_device_config(spi_flash_host_inst_t *host) @@ -351,7 +433,8 @@ esp_err_t _ss_spi_flash_hal_device_config(spi_flash_host_inst_t *host) void _ss_spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_address) { bool valid_addr = (is_spi_host_in_ree(host) && - !esp_tee_flash_check_paddr_in_tee_region(start_address)); + start_address <= FLASH_ADDR_MAX_24BIT && + is_flash_addr_writable(start_address, FLASH_BLOCK_SIZE)); if (!valid_addr) { ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address); @@ -359,13 +442,16 @@ void _ss_spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_a } ESP_FAULT_ASSERT(valid_addr); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); spi_flash_hal_erase_block(host, start_address); + host->driver = orig; } void _ss_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address) { bool valid_addr = (is_spi_host_in_ree(host) && - !esp_tee_flash_check_prange_in_tee_region(start_address, FLASH_SECTOR_SIZE)); + start_address <= FLASH_ADDR_MAX_24BIT && + is_flash_addr_writable(start_address, FLASH_SECTOR_SIZE)); if (!valid_addr) { ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address); @@ -373,13 +459,16 @@ void _ss_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_ } ESP_FAULT_ASSERT(valid_addr); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); spi_flash_hal_erase_sector(host, start_address); + host->driver = orig; } void _ss_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length) { bool valid_addr = (is_spi_host_in_ree(host) && - !esp_tee_flash_check_prange_in_tee_region(address, length) && + address <= FLASH_ADDR_MAX_24BIT && + is_flash_addr_writable(address, length) && esp_tee_buf_in_ree(buffer, length)); if (!valid_addr) { @@ -388,13 +477,15 @@ void _ss_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buf } ESP_FAULT_ASSERT(valid_addr); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); spi_flash_hal_program_page(host, buffer, address, length); + host->driver = orig; } esp_err_t _ss_spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len) { bool valid_addr = (is_spi_host_in_ree(host) && - !esp_tee_flash_check_prange_in_tee_region(address, read_len) && + is_flash_addr_readable(address, read_len) && esp_tee_buf_in_ree(buffer, read_len)); if (!valid_addr) { @@ -403,7 +494,10 @@ esp_err_t _ss_spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint } ESP_FAULT_ASSERT(valid_addr); - return spi_flash_hal_read(host, buffer, address, read_len); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); + esp_err_t r = spi_flash_hal_read(host, buffer, address, read_len); + host->driver = orig; + return r; } void _ss_spi_flash_hal_resume(spi_flash_host_inst_t *host) @@ -415,7 +509,9 @@ void _ss_spi_flash_hal_resume(spi_flash_host_inst_t *host) } ESP_FAULT_ASSERT(valid_addr); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); spi_flash_hal_resume(host); + host->driver = orig; } esp_err_t _ss_spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp) @@ -427,7 +523,10 @@ esp_err_t _ss_spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool } ESP_FAULT_ASSERT(valid_addr); - return spi_flash_hal_set_write_protect(host, wp); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); + esp_err_t r = spi_flash_hal_set_write_protect(host, wp); + host->driver = orig; + return r; } esp_err_t _ss_spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf) @@ -476,7 +575,9 @@ void _ss_spi_flash_hal_suspend(spi_flash_host_inst_t *host) } ESP_FAULT_ASSERT(valid_addr); + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); spi_flash_hal_suspend(host); + host->driver = orig; } /* ---------------------------------------------- SPI Flash Extras ------------------------------------------------- */ @@ -485,6 +586,22 @@ extern uint32_t bootloader_flash_execute_command_common(uint8_t command, uint32_ uint8_t dummy_len, uint8_t mosi_len, uint32_t mosi_data, uint8_t miso_len); +static inline bool ree_flash_cmd_allowed(uint8_t cmd) +{ + switch (cmd) { + case CMD_WRSR3: /* 0x11 - write status register 3 */ + case CMD_RDSR3: /* 0x15 - read status register 3 */ + case CMD_WRENVSR: /* 0x50 - write enable for volatile SR */ + case CMD_WRAP: /* 0x77 - flash wrap enable/clear (alt) */ + case CMD_RDID: /* 0x9F - read chip ID */ + case CMD_HPMEN: /* 0xA3 - HPM enable via command */ + case CMD_BURST_RD: /* 0xC0 - flash wrap enable/clear */ + return true; + default: + return false; + } +} + uint32_t _ss_bootloader_flash_execute_command_common( uint8_t command, uint32_t addr_len, uint32_t address, @@ -492,14 +609,18 @@ uint32_t _ss_bootloader_flash_execute_command_common( uint8_t mosi_len, uint32_t mosi_data, uint8_t miso_len) { - bool valid_addr = (!esp_tee_flash_check_prange_in_tee_region(address, mosi_len) && - !esp_tee_flash_check_prange_in_tee_region(address, miso_len)); + if (!ree_flash_cmd_allowed(command)) { + ESP_LOGD(TAG, "[%s] Disallowed flash command 0x%02x from REE", __func__, command); + return 0; + } + ESP_FAULT_ASSERT(ree_flash_cmd_allowed(command)); - if (!valid_addr) { + bool addr_ok = is_spi_cmd_addr_ok(addr_len, address, mosi_len / 8U, miso_len / 8U); + if (!addr_ok) { ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address); return 0; } - ESP_FAULT_ASSERT(valid_addr); + ESP_FAULT_ASSERT(addr_ok); return bootloader_flash_execute_command_common(command, addr_len, address, dummy_len, mosi_len, mosi_data, miso_len); @@ -508,7 +629,7 @@ uint32_t _ss_bootloader_flash_execute_command_common( esp_err_t _ss_memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size) { bool valid_addr = (is_spi_host_in_ree(host) && - !esp_tee_flash_check_prange_in_tee_region(addr, size)); + is_flash_addr_readable(addr, size)); if (!valid_addr) { return ESP_ERR_INVALID_ARG; @@ -520,14 +641,25 @@ esp_err_t _ss_memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr esp_err_t _ss_spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags) { - bool valid_addr = esp_tee_buf_in_ree(chip, sizeof(struct esp_flash_t)); + spi_flash_host_inst_t *host = NULL; + bool valid_addr = (esp_tee_buf_in_ree(chip, sizeof(struct esp_flash_t)) && + is_spi_host_in_ree((host = chip->host))); if (!valid_addr) { return ESP_ERR_INVALID_ARG; } ESP_FAULT_ASSERT(valid_addr); - return spi_flash_chip_generic_config_host_io_mode(chip, flags); + esp_flash_t chip_snap = { + .host = host, + .read_mode = chip->read_mode, + .hpm_dummy_ena = chip->hpm_dummy_ena, + }; + + const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host); + esp_err_t r = spi_flash_chip_generic_config_host_io_mode(&chip_snap, flags); + host->driver = orig; + return r; } #if CONFIG_IDF_TARGET_ESP32C5 diff --git a/components/esp_tee/subproject/main/include/esp_tee_memory_utils.h b/components/esp_tee/subproject/main/include/esp_tee_memory_utils.h index 7ddb6a0cfb3..e3ec2f50dfa 100644 --- a/components/esp_tee/subproject/main/include/esp_tee_memory_utils.h +++ b/components/esp_tee/subproject/main/include/esp_tee_memory_utils.h @@ -38,8 +38,13 @@ FORCE_INLINE_ATTR bool esp_tee_buf_in_ree(const void *p, size_t len) return false; } - return esp_tee_ptr_in_ree(p) && - esp_tee_ptr_in_ree((const char *)p + len - 1); + uintptr_t end = start + len; + return ((start >= SOC_NS_IDRAM_START && end <= SOC_NS_IDRAM_END) || + (start >= (uintptr_t)esp_tee_app_config.ns_drom_start && end <= SOC_S_MMU_MMAP_RESV_START_VADDR) +#if SOC_RTC_MEM_SUPPORTED + || (start >= SOC_RTC_DATA_LOW && end <= SOC_RTC_DATA_HIGH) +#endif + ); } #ifdef __cplusplus diff --git a/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c index cec537a13c5..a6bff015e23 100644 --- a/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -70,14 +70,9 @@ void esp_tee_soc_secure_sys_init(void) REG_CLR_BIT(DR_REG_INTMTX_BASE + 4 * i, BIT(8)); } - /* TODO: IDF-8958 - * The values for the secure interrupt number and priority and - * the interrupt priority threshold (for both M and U mode) need - * to be investigated further - */ esprv_int_set_threshold(0); - esprv_int_set_priority(TEE_SECURE_INUM, 7); + esprv_int_set_priority(TEE_SECURE_INUM, TEE_SECURE_INUM_PRIO); esprv_int_set_type(TEE_SECURE_INUM, ESP_CPU_INTR_TYPE_LEVEL); esprv_int_enable(BIT(TEE_SECURE_INUM)); esprv_int_set_vectored(TEE_SECURE_INUM, true); 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 0802611ea03..71d0ae73666 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -68,13 +68,7 @@ void esp_tee_soc_secure_sys_init(void) esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM); } - /* TODO: IDF-8958 - * The values for the secure interrupt number and priority and - * the interrupt priority threshold (for both M and U mode) need - * to be investigated further - */ - /* 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_priority(TEE_SECURE_INUM, TEE_SECURE_INUM_PRIO); 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)); 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 index 1cd42774f35..61da60223a0 100644 --- 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -68,18 +68,10 @@ void esp_tee_soc_secure_sys_init(void) esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM); } - /* TODO: IDF-8958 - * The values for the secure interrupt number and priority and - * the interrupt priority threshold (for both M and U mode) need - * to be investigated further - */ -#ifdef SOC_CPU_HAS_FLEXIBLE_INTC - /* TODO: Currently, we do not allow interrupts to be set up with a priority greater than 7, see intr_alloc.c */ - esprv_int_set_priority(TEE_SECURE_INUM, 7); + esprv_int_set_priority(TEE_SECURE_INUM, TEE_SECURE_INUM_PRIO); 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));