feat(esp_tee): Add support for flash memory isolation and protection (SPI1)

This commit is contained in:
Laukik Hase 2025-01-29 12:16:27 +05:30
parent 37525c605d
commit c23714f775
No known key found for this signature in database
GPG Key ID: D6F3208C06086AC8
13 changed files with 463 additions and 31 deletions

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -752,6 +752,15 @@ esp_err_t IRAM_ATTR bootloader_flash_unlock_default(void)
esp_err_t __attribute__((weak, alias("bootloader_flash_unlock_default"))) bootloader_flash_unlock(void);
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 && !NON_OS_BUILD
extern uint32_t bootloader_flash_execute_command_common(
uint8_t command,
uint32_t addr_len, uint32_t address,
uint8_t dummy_len,
uint8_t mosi_len, uint32_t mosi_data,
uint8_t miso_len);
#else
IRAM_ATTR uint32_t bootloader_flash_execute_command_common(
uint8_t command,
uint32_t addr_len, uint32_t address,
@ -804,6 +813,7 @@ IRAM_ATTR uint32_t bootloader_flash_execute_command_common(
}
return ret;
}
#endif
uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{

View File

@ -94,6 +94,10 @@ if(CONFIG_SECURE_ENABLE_TEE AND NOT esp_tee_build)
# Default secure service API families: flash_protection_spi0, flash_protection_spi1,
# interrupt_handling, hal, crypto, efuse, secure_storage, ota, attestation
set(exclude_srv)
if(NOT CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
list(APPEND exclude_srv "flash_protection_spi1")
endif()
if(NOT CONFIG_SECURE_TEE_ATTESTATION)
list(APPEND exclude_srv "attestation")
endif()

View File

@ -110,6 +110,35 @@ menu "ESP-TEE (Trusted Execution Environment)"
endmenu
config SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
bool "Memprot: Isolate TEE flash regions over SPI1"
depends on SECURE_ENABLE_TEE
default n
help
This configuration restricts access to TEE-reserved regions in external flash
by making them inaccessible to the REE via the SPI1 interface (physical addresses).
With this enabled, all SPI flash read, write, or erase operations over SPI1 will
be routed through service calls to the TEE, introducing additional performance
overhead.
When Flash Encryption (SECURE_FLASH_ENC_ENABLED) is enabled, the REE can still
access TEE-related flash partitions over SPI1, but read operations will return
encrypted data contents. This prevents attackers from inferring the TEE contents
with direct reads.
Additionally, with Secure Boot enabled (SECURE_BOOT_V2_ENABLED), any unauthorized
modifications to the TEE firmware will be detected during boot, causing signature
verification to fail. Thus, these options provide a level of protection suitable for
most applications. However, while the TEE firmware integrity is protected, other TEE
partitions (Secure Storage, TEE OTA data) can be manipulated through direct writes.
Enable this option only when complete isolation of all TEE flash regions is required,
even with the associated performance tradeoffs.
Note: All accesses to the TEE partitions over SPI0 (i.e. the MMU) are blocked
unconditionally.
config SECURE_TEE_DEBUG_MODE
bool "Enable Debug Mode"
default y

View File

@ -24,6 +24,77 @@ secure_services:
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:

View File

@ -13,6 +13,8 @@
#include "hal/sha_hal.h"
#include "hal/mmu_types.h"
#include "hal/wdt_hal.h"
#include "hal/spi_flash_types.h"
#include "esp_flash.h"
#include "soc/soc_caps.h"
@ -247,3 +249,101 @@ bool IRAM_ATTR __wrap_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mm
{
return esp_tee_service_call(6, SS_MMU_HAL_PADDR_TO_VADDR, mmu_id, paddr, target, type, out_vaddr);
}
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
/* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */
uint32_t IRAM_ATTR __wrap_spi_flash_hal_check_status(spi_flash_host_inst_t *host)
{
return esp_tee_service_call(2, SS_SPI_FLASH_HAL_CHECK_STATUS, host);
}
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans)
{
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_COMMON_COMMAND, host, trans);
}
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_device_config(spi_flash_host_inst_t *host)
{
return esp_tee_service_call(2, SS_SPI_FLASH_HAL_DEVICE_CONFIG, host);
}
void IRAM_ATTR __wrap_spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_address)
{
esp_tee_service_call(3, SS_SPI_FLASH_HAL_ERASE_BLOCK, host, start_address);
}
void IRAM_ATTR __wrap_spi_flash_hal_erase_chip(spi_flash_host_inst_t *host)
{
esp_tee_service_call(2, SS_SPI_FLASH_HAL_ERASE_CHIP, host);
}
void IRAM_ATTR __wrap_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address)
{
esp_tee_service_call(3, SS_SPI_FLASH_HAL_ERASE_SECTOR, host, start_address);
}
void IRAM_ATTR __wrap_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)
{
esp_tee_service_call(5, SS_SPI_FLASH_HAL_PROGRAM_PAGE, host, buffer, address, length);
}
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)
{
return esp_tee_service_call(5, SS_SPI_FLASH_HAL_READ, host, buffer, address, read_len);
}
void IRAM_ATTR __wrap_spi_flash_hal_resume(spi_flash_host_inst_t *host)
{
esp_tee_service_call(2, SS_SPI_FLASH_HAL_RESUME, host);
}
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp)
{
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_SET_WRITE_PROTECT, host, wp);
}
esp_err_t IRAM_ATTR __wrap_spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf)
{
return esp_tee_service_call(6, SS_SPI_FLASH_HAL_SETUP_READ_SUSPEND, host, sus_conf);
}
bool IRAM_ATTR __wrap_spi_flash_hal_supports_direct_read(spi_flash_host_inst_t *host, const void *p)
{
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_SUPPORTS_DIRECT_READ, host, p);
}
bool IRAM_ATTR __wrap_spi_flash_hal_supports_direct_write(spi_flash_host_inst_t *host, const void *p)
{
return esp_tee_service_call(3, SS_SPI_FLASH_HAL_SUPPORTS_DIRECT_WRITE, host, p);
}
void IRAM_ATTR __wrap_spi_flash_hal_suspend(spi_flash_host_inst_t *host)
{
esp_tee_service_call(2, SS_SPI_FLASH_HAL_SUSPEND, host);
}
/* ---------------------------------------------- SPI Flash Extras ------------------------------------------------- */
uint32_t IRAM_ATTR __wrap_bootloader_flash_execute_command_common(
uint8_t command,
uint32_t addr_len, uint32_t address,
uint8_t dummy_len,
uint8_t mosi_len, uint32_t mosi_data,
uint8_t miso_len)
{
return esp_tee_service_call(8, SS_BOOTLOADER_FLASH_EXECUTE_COMMAND_COMMON,
command, addr_len, address, dummy_len, mosi_len,
mosi_data, miso_len);
}
esp_err_t IRAM_ATTR __wrap_memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size)
{
return esp_tee_service_call(4, SS_MEMSPI_HOST_FLUSH_CACHE, host, addr, size);
}
esp_err_t IRAM_ATTR __wrap_spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags)
{
return esp_tee_service_call(3, SS_SPI_FLASH_CHIP_GENERIC_CONFIG_HOST_IO_MODE, chip, flags);
}
#endif

