From 6af1af7d995aa60e900a922c3b51f8f8b7f9ae2a 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 | 5 + .../components/tee_flash_mgr/esp_tee_flash.c | 36 +++- .../tee_flash_mgr/include/esp_tee_flash.h | 12 ++ .../main/core/esp_secure_dispatcher.c | 16 +- .../main/core/esp_secure_services.c | 22 ++- .../main/core/esp_secure_services_iram.c | 181 +++++++++++++++--- .../main/include/esp_tee_memory_utils.h | 9 +- .../main/soc/esp32c5/esp_tee_secure_sys_cfg.c | 7 +- .../main/soc/esp32c6/esp_tee_secure_sys_cfg.c | 8 +- .../main/soc/esp32c61/esp_tee_apm_prot_cfg.c | 4 +- .../soc/esp32c61/esp_tee_secure_sys_cfg.c | 7 +- .../main/soc/esp32h2/esp_tee_secure_sys_cfg.c | 10 +- 12 files changed, 249 insertions(+), 68 deletions(-) diff --git a/components/esp_tee/include/private/esp_tee_binary.h b/components/esp_tee/include/private/esp_tee_binary.h index 5196dad1107..908e8b4a15c 100644 --- a/components/esp_tee/include/private/esp_tee_binary.h +++ b/components/esp_tee/include/private/esp_tee_binary.h @@ -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..379818c0a6f 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 @@ -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 1760d809515..ee176d437ab 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.c @@ -379,10 +379,15 @@ esp_err_t _ss_esp_hmac_jtag_disable(void) #if SOC_DIG_SIGN_SUPPORTED 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; } @@ -418,6 +423,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; @@ -446,8 +452,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 c5b5092bc2c..7280d074749 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,11 +18,14 @@ #include "hal/spi_flash_hal.h" #include "hal/spi_flash_types.h" #include "esp_flash_chips/spi_flash_chip_generic.h" +#include "esp_flash_chips/spi_flash_defs.h" #include "esp_private/memspi_host_driver.h" #include "esp_private/mspi_timing_tuning.h" #include "esp_flash.h" #include "esp_flash_chips/esp_flash_types.h" +#include "bootloader_flash_priv.h" #include "riscv/rv_utils.h" +#include "soc/soc.h" #include "esp_tee.h" #include "esp_tee_memory_utils.h" @@ -36,28 +40,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); } @@ -68,6 +93,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); } @@ -108,6 +136,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 @@ -291,16 +322,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); } @@ -310,6 +356,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); @@ -324,17 +401,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) @@ -352,7 +435,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); @@ -360,13 +444,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); @@ -374,13 +461,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) { @@ -389,13 +479,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) { @@ -404,7 +496,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) @@ -416,7 +511,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) @@ -428,7 +525,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) @@ -477,7 +577,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 ------------------------------------------------- */ @@ -486,6 +588,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, @@ -493,14 +611,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); @@ -509,7 +631,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; @@ -521,14 +643,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 86e30ce1315..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 @@ -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 1da37191afa..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 @@ -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/esp32c61/esp_tee_apm_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32c61/esp_tee_apm_prot_cfg.c index b3e963aca59..c0526d99b77 100644 --- a/components/esp_tee/subproject/main/soc/esp32c61/esp_tee_apm_prot_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c61/esp_tee_apm_prot_cfg.c @@ -55,9 +55,9 @@ static const char *TAG = "esp_tee_apm_prot_cfg"; /* NOTE: Super-Watchdog and Brownout Detector protection */ #define LP_APM_SWD_REG_START (LP_WDT_SWD_CONFIG_REG) -#define LP_APM_SWD_REG_END (LP_WDT_INT_CLR_REG) +#define LP_APM_SWD_REG_END (LP_WDT_INT_CLR_REG + 4U) #define LP_APM_BOD_REG_START (LP_ANA_BOD_MODE0_CNTL_REG) -#define LP_APM_BOD_REG_END (LP_ANA_LP_INT_CLR_REG) +#define LP_APM_BOD_REG_END (LP_ANA_LP_INT_CLR_REG + 4U) /* NOTE: Following are the master IDs for setting the security mode and access through APM: * +---------+-------------+ diff --git a/components/esp_tee/subproject/main/soc/esp32c61/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32c61/esp_tee_secure_sys_cfg.c index 46cba5c6dee..b1e302bc9b4 100644 --- a/components/esp_tee/subproject/main/soc/esp32c61/esp_tee_secure_sys_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c61/esp_tee_secure_sys_cfg.c @@ -68,14 +68,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/esp32h2/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c index 397329461f1..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 @@ -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));