From 31b113b649c21c1a4909a86ccb19e0b72ddaabcd Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Tue, 20 Jan 2026 14:05:13 +0530 Subject: [PATCH] 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 --- components/esp_tee/Kconfig.projbuild | 1 + components/esp_tee/project_include.cmake | 3 ++- components/esp_tee/subproject/CMakeLists.txt | 14 +++++++++++ .../test_apps/tee_cli_app/sdkconfig.ci.sb_fe | 4 ---- .../tee_test_fw/partitions_tee_ota.csv | 4 ++-- .../tee_test_fw/pytest_esp_tee_ut.py | 24 ++++++++++++------- .../partitions_singleapp_tee.csv | 2 +- .../partitions_two_ota_tee.csv | 4 ++-- .../partition_table/project_include.cmake | 24 +++++++++++++++++++ 9 files changed, 61 insertions(+), 19 deletions(-) diff --git a/components/esp_tee/Kconfig.projbuild b/components/esp_tee/Kconfig.projbuild index cc0db01d3a..929c9ebbcf 100644 --- a/components/esp_tee/Kconfig.projbuild +++ b/components/esp_tee/Kconfig.projbuild @@ -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 diff --git a/components/esp_tee/project_include.cmake b/components/esp_tee/project_include.cmake index 3358a14e56..46fd4fbfe8 100644 --- a/components/esp_tee/project_include.cmake +++ b/components/esp_tee/project_include.cmake @@ -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... diff --git a/components/esp_tee/subproject/CMakeLists.txt b/components/esp_tee/subproject/CMakeLists.txt index 693219c654..402ee3bf65 100644 --- a/components/esp_tee/subproject/CMakeLists.txt +++ b/components/esp_tee/subproject/CMakeLists.txt @@ -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() diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe index 64b7dc33d2..bdec94c11b 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe @@ -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 diff --git a/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv b/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv index b160851614..ea957b9676 100644 --- a/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv +++ b/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv @@ -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, diff --git a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py index d1f5e686f9..9671f85c4c 100644 --- a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py +++ b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py @@ -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'}: diff --git a/components/partition_table/partitions_singleapp_tee.csv b/components/partition_table/partitions_singleapp_tee.csv index d55557eedf..d89deaae96 100644 --- a/components/partition_table/partitions_singleapp_tee.csv +++ b/components/partition_table/partitions_singleapp_tee.csv @@ -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, diff --git a/components/partition_table/partitions_two_ota_tee.csv b/components/partition_table/partitions_two_ota_tee.csv index 7d9669c1db..616d3c5757 100644 --- a/components/partition_table/partitions_two_ota_tee.csv +++ b/components/partition_table/partitions_two_ota_tee.csv @@ -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, diff --git a/components/partition_table/project_include.cmake b/components/partition_table/project_include.cmake index 41f8b2a70e..c5cca171e9 100644 --- a/components/partition_table/project_include.cmake +++ b/components/partition_table/project_include.cmake @@ -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()