View File

@ -54,6 +54,10 @@ list(APPEND srcs "${hal_dir}/apm_hal.c"
"${hal_dir}/brownout_hal.c"
"${hal_dir}/wdt_hal_iram.c")
if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
list(APPEND srcs "${hal_dir}/spi_flash_hal.c")
endif()
# TLSF implementation for heap
list(APPEND include "${heap_dir}/include"
"${heap_dir}/tlsf"

View File

@ -11,7 +11,6 @@
#include "esp_flash.h"
#include "esp_flash_encrypt.h"
#include "esp_rom_efuse.h"
#include "esp_fault.h"
#include "hal/efuse_hal.h"
#include "hal/mmu_types.h"
@ -19,6 +18,11 @@
#include "hal/wdt_hal.h"
#include "hal/sha_hal.h"
#include "hal/spi_flash_hal.h"
#include "hal/spi_flash_types.h"
#include "spi_flash_chip_generic.h"
#include "memspi_host_driver.h"
#include "soc/soc_caps.h"
#include "aes/esp_aes.h"
#include "sha/sha_core.h"
@ -34,6 +38,8 @@
#include "esp_tee_ota_ops.h"
#include "esp_attestation.h"
static __attribute__((unused)) const char *TAG = "esp_tee_sec_srv";
void _ss_invalid_secure_service(void)
{
assert(0);
@ -449,7 +455,7 @@ void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vad
if (vaddr_chk || paddr_chk) {
return;
}
ESP_FAULT_ASSERT(!vaddr_chk && !vaddr_chk);
ESP_FAULT_ASSERT(!vaddr_chk && !paddr_chk);
mmu_hal_map_region(mmu_id, mem_type, vaddr, paddr, len, out_len);
}
@ -484,3 +490,151 @@ bool _ss_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t ta
ESP_FAULT_ASSERT(!paddr_chk);
return mmu_hal_paddr_to_vaddr(mmu_id, paddr, target, type, out_vaddr);
}
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
/* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */
uint32_t _ss_spi_flash_hal_check_status(spi_flash_host_inst_t *host)
{
return spi_flash_hal_check_status(host);
}
esp_err_t _ss_spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans)
{
return spi_flash_hal_common_command(host, trans);
}
esp_err_t _ss_spi_flash_hal_device_config(spi_flash_host_inst_t *host)
{
return spi_flash_hal_device_config(host);
}
void _ss_spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_address)
{
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(start_address);
if (paddr_chk) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
return;
}
ESP_FAULT_ASSERT(!paddr_chk);
spi_flash_hal_erase_block(host, start_address);
}
void _ss_spi_flash_hal_erase_chip(spi_flash_host_inst_t *host)
{
spi_flash_hal_erase_chip(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);
if (paddr_chk) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
return;
}
ESP_FAULT_ASSERT(!paddr_chk);
spi_flash_hal_erase_sector(host, start_address);
}
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);
if (paddr_chk) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
return;
}
bool buf_addr_chk = ((esp_tee_ptr_in_ree((void *)buffer) && esp_tee_ptr_in_ree((void *)(buffer + length))));
if (!buf_addr_chk) {
return;
}
ESP_FAULT_ASSERT(!paddr_chk && buf_addr_chk);
spi_flash_hal_program_page(host, buffer, address, length);
}
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);
if (paddr_chk) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
return ESP_FAIL;
}
bool buf_addr_chk = ((esp_tee_ptr_in_ree((void *)buffer) && esp_tee_ptr_in_ree((void *)(buffer + read_len))));
if (!buf_addr_chk) {
return ESP_FAIL;
}
ESP_FAULT_ASSERT(!paddr_chk && buf_addr_chk);
return spi_flash_hal_read(host, buffer, address, read_len);
}
void _ss_spi_flash_hal_resume(spi_flash_host_inst_t *host)
{
spi_flash_hal_resume(host);
}
esp_err_t _ss_spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp)
{
return spi_flash_hal_set_write_protect(host, wp);
}
esp_err_t _ss_spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf)
{
return spi_flash_hal_setup_read_suspend(host, sus_conf);
}
bool _ss_spi_flash_hal_supports_direct_read(spi_flash_host_inst_t *host, const void *p)
{
return spi_flash_hal_supports_direct_read(host, p);
}
bool _ss_spi_flash_hal_supports_direct_write(spi_flash_host_inst_t *host, const void *p)
{
return spi_flash_hal_supports_direct_write(host, p);
}
void _ss_spi_flash_hal_suspend(spi_flash_host_inst_t *host)
{
spi_flash_hal_suspend(host);
}
/* ---------------------------------------------- SPI Flash Extras ------------------------------------------------- */
extern uint32_t bootloader_flash_execute_command_common(uint8_t command, uint32_t addr_len, uint32_t address,
uint8_t dummy_len, uint8_t mosi_len, uint32_t mosi_data,
uint8_t miso_len);
uint32_t _ss_bootloader_flash_execute_command_common(
uint8_t command,
uint32_t addr_len, uint32_t address,
uint8_t dummy_len,
uint8_t mosi_len, uint32_t mosi_data,
uint8_t miso_len)
{
bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(address);
if (paddr_chk) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
return ESP_FAIL;
}
ESP_FAULT_ASSERT(!paddr_chk);
return bootloader_flash_execute_command_common(command, addr_len, address, dummy_len,
mosi_len, mosi_data, miso_len);
}
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);
if (paddr_chk) {
return ESP_FAIL;
}
ESP_FAULT_ASSERT(!paddr_chk);
return memspi_host_flush_cache(host, addr, size);
}
esp_err_t _ss_spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags)
{
return spi_flash_chip_generic_config_host_io_mode(chip, flags);
}
#endif

