fix(esp_tee): Fix TEE attestation stack protection fault with secure boot enabled

- Increased the TEE stack when secure boot is enabled
- Also, generate a build error when the generated TEE binary image size is
  greater than the TEE partition size
This commit is contained in:
Laukik Hase
2026-01-20 14:05:13 +05:30
parent 5fba5e3931
commit 31b113b649
9 changed files with 61 additions and 19 deletions
+1
View File
@@ -27,6 +27,7 @@ menu "ESP-TEE (Trusted Execution Environment)"
config SECURE_TEE_STACK_SIZE
hex "Stack size"
default 0x1000 if SECURE_BOOT
default 0xc00
range 0x800 0x1000
help
+2 -1
View File
@@ -8,7 +8,7 @@ idf_build_get_property(project_dir PROJECT_DIR)
idf_build_get_property(non_os_build NON_OS_BUILD)
idf_build_get_property(custom_secure_service_dir CUSTOM_SECURE_SERVICE_COMPONENT_DIR)
idf_build_get_property(custom_secure_service_component CUSTOM_SECURE_SERVICE_COMPONENT)
idf_build_get_property(partition_table_bin PARTITION_TABLE_BIN_PATH)
if(NOT CONFIG_SECURE_ENABLE_TEE OR non_os_build)
return()
@@ -80,6 +80,7 @@ externalproject_add(esp_tee
-DCUSTOM_SECURE_SERVICE_COMPONENT=${custom_secure_service_component}
-DCUSTOM_SECURE_SERVICE_COMPONENT_DIR=${custom_secure_service_dir}
-DSECURE_SERVICE_HEADERS_DIR=${secure_service_headers_dir}
-DPARTITION_TABLE_BIN_PATH=${partition_table_bin}
${extra_cmake_args} ${sign_key_arg}
INSTALL_COMMAND ""
BUILD_ALWAYS 1 # no easy way around this...
@@ -98,3 +98,17 @@ if(CONFIG_SECURE_BOOT_V2_ENABLED)
${key_arg}
)
endif()
# Generate TEE post-build check of the TEE size against the partition
partition_table_add_check_tee_size_target(esp_tee_check_size
DEPENDS gen_esp_tee_binary
TEE_BINARY_PATH "${CMAKE_BINARY_DIR}/${esp_tee_unsigned_bin}")
add_dependencies(app esp_tee_check_size)
if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
# Check the size of the TEE + signature block.
partition_table_add_check_tee_size_target(esp_tee_check_size_signed
DEPENDS gen_signed_esp_tee_binary
TEE_BINARY_PATH "${CMAKE_BINARY_DIR}/${project_bin}")
add_dependencies(app esp_tee_check_size_signed)
endif()
@@ -15,7 +15,3 @@ CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC=y
# TEE Secure Storage: Release mode
CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y
CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5
# Increasing TEE DRAM size
# 18KB
CONFIG_SECURE_TEE_DRAM_SIZE=0x5000
@@ -1,7 +1,7 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
tee_0, app, tee_0, , 192K,
tee_1, app, tee_1, , 192K,
tee_0, app, tee_0, , 256K,
tee_1, app, tee_1, , 256K,
tee_otadata, data, tee_ota, , 8K,
secure_storage, data, nvs, , 56K,
ota_0, app, ota_0, , 512K,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 tee_0, app, tee_0, , 192K, tee_0, app, tee_0, , 256K,
4 tee_1, app, tee_1, , 192K, tee_1, app, tee_1, , 256K,
5 tee_otadata, data, tee_ota, , 8K,
6 secure_storage, data, nvs, , 56K,
7 ota_0, app, ota_0, , 512K,
@@ -24,6 +24,12 @@ CONFIG_OTA = [
for target in TESTING_TARGETS
]
CONFIG_TEST = [
# 'config, target, skip_autoflash, markers',
('tee_ota', target, 'y', (pytest.mark.host_test,))
for target in TESTING_TARGETS
]
CONFIG_ALL = [
# 'config, target, markers',
(config, target, (pytest.mark.generic,))
@@ -337,7 +343,7 @@ def tee_ota_stage_checks(dut: IdfDut, stage: TeeOtaStage, offset: str) -> None:
@idf_parametrize(
'config, target, skip_autoflash, markers',
CONFIG_OTA,
CONFIG_TEST,
indirect=['config', 'target', 'skip_autoflash'],
)
def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None:
@@ -352,7 +358,7 @@ def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None:
dut.write('"Test TEE OTA - Reboot without ending OTA"')
# OTA begin checks
tee_ota_stage_checks(dut, TeeOtaStage.BEGIN, '0x40000')
tee_ota_stage_checks(dut, TeeOtaStage.BEGIN, '0x50000')
# after reboot
tee_ota_stage_checks(dut, TeeOtaStage.REBOOT, '0x10000')
@@ -360,7 +366,7 @@ def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None:
@idf_parametrize(
'config, target, skip_autoflash, markers',
CONFIG_OTA,
CONFIG_TEST,
indirect=['config', 'target', 'skip_autoflash'],
)
def test_esp_tee_ota_valid_img(dut: IdfDut) -> None:
@@ -375,23 +381,23 @@ def test_esp_tee_ota_valid_img(dut: IdfDut) -> None:
dut.write('"Test TEE OTA - Valid image"')
# OTA begin checks
tee_ota_stage_checks(dut, TeeOtaStage.BEGIN, '0x40000')
tee_ota_stage_checks(dut, TeeOtaStage.BEGIN, '0x50000')
dut.expect('TEE OTA update successful!', timeout=10)
# after reboot 1
tee_ota_stage_checks(dut, TeeOtaStage.REBOOT, '0x40000')
tee_ota_stage_checks(dut, TeeOtaStage.REBOOT, '0x50000')
# resetting device to check for image validity
dut.serial.hard_reset()
# after reboot 2
dut.expect('TEE otadata - Current image state: VALID', timeout=10)
tee_ota_stage_checks(dut, TeeOtaStage.REBOOT, '0x40000')
tee_ota_stage_checks(dut, TeeOtaStage.REBOOT, '0x50000')
@idf_parametrize(
'config, target, skip_autoflash, markers',
CONFIG_OTA,
CONFIG_TEST,
indirect=['config', 'target', 'skip_autoflash'],
)
def test_esp_tee_ota_rollback(dut: IdfDut) -> None:
@@ -406,12 +412,12 @@ def test_esp_tee_ota_rollback(dut: IdfDut) -> None:
dut.write('"Test TEE OTA - Rollback"')
# OTA begin checks
tee_ota_stage_checks(dut, TeeOtaStage.BEGIN, '0x40000')
tee_ota_stage_checks(dut, TeeOtaStage.BEGIN, '0x50000')
dut.expect('TEE OTA update successful!', timeout=10)
# after reboot 1
dut.expect('TEE otadata - Current image state: NEW', timeout=10)
dut.expect('Loaded TEE app from partition at offset 0x40000', timeout=10)
dut.expect('Loaded TEE app from partition at offset 0x50000', timeout=10)
rst_rsn = dut.expect(r'rst:(0x[0-9A-Fa-f]+) \(([^)]+)\)', timeout=10).group(2).decode()
# NOTE: LP_WDT_SYS (C6/H2) and RTC_WDT_SYS (C5) are expected as bootloader fails to load the dummy TEE app
if rst_rsn not in {'LP_WDT_SYS', 'RTC_WDT_SYS'}:
@@ -1,6 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
tee, app, tee_0, , 192K,
tee, app, tee_0, , 256K,
secure_storage, data, nvs, , 64K,
factory, app, factory, , 1536K,
nvs, data, nvs, , 24K,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 tee, app, tee_0, , 192K, tee, app, tee_0, , 256K,
4 secure_storage, data, nvs, , 64K,
5 factory, app, factory, , 1536K,
6 nvs, data, nvs, , 24K,
@@ -1,7 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
tee_0, app, tee_0, , 192K,
tee_1, app, tee_1, , 192K,
tee_0, app, tee_0, , 256K,
tee_1, app, tee_1, , 256K,
tee_otadata, data, tee_ota, , 8K,
secure_storage, data, nvs, , 56K,
ota_0, app, ota_0, , 1536K,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 tee_0, app, tee_0, , 192K, tee_0, app, tee_0, , 256K,
4 tee_1, app, tee_1, , 192K, tee_1, app, tee_1, , 256K,
5 tee_otadata, data, tee_ota, , 8K,
6 secure_storage, data, nvs, , 56K,
7 ota_0, app, ota_0, , 1536K,
@@ -139,3 +139,27 @@ function(partition_table_add_check_bootloader_size_target target_name)
bootloader ${BOOTLOADER_OFFSET} ${CMD_BOOTLOADER_BINARY_PATH})
add_custom_target(${target_name} COMMAND ${command} DEPENDS ${CMD_DEPENDS})
endfunction()
# Add a custom target (see add_custom_target) that checks a TEE binary
# built by the build system will fit in the TEE partition.
#
# Adding the target doesn't mean it gets called during the build, use add_dependencies to make another
# target depend on this one.
#
# Arguments:
# - target name - (first argument) name of the target to create
# - DEPENDS - dependencies the new target should have (i.e. whatever target generates the TEE binary)
# - TEE_BINARY_PATH - path to TEE binary file
#
# Note: This function uses the PARTITION_TABLE_BIN_PATH variable which is passed from the parent
# build to the TEE subproject via CMAKE_ARGS.
function(partition_table_add_check_tee_size_target target_name)
cmake_parse_arguments(CMD "" "TEE_BINARY_PATH" "DEPENDS" ${ARGN})
idf_build_get_property(python PYTHON)
set(command ${python} ${PARTITION_TABLE_CHECK_SIZES_TOOL_PATH}
--offset ${PARTITION_TABLE_OFFSET}
partition --type app --subtype tee_0
${PARTITION_TABLE_BIN_PATH} ${CMD_TEE_BINARY_PATH})
add_custom_target(${target_name} COMMAND ${command} DEPENDS ${CMD_DEPENDS})
endfunction()