Merge branch 'feat/enable_secure_boot_for_c5' into 'master'

feat: enable secure boot for c5

Closes IDF-8623 and IDF-9478

See merge request espressif/esp-idf!29774
This commit is contained in:
Aditya Patwardhan 2024-06-03 15:35:51 +08:00
commit f412149dc9
15 changed files with 138 additions and 30 deletions

View File

@ -31,6 +31,8 @@
#include "esp32h2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/secure_boot.h"
#endif
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED

View File

@ -25,6 +25,8 @@
#include "esp32h2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/secure_boot.h"
#endif
#if !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_FULL >= 300

View File

@ -21,6 +21,8 @@
#include "esp32h2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/secure_boot.h"
#endif
esp_err_t verify_ecdsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block);

View File

@ -111,6 +111,10 @@ config SOC_FLASH_ENC_SUPPORTED
bool
default y
config SOC_SECURE_BOOT_SUPPORTED
bool
default y
config SOC_PMU_SUPPORTED
bool
default y
@ -631,10 +635,26 @@ config SOC_EFUSE_ECDSA_KEY
bool
default y
config SOC_SECURE_BOOT_V2_RSA
bool
default y
config SOC_SECURE_BOOT_V2_ECC
bool
default y
config SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS
int
default 3
config SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
bool
default y
config SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY
bool
default y
config SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX
int
default 64

View File

@ -56,7 +56,7 @@
#define SOC_ECC_SUPPORTED 1
#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1
#define SOC_FLASH_ENC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8622
// #define SOC_SECURE_BOOT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8623
#define SOC_SECURE_BOOT_SUPPORTED 1
// #define SOC_BOD_SUPPORTED 1 // TODO: [ESP32C5] IDF-8647
// #define SOC_APM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8614, IDF-8615
#define SOC_PMU_SUPPORTED 1 // TODO: [ESP32C5] IDF-8667
@ -467,11 +467,11 @@
#define SOC_EFUSE_ECDSA_KEY 1
/*-------------------------- Secure Boot CAPS----------------------------*/
// #define SOC_SECURE_BOOT_V2_RSA 1
// #define SOC_SECURE_BOOT_V2_ECC 1
#define SOC_SECURE_BOOT_V2_RSA 1
#define SOC_SECURE_BOOT_V2_ECC 1
#define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3
// #define SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1
// #define SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY 1
#define SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1
#define SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY 1
/*-------------------------- Flash Encryption CAPS----------------------------*/
#define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64) // TODO: [ESP32C5] IDF-8622

View File

@ -107,6 +107,10 @@ config SOC_FLASH_ENC_SUPPORTED
bool
default y
config SOC_SECURE_BOOT_SUPPORTED
bool
default y
config SOC_SPI_FLASH_SUPPORTED
bool
default y
@ -663,10 +667,26 @@ config SOC_EFUSE_ECDSA_KEY
bool
default y
config SOC_SECURE_BOOT_V2_RSA
bool
default y
config SOC_SECURE_BOOT_V2_ECC
bool
default y
config SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS
int
default 3
config SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
bool
default y
config SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY
bool
default y
config SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX
int
default 64

View File

@ -54,7 +54,7 @@
#define SOC_ECC_SUPPORTED 1
#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1
#define SOC_FLASH_ENC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8622
// #define SOC_SECURE_BOOT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8623
#define SOC_SECURE_BOOT_SUPPORTED 1
// #define SOC_BOD_SUPPORTED 1 // TODO: [ESP32C5] IDF-8647
// #define SOC_APM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8614, IDF-8615
// #define SOC_PMU_SUPPORTED 1 // TODO: [ESP32C5] IDF-8667
@ -468,11 +468,11 @@
#define SOC_EFUSE_ECDSA_KEY 1
/*-------------------------- Secure Boot CAPS----------------------------*/
// #define SOC_SECURE_BOOT_V2_RSA 1
// #define SOC_SECURE_BOOT_V2_ECC 1
#define SOC_SECURE_BOOT_V2_RSA 1
#define SOC_SECURE_BOOT_V2_ECC 1
#define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3
// #define SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1
// #define SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY 1
#define SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1
#define SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY 1
/*-------------------------- Flash Encryption CAPS----------------------------*/
#define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64) // TODO: [ESP32C5] IDF-8622

