diff --git a/components/esp_tee/test_apps/tee_test_fw/main/CMakeLists.txt b/components/esp_tee/test_apps/tee_test_fw/main/CMakeLists.txt index 9cb889dcdb..995380b79d 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/CMakeLists.txt +++ b/components/esp_tee/test_apps/tee_test_fw/main/CMakeLists.txt @@ -2,7 +2,7 @@ idf_build_get_property(idf_path IDF_PATH) set(priv_requires bootloader_support driver esp_tee esp_timer mbedtls spi_flash) # Test FW related -list(APPEND priv_requires cmock json test_utils unity) +list(APPEND priv_requires cmock json nvs_flash test_utils unity) # TEE related list(APPEND priv_requires tee_sec_storage tee_attestation tee_ota_ops test_sec_srv) @@ -13,7 +13,8 @@ list(APPEND srcs "test_esp_tee_ctx_switch.c" "test_esp_tee_panic.c" "test_esp_tee_sec_stg.c" "test_esp_tee_ota.c" - "test_esp_tee_att.c") + "test_esp_tee_att.c" + "test_esp_tee_flash_prot.c") set(mbedtls_test_srcs_dir "${idf_path}/components/mbedtls/test_apps/main") diff --git a/components/esp_tee/test_apps/tee_test_fw/main/app_main.c b/components/esp_tee/test_apps/tee_test_fw/main/app_main.c index 14c57a8afe..2e720900b9 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/app_main.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/app_main.c @@ -5,6 +5,8 @@ */ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "nvs.h" +#include "nvs_flash.h" #include "unity.h" #include "memory_checks.h" @@ -42,5 +44,6 @@ static void test_task(void *pvParameters) void app_main(void) { + ESP_ERROR_CHECK(nvs_flash_init()); xTaskCreatePinnedToCore(test_task, "testTask", CONFIG_UNITY_FREERTOS_STACK_SIZE, NULL, CONFIG_UNITY_FREERTOS_PRIORITY, NULL, CONFIG_UNITY_FREERTOS_CPU); } diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c new file mode 100644 index 0000000000..3949878a36 --- /dev/null +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c @@ -0,0 +1,151 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "esp_log.h" +#include "esp_system.h" +#include "esp_heap_caps.h" + +#include "esp_flash.h" +#include "esp_rom_spiflash.h" +#include "spi_flash_mmap.h" +#include "esp_private/cache_utils.h" +#include "esp_partition.h" +#include "nvs_flash.h" + +#include "esp_tee.h" +#include "esp_tee_sec_storage.h" +#include "secure_service_num.h" + +#include "unity.h" + +#define BOOT_COUNT_NAMESPACE "boot_count" + +static const char *TAG = "test_esp_tee_flash_prot"; + +static void set_boot_count_in_nvs(uint8_t boot_count) +{ + nvs_handle_t boot_count_handle; + TEST_ESP_OK(nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle)); + TEST_ESP_OK(nvs_set_u8(boot_count_handle, "boot_count", boot_count)); + TEST_ESP_OK(nvs_commit(boot_count_handle)); + nvs_close(boot_count_handle); +} + +static uint8_t get_boot_count_from_nvs(void) +{ + nvs_handle_t boot_count_handle; + esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READONLY, &boot_count_handle); + if (err == ESP_ERR_NVS_NOT_FOUND) { + set_boot_count_in_nvs(0); + } + uint8_t boot_count; + TEST_ESP_OK(nvs_get_u8(boot_count_handle, "boot_count", &boot_count)); + nvs_close(boot_count_handle); + return boot_count; +} + +static void test_initial_boot(void) +{ + ESP_LOGI(TAG, "Boot: 1"); + set_boot_count_in_nvs(1); + esp_restart(); +} + +/* ---------------------------------------------- API family 1: esp_partition ------------------------------------------------- */ + +static void test_esp_partition_mmap_api(void) +{ + uint8_t boot_count = get_boot_count_from_nvs(); + boot_count++; + set_boot_count_in_nvs(boot_count); + + const esp_partition_t *part = NULL; + esp_partition_mmap_handle_t out_handle; + const void *outptr = NULL; + + switch (boot_count) { + case 2: + part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_0, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); + ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); + TEST_FAIL_MESSAGE("System fault should have been generated"); + break; + case 3: + part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_1, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_INST, &outptr, &out_handle)); + ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); + TEST_FAIL_MESSAGE("System fault should have been generated"); + break; + case 4: + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); + ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); + TEST_FAIL_MESSAGE("System fault should have been generated"); + break; + case 5: + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); + ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); + TEST_FAIL_MESSAGE("System fault should have been generated"); + break; + default: + TEST_FAIL_MESSAGE("Unexpected stage"); + break; + } +} + +TEST_CASE_MULTIPLE_STAGES("Test REE-TEE isolation: Flash - SPI0 (esp_partition_mmap)", "[flash_prot][timeout=60]", + test_initial_boot, test_esp_partition_mmap_api, test_esp_partition_mmap_api, + test_esp_partition_mmap_api, test_esp_partition_mmap_api); + +/* ---------------------------------------------- API family 2: spi_flash ------------------------------------------------- */ + +static void test_spi_flash_mmap_api(void) +{ + uint8_t boot_count = get_boot_count_from_nvs(); + boot_count++; + set_boot_count_in_nvs(boot_count); + + const esp_partition_t *part = NULL; + spi_flash_mmap_handle_t handle; + const void *ptr = NULL; + + switch (boot_count) { + case 2: + part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_0, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_DATA, &ptr, &handle)); + ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); + TEST_FAIL_MESSAGE("System fault should have been generated"); + break; + case 3: + part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_1, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_INST, &ptr, &handle)); + ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); + TEST_FAIL_MESSAGE("System fault should have been generated"); + break; + case 4: + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_DATA, &ptr, &handle)); + ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); + TEST_FAIL_MESSAGE("System fault should have been generated"); + break; + default: + TEST_FAIL_MESSAGE("Unexpected stage"); + break; + } +} + +TEST_CASE_MULTIPLE_STAGES("Test REE-TEE isolation: Flash - SPI0 (spi_flash_mmap)", "[flash_prot][timeout=60]", + test_initial_boot, test_spi_flash_mmap_api, test_spi_flash_mmap_api, + test_spi_flash_mmap_api); 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 a9eb544d22..2d65585fed 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 @@ -8,6 +8,8 @@ #include "soc/efuse_reg.h" #include "soc/lp_analog_peri_reg.h" #include "soc/lp_wdt_reg.h" +#include "soc/spi_mem_reg.h" +#include "soc/ext_mem_defs.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -46,6 +48,15 @@ TEST_CASE("Test APM violation interrupt: eFuse", "[apm_violation]") TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); } +TEST_CASE("Test APM violation interrupt: MMU", "[apm_violation]") +{ + uint32_t val = UINT32_MAX; + REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), SOC_MMU_ENTRY_NUM - 2); + val = REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0)); + TEST_ASSERT_EQUAL(0, val); + TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); +} + /* TEE IRAM: Reserved/Vector-table boundary */ TEST_CASE("Test TEE-TEE violation: IRAM (W1)", "[exception]") { 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 05ba445334..0d41fef279 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 @@ -40,7 +40,7 @@ REE_ISOLATION_TEST_EXC_RSN: Dict[str, Any] = { } } -TEE_APM_VIOLATION_EXC_CHK = ['AES', 'eFuse'] +TEE_APM_VIOLATION_EXC_CHK = ['AES', 'eFuse', 'MMU'] # ---------------- TEE default tests ---------------- @@ -134,6 +134,53 @@ def test_esp_tee_isolation_checks(dut: IdfDut) -> None: raise RuntimeError('Incorrect exception received!') dut.expect('Exception origin: U-mode') + +def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int) -> None: + 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: + rst_rsn = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=30).group(2).decode() + if rst_rsn != 'Cache error': + raise RuntimeError('Incorrect reset reason observed after TEE image failure!') + + if stage != stages: + dut.expect_exact('Press ENTER to see the list of tests.') + + +@pytest.mark.generic +@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) +@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: + # Flash the bootloader, TEE and REE firmware + dut.serial.custom_flash() + + # start test + extra_data = dut.parse_test_menu() + for test_case in extra_data: + if test_case.name == 'Test REE-TEE isolation: Flash - SPI1 (esp_partition_mmap)': + run_multiple_stages(dut, test_case.index, len(test_case.subcases)) + else: + continue + + +@pytest.mark.generic +@pytest.mark.parametrize('config', CONFIGS_OTA, indirect=True) +@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) +def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: + # Flash the bootloader, TEE and REE firmware + dut.serial.custom_flash() + + # start test + extra_data = dut.parse_test_menu() + for test_case in extra_data: + if test_case.name == 'Test REE-TEE isolation: Flash - SPI0 (spi_flash_mmap)': + run_multiple_stages(dut, test_case.index, len(test_case.subcases)) + else: + continue + # ---------------- TEE Local OTA tests ----------------