mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-08 04:02:27 +00:00
179 lines
7.2 KiB
Python
179 lines
7.2 KiB
Python
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
# pylint: disable=W0621 # redefined-outer-name
|
|
import os
|
|
import tempfile
|
|
from typing import Any
|
|
|
|
import espsecure
|
|
import esptool
|
|
import pytest
|
|
from _pytest.fixtures import FixtureRequest
|
|
from _pytest.monkeypatch import MonkeyPatch
|
|
from pytest_embedded_idf.serial import IdfSerial
|
|
from pytest_embedded_serial_esp.serial import EspSerial
|
|
|
|
esp_tee_empty_bin = {
|
|
'esp32c6': [
|
|
0xE9, 0x04, 0x02, 0x10, 0x00, 0x00, 0x80, 0x40, 0xEE, 0x00, 0x00, 0x00,
|
|
0x0D, 0x00, 0x00, 0x00, 0x00, 0x63, 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
|
|
0xF4, 0xA4, 0xCF, 0x06, 0xAE, 0x94, 0x75, 0x47, 0xBC, 0x88, 0xA2, 0xCA,
|
|
0x52, 0x97, 0x7A, 0x5C, 0x55, 0x43, 0xD9, 0xF5, 0xD3, 0x45, 0xD1, 0x34,
|
|
0xFC, 0x74, 0xB2, 0xB9, 0x34, 0x72, 0xC3, 0x00
|
|
]
|
|
}
|
|
|
|
|
|
# This is a custom IdfSerial class to support custom functionality
|
|
# which is required only for this test
|
|
class TEESerial(IdfSerial):
|
|
def __init__(self, *args, **kwargs) -> None: # type: ignore
|
|
super().__init__(*args, **kwargs)
|
|
|
|
def _get_flash_size(self) -> Any:
|
|
return self.app.sdkconfig.get('ESPTOOLPY_FLASHSIZE', '')
|
|
|
|
@EspSerial.use_esptool()
|
|
def bootloader_force_flash_if_req(self) -> None:
|
|
# Forcefully flash the bootloader only if security features are enabled
|
|
if any((
|
|
self.app.sdkconfig.get('SECURE_BOOT', True),
|
|
self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True),
|
|
)):
|
|
offs = int(self.app.sdkconfig.get('BOOTLOADER_OFFSET_IN_FLASH', 0))
|
|
bootloader_path = os.path.join(self.app.binary_path, 'bootloader', 'bootloader.bin')
|
|
encrypt = '--encrypt' if self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED') else ''
|
|
flash_size = self._get_flash_size()
|
|
|
|
esptool.main(
|
|
f'--no-stub write_flash {offs} {bootloader_path} --force {encrypt} --flash_size {flash_size}'.split(),
|
|
esp=self.esp
|
|
)
|
|
|
|
@EspSerial.use_esptool()
|
|
def custom_erase_partition(self, partition: str) -> None:
|
|
if self.app.sdkconfig.get('SECURE_ENABLE_SECURE_ROM_DL_MODE'):
|
|
with tempfile.NamedTemporaryFile(delete=True) as temp_file:
|
|
offs = self.app.partition_table[partition]['offset']
|
|
size = self.app.partition_table[partition]['size']
|
|
flash_size = self._get_flash_size()
|
|
|
|
binstr = b'\xff' * int(size)
|
|
temp_file.write(binstr)
|
|
temp_file.flush()
|
|
|
|
esptool.main(
|
|
f'--no-stub write_flash {offs} {temp_file.name} --flash_size {flash_size}'.split(),
|
|
esp=self.esp
|
|
)
|
|
else:
|
|
self.erase_partition(partition)
|
|
|
|
@EspSerial.use_esptool()
|
|
def copy_test_tee_img(self, partition: str, is_rollback: bool = False) -> None:
|
|
offs = self.app.partition_table[partition]['offset']
|
|
no_stub = '--no-stub' if self.app.sdkconfig.get('SECURE_ENABLE_SECURE_ROM_DL_MODE') else ''
|
|
encrypt = '--encrypt' if self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED') else ''
|
|
flash_size = self._get_flash_size()
|
|
|
|
flash_file = os.path.join(self.app.binary_path, 'esp_tee', 'esp_tee.bin')
|
|
|
|
if is_rollback:
|
|
datafile = 'esp_tee_empty.bin'
|
|
datafile_signed = 'esp_tee_empty_signed.bin'
|
|
flash_file = datafile
|
|
|
|
with open(datafile, 'wb') as data_file:
|
|
bin_data = esp_tee_empty_bin.get(self.app.sdkconfig.get('IDF_TARGET'), None)
|
|
if bin_data is not None:
|
|
data_file.write(bytes(bin_data))
|
|
data_file.flush()
|
|
|
|
if self.app.sdkconfig.get('SECURE_BOOT'):
|
|
keyfile = self.app.sdkconfig.get('SECURE_BOOT_SIGNING_KEY')
|
|
# Signing the image with espsecure
|
|
espsecure.main(
|
|
f'sign_data --version 2 --append_signatures --keyfile {keyfile} --output {datafile_signed} {datafile}'.split()
|
|
)
|
|
flash_file = datafile_signed
|
|
|
|
esptool.main(
|
|
f'{no_stub} write_flash {offs} {flash_file} {encrypt} --flash_size {flash_size}'.split(),
|
|
esp=self.esp
|
|
)
|
|
|
|
if is_rollback:
|
|
if os.path.exists(datafile):
|
|
os.remove(datafile)
|
|
if os.path.exists(datafile_signed):
|
|
os.remove(datafile_signed)
|
|
|
|
@EspSerial.use_esptool()
|
|
def custom_flash(self) -> None:
|
|
self.bootloader_force_flash_if_req()
|
|
self.flash()
|
|
|
|
@EspSerial.use_esptool()
|
|
def custom_flash_w_test_tee_img_gen(self) -> None:
|
|
self.bootloader_force_flash_if_req()
|
|
self.flash()
|
|
self.copy_test_tee_img('ota_1', False)
|
|
|
|
@EspSerial.use_esptool()
|
|
def custom_flash_w_test_tee_img_rb(self) -> None:
|
|
self.bootloader_force_flash_if_req()
|
|
self.flash()
|
|
self.copy_test_tee_img('ota_1', True)
|
|
|
|
@EspSerial.use_esptool()
|
|
def custom_flash_with_empty_sec_stg(self) -> None:
|
|
self.bootloader_force_flash_if_req()
|
|
self.flash()
|
|
self.custom_erase_partition('secure_storage')
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
def monkeypatch_module(request: FixtureRequest) -> MonkeyPatch:
|
|
mp = MonkeyPatch()
|
|
request.addfinalizer(mp.undo)
|
|
return mp
|
|
|
|
|
|
@pytest.fixture(scope='module', autouse=True)
|
|
def replace_dut_class(monkeypatch_module: MonkeyPatch) -> None:
|
|
monkeypatch_module.setattr('pytest_embedded_idf.IdfSerial', TEESerial)
|