View File

@ -226,8 +226,6 @@ api-reference/protocols/mdns.rst
api-reference/protocols/index.rst
api-reference/protocols/asio.rst
security/flash-encryption.rst
security/secure-boot-v2.rst
security/secure-boot-v1.rst
about.rst
resources.rst
migration-guides/release-5.x/5.2/ieee802154.rst

View File

@ -3,11 +3,11 @@
Secure Boot V2
==============
{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2="ECDSA", esp32c6="RSA-PSS or ECDSA", esp32h2="RSA-PSS or ECDSA", esp32p4="RSA-PSS or ECDSA"}
{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2="ECDSA", esp32c6="RSA-PSS or ECDSA", esp32h2="RSA-PSS or ECDSA", esp32p4="RSA-PSS or ECDSA", esp32c5="RSA-PSS or ECDSA"}
{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2="ECDSA-256 or ECDSA-192", esp32c6="RSA-3072, ECDSA-256, or ECDSA-192", esp32h2="RSA-3072, ECDSA-256, or ECDSA-192", esp32p4="RSA-3072, ECDSA-256, or ECDSA-192"}
{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2="ECDSA-256 or ECDSA-192", esp32c6="RSA-3072, ECDSA-256, or ECDSA-192", esp32h2="RSA-3072, ECDSA-256, or ECDSA-192", esp32p4="RSA-3072, ECDSA-256, or ECDSA-192", esp32c5="RSA-3072, ECDSA-256, or ECDSA-192"}
{IDF_TARGET_SECURE_BOOT_OPTION_TEXT:default="", esp32c6="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu.", esp32h2="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu.", esp32p4="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu."}
{IDF_TARGET_SECURE_BOOT_OPTION_TEXT:default="", esp32c6="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu.", esp32h2="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu.", esp32p4="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu.", esp32c5="RSA is recommended because of faster verification time. You can choose between RSA and ECDSA scheme from the menu."}
{IDF_TARGET_ECO_VERSION:default="", esp32="(ECO 3 onwards)", esp32c3="(ECO 3 onwards)"}
@ -142,7 +142,7 @@ The signature block starts on a 4 KB aligned boundary and has a flash sector of
RSA is recommended for use cases where fast bootup time is required whereas ECDSA is recommended for use cases where shorter key length is required.
.. only:: not esp32p4
.. only:: not esp32p4 or not esp32c5
.. list-table:: Comparison between signature verification time
:widths: 10 10 20

View File

@ -560,6 +560,8 @@ def test_examples_efuse_with_virt_secure_boot_v2_pre_loaded(dut: Dut) -> None:
@pytest.mark.esp32c3
@pytest.mark.esp32c2
# TODO: [ESP32C5] IDF-10043
# @pytest.mark.esp32c5
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.esp32p4
@ -633,6 +635,8 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(dut: Dut) -> None:
@pytest.mark.esp32c3
@pytest.mark.esp32c2
# TODO: [ESP32C5] IDF-10043
# @pytest.mark.esp32c5
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.esp32p4

View File

@ -0,0 +1,18 @@
# FLASH_ENCRYPTION & SECURE_BOOT_V2 with EFUSE_VIRTUAL_KEEP_IN_FLASH
CONFIG_IDF_TARGET="esp32c5"
CONFIG_PARTITION_TABLE_OFFSET=0xD000
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="test/partitions_efuse_emul.csv"
CONFIG_SECURE_BOOT=y
CONFIG_SECURE_BOOT_V2_ENABLED=y
CONFIG_SECURE_BOOT_SIGNING_KEY="test/secure_boot_signing_key.pem"
CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE=y
CONFIG_SECURE_FLASH_ENC_ENABLED=y
# IMPORTANT: ONLY VIRTUAL eFuse MODE!
CONFIG_EFUSE_VIRTUAL=y
CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH=y

View File

