fix(esp_tee): Correct flash operation bound checks to handle all overlap cases
- Ensure bound checks correctly handle all scenarios, including when a requested operation's (SPI0/1) range fully contains the TEE-protected region. - Disable delegation of INTWDT timeout and Cache error interrupts as they reset the device after the panic handler
This commit is contained in:
@@ -138,7 +138,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "rom/spi_flash.h"
|
||||
|
||||
extern bool esp_tee_flash_check_paddr_in_active_tee_part(size_t paddr);
|
||||
extern bool esp_tee_flash_check_prange_in_active_tee_part(const size_t paddr, const size_t len);
|
||||
#endif
|
||||
|
||||
static const char *TAG = "bootloader_flash";
|
||||
@@ -524,7 +524,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
* by validating the address before proceeding.
|
||||
*/
|
||||
#if ESP_TEE_BUILD
|
||||
bool addr_chk = esp_tee_flash_check_paddr_in_active_tee_part(dest_addr);
|
||||
bool addr_chk = esp_tee_flash_check_prange_in_active_tee_part(dest_addr, size);
|
||||
if (addr_chk) {
|
||||
ESP_EARLY_LOGE(TAG, "bootloader_flash_write invalid dest_addr");
|
||||
return ESP_FAIL;
|
||||
@@ -578,7 +578,7 @@ esp_err_t bootloader_flash_erase_sector(size_t sector)
|
||||
esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
{
|
||||
#if ESP_TEE_BUILD
|
||||
bool addr_chk = esp_tee_flash_check_paddr_in_active_tee_part(start_addr);
|
||||
bool addr_chk = esp_tee_flash_check_prange_in_active_tee_part(start_addr, size);
|
||||
if (addr_chk) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -208,3 +208,36 @@ bool esp_tee_flash_check_paddr_in_active_tee_part(const size_t paddr)
|
||||
{
|
||||
return ((paddr >= tee_prot_ctx.active_part_start_paddr) && (paddr < tee_prot_ctx.active_part_end_paddr));
|
||||
}
|
||||
|
||||
bool esp_tee_flash_check_vrange_in_tee_region(const size_t vaddr, const size_t len)
|
||||
{
|
||||
size_t vaddr_end = vaddr + len;
|
||||
if (vaddr_end < vaddr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prot_reg1_overlap = ((vaddr < SOC_S_IROM_HIGH) && (vaddr_end > SOC_S_DROM_LOW));
|
||||
bool prot_reg2_overlap = ((vaddr < SOC_MMU_END_VADDR) && (vaddr_end > SOC_S_MMU_MMAP_RESV_START_VADDR));
|
||||
|
||||
return (prot_reg1_overlap || prot_reg2_overlap);
|
||||
}
|
||||
|
||||
bool esp_tee_flash_check_prange_in_tee_region(const size_t paddr, const size_t len)
|
||||
{
|
||||
size_t paddr_end = paddr + len;
|
||||
if (paddr_end < paddr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ((paddr < tee_prot_ctx.flash_reg_end_paddr) && (paddr_end > tee_prot_ctx.flash_reg_start_paddr));
|
||||
}
|
||||
|
||||
bool esp_tee_flash_check_prange_in_active_tee_part(const size_t paddr, const size_t len)
|
||||
{
|
||||
size_t paddr_end = paddr + len;
|
||||
if (paddr_end < paddr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ((paddr < tee_prot_ctx.active_part_end_paddr) && (paddr_end > tee_prot_ctx.active_part_start_paddr));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -80,7 +80,7 @@ esp_partition_info_t *esp_tee_flash_get_running_ree_partition(void);
|
||||
/**
|
||||
* @brief Check if the given virtual address falls within the TEE flash protected region
|
||||
*
|
||||
* @param addr Virtual address to check
|
||||
* @param vaddr Virtual address to check
|
||||
*
|
||||
* @return bool true if address is within protected region, false otherwise
|
||||
*/
|
||||
@@ -89,7 +89,7 @@ bool esp_tee_flash_check_vaddr_in_tee_region(const size_t vaddr);
|
||||
/**
|
||||
* @brief Check if the given physical address falls within the TEE flash protected region
|
||||
*
|
||||
* @param addr Physical address to check
|
||||
* @param paddr Physical address to check
|
||||
*
|
||||
* @return bool true if address is within protected region, false otherwise
|
||||
*/
|
||||
@@ -98,8 +98,38 @@ bool esp_tee_flash_check_paddr_in_tee_region(const size_t paddr);
|
||||
/**
|
||||
* @brief Check if the given physical address falls within the active TEE partition
|
||||
*
|
||||
* @param dest_addr Physical address to check
|
||||
* @param paddr Physical address to check
|
||||
*
|
||||
* @return bool true if address is within active TEE partition, false otherwise
|
||||
*/
|
||||
bool esp_tee_flash_check_paddr_in_active_tee_part(const size_t paddr);
|
||||
|
||||
/**
|
||||
* @brief Check if the given virtual address range overlaps with TEE flash protected regions
|
||||
*
|
||||
* @param vaddr Starting virtual address of the range to check
|
||||
* @param len Length of the address range in bytes
|
||||
*
|
||||
* @return bool true if any part of the range overlaps with protected regions, false otherwise
|
||||
*/
|
||||
bool esp_tee_flash_check_vrange_in_tee_region(const size_t vaddr, const size_t len);
|
||||
|
||||
/**
|
||||
* @brief Check if the given physical address range overlaps with TEE flash protected region
|
||||
*
|
||||
* @param paddr Starting physical address of the range to check
|
||||
* @param len Length of the address range in bytes
|
||||
*
|
||||
* @return bool true if any part of the range overlaps with TEE protected region, false otherwise
|
||||
*/
|
||||
bool esp_tee_flash_check_prange_in_tee_region(const size_t paddr, const size_t len);
|
||||
|
||||
/**
|
||||
* @brief Check if the given physical address range overlaps with active TEE partition
|
||||
*
|
||||
* @param paddr Starting physical address of the range to check
|
||||
* @param len Length of the address range in bytes
|
||||
*
|
||||
* @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);
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
.equ RTNVAL, 0xc0de
|
||||
.equ ECALL_U_MODE, 0x8
|
||||
.equ ECALL_M_MODE, 0xb
|
||||
.equ TEE_INTR_DELEG_MASK, ~(1U << TEE_SECURE_INUM)
|
||||
/* NOTE: INTWDT timeout and Cache error interrupts trigger the panic
|
||||
* handler before reset, so they don’t need to be delegated. */
|
||||
.equ TEE_INTR_DELEG_MASK, ~((1U << TEE_SECURE_INUM) | (1U << ETS_INT_WDT_INUM) | (1U << ETS_CACHEERR_INUM))
|
||||
|
||||
.global esp_tee_global_interrupt_handler
|
||||
.global esp_tee_service_dispatcher
|
||||
|
||||
@@ -219,8 +219,8 @@ esp_err_t _ss_esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pb
|
||||
void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr,
|
||||
uint32_t paddr, uint32_t len, uint32_t *out_len)
|
||||
{
|
||||
bool vaddr_chk = esp_tee_flash_check_vaddr_in_tee_region(vaddr);
|
||||
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(paddr);
|
||||
bool vaddr_chk = esp_tee_flash_check_vrange_in_tee_region(vaddr, len);
|
||||
bool paddr_chk = esp_tee_flash_check_prange_in_tee_region(paddr, len);
|
||||
if (vaddr_chk || paddr_chk) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x | 0x%08x", __func__, vaddr, paddr);
|
||||
return;
|
||||
@@ -232,7 +232,7 @@ void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vad
|
||||
|
||||
void _ss_mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len)
|
||||
{
|
||||
bool vaddr_chk = esp_tee_flash_check_vaddr_in_tee_region(vaddr);
|
||||
bool vaddr_chk = esp_tee_flash_check_vrange_in_tee_region(vaddr, len);
|
||||
if (vaddr_chk) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, vaddr);
|
||||
return;
|
||||
@@ -279,7 +279,8 @@ 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 paddr_chk = esp_tee_flash_check_paddr_in_tee_region(trans->address);
|
||||
bool paddr_chk = esp_tee_flash_check_prange_in_tee_region(trans->address, trans->mosi_len);
|
||||
paddr_chk |= esp_tee_flash_check_prange_in_tee_region(trans->address, trans->miso_len);
|
||||
if (paddr_chk) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, trans->address);
|
||||
return ESP_FAIL;
|
||||
@@ -310,7 +311,7 @@ void _ss_spi_flash_hal_erase_chip(spi_flash_host_inst_t *host)
|
||||
|
||||
void _ss_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address)
|
||||
{
|
||||
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(start_address);
|
||||
bool paddr_chk = esp_tee_flash_check_prange_in_tee_region(start_address, FLASH_SECTOR_SIZE);
|
||||
if (paddr_chk) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
|
||||
return;
|
||||
@@ -321,7 +322,7 @@ void _ss_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_
|
||||
|
||||
void _ss_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)
|
||||
{
|
||||
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(address);
|
||||
bool paddr_chk = esp_tee_flash_check_prange_in_tee_region(address, length);
|
||||
if (paddr_chk) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
||||
return;
|
||||
@@ -338,7 +339,7 @@ void _ss_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buf
|
||||
|
||||
esp_err_t _ss_spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)
|
||||
{
|
||||
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(address);
|
||||
bool paddr_chk = esp_tee_flash_check_prange_in_tee_region(address, read_len);
|
||||
if (paddr_chk) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
||||
return ESP_FAIL;
|
||||
@@ -396,10 +397,11 @@ uint32_t _ss_bootloader_flash_execute_command_common(
|
||||
uint8_t mosi_len, uint32_t mosi_data,
|
||||
uint8_t miso_len)
|
||||
{
|
||||
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(address);
|
||||
bool paddr_chk = esp_tee_flash_check_prange_in_tee_region(address, mosi_len);
|
||||
paddr_chk |= esp_tee_flash_check_prange_in_tee_region(address, miso_len);
|
||||
if (paddr_chk) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
||||
return ESP_FAIL;
|
||||
return 0;
|
||||
}
|
||||
ESP_FAULT_ASSERT(!paddr_chk);
|
||||
return bootloader_flash_execute_command_common(command, addr_len, address, dummy_len,
|
||||
@@ -408,7 +410,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 paddr_chk = esp_tee_flash_check_paddr_in_tee_region(addr);
|
||||
bool paddr_chk = esp_tee_flash_check_prange_in_tee_region(addr, size);
|
||||
if (paddr_chk) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -250,6 +250,16 @@ TEST_CASE_MULTIPLE_STAGES("Test REE-TEE isolation: Flash - SPI0 (spi_flash_mmap)
|
||||
test_initial_boot, test_spi_flash_mmap_api, test_spi_flash_mmap_api,
|
||||
test_spi_flash_mmap_api);
|
||||
|
||||
TEST_CASE("Test REE-TEE isolation: MMU-spillover", "[exception]")
|
||||
{
|
||||
const void *ptr;
|
||||
spi_flash_mmap_handle_t handle;
|
||||
const size_t len = 0x100000; // 1MB
|
||||
TEST_ESP_OK(spi_flash_mmap(0x00, len, SPI_FLASH_MMAP_DATA, &ptr, &handle));
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 32, ESP_LOG_INFO);
|
||||
TEST_FAIL_MESSAGE("Exception should have been generated!");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------- API family 3: esp_flash ------------------------------------------------- */
|
||||
|
||||
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
|
||||
|
||||
@@ -52,6 +52,7 @@ REE_ISOLATION_TEST_EXC_RSN: Dict[str, str] = {
|
||||
('IROM-W1'): 'Store access fault',
|
||||
('DROM-R1'): 'Load access fault',
|
||||
('DROM-W1'): 'Store access fault',
|
||||
('MMU-spillover'): 'Cache error',
|
||||
}
|
||||
|
||||
TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR', 'SWDT/BOD']
|
||||
|
||||
@@ -117,6 +117,12 @@ TEST_CASE("Test esp_sha()", "[hw_crypto]")
|
||||
#endif
|
||||
}
|
||||
|
||||
/* NOTE: This test attempts to mmap 1MB of flash starting from address 0x00, which overlaps
|
||||
* the entire TEE protected region, causing the mmap operation to fail and triggering an
|
||||
* exception in the subsequent steps.
|
||||
*/
|
||||
#if !CONFIG_SECURE_ENABLE_TEE
|
||||
|
||||
TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]")
|
||||
{
|
||||
int r = -1;
|
||||
@@ -173,6 +179,7 @@ TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]")
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if CONFIG_MBEDTLS_HARDWARE_SHA
|
||||
|
||||
|
||||
Reference in New Issue
Block a user