From 76e2e6d53f442149dbc2b06766b72bc0b8c330a7 Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Tue, 3 Feb 2026 14:12:54 +0530 Subject: [PATCH] feat: enable support for secure boot in esp32h4 --- .../src/esp32h4/secure_boot_secure_features.c | 60 +++++++++++++++++-- .../esp32h4/include/esp32h4/rom/secure_boot.h | 24 +++++++- .../esp32h4/include/soc/Kconfig.soc_caps.in | 6 +- components/soc/esp32h4/include/soc/soc_caps.h | 4 +- docs/en/security/secure-boot-v2.rst | 6 +- docs/zh_CN/security/secure-boot-v2.rst | 6 +- .../security/secure_boot/conftest.py | 17 +++++- 7 files changed, 105 insertions(+), 18 deletions(-) diff --git a/components/bootloader_support/src/esp32h4/secure_boot_secure_features.c b/components/bootloader_support/src/esp32h4/secure_boot_secure_features.c index c6a210997cd..67489ac75aa 100644 --- a/components/bootloader_support/src/esp32h4/secure_boot_secure_features.c +++ b/components/bootloader_support/src/esp32h4/secure_boot_secure_features.c @@ -1,23 +1,73 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include -#include "esp_flash_encrypt.h" #include "esp_secure_boot.h" #include "esp_efuse.h" #include "esp_efuse_table.h" #include "esp_log.h" #include "sdkconfig.h" -//TODO: [ESP32H4] IDF-12262 - ESP_LOG_ATTR_TAG(TAG, "secure_boot"); esp_err_t esp_secure_boot_enable_secure_features(void) { - abort(); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT); + +#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE + ESP_LOGI(TAG, "Enabling Security download mode..."); + esp_err_t err = esp_efuse_enable_rom_secure_download_mode(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not enable Security download mode..."); + return err; + } +#elif CONFIG_SECURE_DISABLE_ROM_DL_MODE + ESP_LOGI(TAG, "Disable ROM Download mode..."); + esp_err_t err = esp_efuse_disable_rom_download_mode(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not disable ROM Download mode..."); + return err; + } +#else + ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED"); +#endif + +#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG + ESP_LOGI(TAG, "Disable hardware & software JTAG..."); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG); + esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count); +#else + ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED"); +#endif + +#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE + esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE); +#endif + +#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS + esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_SHA384_EN); +#endif + + esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); + +#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS + bool rd_dis_now = true; +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + /* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot + when Flash Encryption is being enabled */ + rd_dis_now = esp_efuse_is_flash_encryption_enabled(); +#endif + if (rd_dis_now) { + ESP_LOGI(TAG, "Prevent read disabling of additional efuses..."); + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); + } +#else + ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED"); +#endif + return ESP_OK; } diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h b/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h index 3e67bf09936..8b0b0bd633c 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,8 +16,6 @@ extern "C" { #endif -//TODO: [ESP32H4] IDF-12262 inherit from verification branch, need check - #if CONFIG_SECURE_BOOT_V2_ENABLED || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT typedef struct ets_secure_boot_sig_block ets_secure_boot_sig_block_t; @@ -89,6 +87,25 @@ struct ets_secure_boot_sig_block { #elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME +#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS +struct __attribute((packed)) ets_secure_boot_sig_block { + uint8_t magic_byte; + uint8_t version; + uint8_t sha_version; + uint8_t _reserved2; + uint8_t image_digest[48]; + struct { + struct { + uint8_t curve_id; /* ETS_ECDSA_CURVE_P192 / ETS_ECDSA_CURVE_P256 / ETS_ECDSA_CURVE_P384 */ + uint8_t point[96]; /* X followed by Y (both little-endian), plus zero bytes if P192 */ + } key; + uint8_t signature[96]; /* r followed by s (both little-endian) */ + uint8_t padding[951]; + } ecdsa; + uint32_t block_crc; /* note: crc covers all bytes in the structure before it, regardless of version field */ + uint8_t _padding[16]; +}; +#else struct __attribute((packed)) ets_secure_boot_sig_block { uint8_t magic_byte; uint8_t version; @@ -106,6 +123,7 @@ struct __attribute((packed)) ets_secure_boot_sig_block { uint32_t block_crc; /* note: crc covers all bytes in the structure before it, regardless of version field */ uint8_t _padding[16]; }; +#endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */ #endif ESP_STATIC_ASSERT(sizeof(ets_secure_boot_sig_block_t) == 1216, "invalid sig block size"); diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index d689ed86fb9..e14263c9c05 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -151,6 +151,10 @@ config SOC_FLASH_ENC_SUPPORTED bool default n +config SOC_SECURE_BOOT_SUPPORTED + bool + default y + config SOC_BOD_SUPPORTED bool default y @@ -941,7 +945,7 @@ config SOC_EFUSE_XTS_AES_KEY_256 config SOC_SECURE_BOOT_V2_RSA bool - default y + default n config SOC_SECURE_BOOT_V2_ECC bool diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 62c28c4bd7c..40767ec95b7 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -72,7 +72,7 @@ #define SOC_ECC_SUPPORTED 1 #define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 #define SOC_FLASH_ENC_SUPPORTED 0 // TODO: [ESP32H4] IDF-12261 -// #define SOC_SECURE_BOOT_SUPPORTED 1 // TODO: [ESP32H4] IDF-12262 +#define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 // #define SOC_APM_SUPPORTED 1 // TODO: [ESP32H4] IDF-12256 @@ -416,7 +416,7 @@ #define SOC_EFUSE_XTS_AES_KEY_256 1 /*-------------------------- Secure Boot CAPS----------------------------*/ -#define SOC_SECURE_BOOT_V2_RSA 1 +#define SOC_SECURE_BOOT_V2_RSA 0 #define SOC_SECURE_BOOT_V2_ECC 1 #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 #define SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1 diff --git a/docs/en/security/secure-boot-v2.rst b/docs/en/security/secure-boot-v2.rst index 934b13a254e..f21e721042c 100644 --- a/docs/en/security/secure-boot-v2.rst +++ b/docs/en/security/secure-boot-v2.rst @@ -5,9 +5,9 @@ Secure Boot v2 :link_to_translation:`zh_CN:[中文]` -{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2, esp32c61="ECDSA", esp32c6, esp32h2, esp32p4, esp32c5, esp32h21="RSA-PSS or ECDSA"} +{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2, esp32c61, esp32h4="ECDSA", esp32c6, esp32h2, esp32p4, esp32c5, esp32h21="RSA-PSS or ECDSA"} -{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2, esp32c61="ECDSA-256", esp32c6, esp32h2, esp32p4, esp32h21="RSA-3072, ECDSA-256", esp32c5="RSA-3072, ECDSA-384, ECDSA-256"} +{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2, esp32c61="ECDSA-256", esp32c6, esp32h2, esp32p4, esp32h21="RSA-3072, ECDSA-256", esp32h4="ECDSA-384, ECDSA-256", esp32c5="RSA-3072, ECDSA-384, ECDSA-256"} {IDF_TARGET_SECURE_BOOT_OPTION_TEXT:default="", esp32c6, esp32h2, esp32p4, esp32h21="RSA is recommended for faster verification. You can choose either the RSA or ECDSA scheme from the menu.", esp32c5="ECDSA is recommended for faster verification. You can choose either the RSA or ECDSA scheme from the menu."} @@ -25,7 +25,7 @@ Secure Boot v2 {IDF_TARGET_CPU_FREQ:default="", esp32c5="240 MHz", esp32c6="160 MHz", esp32h2="96 MHz", esp32p4="360 MHz"} -{IDF_TARGET_SBV2_DEFAULT_SCHEME:default="RSA", esp32c2, esp32c61, esp32c5="ECDSA (v2)"} +{IDF_TARGET_SBV2_DEFAULT_SCHEME:default="RSA", esp32c2, esp32c61, esp32c5, esp32h4="ECDSA (v2)"} {IDF_TARGET_EFUSE_WR_DIS_RD_DIS:default="ESP_EFUSE_WR_DIS_RD_DIS", esp32="ESP_EFUSE_WR_DIS_EFUSE_RD_DISABLE"} diff --git a/docs/zh_CN/security/secure-boot-v2.rst b/docs/zh_CN/security/secure-boot-v2.rst index f3465f53058..ee049884af5 100644 --- a/docs/zh_CN/security/secure-boot-v2.rst +++ b/docs/zh_CN/security/secure-boot-v2.rst @@ -5,9 +5,9 @@ :link_to_translation:`en:[English]` -{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2, esp32c61="ECDSA", esp32c6, esp32h2, esp32p4, esp32c5, esp32h21="RSA-PSS 或 ECDSA"} +{IDF_TARGET_SBV2_SCHEME:default="RSA-PSS", esp32c2, esp32c61, esp32h4="ECDSA", esp32c6, esp32h2, esp32p4, esp32c5, esp32h21="RSA-PSS 或 ECDSA"} -{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2, esp32c61="ECDSA-256", esp32c6, esp32h2, esp32p4, esp32h21="RSA-3072、ECDSA-256", esp32c5="RSA-3072、ECDSA-384、ECDSA-256"} +{IDF_TARGET_SBV2_KEY:default="RSA-3072", esp32c2, esp32c61="ECDSA-256", esp32c6, esp32h2, esp32p4, esp32h21="RSA-3072、ECDSA-256", esp32h4="ECDSA-384、ECDSA-256", esp32c5="RSA-3072、ECDSA-384、ECDSA-256"} {IDF_TARGET_SECURE_BOOT_OPTION_TEXT:default="", esp32c6, esp32h2, esp32p4, esp32h21="推荐使用 RSA,其验证时间更短。可以在菜单中选择 RSA 或 ECDSA 方案。", esp32c5="推荐使用 ECDSA,其验证时间更短。可以在菜单中选择 RSA 或 ECDSA 方案。"} @@ -25,7 +25,7 @@ {IDF_TARGET_CPU_FREQ:default="", esp32c5="240 MHz", esp32c6="160 MHz", esp32h2="96 MHz", esp32p4="360 MHz"} -{IDF_TARGET_SBV2_DEFAULT_SCHEME:default="RSA", esp32c2, esp32c61, esp32c5="ECDSA (v2)"} +{IDF_TARGET_SBV2_DEFAULT_SCHEME:default="RSA", esp32c2, esp32c61, esp32c5, esp32h4="ECDSA (v2)"} {IDF_TARGET_EFUSE_WR_DIS_RD_DIS:default="ESP_EFUSE_WR_DIS_RD_DIS", esp32="ESP_EFUSE_WR_DIS_EFUSE_RD_DISABLE"} diff --git a/tools/test_apps/security/secure_boot/conftest.py b/tools/test_apps/security/secure_boot/conftest.py index 6267ca6949d..9331d752eb1 100644 --- a/tools/test_apps/security/secure_boot/conftest.py +++ b/tools/test_apps/security/secure_boot/conftest.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # pylint: disable=W0621 # redefined-outer-name import os @@ -202,6 +202,20 @@ class Esp32h21FpgaDut(FpgaDut): self.serial.burn_efuse_key_digest(digest, f'SECURE_BOOT_DIGEST{key_index}', f'BLOCK_KEY{block}') +class Esp32h4FpgaDut(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, f'SECURE_BOOT_DIGEST{key_index}', f'BLOCK_KEY{block}') + + @pytest.fixture(scope='module') def monkeypatch_module(request: FixtureRequest) -> MonkeyPatch: mp = MonkeyPatch() @@ -218,6 +232,7 @@ def replace_dut_class(monkeypatch_module: MonkeyPatch, pytestconfig: pytest.Conf 'esp32c5': Esp32c5FpgaDut, 'esp32c61': Esp32c61FpgaDut, 'esp32h21': Esp32h21FpgaDut, + 'esp32h4': Esp32h4FpgaDut, } target = pytestconfig.getoption('target')