@ -0,0 +1,16 @@
# SECURE_BOOT_V2 with EFUSE_VIRTUAL_KEEP_IN_FLASH
CONFIG_IDF_TARGET="esp32c5"
CONFIG_PARTITION_TABLE_OFFSET=0xC000
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="test/partitions_efuse_emul.csv"
CONFIG_SECURE_BOOT=y
CONFIG_SECURE_BOOT_V2_ENABLED=y
CONFIG_SECURE_BOOT_SIGNING_KEY="test/secure_boot_signing_key.pem"
CONFIG_SECURE_INSECURE_ALLOW_DL_MODE=y
# IMPORTANT: ONLY VIRTUAL eFuse MODE!
CONFIG_EFUSE_VIRTUAL=y
CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH=y

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
# Secure Boot
@ -16,6 +16,7 @@ Any of the following ESP module:
* ESP32C3-ECO3 (supports Secure Boot V2)
* ESP32S3 (supports Secure Boot V2)
* ESP32P4 (supports Secure Boot V2)
* ESP32C5 (supports Secure Boot V2)
It is recommended to use Secure Boot V2 from ESP32-ECO3 onwards.
@ -70,7 +71,7 @@ Purpose of the test case (`pytest_secure_boot.py`) is to test the secure boot im
### Hardware required
* FPGA setup with ESP32C3/ESP32S3/ESP32P4 image
* FPGA setup with ESP32C3/ESP32S3/ESP32P4/ESP32C5 image
* COM port for programming and export it as ESPPORT
e.g `export ESPPORT=/dev/ttyUSB0`
@ -83,7 +84,7 @@ Purpose of the test case (`pytest_secure_boot.py`) is to test the secure boot im
```
export IDF_ENV_FPGA=1
idf.py set-target esp32c3 #(or esp32s3 / esp32p4)
idf.py set-target esp32c3 #(or esp32s3 / esp32p4 / esp32c5)
idf.py menuconfig
```

View File

@ -1,6 +1,5 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# pylint: disable=W0621 # redefined-outer-name
import os
import subprocess
@ -56,7 +55,7 @@ class FpgaSerial(IdfSerial):
if subprocess.run(
f'{sys.executable} -m esptool --port {self.esp_port} --no-stub write_flash {str(offs)} {partition_table_path}'.split()
).returncode != 0:
raise RuntimeError('Flashing the patition table binary failed')
raise RuntimeError('Flashing the partition table binary failed')
@EspSerial.use_esptool(hard_reset_after=True, no_stub=True)
def app_flash(self, app_path: str) -> None:
@ -173,6 +172,20 @@ class Esp32p4FpgaDut(FpgaDut):
self.serial.burn_efuse_key_digest(digest, 'SECURE_BOOT_DIGEST%d' % key_index, 'BLOCK_KEY%d' % block)
class Esp32c5FpgaDut(FpgaDut):
SECURE_BOOT_EN_KEY = 'SECURE_BOOT_EN'
SECURE_BOOT_EN_VAL = 1
def burn_wafer_version(self) -> None:
pass
def secure_boot_burn_en_bit(self) -> None:
self.serial.burn_efuse(self.SECURE_BOOT_EN_KEY, self.SECURE_BOOT_EN_VAL)
def secure_boot_burn_digest(self, digest: str, key_index: int = 0, block: int = 0) -> None:
self.serial.burn_efuse_key_digest(digest, 'SECURE_BOOT_DIGEST%d' % key_index, 'BLOCK_KEY%d' % block)
@pytest.fixture(scope='module')
def monkeypatch_module(request: FixtureRequest) -> MonkeyPatch:
mp = MonkeyPatch()
@ -189,5 +202,7 @@ def replace_dut_class(monkeypatch_module: MonkeyPatch, pytestconfig: pytest.Conf
monkeypatch_module.setattr('pytest_embedded_idf.IdfDut', Esp32s3FpgaDut)
elif target == 'esp32p4':
monkeypatch_module.setattr('pytest_embedded_idf.IdfDut', Esp32p4FpgaDut)
elif target == 'esp32c5':
monkeypatch_module.setattr('pytest_embedded_idf.IdfDut', Esp32c5FpgaDut)
monkeypatch_module.setattr('pytest_embedded_idf.IdfSerial', FpgaSerial)

View File

@ -1,7 +1,5 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
from __future__ import print_function
import os
import struct
import zlib
@ -18,17 +16,19 @@ from pytest_embedded import Dut
# e.g export EFUSEPORT=/dev/ttyUSB1
# 4. Run these tests
CORRUPT_ALL_BLOCKS = 0xFF
def corrupt_signature(signed_bootloader, seed=0, corrupt_sig=True, corrupt_crc=False, corrupt_single_block=None):
def corrupt_signature(signed_bootloader, seed=0, corrupt_sig=True, corrupt_crc=False, corrupt_block=CORRUPT_ALL_BLOCKS):
# type: (bytes, int, bool, bool, int) -> bytes
image = signed_bootloader[:-4096]
signature = signed_bootloader[-4096:]
sig_blocks = (signature[0:1216], signature[1216:2432], signature[2432:3648])
new_blocks = tuple(corrupt_sig_block(s, seed, corrupt_sig, corrupt_crc) for s in sig_blocks)
# if corrupt_single_block is None, corrupt all blocks
# if corrupt_block is CORRUPT_ALL_BLOCKS, corrupt all blocks
# otherwise, only corrupt the one with that index set
corr_sig_blocks = tuple(new_blocks[n] if corrupt_single_block in [None, n] else sig_blocks[n] for n in range(3))
corr_sig_blocks = tuple(new_blocks[n] if corrupt_block in [CORRUPT_ALL_BLOCKS, n] else sig_blocks[n] for n in range(3))
return image + b''.join(corr_sig_blocks) + signature[3648:]
@ -80,6 +80,8 @@ def dut_start_secure_app(dut: Dut) -> None:
# Test secure boot flow.
# Correctly signed bootloader + correctly signed app should work
@pytest.mark.esp32c3
# TODO: [ESP32C5] IDF-10043
# @pytest.mark.esp32c5
@pytest.mark.esp32s3
@pytest.mark.esp32p4
def test_examples_security_secure_boot(dut: Dut) -> None:
@ -92,6 +94,8 @@ def test_examples_security_secure_boot(dut: Dut) -> None:
# Test efuse key index and key block combination.
# Any key index can be written to any key block and should work
@pytest.mark.esp32c3
# TODO: [ESP32C5] IDF-10043
# @pytest.mark.esp32c5
@pytest.mark.esp32s3
@pytest.mark.esp32p4
# Increasing the test timeout to 1200s as the test runs for 18 iterations
@ -114,6 +118,8 @@ def test_examples_security_secure_boot_key_combo(dut: Dut) -> None:
# Test secure boot key revoke.
# If a key is revoked, bootloader signed with that key should fail verification
@pytest.mark.esp32c3
# TODO: [ESP32C5] IDF-10043
# @pytest.mark.esp32c5
@pytest.mark.esp32s3
@pytest.mark.esp32p4
def test_examples_security_secure_boot_key_revoke(dut: Dut) -> None:
@ -133,6 +139,8 @@ def test_examples_security_secure_boot_key_revoke(dut: Dut) -> None:
# Test bootloader signature corruption.
# Corrupt one byte at a time of bootloader signature and test that the verification fails
@pytest.mark.esp32c3
# TODO: [ESP32C5] IDF-10043
# @pytest.mark.esp32c5
@pytest.mark.esp32s3
@pytest.mark.esp32p4
@pytest.mark.timeout(18000)
@ -170,6 +178,8 @@ def test_examples_security_secure_boot_corrupt_bl_sig(dut: Dut) -> None:
# Test app signature corruption.
# Corrupt app signature, one byte at a time, and test that the verification fails
@pytest.mark.esp32c3
# TODO: [ESP32C5] IDF-10043
# @pytest.mark.esp32c5
@pytest.mark.esp32s3
@pytest.mark.esp32p4
@pytest.mark.timeout(18000)
@ -213,6 +223,6 @@ def test_examples_security_secure_boot_corrupt_app_sig(dut: Dut) -> None:
dut.secure_boot_burn_en_bit()
dut.secure_boot_burn_digest('test_rsa_3072_key.pem', 0, 0)
dut.expect('Sig block 0 invalid: {}'.format('CRC mismatch' if dut.target == 'esp32p4' else 'Stored CRC ends'), timeout=2)
dut.expect('Sig block 0 invalid: {}'.format('CRC mismatch' if dut.target == 'esp32p4' or dut.target == 'esp32c5' else 'Stored CRC ends'), timeout=2)
dut.expect('Secure boot signature verification failed', timeout=2)
dut.expect('No bootable app partitions in the partition table', timeout=2)