From 832124f19844a0d67f9c31ecfc1a2fbef33a37f2 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Mon, 14 Apr 2025 17:22:16 +0530 Subject: [PATCH] fix(esp_tee): Place APM HAL in TEE IRAM when SPI1 protection is enabled - Place the APM HAL into TEE IRAM when `CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1` is enabled, as APM violations related to SPI1 can occur with the flash cache disabled. - Also fix an issue where flash protection tests were passing due to incorrect checks --- .../subproject/main/ld/esp32c6/esp_tee.ld.in | 6 ++- .../tee_test_fw/pytest_esp_tee_ut.py | 50 +++++++++---------- 2 files changed, 29 insertions(+), 27 deletions(-) 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 30d0f8b9f0..7c5a572861 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 @@ -170,7 +170,7 @@ SECTIONS * | MMU | text+rodata | SRAM | * | CACHE | text+rodata | SRAM | * | WDT | text | SRAM | - * | APM | text | Flash | + * | APM | text | Flash* | * | AES | text | Flash | * | SHA | text | Flash | * | HMAC | text | Flash | @@ -198,7 +198,11 @@ SECTIONS *libhal.a:hmac_hal.c*(.literal .text .literal.* .text.*) *libhal.a:ds_hal.c*(.literal .text .literal.* .text.*) *libhal.a:ecc_hal.c*(.literal .text .literal.* .text.*) + /* NOTE: There is a possibility of APM violations (SPI1 flash protection) + * being triggered with the flash cache disabled */ +#if !CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) +#endif *libhal.a:brownout_hal.c*(.literal .text .literal.* .text.*) *libhal.a:spi_flash_hal.c*(.literal .text .literal.* .text.*) /* These HAL modules have functions marked with the IRAM_ATTR attribute which get placed in the SRAM */ 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 742c7f9923..b0d2afc6b2 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 @@ -155,47 +155,45 @@ class TeeFlashAccessApi(Enum): ESP_ROM_SPIFLASH = 5 -def check_panic_or_reset(dut: IdfDut) -> None: - try: - exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=5).group(2).decode() - if exc not in {'Cache error', 'APM - Authority exception'}: - raise RuntimeError('Flash operation incorrect exception') - except Exception: - rst_rsn = dut.expect(r'rst:(0x[0-9A-Fa-f]+) \(([^)]+)\)', timeout=5).group(2).decode() - # Fault assert check produces this reset reason - if rst_rsn != 'LP_SW_HPSYS': - raise RuntimeError('Flash operation incorrect reset reason') +def expect_panic_rsn(dut: IdfDut, expected_rsn: str) -> None: + actual_rsn = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=10).group(2).decode() + if actual_rsn != expected_rsn: + raise RuntimeError(f'Incorrect exception: {actual_rsn} (expected: {expected_rsn})') def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFlashAccessApi) -> None: - exp_seq = { + expected_ops = { TeeFlashAccessApi.ESP_PARTITION: ['read', 'program_page', 'program_page', 'erase_sector'], TeeFlashAccessApi.ESP_FLASH: ['program_page', 'read', 'erase_sector', 'program_page'], } + flash_enc_enabled = dut.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True) + for stage in range(1, stages + 1): dut.write(str(test_case_num)) dut.expect(r'\s+\((\d+)\)\s+"([^"]+)"\r?\n', timeout=30) dut.write(str(stage)) - if 1 < stage <= stages: - if api in exp_seq: - try: - match = dut.expect( - r'\[_ss_spi_flash_hal_(\w+)\] Illegal flash access at \s*(0x[0-9a-fA-F]+)', timeout=5 - ) - fault_api = match.group(1).decode() - if fault_api != exp_seq[api][stage - 2]: - raise RuntimeError('Flash operation address check failed') - except Exception: + if stage > 1: + if api in {TeeFlashAccessApi.ESP_PARTITION_MMAP, TeeFlashAccessApi.SPI_FLASH_MMAP}: + expect_panic_rsn(dut, 'Cache error') + elif api in {TeeFlashAccessApi.ESP_PARTITION, TeeFlashAccessApi.ESP_FLASH}: + op_index = stage - 2 + curr_op = expected_ops[api][op_index] + if api == TeeFlashAccessApi.ESP_PARTITION and curr_op == 'read' and flash_enc_enabled: # NOTE: The esp_partition_read API handles both decrypted # and plaintext reads. When flash encryption is enabled, # it uses the MMU HAL instead of the SPI flash HAL. - exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=5).group(2).decode() - if exc != 'Cache error': - raise RuntimeError('Flash operation incorrect exception') - else: - check_panic_or_reset(dut) + expect_panic_rsn(dut, 'Cache error') + else: + match = dut.expect( + r'\[_ss_spi_flash_hal_(\w+)\] Illegal flash access at \s*(0x[0-9a-fA-F]+)', timeout=10 + ) + actual_op = match.group(1).decode() + if actual_op != curr_op: + raise RuntimeError(f'Unexpected flash operation: {actual_op} (expected: {curr_op})') + elif api == TeeFlashAccessApi.ESP_ROM_SPIFLASH: + expect_panic_rsn(dut, 'APM - Authority exception') if stage != stages: dut.expect_exact('Press ENTER to see the list of tests.')