From d6c11846766c92a40a1d1262659fc718b7463f1f Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Fri, 19 Sep 2025 13:01:32 +0530 Subject: [PATCH] fix(bootloader_support): Reorder write protection bits of some shared security efuses --- components/bootloader/Kconfig.projbuild | 25 +++++++++++++++++++ .../src/esp32c5/secure_boot_secure_features.c | 2 -- .../bootloader_support/src/secure_boot.c | 8 ++++++ components/esp_security/Kconfig | 10 ++++++-- components/esp_security/src/init.c | 25 ++++++++++++++++--- docs/en/security/flash-encryption.rst | 4 +++ ...security-features-enablement-workflows.rst | 3 +-- 7 files changed, 68 insertions(+), 9 deletions(-) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 19e5108f85..4e080668af 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -972,6 +972,24 @@ menu "Security features" so that the bootloader would not need to enable secure boot and thus you could avoid its revocation strategy. + config SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA + bool "Skip write-protection of SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH" + default y if SECURE_FLASH_PSEUDO_ROUND_FUNC + default n + depends on SOC_ECDSA_SUPPORT_CURVE_P384 && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND + help + If not set (default, recommended), on the first boot when Secure Boot is enabled for + targets that support Secure Boot using ECDSA-P384, the bootloader will burn the write-protection bit of + of SECURE_BOOT_SHA384_EN that could be shared by multiple other efuse bits like + SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH / XTS_DPA_PSEUDO_LEVEL. + + Once this efuse bit is write-protected you cannot update the values of the shared efuses, for example, + the security strength value of XTS_DPA_PSEUDO_LEVEL or setting ECC_FORCE_CONST_TIME. + + List of eFuses with the same write protection bit: + + ESP32-C5: XTS_DPA_PSEUDO_LEVEL and ECC_FORCE_CONST_TIME + config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC bool "Leave UART bootloader encryption enabled" depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT @@ -1055,6 +1073,7 @@ menu "Security features" ESP32-S3: DIS_ICACHE, DIS_DCACHE, DIS_DOWNLOAD_ICACHE, DIS_DOWNLOAD_DCACHE, DIS_FORCE_DOWNLOAD, DIS_USB_OTG, DIS_TWAI, DIS_APP_CPU, DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT, DIS_USB_JTAG, DIS_USB_SERIAL_JTAG, STRAP_JTAG_SEL, USB_PHY_SEL. + endmenu # Potentially Insecure config SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART @@ -1101,6 +1120,12 @@ menu "Security features" The strength of the pseudo rounds functions can be configured to low, medium and high, each denoting the values that would be stored in the efuses field. By default the value to set to low. + + It is recommended that the required strength of the pseudo rounds function should be set during the + first boot itself. If your workflow needs to update the function's strength after the first boot, + you should enable CONFIG_SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA to avoid write protecting this + bit during the boot up for targets that support Secure Boot using ECDSA-P384. + You can configure the strength of the pseudo rounds functions according to your use cases, for example, increasing the strength would provide higher security but would slow down the flash encryption/decryption operations. diff --git a/components/bootloader_support/src/esp32c5/secure_boot_secure_features.c b/components/bootloader_support/src/esp32c5/secure_boot_secure_features.c index 5da95e3528..cc9f57b766 100644 --- a/components/bootloader_support/src/esp32c5/secure_boot_secure_features.c +++ b/components/bootloader_support/src/esp32c5/secure_boot_secure_features.c @@ -53,8 +53,6 @@ esp_err_t esp_secure_boot_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_SHA384_EN); #endif - esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_SECURE_BOOT_SHA384_EN); - esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); #ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS diff --git a/components/bootloader_support/src/secure_boot.c b/components/bootloader_support/src/secure_boot.c index a7d566e8fd..05ab0694eb 100644 --- a/components/bootloader_support/src/secure_boot.c +++ b/components/bootloader_support/src/secure_boot.c @@ -429,6 +429,13 @@ bool esp_secure_boot_cfg_verify_release_mode(void) } #if SOC_ECDSA_SUPPORT_CURVE_P384 +#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS + secure = esp_efuse_read_field_bit(ESP_EFUSE_SECURE_BOOT_SHA384_EN); + result &= secure; + if (!secure) { + ESP_LOGW(TAG, "Not enabled Secure Boot using SHA-384 mode (set SECURE_BOOT_SHA384_EN->1)"); + } +#else /* When using Secure Boot with SHA-384, the efuse bit representing Secure Boot with SHA-384 would already be programmed. * But in the case of the existing Secure Boot V2 schemes using SHA-256, the efuse bit representing * Secure Boot with SHA-384 needs to be write-protected, so that an attacker cannot perform a denial-of-service @@ -439,6 +446,7 @@ bool esp_secure_boot_cfg_verify_release_mode(void) if (!secure) { ESP_LOGW(TAG, "Not write-protected secure boot using SHA-384 mode (set WR_DIS_SECURE_BOOT_SHA384_EN->1)"); } +#endif #endif secure = (num_keys != 0); diff --git a/components/esp_security/Kconfig b/components/esp_security/Kconfig index 50d0caf4ea..feadfe56a2 100644 --- a/components/esp_security/Kconfig +++ b/components/esp_security/Kconfig @@ -40,7 +40,7 @@ menu "ESP Security Specific" config ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL bool "Forcefully enable ECC constant time point multiplication operations" depends on SOC_ECC_CONSTANT_TIME_POINT_MUL - default N + default n help If enabled, the app startup code will burn the ECC_FORCE_CONST_TIME efuse bit to force the ECC peripheral to always perform constant time point multiplication operations, @@ -51,10 +51,16 @@ menu "ESP Security Specific" time point multiplication operations by changing the default ESP-IDF configurations. Performing constant time operations protect the ECC multiplication operations from timing attacks. + For targets that support Secure Boot using ECDSA-P384, the write-protection bit of the efuse + bit could be shared by multiple other efuse bits and can be programmed by the application when + Secure Boot is enabled. + Thus, you could select CONFIG_SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA, in case you would like + to skip the write-protection of the efuse bit. + config ESP_ECDSA_ENABLE_P192_CURVE bool "Enable ECDSA 192-curve operations" depends on SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED - default N + default n help By default, only the 256-bit curve operations are allowed. If this configuration is enabled, it will set the eFuse to allow ECDSA operations using both the 192-bit and 256-bit curves. diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index 14ede2dc0d..56e812c4cf 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.c @@ -46,6 +46,8 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) esp_crypto_dpa_protection_startup(); #endif + esp_err_t err = ESP_FAIL; + #if CONFIG_ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL bool force_constant_time = true; #if CONFIG_IDF_TARGET_ESP32H2 @@ -55,7 +57,7 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) #endif if (!esp_efuse_read_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME) && force_constant_time) { ESP_EARLY_LOGD(TAG, "Forcefully enabling ECC constant time operations"); - esp_err_t err = esp_efuse_write_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME); + err = esp_efuse_write_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME); if (err != ESP_OK) { ESP_EARLY_LOGE(TAG, "Enabling ECC constant time operations forcefully failed."); return err; @@ -64,13 +66,30 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) #endif #if CONFIG_ESP_ECDSA_ENABLE_P192_CURVE - esp_err_t err = esp_efuse_enable_ecdsa_p192_curve_mode(); + err = esp_efuse_enable_ecdsa_p192_curve_mode(); if (err != ESP_OK) { return err; } #endif - return ESP_OK; +#if CONFIG_SECURE_BOOT_V2_ENABLED +#if !CONFIG_SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA +// C5 +#if SOC_ECDSA_SUPPORT_CURVE_P384 && !CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS + // Since SECURE_BOOT_SHA384_EN, XTS_DPA_PSEUDO_LEVEL, and ECC_FORCE_CONST_TIME share the + // same write-protection bit, these efuses should only be write-protected after all of + // them have been programmed. + err = esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_SECURE_BOOT_SHA384_EN); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write protect the SECURE_BOOT_SHA384_EN efuse bit."); + return err; + } +#endif +#endif +#endif + + err = ESP_OK; + return err; } void esp_security_init_include_impl(void) diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index 7685295383..30f81513cb 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -876,6 +876,10 @@ It is recommended to use flash encryption in combination with Secure Boot. Howev - :ref:`Re-flashing via Pregenerated Flash Encryption Key ` is still possible, provided the bootloader is not re-flashed. Re-flashing the bootloader requires the same :ref:`Re-flashable ` option to be enabled in the Secure Boot config. +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND and SOC_ECDSA_SUPPORT_CURVE_P384 + + - It is recommended that the required :ref: `strength of the pseudo rounds function ` should be set during the first boot itself when flash encryption release mode is enabled. If your workflow needs to update the function's strength after the first boot, you should enable :ref:`CONFIG_SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA` to avoid write protecting this bit during the boot up. + .. _flash-encryption-advanced-features: Advanced Features diff --git a/docs/en/security/security-features-enablement-workflows.rst b/docs/en/security/security-features-enablement-workflows.rst index 01b579517d..2dd5283e05 100644 --- a/docs/en/security/security-features-enablement-workflows.rst +++ b/docs/en/security/security-features-enablement-workflows.rst @@ -500,8 +500,7 @@ In this workflow we shall use ``espsecure`` tool to generate signing keys and us :SOC_EFUSE_DIS_USB_JTAG: - ``DIS_USB_JTAG``: Disable USB switch to JTAG. :SOC_EFUSE_DIS_PAD_JTAG: - ``DIS_PAD_JTAG``: Disable JTAG permanently. :SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS: - ``SECURE_BOOT_AGGRESSIVE_REVOKE``: Aggressive revocation of key digests, see :ref:`secure-boot-v2-aggressive-key-revocation` for more details. - :SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED: - ``WR_DIS_ECDSA_CURVE_MODE``: Disable writing to the ECDSA curve mode eFuse bit. - :SOC_ECDSA_SUPPORT_CURVE_P384: - ``WR_DIS_SECURE_BOOT_SHA384_EN``: Disable writing to the SHA-384 secure boot eFuse bit. + :SOC_ECDSA_SUPPORT_CURVE_P384: - ``WR_DIS_SECURE_BOOT_SHA384_EN``: Disable writing to the SHA-384 secure boot eFuse bit (As this write protection bit is shared with XTS_DPA_PSEUDO_LEVEL and ECC_FORCE_CONST_TIME, it is recommended to write protect this bit only after configuring all the other shared efuses). The respective eFuses can be burned by running: