diff --git a/components/esp_tee/include/private/esp_tee_binary.h b/components/esp_tee/include/private/esp_tee_binary.h index c66f3ad617..5196dad110 100644 --- a/components/esp_tee/include/private/esp_tee_binary.h +++ b/components/esp_tee/include/private/esp_tee_binary.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,7 @@ extern "C" { #define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) (((addr) + (SOC_MMU_PAGE_SIZE) - 1) & ~((SOC_MMU_PAGE_SIZE) - 1)) #define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ((addr) & ~((SOC_MMU_PAGE_SIZE) - 1)) +/* Alignment Checks */ #if ((CONFIG_SECURE_TEE_IRAM_SIZE) & (0xFF)) #error "CONFIG_SECURE_TEE_IRAM_SIZE must be 256-byte (0x100) aligned" #endif @@ -43,6 +44,14 @@ extern "C" { #error "CONFIG_SECURE_TEE_INTR_STACK_SIZE must be 16-byte (0x10) aligned" #endif +#if ((CONFIG_SECURE_TEE_IROM_SIZE) % SOC_MMU_PAGE_SIZE) +#error "CONFIG_SECURE_TEE_IROM_SIZE must be a multiple of SOC_MMU_PAGE_SIZE" +#endif + +#if ((CONFIG_SECURE_TEE_DROM_SIZE) % SOC_MMU_PAGE_SIZE) +#error "CONFIG_SECURE_TEE_DROM_SIZE must be a multiple of SOC_MMU_PAGE_SIZE" +#endif + /* TEE Secure Storage partition label and NVS namespace */ #define ESP_TEE_SEC_STG_PART_LABEL "secure_storage" #define ESP_TEE_SEC_STG_NVS_NAMESPACE "tee_sec_stg_ns" diff --git a/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c b/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c index b998b3aade..51e7fbbdb5 100644 --- a/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c +++ b/components/esp_tee/subproject/components/attestation/esp_att_utils_crypto.c @@ -222,7 +222,7 @@ esp_err_t esp_att_utils_ecdsa_get_pubkey_digest(const esp_att_ecdsa_keypair_t *k return ESP_FAIL; } size_t pubkey_digest_len = 0; - status = psa_hash_finish(&hash_op, pubkey_digest, len, &pubkey_digest_len); + status = psa_hash_finish(&hash_op, pubkey_digest, sizeof(pubkey_digest), &pubkey_digest_len); if (status != PSA_SUCCESS) { return ESP_FAIL; } diff --git a/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in index 8dd92e2cdb..33d63a7ffd 100644 --- a/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in @@ -236,8 +236,3 @@ ASSERT ((_tee_iram_end <= _tee_dram_start), "Error: TEE IRAM segment overflowed into the DRAM segment! Increase CONFIG_SECURE_TEE_IRAM_SIZE as required."); ASSERT((_tee_heap_end >= _tee_heap_start + 0x2000), "Error: TEE heap size is too small - minimum is 8KB (0x2000)! Increase CONFIG_SECURE_TEE_DRAM_SIZE as required."); -/* MMU Page Alignment Checks */ -ASSERT ((CONFIG_SECURE_TEE_IROM_SIZE % 0x10000) == 0, - "Error: SECURE_TEE_IROM_SIZE must be a multiple of MMU_PAGE_SIZE (0x10000/64KB)!"); -ASSERT ((CONFIG_SECURE_TEE_DROM_SIZE % 0x10000) == 0, - "Error: SECURE_TEE_DROM_SIZE must be a multiple of MMU_PAGE_SIZE (0x10000/64KB)!"); diff --git a/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in index 1817b7a441..880d3aecfe 100644 --- a/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in @@ -241,8 +241,3 @@ ASSERT ((_tee_iram_end <= _tee_dram_start), "Error: TEE IRAM segment overflowed into the DRAM segment! Increase CONFIG_SECURE_TEE_IRAM_SIZE as required."); ASSERT((_tee_heap_end >= _tee_heap_start + 0x2000), "Error: TEE heap size is too small - minimum is 8KB (0x2000)! Increase CONFIG_SECURE_TEE_DRAM_SIZE as required."); -/* MMU Page Alignment Checks */ -ASSERT ((CONFIG_SECURE_TEE_IROM_SIZE % CONFIG_MMU_PAGE_SIZE) == 0, - "Error: SECURE_TEE_IROM_SIZE must be a multiple of MMU_PAGE_SIZE (CONFIG_MMU_PAGE_SIZE)!"); -ASSERT ((CONFIG_SECURE_TEE_DROM_SIZE % CONFIG_MMU_PAGE_SIZE) == 0, - "Error: SECURE_TEE_DROM_SIZE must be a multiple of MMU_PAGE_SIZE (CONFIG_MMU_PAGE_SIZE)!"); diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_panic.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_panic.c index baea1edde0..4eaf26441e 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_panic.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_panic.c @@ -14,6 +14,7 @@ extern int _tee_vec_end; extern int _tee_iram_start; extern int _tee_iram_end; extern int _tee_dram_start; +extern int _tee_intr_stack; typedef void (*func_ptr)(void); @@ -64,13 +65,13 @@ static void do_stack_smash(bool underflow, int depth, volatile uint8_t *sink) /* Underflow path */ asm volatile( - "li t0, 2048\n" - "add sp, sp, t0\n" + "mv sp, %0\n" :: "r"(&_tee_intr_stack) ); - volatile uint8_t a = 1; - volatile uint8_t b = a; - (void)b; + /* The blocking delay ensures that the stack protection fault interrupt is + * captured and handled by the CPU before the current function returns. + */ + esp_rom_delay_us(10); } void _ss_esp_tee_test_stack_overflow(void) diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c index b21968fd46..7938207616 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c @@ -229,43 +229,74 @@ TEST_CASE("Test REE-TEE isolation: DROM-W1", "[exception]") TEST_FAIL_MESSAGE("Exception should have been generated"); } -static void do_stack_smash(bool underflow, int depth, volatile uint8_t *sink) +static void do_stack_overflow(int depth, volatile uint8_t *sink) { - /* Overflow path */ - if (!underflow) { - if (depth == -1) { - return; // unreachable - } - - uint8_t buffer[1024]; - buffer[0] = (uint8_t)depth; - *sink = buffer[0]; - - do_stack_smash(false, depth + 1, sink); - return; + if (depth == -1) { + return; // unreachable } - /* Underflow path */ - asm volatile( - "li t0, 4096\n" - "add sp, sp, t0\n" + uint8_t buffer[1024]; + buffer[0] = (uint8_t)depth; + *sink = buffer[0]; + + do_stack_overflow(depth + 1, sink); +} + +static void __attribute__((noinline)) do_stack_underflow(void *underflow) +{ + __asm__ __volatile__( + "mv sp, %0\n" :: "r"(underflow) ); - volatile uint8_t temp = 1; - (void)temp; + /* The blocking delay ensures that the stack protection fault interrupt is + * captured and handled by the CPU before the current function returns. + */ + esp_rom_delay_us(10); +} + +typedef struct { + bool underflow; + StackType_t *underflow_stack; +} StackProtectionTaskArgs; + +static void tStackProtection(void *pvParameters) +{ + StackProtectionTaskArgs *tArgs = (StackProtectionTaskArgs *)pvParameters; + + if (!tArgs->underflow) { /* Overflow path */ + volatile uint8_t sink = 0; + do_stack_overflow(1, &sink); + } else { /* Underflow path */ + do_stack_underflow((void *)tArgs->underflow_stack); + } +} + +static void do_stack_smash(bool underflow) +{ + static struct { + StackType_t StackBuffer[2048]; + StackType_t Underflow[1024]; + StackType_t UnderflowEnd[0]; + } tData; + + static StaticTask_t TaskBuffer; + static StackProtectionTaskArgs taskArgs; + taskArgs.underflow = underflow; + taskArgs.underflow_stack = tData.UnderflowEnd; + + TaskHandle_t handle = xTaskCreateStatic(tStackProtection, "tStackProt", sizeof(tData.StackBuffer) / sizeof(StackType_t), &taskArgs, 10, tData.StackBuffer, &TaskBuffer); + TEST_ASSERT_NULL(handle); } TEST_CASE("Test REE stack overflow", "[exception]") { - volatile uint8_t sink = 0; - do_stack_smash(false, 1, &sink); + do_stack_smash(false); TEST_FAIL_MESSAGE("Exception should have been generated"); } TEST_CASE("Test REE stack underflow", "[exception]") { - volatile uint8_t sink = 0; - do_stack_smash(true, 0, &sink); + do_stack_smash(true); TEST_FAIL_MESSAGE("Exception should have been generated"); } 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 e7b71b8f6c..73590e48d2 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 @@ -84,6 +84,9 @@ def test_esp_tee_aes_perf(dut: IdfDut) -> None: def run_exception_case( dut: IdfDut, menu_prefix: str, test_name: str, expected: str, check_origin: bool = False ) -> None: + # Panics are expected during these tests + dut.skip_decode_panic = True + dut.expect_exact('Press ENTER to see the list of tests') dut.write(f'"{menu_prefix}: {test_name}"') @@ -137,6 +140,9 @@ def test_esp_tee_apm_violation(dut: IdfDut) -> None: indirect=['config', 'target'], ) def test_esp_tee_stack_smashing(dut: IdfDut) -> None: + # Panics are expected during this test + dut.skip_decode_panic = True + for env in ('REE', 'TEE'): for case in ('overflow', 'underflow'): dut.expect_exact('Press ENTER to see the list of tests') @@ -229,6 +235,9 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl def run_flash_access_test(dut: IdfDut, api: TeeFlashAccessApi, test_name: str) -> None: + # Panics are expected during these tests + dut.skip_decode_panic = True + dut.serial.custom_flash() extra_data = dut._parse_test_menu() @@ -396,6 +405,9 @@ def test_esp_tee_ota_valid_img(dut: IdfDut) -> None: indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_ota_rollback(dut: IdfDut) -> None: + # Panics are expected during these tests + dut.skip_decode_panic = True + # Flashing the TEE app to the non-secure app's passive partition dut.serial.custom_flash_w_test_tee_img_rb()