From bb55b0cefc4bb2230405f7890bc79a07054d4a3c Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 23 Jul 2025 14:34:15 +0530 Subject: [PATCH] ci(esp_tee): Enable the TEE test-apps for ESP32-C5 --- .../esp_tee/test_apps/.build-test-rules.yml | 8 +- .../esp_tee/test_apps/tee_cli_app/README.md | 4 +- .../test_apps/tee_cli_app/main/tee_srv_ota.c | 1 - .../test_apps/tee_cli_app/pytest_tee_cli.py | 52 ++++-------- .../test_apps/tee_cli_app/sdkconfig.defaults | 2 +- .../tee_cli_app/test_certs/server_cert.pem | 43 ++++++---- .../tee_cli_app/test_certs/server_key.pem | 64 ++++++++------ .../esp_tee/test_apps/tee_test_fw/README.md | 4 +- .../esp_tee/test_apps/tee_test_fw/conftest.py | 51 ++++++++++-- .../main/test_esp_tee_flash_prot.c | 50 +++++++++-- .../tee_test_fw/main/test_esp_tee_panic.c | 82 +++++++++--------- .../tee_test_fw/pytest_esp_tee_ut.py | 83 ++++++++++--------- .../test_apps/tee_test_fw/sdkconfig.defaults | 1 + 13 files changed, 267 insertions(+), 178 deletions(-) diff --git a/components/esp_tee/test_apps/.build-test-rules.yml b/components/esp_tee/test_apps/.build-test-rules.yml index 04999bc2f9..906c6b73c3 100644 --- a/components/esp_tee/test_apps/.build-test-rules.yml +++ b/components/esp_tee/test_apps/.build-test-rules.yml @@ -2,10 +2,10 @@ components/esp_tee/test_apps/tee_cli_app: disable: - - if: IDF_TARGET not in ["esp32c6"] - reason: only supported with esp32c6 for now + - if: IDF_TARGET not in ["esp32c6", "esp32c5"] + reason: only supported with c6 and c5 components/esp_tee/test_apps/tee_test_fw: disable: - - if: IDF_TARGET not in ["esp32c6", "esp32h2"] - reason: only supported with esp32c6 and esp32h2 for now + - if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5"] + reason: only supported with c6, h2 and c5 diff --git a/components/esp_tee/test_apps/tee_cli_app/README.md b/components/esp_tee/test_apps/tee_cli_app/README.md index 3b4ab26325..66cfc49649 100644 --- a/components/esp_tee/test_apps/tee_cli_app/README.md +++ b/components/esp_tee/test_apps/tee_cli_app/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | -| ----------------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | +| ----------------- | -------- | -------- | # TEE CLI Application: Secure Services Demonstration diff --git a/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c b/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c index 42aacd3a37..aadabe9ff4 100644 --- a/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c +++ b/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c @@ -111,7 +111,6 @@ static void tee_ota_task(void *pvParameter) task_fatal_error(); } else if (data_read > 0) { if (image_header_was_checked == false) { - /* TODO: TEE image header is missing the `esp_app_desc_t` configuration structure */ if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)) { esp_image_header_t img_hdr; memcpy(&img_hdr, ota_write_data, sizeof(esp_image_header_t)); diff --git a/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py index 587c297c13..d749ee32a7 100644 --- a/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py +++ b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py @@ -6,11 +6,9 @@ import json import logging import multiprocessing import os -import socket import ssl import time from typing import Any -from typing import Callable import pexpect import pytest @@ -22,7 +20,6 @@ from ecdsa.keys import VerifyingKey from ecdsa.util import sigdecode_der from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize -from RangeHTTPServer import RangeRequestHandler TEST_MSG = 'hello world' @@ -36,12 +33,12 @@ key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/ @pytest.mark.generic -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_tee_cli_secure_storage(dut: Dut) -> None: # Dumping the REE binary size binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin') bin_size = os.path.getsize(binary_file) - logging.info('tee_cli_bin_size : {}KB'.format(bin_size // 1024)) + logging.info(f'tee_cli_bin_size : {bin_size // 1024}KB') # Starting the test dut.expect('ESP-TEE: Secure services demonstration', timeout=30) @@ -122,12 +119,12 @@ def verify_att_token_signature(att_tk: str) -> Any: @pytest.mark.generic -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_tee_cli_attestation(dut: Dut) -> None: # Dumping the REE binary size binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin') bin_size = os.path.getsize(binary_file) - logging.info('tee_cli_bin_size : {}KB'.format(bin_size // 1024)) + logging.info(f'tee_cli_bin_size : {bin_size // 1024}KB') # Starting the test dut.expect('ESP-TEE: Secure services demonstration', timeout=30) @@ -149,41 +146,22 @@ def test_tee_cli_attestation(dut: Dut) -> None: ####################################### -def https_request_handler() -> Callable[..., http.server.BaseHTTPRequestHandler]: - """ - Returns a request handler class that handles broken pipe exception - """ - - class RequestHandler(RangeRequestHandler): - def finish(self) -> None: - try: - if not self.wfile.closed: - self.wfile.flush() - self.wfile.close() - except socket.error: - pass - self.rfile.close() - - def handle(self) -> None: - try: - RangeRequestHandler.handle(self) - except socket.error: - pass - - return RequestHandler - - def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> None: os.chdir(ota_image_dir) - requestHandler = https_request_handler() - httpd = http.server.HTTPServer((server_ip, server_port), requestHandler) + server_address = (server_ip, server_port) - httpd.socket = ssl.wrap_socket(httpd.socket, keyfile=key_file, certfile=server_file, server_side=True) + Handler = http.server.SimpleHTTPRequestHandler + httpd = http.server.HTTPServer(server_address, Handler) + + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain(certfile=server_file, keyfile=key_file) + + httpd.socket = context.wrap_socket(httpd.socket, server_side=True) httpd.serve_forever() @pytest.mark.wifi_high_traffic -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. @@ -214,7 +192,7 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: # Starting the test dut.expect('ESP-TEE: Secure services demonstration', timeout=30) - time.sleep(1) + time.sleep(2) # Connecting to Wi-Fi env_name = 'wifi_high_traffic' @@ -225,7 +203,7 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: # Fetch the DUT IP address try: ip_address = dut.expect(r'got ip:(\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode() - print('Connected to AP/Ethernet with IP: {}'.format(ip_address)) + print(f'Connected to AP/Ethernet with IP: {ip_address}') except pexpect.exceptions.TIMEOUT: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults index 2e0a48855a..c35d9943e4 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults @@ -14,7 +14,7 @@ CONFIG_FREERTOS_UNICORE=y # TEE: OTA-related CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y -CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=45000 +CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=30000 # Custom certificates for testing CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y diff --git a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem index b29ba7ab1f..ff3cfba30a 100644 --- a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem +++ b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem @@ -1,20 +1,27 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem index 20a4bdb624..77787dc494 100644 --- a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem +++ b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem @@ -1,28 +1,40 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP -wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu -c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m -KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO -2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv -L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO -AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH -fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj -z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF -gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z -Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q -jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz -i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw -8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N -JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq -gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv -kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN -P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al -pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG -1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU -10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ -hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O -rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G -rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ -YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG -vSXnRLaxQhooWm+IuX9SuBQ= +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 +Q4QjfIE8PkLbVa1oC3niOWdo -----END PRIVATE KEY----- diff --git a/components/esp_tee/test_apps/tee_test_fw/README.md b/components/esp_tee/test_apps/tee_test_fw/README.md index 5396aaf280..1488da3165 100644 --- a/components/esp_tee/test_apps/tee_test_fw/README.md +++ b/components/esp_tee/test_apps/tee_test_fw/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | -------- | ## ESP-TEE: Test Suite diff --git a/components/esp_tee/test_apps/tee_test_fw/conftest.py b/components/esp_tee/test_apps/tee_test_fw/conftest.py index d344c193f0..2a180f99b9 100644 --- a/components/esp_tee/test_apps/tee_test_fw/conftest.py +++ b/components/esp_tee/test_apps/tee_test_fw/conftest.py @@ -10,8 +10,6 @@ import sys import tempfile from pathlib import Path from typing import Any -from typing import Dict -from typing import List import espsecure import esptool @@ -104,7 +102,48 @@ esp_tee_empty_bin = { 0xDC, 0x60, 0x86, 0x6C, 0x37, 0x76, 0xAA, 0x30, 0x1F, 0x61, 0x48, 0x23, 0xEA, 0x34, 0xAA, 0x19, 0xE8, 0xDE, 0x04, 0x7D, 0x2A, 0x30, 0xC1, 0xDD, 0x61, 0x38, 0x9D, 0xB5, 0xCA, 0x13, 0x5A, 0x79 - ] + ], + 'esp32c5': [ + 0xE9, 0x04, 0x02, 0x1F, 0x00, 0x00, 0x80, 0x40, 0xEE, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x64, 0x00, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + # DROM segment + 0x20, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, + # esp_app_desc structure + 0x32, 0x54, 0xCD, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x35, 0x2E, 0x35, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x65, 0x73, 0x70, 0x5F, 0x74, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x30, 0x3A, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x76, 0x20, 0x31, 0x31, 0x20, 0x32, + 0x30, 0x32, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x35, 0x2E, 0x35, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2D, 0x63, 0x66, 0x8B, 0x75, 0xFA, 0x59, 0x05, + 0x53, 0x34, 0x91, 0x71, 0x51, 0x33, 0x91, 0xDD, 0xF8, 0xB1, 0xFE, 0x83, + 0x06, 0xEB, 0x03, 0x80, 0x45, 0xC9, 0x18, 0x20, 0x83, 0x7E, 0x2E, 0x43, + *([0x00] * 0x58), + # Padding + *([0x00] * 0x100), + # IRAM segment + 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x00, 0x00, + *([0x00] * 0x20), + # PADDING segment + 0x00, 0x00, 0x00, 0x00, 0xC8, 0x7D, 0x00, 0x00, + *([0x00] * 0x7DC8), + # IROM segment + 0x20, 0x80, 0x00, 0x42, 0x00, 0x01, 0x00, 0x00, + *([0x00] * 0x100), + # Padding + *([0x00] * 0x0F), + # CRC8 checksum + 0x56, + # Image SHA256 + 0xCD, 0xCC, 0xF2, 0xE3, 0x52, 0x76, 0xE5, 0x6D, 0xF6, 0x32, 0x95, 0x27, + 0x5F, 0xF3, 0xD8, 0x90, 0xD7, 0x95, 0xA0, 0x95, 0xD5, 0xDA, 0xE7, 0xA4, + 0x58, 0x08, 0x84, 0xBB, 0x8F, 0x29, 0xAB, 0xE4 + ], } # fmt: on @@ -233,7 +272,7 @@ class TEESerial(IdfSerial): self.flash() self.custom_erase_partition('secure_storage') - KEY_DEFS: List[Dict[str, Any]] = [ + KEY_DEFS: list[dict[str, Any]] = [ {'key': 'aes256_key0', 'type': 'aes256', 'input': None, 'write_once': True}, { 'key': 'aes256_key1', @@ -264,7 +303,7 @@ class TEESerial(IdfSerial): NVS_CSV_PATH = TMP_DIR / 'tee_sec_stg_val.csv' NVS_BIN_PATH = TMP_DIR / 'tee_sec_stg_nvs.bin' - def run_command(self, command: List[str]) -> None: + def run_command(self, command: list[str]) -> None: try: subprocess.check_call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: @@ -276,7 +315,7 @@ class TEESerial(IdfSerial): def create_tee_sec_stg_csv(self, tmp_dir: Path) -> Path: csv_path = self.NVS_CSV_PATH - rows: List[List[str]] = [ + rows: list[list[str]] = [ ['key', 'type', 'encoding', 'value'], ['tee_sec_stg_ns', 'namespace', '', ''], ] 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 index 7c5d3cb9b9..bbde60b5c6 100644 --- 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 @@ -22,6 +22,7 @@ #include "unity.h" #include "ccomp_timer.h" +#include "sdkconfig.h" #define BOOT_COUNT_NAMESPACE "boot_count" #define TEST_PART_LABEL "custom" @@ -29,6 +30,30 @@ #define ESP_TEE_SEC_STG_PART_LABEL "secure_storage" +__attribute__((unused)) static const uint32_t mmu_op_fail_seq[8] = {[0 ... 7] = 0x0addbad0}; + +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#define SOC_TEE_FLASH_OP_FAIL_FAULT 1 +#else +#define SOC_TEE_FLASH_OP_FAIL_FAULT 0 +#endif + +#if SOC_TEE_FLASH_OP_FAIL_FAULT +#define CHECK_MMU_OP_FAIL(ptr_) do {} while (0) +#else +#define CHECK_MMU_OP_FAIL(ptr_) \ + do { \ + TEST_ASSERT_EQUAL_HEX8_ARRAY(mmu_op_fail_seq, (ptr_), 0x20); \ + esp_restart(); \ + } while (0) +#endif + +#if SOC_TEE_FLASH_OP_FAIL_FAULT +#define CHECK_FLASH_OP_FAIL(err) TEST_ESP_ERR(ESP_FAIL, err) +#else +#define CHECK_FLASH_OP_FAIL(err) do { (void)(err); esp_restart(); } while (0) +#endif + static const char *TAG = "test_esp_tee_flash_prot"; static void set_boot_count_in_nvs(uint8_t boot_count) @@ -77,6 +102,7 @@ static void test_esp_partition_mmap_api(void) 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)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -84,6 +110,7 @@ static void test_esp_partition_mmap_api(void) 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)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -91,6 +118,7 @@ static void test_esp_partition_mmap_api(void) 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)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -98,6 +126,7 @@ static void test_esp_partition_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, ESP_TEE_SEC_STG_PART_LABEL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -117,7 +146,8 @@ 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))); + esp_err_t err = esp_partition_read(part, 0x00, buf_r, sizeof(buf_r)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_partition_api_w(const esp_partition_t *part) @@ -125,13 +155,15 @@ 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_ERR(ESP_FAIL, esp_partition_write(part, 0x00, buf_w, sizeof(buf_w))); + esp_err_t err = esp_partition_write(part, 0x00, buf_w, sizeof(buf_w)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_partition_api_e(const esp_partition_t *part) { TEST_ASSERT_NOT_NULL(part); - TEST_ESP_ERR(ESP_FAIL, esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE)); + esp_err_t err = esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_partition_api(void) @@ -188,6 +220,7 @@ static void test_spi_flash_mmap_api(void) 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)); + CHECK_MMU_OP_FAIL(ptr); ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -195,6 +228,7 @@ static void test_spi_flash_mmap_api(void) 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)); + CHECK_MMU_OP_FAIL(ptr); ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -202,6 +236,7 @@ static void test_spi_flash_mmap_api(void) 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)); + CHECK_MMU_OP_FAIL(ptr); ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -222,19 +257,22 @@ 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))); + esp_err_t err = esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_flash_api_w(uint32_t paddr) { uint8_t buf_w[128]; memset(buf_w, 0xA5, sizeof(buf_w)); - TEST_ESP_ERR(ESP_FAIL, esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w))); + esp_err_t err = esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_flash_api_e(uint32_t paddr) { - TEST_ESP_ERR(ESP_FAIL, esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE)); + esp_err_t err = esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_flash_api(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 79c9acc1ff..115ed26010 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 @@ -35,102 +35,117 @@ extern uint32_t _instruction_reserved_start; #define TEST_APM_EFUSE_PROT_REG EFUSE_RD_KEY5_DATA0_REG #endif -TEST_CASE("Test APM violation interrupt: eFuse", "[apm_violation]") +TEST_CASE("Test APM violation: eFuse", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(TEST_APM_EFUSE_PROT_REG); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: MMU", "[apm_violation]") +TEST_CASE("Test APM violation: 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"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: AES", "[apm_violation]") +TEST_CASE("Test APM violation: AES", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(AES_KEY_2_REG); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: HMAC", "[apm_violation]") +TEST_CASE("Test APM violation: HMAC", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(HMAC_SET_PARA_KEY_REG); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: DS", "[apm_violation]") +TEST_CASE("Test APM violation: DS", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(DS_Z_MEM); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: SHA PCR", "[apm_violation]") +TEST_CASE("Test APM violation: SHA PCR", "[apm_violation]") { uint32_t val = 0; REG_WRITE(PCR_SHA_CONF_REG, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: ECC PCR", "[apm_violation]") +TEST_CASE("Test APM violation: ECC PCR", "[apm_violation]") { uint32_t val = 0; REG_WRITE(PCR_ECC_CONF_REG, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -/* TEE IRAM: Reserved/Vector-table boundary */ -TEST_CASE("Test TEE-TEE violation: IRAM (W1)", "[exception]") +// NOTE: For C6/H2, SWDT and BOD are protected using PMP, thus this test +// generates a store access fault instead of APM violation +TEST_CASE("Test APM violation: SWDT/BOD", "[exception]") { - esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG1_WRITE_VIOLATION); +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 + REG_WRITE(LP_ANALOG_PERI_LP_ANA_FIB_ENABLE_REG, 0); +#else + REG_WRITE(LP_ANA_FIB_ENABLE_REG, 0); +#endif TEST_FAIL_MESSAGE("Exception should have been generated"); } /* Illegal memory space: Write */ -TEST_CASE("Test TEE-TEE violation: Reserved (W1)", "[exception]") +TEST_CASE("Test TEE-TEE violation: Reserved-W1", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_RESV_REG1_WRITE_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } /* Illegal memory space: Execution */ -TEST_CASE("Test TEE-TEE violation: Reserved (X1)", "[exception]") +TEST_CASE("Test TEE-TEE violation: Reserved-X1", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_RESV_REG1_EXEC_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } +// TODO: [IDF-13827] Enable when TEE SRAM is partitioned as IRAM (RX) and DRAM (RW) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5) +/* TEE IRAM: Reserved/Vector-table boundary */ +TEST_CASE("Test TEE-TEE violation: IRAM-W1", "[exception]") +{ + esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG1_WRITE_VIOLATION); + TEST_FAIL_MESSAGE("Exception should have been generated"); +} + /* TEE IRAM: Vector table region */ -TEST_CASE("Test TEE-TEE violation: IRAM (W2)", "[exception]") +TEST_CASE("Test TEE-TEE violation: IRAM-W2", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG2_WRITE_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE DRAM: Stack region */ -TEST_CASE("Test TEE-TEE violation: DRAM (X1)", "[exception]") +TEST_CASE("Test TEE-TEE violation: DRAM-X1", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_DRAM_REG1_EXEC_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE DRAM: Heap region */ -TEST_CASE("Test TEE-TEE violation: DRAM (X2)", "[exception]") +TEST_CASE("Test TEE-TEE violation: DRAM-X2", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_DRAM_REG2_EXEC_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } +#endif /* Illegal Instruction */ TEST_CASE("Test TEE-TEE violation: Illegal Instruction", "[exception]") @@ -140,7 +155,7 @@ TEST_CASE("Test TEE-TEE violation: Illegal Instruction", "[exception]") } /* TEE DRAM -REE IRAM Boundary */ -TEST_CASE("Test REE-TEE isolation: DRAM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DRAM-R1", "[exception]") { uint32_t* val = (uint32_t *)(&_iram_start - 0x04); TEST_ASSERT_EQUAL(0, *val); @@ -148,14 +163,14 @@ TEST_CASE("Test REE-TEE isolation: DRAM (R1)", "[exception]") } /* TEE DRAM -REE IRAM Boundary */ -TEST_CASE("Test REE-TEE isolation: DRAM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DRAM-W1", "[exception]") { *(uint32_t *)(&_iram_start - 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE IRAM region */ -TEST_CASE("Test REE-TEE isolation: IRAM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IRAM-R1", "[exception]") { uint32_t *val = (uint32_t *)(&_iram_start - (CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) + 0x04); TEST_ASSERT_EQUAL(0, *val); @@ -163,14 +178,14 @@ TEST_CASE("Test REE-TEE isolation: IRAM (R1)", "[exception]") } /* TEE IRAM region */ -TEST_CASE("Test REE-TEE isolation: IRAM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IRAM-W1", "[exception]") { *(uint32_t *)(&_iram_start - (CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) + 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE IROM region */ -TEST_CASE("Test REE-TEE isolation: IROM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IROM-R1", "[exception]") { uint32_t *val = (uint32_t *)(SOC_IROM_LOW + 0x04); TEST_ASSERT_EQUAL(0, *val); @@ -178,14 +193,14 @@ TEST_CASE("Test REE-TEE isolation: IROM (R1)", "[exception]") } /* TEE IROM region */ -TEST_CASE("Test REE-TEE isolation: IROM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IROM-W1", "[exception]") { *(uint32_t *)(SOC_IROM_LOW + 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE DROM - REE IROM boundary */ -TEST_CASE("Test REE-TEE isolation: DROM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DROM-R1", "[exception]") { const uint32_t test_addr = ALIGN_DOWN_TO_MMU_PAGE_SIZE((uint32_t)&_instruction_reserved_start); uint32_t *val = (uint32_t *)(test_addr - 0x04); @@ -194,16 +209,9 @@ TEST_CASE("Test REE-TEE isolation: DROM (R1)", "[exception]") } /* TEE DROM - REE IROM boundary */ -TEST_CASE("Test REE-TEE isolation: DROM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DROM-W1", "[exception]") { const uint32_t test_addr = ALIGN_DOWN_TO_MMU_PAGE_SIZE((uint32_t)&_instruction_reserved_start); *(uint32_t *)(test_addr - 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } - -/* SWDT/BOD Reset register */ -TEST_CASE("Test REE-TEE isolation: SWDT/BOD (W)", "[exception]") -{ - REG_WRITE(LP_ANALOG_PERI_LP_ANA_FIB_ENABLE_REG, 0); - 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 409c0bdfc3..94c77c7da5 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 @@ -2,8 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import re from enum import Enum -from typing import Dict -from typing import Tuple import pytest from pytest_embedded_idf import IdfDut @@ -11,7 +9,7 @@ from pytest_embedded_idf.utils import idf_parametrize # ---------------- Pytest build parameters ---------------- -SUPPORTED_TARGETS = ['esp32c6', 'esp32h2'] +SUPPORTED_TARGETS = ['esp32c6', 'esp32h2', 'esp32c5'] CONFIG_DEFAULT = [ # 'config, target, markers', @@ -34,28 +32,27 @@ CONFIG_ALL = [ # ---------------- Exception test-cases reasons ---------------- -TEE_VIOLATION_TEST_EXC_RSN: Dict[Tuple[str, str], str] = { - ('Reserved', 'W1'): 'Store access fault', - ('Reserved', 'X1'): 'Instruction access fault', - ('IRAM', 'W1'): 'Store access fault', - ('IRAM', 'W2'): 'Store access fault', - ('DRAM', 'X1'): 'Instruction access fault', - ('DRAM', 'X2'): 'Instruction access fault', +TEE_VIOLATION_TEST_EXC_RSN: dict[str, str] = { + ('Reserved-W1'): 'Store access fault', + ('Reserved-X1'): 'Instruction access fault', + ('IRAM-W1'): 'Store access fault', + ('IRAM-W2'): 'Store access fault', + ('DRAM-X1'): 'Instruction access fault', + ('DRAM-X2'): 'Instruction access fault', } -REE_ISOLATION_TEST_EXC_RSN: Dict[Tuple[str, str], str] = { - ('DRAM', 'R1'): 'Load access fault', - ('DRAM', 'W1'): 'Store access fault', - ('IRAM', 'R1'): 'Load access fault', - ('IRAM', 'W1'): 'Store access fault', - ('IROM', 'R1'): 'Load access fault', - ('IROM', 'W1'): 'Store access fault', - ('DROM', 'R1'): 'Load access fault', - ('DROM', 'W1'): 'Store access fault', - ('SWDT/BOD', 'W'): 'Store access fault', +REE_ISOLATION_TEST_EXC_RSN: dict[str, str] = { + ('DRAM-R1'): 'Load access fault', + ('DRAM-W1'): 'Store access fault', + ('IRAM-R1'): 'Load access fault', + ('IRAM-W1'): 'Store access fault', + ('IROM-R1'): 'Load access fault', + ('IROM-W1'): 'Store access fault', + ('DROM-R1'): 'Load access fault', + ('DROM-W1'): 'Store access fault', } -TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR'] +TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR', 'SWDT/BOD'] # ---------------- TEE default tests ---------------- @@ -118,10 +115,12 @@ def test_esp_tee_aes_perf(dut: IdfDut) -> None: def test_esp_tee_apm_violation(dut: IdfDut) -> None: for check in TEE_APM_VIOLATION_EXC_CHK: dut.expect_exact('Press ENTER to see the list of tests') - dut.write(f'"Test APM violation interrupt: {check}"') + dut.write(f'"Test APM violation: {check}"') exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() - if dut.target == 'esp32h2' and check == 'eFuse': + if dut.target == 'esp32c5' or (dut.target == 'esp32h2' and check == 'eFuse'): exp_str = 'APM - Space exception' + elif check == 'SWDT/BOD': + exp_str = 'Store access fault' else: exp_str = 'APM - Authority exception' if exc != exp_str: @@ -148,13 +147,12 @@ def test_esp_tee_illegal_instruction(dut: IdfDut) -> None: ) def test_esp_tee_violation_checks(dut: IdfDut) -> None: checks_list = TEE_VIOLATION_TEST_EXC_RSN - for test in checks_list: - memory, access_type = test - expected_exc = checks_list[test] - if expected_exc is None: + for test, expected_exc in checks_list.items(): + if expected_exc is None or dut.target == 'esp32c5': + # TODO: Enable when TEE SRAM is partitioned as IRAM (RX) and DRAM (RW) continue dut.expect_exact('Press ENTER to see the list of tests') - dut.write(f'"Test TEE-TEE violation: {memory} ({access_type})"') + dut.write(f'"Test TEE-TEE violation: {test}"') actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if actual_exc != expected_exc: raise RuntimeError('Incorrect exception received!') @@ -167,13 +165,11 @@ def test_esp_tee_violation_checks(dut: IdfDut) -> None: ) def test_esp_tee_isolation_checks(dut: IdfDut) -> None: checks_list = REE_ISOLATION_TEST_EXC_RSN - for test in checks_list: - memory, access_type = test - expected_exc = checks_list[test] + for test, expected_exc in checks_list.items(): if expected_exc is None: continue dut.expect_exact('Press ENTER to see the list of tests') - dut.write(f'"Test REE-TEE isolation: {memory} ({access_type})"') + dut.write(f'"Test REE-TEE isolation: {test}"') actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if actual_exc != expected_exc: raise RuntimeError('Incorrect exception received!') @@ -215,6 +211,8 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl flash_enc_enabled = dut.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True) + SOC_TEE_FLASH_OP_FAIL_FAULT = ['esp32c6', 'esp32h2'] + for stage in range(1, stages + 1): dut.write(str(test_case_num)) dut.expect(r'\s+\((\d+)\)\s+"([^"]+)"\r?\n', timeout=30) @@ -222,7 +220,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl if stage > 1: if api in {TeeFlashAccessApi.ESP_PARTITION_MMAP, TeeFlashAccessApi.SPI_FLASH_MMAP}: - expect_panic_rsn(dut, 'Cache error') + if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT: + expect_panic_rsn(dut, 'Cache error') + else: + dut.expect(r'\[_ss_mmu_hal_map_region] Illegal flash access at\s+\S+\s*\|\s*\S+', timeout=10) elif api in {TeeFlashAccessApi.ESP_PARTITION, TeeFlashAccessApi.ESP_FLASH}: op_index = stage - 2 curr_op = expected_ops[api][op_index] @@ -230,7 +231,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl # 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. - expect_panic_rsn(dut, 'Cache error') + if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT: + expect_panic_rsn(dut, 'Cache error') + else: + dut.expect(r'\[_ss_mmu_hal_map_region] Illegal flash access at\s+\S+\s*\|\s*\S+', timeout=10) else: match = dut.expect( r'\[_ss_spi_flash_hal_(\w+)\] Illegal flash access at \s*(0x[0-9a-fA-F]+)', timeout=10 @@ -239,7 +243,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl if not re.fullmatch(curr_op, actual_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 dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT: + expect_panic_rsn(dut, 'APM - Authority exception') + else: + expect_panic_rsn(dut, 'APM - Space exception') if stage != stages: dut.expect_exact('Press ENTER to see the list of tests.') @@ -340,7 +347,7 @@ def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: @pytest.mark.generic @idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) +@idf_parametrize('target', SUPPORTED_TARGETS, indirect=['target']) def test_esp_tee_ota_negative(dut: IdfDut) -> None: # start test dut.expect_exact('Press ENTER to see the list of tests') @@ -474,8 +481,8 @@ def test_esp_tee_ota_rollback(dut: IdfDut) -> None: dut.expect('TEE otadata - Current image state: NEW', timeout=10) dut.expect('Loaded TEE app from partition at offset 0x40000', timeout=10) rst_rsn = dut.expect(r'rst:(0x[0-9A-Fa-f]+) \(([^)]+)\)', timeout=30).group(2).decode() - # NOTE: LP_WDT_SYS is for ESP32-C6 case as bootloader fails to load the dummy TEE app - if rst_rsn != 'LP_WDT_SYS': + # NOTE: LP_WDT_SYS (C6/H2) and RTC_WDT_SYS (C5) are expected as bootloader fails to load the dummy TEE app + if rst_rsn not in {'LP_WDT_SYS', 'RTC_WDT_SYS'}: raise RuntimeError('Incorrect reset reason observed after TEE image failure!') # after rollback diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults index 9e3a863aba..4699b02915 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults @@ -9,6 +9,7 @@ CONFIG_SECURE_TEE_TEST_MODE=y # Setting partition table CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y +CONFIG_PARTITION_TABLE_OFFSET=0xF000 # TEE IRAM size CONFIG_SECURE_TEE_IRAM_SIZE=0x8400