forked from espressif/esp-idf
ci(esp_tee): Add tests for verifying behaviour for illegal flash accesses (SPI1)
This commit is contained in:
@@ -2,6 +2,9 @@
|
|||||||
CONFIG_SECURE_ENABLE_TEE=y
|
CONFIG_SECURE_ENABLE_TEE=y
|
||||||
CONFIG_SECURE_TEE_IRAM_SIZE=0x9000
|
CONFIG_SECURE_TEE_IRAM_SIZE=0x9000
|
||||||
|
|
||||||
|
# Enabling flash protection over SPI1
|
||||||
|
CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1=y
|
||||||
|
|
||||||
# Custom partition table
|
# Custom partition table
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||||
CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y
|
CONFIG_PARTITION_TABLE_TWO_OTA_TEE=y
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -21,8 +21,11 @@
|
|||||||
#include "secure_service_num.h"
|
#include "secure_service_num.h"
|
||||||
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
|
#include "ccomp_timer.h"
|
||||||
|
|
||||||
#define BOOT_COUNT_NAMESPACE "boot_count"
|
#define BOOT_COUNT_NAMESPACE "boot_count"
|
||||||
|
#define TEST_PART_LABEL "custom"
|
||||||
|
#define TEST_BUF_SZ 256
|
||||||
|
|
||||||
static const char *TAG = "test_esp_tee_flash_prot";
|
static const char *TAG = "test_esp_tee_flash_prot";
|
||||||
|
|
||||||
@@ -106,6 +109,66 @@ TEST_CASE_MULTIPLE_STAGES("Test REE-TEE isolation: Flash - SPI0 (esp_partition_m
|
|||||||
test_initial_boot, test_esp_partition_mmap_api, test_esp_partition_mmap_api,
|
test_initial_boot, test_esp_partition_mmap_api, test_esp_partition_mmap_api,
|
||||||
test_esp_partition_mmap_api, test_esp_partition_mmap_api);
|
test_esp_partition_mmap_api, test_esp_partition_mmap_api);
|
||||||
|
|
||||||
|
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
|
||||||
|
static void test_esp_partition_api_r(const esp_partition_t *part)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
uint8_t buf_r[128];
|
||||||
|
memset(buf_r, 0x00, sizeof(buf_r));
|
||||||
|
TEST_ESP_ERR(ESP_FAIL, esp_partition_read(part, 0x00, buf_r, sizeof(buf_r)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_esp_partition_api_w(const esp_partition_t *part)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
uint8_t buf_w[128];
|
||||||
|
memset(buf_w, 0xA5, sizeof(buf_w));
|
||||||
|
TEST_ESP_OK(esp_partition_write(part, 0x00, buf_w, sizeof(buf_w)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_esp_partition_api_e(const esp_partition_t *part)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
TEST_ESP_OK(esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_esp_partition_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;
|
||||||
|
switch (boot_count) {
|
||||||
|
case 2:
|
||||||
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_0, NULL);
|
||||||
|
test_esp_partition_api_r(part);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_1, NULL);
|
||||||
|
test_esp_partition_api_w(part);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL);
|
||||||
|
test_esp_partition_api_w(part);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL);
|
||||||
|
test_esp_partition_api_e(part);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_STAGES("Test REE-TEE isolation: Flash - SPI1 (esp_partition)", "[flash_prot][timeout=60]",
|
||||||
|
test_initial_boot, test_esp_partition_api, test_esp_partition_api,
|
||||||
|
test_esp_partition_api, test_esp_partition_api);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------- API family 2: spi_flash ------------------------------------------------- */
|
/* ---------------------------------------------- API family 2: spi_flash ------------------------------------------------- */
|
||||||
|
|
||||||
static void test_spi_flash_mmap_api(void)
|
static void test_spi_flash_mmap_api(void)
|
||||||
@@ -149,3 +212,172 @@ static void test_spi_flash_mmap_api(void)
|
|||||||
TEST_CASE_MULTIPLE_STAGES("Test REE-TEE isolation: Flash - SPI0 (spi_flash_mmap)", "[flash_prot][timeout=60]",
|
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_initial_boot, test_spi_flash_mmap_api, test_spi_flash_mmap_api,
|
||||||
test_spi_flash_mmap_api);
|
test_spi_flash_mmap_api);
|
||||||
|
|
||||||
|
/* ---------------------------------------------- API family 3: esp_flash ------------------------------------------------- */
|
||||||
|
|
||||||
|
#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1
|
||||||
|
static void test_esp_flash_api_r(uint32_t paddr)
|
||||||
|
{
|
||||||
|
uint8_t buf_r[128];
|
||||||
|
memset(buf_r, 0x00, sizeof(buf_r));
|
||||||
|
TEST_ESP_ERR(ESP_FAIL, esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_esp_flash_api_w(uint32_t paddr)
|
||||||
|
{
|
||||||
|
uint8_t buf_w[128];
|
||||||
|
memset(buf_w, 0xA5, sizeof(buf_w));
|
||||||
|
TEST_ESP_OK(esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_esp_flash_api_e(uint32_t paddr)
|
||||||
|
{
|
||||||
|
TEST_ESP_OK(esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_esp_flash_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;
|
||||||
|
|
||||||
|
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_flash_api_w(part->address);
|
||||||
|
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_flash_api_r(part->address);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL);
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
test_esp_flash_api_e(part->address);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL);
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
test_esp_flash_api_w(part->address);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_STAGES("Test REE-TEE isolation: Flash - SPI1 (esp_flash)", "[flash_prot][timeout=60]",
|
||||||
|
test_initial_boot, test_esp_flash_api, test_esp_flash_api, test_esp_flash_api,
|
||||||
|
test_esp_flash_api);
|
||||||
|
|
||||||
|
/* ---------------------------------------------- API family 4: esp_rom ------------------------------------------------- */
|
||||||
|
|
||||||
|
static IRAM_ATTR void test_esp_rom_spiflash_api_r(uint32_t paddr)
|
||||||
|
{
|
||||||
|
uint32_t buf_r[32];
|
||||||
|
memset(buf_r, 0x00, sizeof(buf_r));
|
||||||
|
esp_rom_spiflash_result_t rc = esp_rom_spiflash_read(paddr, buf_r, sizeof(buf_r));
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_ROM_SPIFLASH_RESULT_OK, rc);
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP(TAG, buf_r, sizeof(buf_r), ESP_LOG_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR void test_esp_rom_spiflash_api_w(uint32_t paddr)
|
||||||
|
{
|
||||||
|
uint32_t buf_w[32];
|
||||||
|
memset(buf_w, 0xA5, sizeof(buf_w));
|
||||||
|
spi_flash_disable_interrupts_caches_and_other_cpu();
|
||||||
|
esp_rom_spiflash_result_t rc = esp_rom_spiflash_write(paddr, buf_w, sizeof(buf_w));
|
||||||
|
spi_flash_enable_interrupts_caches_and_other_cpu();
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_ROM_SPIFLASH_RESULT_OK, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR void test_esp_rom_spiflash_api_e(uint32_t paddr)
|
||||||
|
{
|
||||||
|
spi_flash_disable_interrupts_caches_and_other_cpu();
|
||||||
|
esp_rom_spiflash_result_t rc = esp_rom_spiflash_erase_area(paddr, SPI_FLASH_SEC_SIZE);
|
||||||
|
spi_flash_enable_interrupts_caches_and_other_cpu();
|
||||||
|
TEST_ASSERT_EQUAL_HEX(ESP_ROM_SPIFLASH_RESULT_OK, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_esp_rom_spiflash_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;
|
||||||
|
|
||||||
|
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_rom_spiflash_api_r(part->address);
|
||||||
|
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_rom_spiflash_api_w(part->address);
|
||||||
|
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_SEC_STORAGE, NULL);
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
test_esp_rom_spiflash_api_e(part->address);
|
||||||
|
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_OTA, NULL);
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
test_esp_rom_spiflash_api_w(part->address);
|
||||||
|
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 - SPI1 (esp_rom_spiflash)", "[flash_prot][timeout=60]",
|
||||||
|
test_initial_boot, test_esp_rom_spiflash_api, test_esp_rom_spiflash_api,
|
||||||
|
test_esp_rom_spiflash_api, test_esp_rom_spiflash_api);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("Test TEE flash read/write performance", "[flash_prot]")
|
||||||
|
{
|
||||||
|
const esp_partition_t *part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, TEST_PART_LABEL);
|
||||||
|
TEST_ASSERT_NOT_NULL(part);
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_partition_erase_range(part, 0x00, part->size));
|
||||||
|
TEST_ASSERT_TRUE((part->size % TEST_BUF_SZ) == 0);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "R/W operations over a %luKB partition in %luB chunks...", part->size / 1024, TEST_BUF_SZ);
|
||||||
|
|
||||||
|
uint8_t buf_w[TEST_BUF_SZ];
|
||||||
|
memset(buf_w, 0xA5, sizeof(buf_w));
|
||||||
|
|
||||||
|
float write_usec, read_usec;
|
||||||
|
ccomp_timer_start();
|
||||||
|
for (size_t offs = 0; offs < part->size; offs += TEST_BUF_SZ) {
|
||||||
|
TEST_ESP_OK(esp_partition_write(part, offs, buf_w, TEST_BUF_SZ));
|
||||||
|
}
|
||||||
|
write_usec = ccomp_timer_stop();
|
||||||
|
ESP_LOGI(TAG, "[Time taken] Write: %.2fus", write_usec);
|
||||||
|
|
||||||
|
uint8_t buf_r[TEST_BUF_SZ] = {};
|
||||||
|
|
||||||
|
ccomp_timer_start();
|
||||||
|
for (size_t offs = 0; offs < part->size; offs += TEST_BUF_SZ) {
|
||||||
|
TEST_ESP_OK(esp_partition_read(part, offs, buf_r, TEST_BUF_SZ));
|
||||||
|
}
|
||||||
|
read_usec = ccomp_timer_stop();
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(buf_w, buf_r, TEST_BUF_SZ);
|
||||||
|
ESP_LOGI(TAG, "[Time taken] Read: %.2fus", read_usec);
|
||||||
|
}
|
||||||
|
@@ -4,3 +4,4 @@ tee, app, tee_0, , 192K,
|
|||||||
secure_storage, data, tee_sec_stg, , 64K,
|
secure_storage, data, tee_sec_stg, , 64K,
|
||||||
factory, app, factory, , 512K,
|
factory, app, factory, , 512K,
|
||||||
nvs, data, nvs, , 24K,
|
nvs, data, nvs, , 24K,
|
||||||
|
custom, data, , , 1M
|
||||||
|
|
@@ -8,3 +8,4 @@ ota_0, app, ota_0, , 512K,
|
|||||||
ota_1, app, ota_1, , 512K,
|
ota_1, app, ota_1, , 512K,
|
||||||
otadata, data, ota, , 8K,
|
otadata, data, ota, , 8K,
|
||||||
nvs, data, nvs, , 24K,
|
nvs, data, nvs, , 24K,
|
||||||
|
custom, data, , , 1M
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -15,6 +15,11 @@ CONFIGS_OTA = [
|
|||||||
pytest.param('ota', marks=[pytest.mark.esp32c6])
|
pytest.param('ota', marks=[pytest.mark.esp32c6])
|
||||||
]
|
]
|
||||||
|
|
||||||
|
CONFIGS_ALL = [
|
||||||
|
pytest.param('default', marks=[pytest.mark.esp32c6]),
|
||||||
|
pytest.param('ota', marks=[pytest.mark.esp32c6])
|
||||||
|
]
|
||||||
|
|
||||||
TEE_VIOLATION_TEST_EXC_RSN: Dict[str, Any] = {
|
TEE_VIOLATION_TEST_EXC_RSN: Dict[str, Any] = {
|
||||||
'esp32c6': {
|
'esp32c6': {
|
||||||
('Reserved', 'W1'): 'Store access fault',
|
('Reserved', 'W1'): 'Store access fault',
|
||||||
@@ -42,6 +47,8 @@ REE_ISOLATION_TEST_EXC_RSN: Dict[str, Any] = {
|
|||||||
|
|
||||||
TEE_APM_VIOLATION_EXC_CHK = ['AES', 'eFuse', 'MMU']
|
TEE_APM_VIOLATION_EXC_CHK = ['AES', 'eFuse', 'MMU']
|
||||||
|
|
||||||
|
TEST_PARTITION_LABEL = 'test'
|
||||||
|
|
||||||
# ---------------- TEE default tests ----------------
|
# ---------------- TEE default tests ----------------
|
||||||
|
|
||||||
|
|
||||||
@@ -52,14 +59,14 @@ def test_esp_tee(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True)
|
@pytest.mark.parametrize('config', CONFIGS_ALL, indirect=True)
|
||||||
def test_esp_tee_crypto_aes(dut: IdfDut) -> None:
|
def test_esp_tee_crypto_aes(dut: IdfDut) -> None:
|
||||||
dut.run_all_single_board_cases(group='aes')
|
dut.run_all_single_board_cases(group='aes')
|
||||||
dut.run_all_single_board_cases(group='aes-gcm')
|
dut.run_all_single_board_cases(group='aes-gcm')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True)
|
@pytest.mark.parametrize('config', CONFIGS_ALL, indirect=True)
|
||||||
def test_esp_tee_crypto_sha(dut: IdfDut) -> None:
|
def test_esp_tee_crypto_sha(dut: IdfDut) -> None:
|
||||||
dut.run_all_single_board_cases(group='mbedtls')
|
dut.run_all_single_board_cases(group='mbedtls')
|
||||||
dut.run_all_single_board_cases(group='hw_crypto')
|
dut.run_all_single_board_cases(group='hw_crypto')
|
||||||
@@ -67,7 +74,7 @@ def test_esp_tee_crypto_sha(dut: IdfDut) -> None:
|
|||||||
|
|
||||||
# NOTE: Stress testing the AES performance case for interrupt-related edge-cases
|
# NOTE: Stress testing the AES performance case for interrupt-related edge-cases
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@pytest.mark.parametrize('config', CONFIGS_DEFAULT, indirect=True)
|
@pytest.mark.parametrize('config', CONFIGS_ALL, indirect=True)
|
||||||
def test_esp_tee_aes_perf(dut: IdfDut) -> None:
|
def test_esp_tee_aes_perf(dut: IdfDut) -> None:
|
||||||
# start test
|
# start test
|
||||||
for i in range(24):
|
for i in range(24):
|
||||||
@@ -134,17 +141,56 @@ 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')
|
||||||
|
|
||||||
|
# ---------------- TEE Flash Protection Tests ----------------
|
||||||
|
|
||||||
|
|
||||||
|
class TeeFlashAccessApi(Enum):
|
||||||
|
ESP_PARTITION_MMAP = 1
|
||||||
|
SPI_FLASH_MMAP = 2
|
||||||
|
ESP_PARTITION = 3
|
||||||
|
ESP_FLASH = 4
|
||||||
|
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', '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 run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFlashAccessApi) -> None:
|
||||||
|
exp_seq = {
|
||||||
|
TeeFlashAccessApi.ESP_PARTITION: ['read', 'program_page', 'program_page', 'erase_sector'],
|
||||||
|
TeeFlashAccessApi.ESP_FLASH: ['program_page', 'read', 'erase_sector', 'program_page']
|
||||||
|
}
|
||||||
|
|
||||||
def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int) -> None:
|
|
||||||
for stage in range(1, stages + 1):
|
for stage in range(1, stages + 1):
|
||||||
dut.write(str(test_case_num))
|
dut.write(str(test_case_num))
|
||||||
dut.expect(r'\s+\((\d+)\)\s+"([^"]+)"\r?\n', timeout=30)
|
dut.expect(r'\s+\((\d+)\)\s+"([^"]+)"\r?\n', timeout=30)
|
||||||
dut.write(str(stage))
|
dut.write(str(stage))
|
||||||
|
|
||||||
if 1 < stage <= stages:
|
if 1 < stage <= stages:
|
||||||
rst_rsn = dut.expect(r"Core ([01]) panic\'ed \(([^)]+)\)", timeout=30).group(2).decode()
|
if api in exp_seq:
|
||||||
if rst_rsn != 'Cache error':
|
try:
|
||||||
raise RuntimeError('Incorrect reset reason observed after TEE image failure!')
|
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:
|
||||||
|
# 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)
|
||||||
|
|
||||||
if stage != stages:
|
if stage != stages:
|
||||||
dut.expect_exact('Press ENTER to see the list of tests.')
|
dut.expect_exact('Press ENTER to see the list of tests.')
|
||||||
@@ -160,8 +206,8 @@ def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None:
|
|||||||
# start test
|
# start test
|
||||||
extra_data = dut.parse_test_menu()
|
extra_data = dut.parse_test_menu()
|
||||||
for test_case in extra_data:
|
for test_case in extra_data:
|
||||||
if test_case.name == 'Test REE-TEE isolation: Flash - SPI1 (esp_partition_mmap)':
|
if test_case.name == 'Test REE-TEE isolation: Flash - SPI0 (esp_partition_mmap)':
|
||||||
run_multiple_stages(dut, test_case.index, len(test_case.subcases))
|
run_multiple_stages(dut, test_case.index, len(test_case.subcases), TeeFlashAccessApi.ESP_PARTITION_MMAP)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -177,7 +223,55 @@ def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None:
|
|||||||
extra_data = dut.parse_test_menu()
|
extra_data = dut.parse_test_menu()
|
||||||
for test_case in extra_data:
|
for test_case in extra_data:
|
||||||
if test_case.name == 'Test REE-TEE isolation: Flash - SPI0 (spi_flash_mmap)':
|
if test_case.name == 'Test REE-TEE isolation: Flash - SPI0 (spi_flash_mmap)':
|
||||||
run_multiple_stages(dut, test_case.index, len(test_case.subcases))
|
run_multiple_stages(dut, test_case.index, len(test_case.subcases), TeeFlashAccessApi.SPI_FLASH_MMAP)
|
||||||
|
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_esp_rom_spiflash(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_rom_spiflash)':
|
||||||
|
run_multiple_stages(dut, test_case.index, len(test_case.subcases), TeeFlashAccessApi.ESP_ROM_SPIFLASH)
|
||||||
|
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_esp_partition(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)':
|
||||||
|
run_multiple_stages(dut, test_case.index, len(test_case.subcases), TeeFlashAccessApi.ESP_PARTITION)
|
||||||
|
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_esp_flash(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_flash)':
|
||||||
|
run_multiple_stages(dut, test_case.index, len(test_case.subcases), TeeFlashAccessApi.ESP_FLASH)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@@ -9,3 +9,6 @@ CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG=y
|
|||||||
|
|
||||||
# secure storage key slot for attestation
|
# secure storage key slot for attestation
|
||||||
CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID=14
|
CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID=14
|
||||||
|
|
||||||
|
# Enabling flash protection over SPI1
|
||||||
|
CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1=y
|
||||||
|
Reference in New Issue
Block a user