diff --git a/components/esp_tee/Kconfig.projbuild b/components/esp_tee/Kconfig.projbuild index 4a36ab36152..99d5f4e4ffb 100644 --- a/components/esp_tee/Kconfig.projbuild +++ b/components/esp_tee/Kconfig.projbuild @@ -13,15 +13,15 @@ menu "ESP-TEE (Trusted Execution Environment)" config SECURE_TEE_IRAM_SIZE hex "IRAM region size" default 0x8000 - range 0x7000 0xA000 + range 0x5000 0xA000 help This configuration sets the IRAM size for the TEE module. This should be 256-byte (0x100) aligned. config SECURE_TEE_DRAM_SIZE hex "DRAM region size" - default 0x6000 - range 0x5000 0x7000 + default 0x5000 + range 0x4000 0x7000 help This configuration sets the DRAM size for the TEE module. This should be 256-byte (0x100) aligned. diff --git a/components/esp_tee/subproject/components/tee_ota_ops/CMakeLists.txt b/components/esp_tee/subproject/components/tee_ota_ops/CMakeLists.txt index e5ac22068a2..841fa3eb1a9 100644 --- a/components/esp_tee/subproject/components/tee_ota_ops/CMakeLists.txt +++ b/components/esp_tee/subproject/components/tee_ota_ops/CMakeLists.txt @@ -1,15 +1,16 @@ idf_build_get_property(esp_tee_build ESP_TEE_BUILD) set(srcs) -set(priv_requires) +set(priv_requires esp_tee) set(include_dirs "include") if(esp_tee_build) list(APPEND srcs "esp_tee_ota_ops.c") - list(APPEND priv_requires bootloader_support esp_tee log spi_flash tee_flash_mgr) + list(APPEND priv_requires bootloader_support log spi_flash tee_flash_mgr) else() - list(APPEND srcs "esp_tee_ota_ops_wrapper.c") - list(APPEND priv_requires esp_tee) + if(CONFIG_SECURE_ENABLE_TEE) + list(APPEND srcs "esp_tee_ota_ops_wrapper.c") + endif() endif() idf_component_register(SRCS ${srcs} diff --git a/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt b/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt index 2d911922c64..c93459e419b 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt +++ b/components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt @@ -7,7 +7,9 @@ if(esp_tee_build) list(APPEND srcs "tee_sec_storage.c") list(APPEND priv_requires efuse esp_partition log mbedtls nvs_flash spi_flash tee_flash_mgr) else() - list(APPEND srcs "tee_sec_storage_wrapper.c") + if(CONFIG_SECURE_ENABLE_TEE) + list(APPEND srcs "tee_sec_storage_wrapper.c") + endif() endif() idf_component_register(SRCS ${srcs} diff --git a/components/esp_tee/test_apps/tee_cli_app/CMakeLists.txt b/components/esp_tee/test_apps/tee_cli_app/CMakeLists.txt index 721b1cfd91f..627174bcd35 100644 --- a/components/esp_tee/test_apps/tee_cli_app/CMakeLists.txt +++ b/components/esp_tee/test_apps/tee_cli_app/CMakeLists.txt @@ -4,4 +4,7 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) + project(tee_cli) diff --git a/components/esp_tee/test_apps/tee_cli_app/main/CMakeLists.txt b/components/esp_tee/test_apps/tee_cli_app/main/CMakeLists.txt index eb4fc24f4e6..b795bad4696 100644 --- a/components/esp_tee/test_apps/tee_cli_app/main/CMakeLists.txt +++ b/components/esp_tee/test_apps/tee_cli_app/main/CMakeLists.txt @@ -8,4 +8,6 @@ if(CONFIG_SECURE_TEE_ATTESTATION) endif() idf_component_register(SRCS ${srcs} - INCLUDE_DIRS ".") + INCLUDE_DIRS "." + PRIV_REQUIRES app_update console esp_event esp_http_client + esp_https_ota esp_wifi mbedtls nvs_flash) 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 d749ee32a7e..f15739e14a6 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 @@ -176,6 +176,13 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: server_port = 8001 tee_bin = 'esp_tee/esp_tee.bin' user_bin = 'tee_cli.bin' + prev_tee_offs = None + prev_app_offs = None + + # Fetch Wi-Fi credentials + env_name = 'wifi_high_traffic' + ap_ssid = get_env_config_variable(env_name, 'ap_ssid') + ap_password = get_env_config_variable(env_name, 'ap_password') # Start server thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port)) @@ -187,17 +194,26 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: # start test for i in range(iterations): # Boot up sequence checks - dut.expect('Loaded TEE app from partition at offset', timeout=30) - dut.expect('Loaded app from partition at offset', timeout=30) + curr_tee_offs = ( + dut.expect(r'Loaded TEE app from partition at offset (0x[0-9a-fA-F]+)', timeout=30).group(1).decode() + ) + curr_app_offs = ( + dut.expect(r'Loaded app from partition at offset (0x[0-9a-fA-F]+)', timeout=30).group(1).decode() + ) + + # Check for offset change across iterations + if prev_tee_offs is not None and curr_tee_offs == prev_tee_offs: + raise ValueError('Updated TEE app is not running') + + prev_tee_offs = curr_tee_offs + if prev_app_offs is None: + prev_app_offs = curr_app_offs # Starting the test dut.expect('ESP-TEE: Secure services demonstration', timeout=30) time.sleep(2) # Connecting to Wi-Fi - env_name = 'wifi_high_traffic' - ap_ssid = get_env_config_variable(env_name, 'ap_ssid') - ap_password = get_env_config_variable(env_name, 'ap_password') dut.write(f'wifi_connect {ap_ssid} {ap_password}') # Fetch the DUT IP address @@ -213,6 +229,11 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: if i == (iterations - 1): dut.write(f'user_ota https://{host_ip}:{str(server_port)}/{user_bin}') dut.expect('OTA Succeed, Rebooting', timeout=150) + curr_app_offs = ( + dut.expect(r'Loaded app from partition at offset (0x[0-9a-fA-F]+)', timeout=30).group(1).decode() + ) + if curr_app_offs == prev_app_offs: + raise ValueError('Updated user app is not running') else: dut.write(f'tee_ota https://{host_ip}:{str(server_port)}/{tee_bin}') dut.expect('esp_tee_ota_end succeeded', timeout=150) diff --git a/components/esp_tee/test_apps/tee_test_fw/CMakeLists.txt b/components/esp_tee/test_apps/tee_test_fw/CMakeLists.txt index 0269fa88013..479630f340c 100644 --- a/components/esp_tee/test_apps/tee_test_fw/CMakeLists.txt +++ b/components/esp_tee/test_apps/tee_test_fw/CMakeLists.txt @@ -6,4 +6,7 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) # For registering the test-specific and attestation secure services include(${CMAKE_CURRENT_LIST_DIR}/components/test_sec_srv/test_tee_project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) + project(esp_tee_test) 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 4c51d552f02..fa10a28e267 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 @@ -1,8 +1,8 @@ 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 esp_driver_gptimer esp_tee esp_timer mbedtls spi_flash) # Test FW related -list(APPEND priv_requires cmock json nvs_flash test_utils unity) +list(APPEND priv_requires json nvs_flash test_utils unity) # TEE related list(APPEND priv_requires tee_sec_storage tee_attestation tee_ota_ops test_sec_srv) 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 40bae746559..da637da3374 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 @@ -14,20 +14,20 @@ SUPPORTED_TARGETS = ['esp32c6', 'esp32h2', 'esp32c5'] CONFIG_DEFAULT = [ # 'config, target, markers', - ('default', target, (pytest.mark.generic,)) + ('tee_default', target, (pytest.mark.generic,)) for target in SUPPORTED_TARGETS ] CONFIG_OTA = [ # 'config, target, skip_autoflash, markers', - ('ota', target, 'y', (pytest.mark.generic,)) + ('tee_ota', target, 'y', (pytest.mark.generic,)) for target in SUPPORTED_TARGETS ] CONFIG_ALL = [ # 'config, target, markers', (config, target, (pytest.mark.generic,)) - for config in ['default', 'ota'] + for config in ['tee_default', 'tee_ota'] for target in SUPPORTED_TARGETS ] @@ -97,12 +97,7 @@ def test_esp_tee_crypto_sha(dut: IdfDut) -> None: def test_esp_tee_aes_perf(dut: IdfDut) -> None: # start test for i in range(24): - if not i: - dut.expect_exact('Press ENTER to see the list of tests') - else: - dut.expect_exact("Enter next test, or 'enter' to see menu") - dut.write('"mbedtls AES performance"') - dut.expect_unity_test_output(timeout=60) + dut.run_all_single_board_cases(name=['mbedtls AES performance']) # ---------------- TEE Exceptions generation Tests ---------------- @@ -263,7 +258,7 @@ def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: dut.serial.custom_flash() # start test - extra_data = dut.parse_test_menu() + extra_data = dut._parse_test_menu() for test_case in extra_data: if test_case.name == 'Test REE-TEE isolation: Flash - SPI0 (esp_partition_mmap)': run_multiple_stages(dut, test_case.index, len(test_case.subcases), TeeFlashAccessApi.ESP_PARTITION_MMAP) @@ -281,7 +276,7 @@ def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: dut.serial.custom_flash() # start test - extra_data = dut.parse_test_menu() + 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), TeeFlashAccessApi.SPI_FLASH_MMAP) @@ -299,7 +294,7 @@ def test_esp_tee_flash_prot_esp_rom_spiflash(dut: IdfDut) -> None: dut.serial.custom_flash() # start test - extra_data = dut.parse_test_menu() + 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) @@ -317,7 +312,7 @@ def test_esp_tee_flash_prot_esp_partition(dut: IdfDut) -> None: dut.serial.custom_flash() # start test - extra_data = dut.parse_test_menu() + 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) @@ -335,7 +330,7 @@ def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: dut.serial.custom_flash() # start test - extra_data = dut.parse_test_menu() + 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) @@ -347,13 +342,11 @@ def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: @pytest.mark.generic -@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('config', ['tee_ota'], indirect=['config']) @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') - dut.write('[ota_neg_1]') - dut.expect_unity_test_output(timeout=120) + dut.run_all_single_board_cases(group='ota_neg_1', timeout=30) # erasing TEE otadata dut.serial.erase_partition('tee_otadata') @@ -369,9 +362,7 @@ def test_esp_tee_ota_corrupted_img(dut: IdfDut) -> None: dut.serial.custom_flash_w_test_tee_img_gen() # start test - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('"Test TEE OTA - Corrupted image"') - dut.expect_unity_test_output(timeout=120) + dut.run_all_single_board_cases(name=['Test TEE OTA - Corrupted image'], timeout=30) # erasing TEE otadata dut.serial.erase_partition('tee_otadata') diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.default b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_default similarity index 100% rename from components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.default rename to components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_default diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.ota b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_ota similarity index 100% rename from components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.ota rename to components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_ota 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 4699b02915a..c7570128d89 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults @@ -1,6 +1,7 @@ # Test-app related CONFIG_FREERTOS_HZ=1000 CONFIG_ESP_TASK_WDT_INIT=n +CONFIG_HEAP_POISONING_COMPREHENSIVE=y # Enabling TEE CONFIG_SECURE_ENABLE_TEE=y diff --git a/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py b/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py index a628d9b3906..c8d7aba6064 100644 --- a/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py +++ b/examples/security/tee/tee_secure_ota/pytest_tee_secure_ota.py @@ -3,10 +3,8 @@ import http.server import multiprocessing import os -import socket import ssl import time -from typing import Callable import pexpect import pytest @@ -14,42 +12,22 @@ from common_test_methods import get_env_config_variable from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize -from RangeHTTPServer import RangeRequestHandler server_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/server_cert.pem') key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/server_key.pem') -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() @@ -69,6 +47,8 @@ def test_examples_tee_secure_ota_example(dut: Dut) -> None: server_port = 8001 tee_bin = 'esp_tee/esp_tee.bin' user_bin = 'tee_secure_ota.bin' + prev_tee_offs = None + prev_app_offs = None # Start server thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port)) @@ -80,8 +60,19 @@ def test_examples_tee_secure_ota_example(dut: Dut) -> None: # start test for i in range(iterations): # Boot up sequence checks - dut.expect('Loaded TEE app from partition at offset', timeout=30) - dut.expect('Loaded app from partition at offset', timeout=30) + curr_tee_offs = ( + dut.expect(r'Loaded TEE app from partition at offset (0x[0-9a-fA-F]+)', timeout=30).group(1).decode() + ) + curr_app_offs = ( + dut.expect(r'Loaded app from partition at offset (0x[0-9a-fA-F]+)', timeout=30).group(1).decode() + ) + + # Check for offset change across iterations + if prev_tee_offs is not None and curr_tee_offs == prev_tee_offs: + raise ValueError('Updated TEE app is not running') + prev_tee_offs = curr_tee_offs + if prev_app_offs is None: + prev_app_offs = curr_app_offs # Starting the test dut.expect('OTA with TEE enabled', timeout=30) @@ -96,7 +87,7 @@ def test_examples_tee_secure_ota_example(dut: Dut) -> None: dut.write(f'{ap_ssid} {ap_password}') try: ip_address = dut.expect(r'IPv4 address: (\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') @@ -107,6 +98,11 @@ def test_examples_tee_secure_ota_example(dut: Dut) -> None: if i == (iterations - 1): dut.write(f'user_ota https://{host_ip}:{str(server_port)}/{user_bin}') dut.expect('OTA Succeed, Rebooting', timeout=150) + curr_app_offs = ( + dut.expect(r'Loaded app from partition at offset (0x[0-9a-fA-F]+)', timeout=30).group(1).decode() + ) + if curr_app_offs == prev_app_offs: + raise ValueError('Updated user app is not running') else: dut.write(f'tee_ota https://{host_ip}:{str(server_port)}/{tee_bin}') dut.expect('esp_tee_ota_end succeeded', timeout=60)