mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
ci(esp_tee): Add tests for verifying behaviour for illegal flash accesses (SPI0)
This commit is contained in:
parent
1499c65754
commit
86125aeb98
@ -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)
|
set(priv_requires bootloader_support driver esp_tee esp_timer mbedtls spi_flash)
|
||||||
# Test FW related
|
# 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
|
# TEE related
|
||||||
list(APPEND priv_requires tee_sec_storage tee_attestation tee_ota_ops test_sec_srv)
|
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_panic.c"
|
||||||
"test_esp_tee_sec_stg.c"
|
"test_esp_tee_sec_stg.c"
|
||||||
"test_esp_tee_ota.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")
|
set(mbedtls_test_srcs_dir "${idf_path}/components/mbedtls/test_apps/main")
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "memory_checks.h"
|
#include "memory_checks.h"
|
||||||
|
|
||||||
@ -42,5 +44,6 @@ static void test_task(void *pvParameters)
|
|||||||
|
|
||||||
void app_main(void)
|
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);
|
xTaskCreatePinnedToCore(test_task, "testTask", CONFIG_UNITY_FREERTOS_STACK_SIZE, NULL, CONFIG_UNITY_FREERTOS_PRIORITY, NULL, CONFIG_UNITY_FREERTOS_CPU);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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);
|
@ -8,6 +8,8 @@
|
|||||||
#include "soc/efuse_reg.h"
|
#include "soc/efuse_reg.h"
|
||||||
#include "soc/lp_analog_peri_reg.h"
|
#include "soc/lp_analog_peri_reg.h"
|
||||||
#include "soc/lp_wdt_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/FreeRTOS.h"
|
||||||
#include "freertos/task.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_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 */
|
/* TEE IRAM: Reserved/Vector-table boundary */
|
||||||
TEST_CASE("Test TEE-TEE violation: IRAM (W1)", "[exception]")
|
TEST_CASE("Test TEE-TEE violation: IRAM (W1)", "[exception]")
|
||||||
{
|
{
|
||||||
|
@ -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 ----------------
|
# ---------------- TEE default tests ----------------
|
||||||
|
|
||||||
@ -134,6 +134,53 @@ def test_esp_tee_isolation_checks(dut: IdfDut) -> None:
|
|||||||
raise RuntimeError('Incorrect exception received!')
|
raise RuntimeError('Incorrect exception received!')
|
||||||
dut.expect('Exception origin: U-mode')
|
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 ----------------
|
# ---------------- TEE Local OTA tests ----------------
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user