View File

@ -104,6 +104,8 @@ SECTIONS
_rodata_start = ABSOLUTE(.);
*libtee_flash_mgr.a:*(.rodata .srodata .rodata.* .srodata.*)
*libbootloader_support.a:bootloader_flash.*(.rodata .srodata .rodata.* .srodata.*)
*libmain.a:esp_secure_services.c.*(.rodata .srodata .rodata.* .srodata.*)
*libmain.a:esp_secure_dispatcher.c.*(.rodata .srodata .rodata.* .srodata.*)
*libmain.a:panic_helper_riscv.*(.rodata .srodata .rodata.* .srodata.*)
*libmain.a:esp_tee_apm_intr.c.*(.rodata .srodata .rodata.* .srodata.*)
_rodata_end = ABSOLUTE(.);

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -35,6 +35,14 @@ static const char *TAG = "esp_tee_apm_prot_cfg";
#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_EXT_BASE
#else
#define HP_APM_SPI1_REG_END HP_APM_SPI1_REG_START
#endif
/*----------------------- HP APM range and filter configuration -----------------------*/
/* HP_APM: REE0 mode accessible regions */
@ -56,52 +64,61 @@ apm_ctrl_region_config_data_t hp_apm_pms_data[] = {
.regn_pms = 0x6,
.filter_enable = 1,
},
/* Region 2: Peripherals [MMU - Interrupt Matrix] (RW) */
/* Protected: Interrupt Matrix */
/* Region 2: Peripherals [MMU - SPI1] (RW) */
/* Protected: SPI1 */
{
.regn_num = 2,
.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 3: Peripherals [SPI1 - Interrupt Matrix] (RW) */
/* Protected: Interrupt Matrix */
{
.regn_num = 3,
.regn_start_addr = HP_APM_SPI1_REG_END,
.regn_end_addr = (DR_REG_INTMTX_BASE - 0x4),
.regn_pms = 0x6,
.filter_enable = 1,
},
/* Region 3: Peripherals [H/W Lock - AES] (RW) */
/* Region 4: Peripherals [H/W Lock - AES] (RW) */
/* Protected: AES, SHA */
{
.regn_num = 3,
.regn_num = 4,
.regn_start_addr = DR_REG_ATOMIC_BASE,
.regn_end_addr = (DR_REG_AES_BASE - 0x4),
.regn_pms = 0x6,
.filter_enable = 1,
},
/* Region 4: Peripherals [RSA - TEE Controller & APM] (RW) */
/* Region 5: Peripherals [RSA - TEE Controller & APM] (RW) */
/* Protected: APM, TEE Controller */
{
.regn_num = 4,
.regn_num = 5,
.regn_start_addr = DR_REG_RSA_BASE,
.regn_end_addr = (DR_REG_TEE_BASE - 0x4),
.regn_pms = 0x6,
.filter_enable = 1,
},
/* Region 5: Peripherals [Miscellaneous - PMU] (RW) */
/* Region 6: Peripherals [Miscellaneous - PMU] (RW) */
{
.regn_num = 5,
.regn_num = 6,
.regn_start_addr = DR_REG_MISC_BASE,
.regn_end_addr = (DR_REG_PMU_BASE - 0x04),
.regn_pms = 0x6,
.filter_enable = 1,
},
/* Region 6: Peripherals [DEBUG - PWDET] (RW) */
/* Region 7: Peripherals [DEBUG - PWDET] (RW) */
{
.regn_num = 6,
.regn_num = 7,
.regn_start_addr = DR_REG_OPT_DEBUG_BASE,
.regn_end_addr = 0x600D0000,
.regn_pms = 0x6,
.filter_enable = 1,
},
/* Region 7: REE SRAM region (RW) */
/* Region 8: REE SRAM region (RW) */
{
.regn_num = 7,
.regn_num = 8,
.regn_start_addr = SOC_NS_IRAM_START,
.regn_end_addr = SOC_IRAM_HIGH,
.regn_pms = 0x6,
@ -147,9 +164,9 @@ apm_ctrl_secure_mode_config_t hp_apm_sec_mode_data = {
/* HP_APM: TEE mode accessible regions */
apm_ctrl_region_config_data_t hp_apm_pms_data_tee[] = {
/* Region 8: Entire memory region (RWX)*/
/* Region 9: Entire memory region (RWX)*/
{
.regn_num = 8,
.regn_num = 9,
.regn_start_addr = 0x0,
.regn_end_addr = ~0x0,
.regn_pms = 0x7,

View File

@ -425,6 +425,7 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u
return (timeout_us > 0) ? ESP_OK : ESP_ERR_TIMEOUT;
}
#if !CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags)
{
uint32_t dummy_cyclelen_base;
@ -483,6 +484,7 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t
return chip->host->driver->configure_host_io_mode(chip->host, read_command, addr_bitlen, dummy_cyclelen_base, read_mode);
}
#endif
esp_err_t spi_flash_chip_generic_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode)
{

View File

@ -100,10 +100,6 @@ External Memory (Flash)
Designated partitions in the external flash are reserved for the TEE, serving various purposes, including TEE code execution via XIP, secure storage, and OTA data. The PMS safeguards these partitions from unauthorized access, with the APM module protecting the MMU and SPI1 controller registers, and the PMP securing the cache.
.. note::
Flash memory protection is under development and will be introduced in the next revision of ESP-TEE.
.. figure:: ../../../_static/esp_tee/{IDF_TARGET_PATH_NAME}/esp_tee_flash_layout.png
:align: center
:scale: 80%
@ -112,6 +108,53 @@ Designated partitions in the external flash are reserved for the TEE, serving va
ESP-TEE: Flash Memory Map for {IDF_TARGET_NAME}
.. _tee-flash-prot-scope:
**Flash Protection - Virtual and Physical Access**
The key interfaces for flash memory protection are the cache connected to SPI0, which provides virtual access to flash memory, and the SPI1 controller, which provides physical access. By default, the cache and the MMU registers are secured by the PMS, preventing virtual access to the TEE-related flash partitions from the REE.
When :doc:`Flash Encryption <../flash-encryption>` is enabled, the REE can still access TEE flash regions via SPI1, but read operations will return encrypted data. Since neither the REE nor TEE has direct access to the flash encryption key, this prevents attackers from inferring TEE contents through direct reads.
Additionally with :ref:`Secure Boot <secure_boot-guide>` enabled, any unauthorized modifications to the TEE firmware will be detected during boot, causing signature verification to fail. Thus, the combination of Flash Encryption and Secure Boot provides a robust level of protection suitable for most applications.
However, do note that while the TEE firmware integrity is protected, other TEE partitions (e.g., :doc:`Secure Storage <tee-sec-storage>`, :ref:`TEE OTA data <tee-ota-data-partition>`) can be modified through direct writes.
For stronger isolation, you can enable :ref:`CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1`, which completely blocks access to all TEE flash regions via SPI1 for the REE. With this setting, all SPI flash read, write, and erase operations are routed through service calls to the TEE. While this option provides enhanced security, it introduces some performance overhead.
The table below shows the rough time taken to read and write to a 1MB partition in 256B chunks with :doc:`../../api-reference/storage/partition`, highlighting the impact of ESP-TEE and the :ref:`CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1` configuration.
.. list-table:: Flash Protection: Performance Impact
:header-rows: 1
* - Case
- Read (ms)
- Read Δ (ms)
- Read Δ (%)
- Write (ms)
- Write Δ (ms)
- Write Δ (%)
* - ESP-TEE disabled
- 262.01
- -
- -
- 3394.23
- -
- -
* - ESP-TEE enabled
- 279.86
- +17.85
- +6.81%
- 3415.64
- +21.41
- +0.63%
* - ESP-TEE + SPI1 protected
- 359.73
- +97.72
- +37.33%
- 3778.65
- +384.42
- +11.32%
Peripherals
~~~~~~~~~~~

View File

@ -67,10 +67,6 @@ The TEE Secure Storage feature supports two modes (:ref:`CONFIG_SECURE_TEE_SEC_S
All the assets pertaining to the TEE secure storage are protected by the APM peripheral and thus, are inaccessible to the REE application. Any attempt to directly access them would result in a system fault.
.. note::
Flash memory protection is currently not implemented - it will be added soon in the next revision of the ESP-TEE framework.
.. note::
- Currently, the TEE secure storage supports the storage of two types of cryptographic keys:

View File

@ -71,10 +71,6 @@ Memory Allocation
ESP-TEE divides the memory into separate regions for the TEE and REE, allocating part of the internal SRAM and external flash memory to the TEE. This separation safeguards sensitive data and operations within the TEE, preventing unauthorized access from the REE.
.. note::
Flash memory protection is under development and will be introduced in the next revision of ESP-TEE.
.. _tee-internal-memory:
Internal Memory (SRAM)
@ -105,10 +101,14 @@ Example partition table is given below: ::
nvs, data, nvs, 0x150000, 24K,
phy_init, data, phy, 0x156000, 4K,
.. note::
.. important::
The partition following the last TEE-related partition must be aligned to the configured MMU page size. This alignment is required to prevent secure boot verification failures when validating the user application (REE) image.
.. note::
For more details on the default policy and scope of flash memory protection with ESP-TEE, refer to the :ref:`Flash Protection - Virtual and Physical Access <tee-flash-prot-scope>` section from the advanced guide.
.. _tee-secure-services:
Secure Services