Merge branch 'fix/ecdsa_ecc_hw_input_validation' into 'master'

Validate ECDSA signature range and harden ECC memory power-down

See merge request espressif/esp-idf!48958
This commit is contained in:
Mahavir Jain
2026-06-09 14:40:24 +05:30
47 changed files with 427 additions and 61 deletions
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,6 +12,7 @@
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
#include "soc/pcr_reg.h" #include "soc/pcr_reg.h"
#include "esp_fault.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -47,11 +48,17 @@ static inline void ecc_ll_reset_register(void)
PCR.ecdsa_conf.ecdsa_rst_en = 0; PCR.ecdsa_conf.ecdsa_rst_en = 0;
} }
static inline void ecc_ll_clear_force_pd(void)
{
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
}
static inline void ecc_ll_power_up(void) static inline void ecc_ll_power_up(void)
{ {
/* Power up the ECC peripheral (default state is power-down) */ /* Power up the ECC peripheral (default state is power-down) */
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
} }
static inline void ecc_ll_power_down(void) static inline void ecc_ll_power_down(void)
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,6 +12,7 @@
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
#include "soc/pcr_reg.h" #include "soc/pcr_reg.h"
#include "esp_fault.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -46,6 +47,7 @@ static inline void ecc_ll_power_up(void)
{ {
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
} }
static inline void ecc_ll_power_down(void) static inline void ecc_ll_power_down(void)
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,6 +12,7 @@
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
#include "soc/pcr_reg.h" #include "soc/pcr_reg.h"
#include "esp_fault.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -49,9 +50,10 @@ static inline void ecc_ll_reset_register(void)
static inline void ecc_ll_power_up(void) static inline void ecc_ll_power_up(void)
{ {
/* Power up the ECC peripheral (default state is power-down) */ /* Power up the ECC peripheral (default state is power-up) */
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
} }
static inline void ecc_ll_power_down(void) static inline void ecc_ll_power_down(void)
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,6 +12,7 @@
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
#include "soc/pcr_reg.h" #include "soc/pcr_reg.h"
#include "esp_fault.h"
#include "soc/chip_revision.h" #include "soc/chip_revision.h"
#include "hal/efuse_hal.h" #include "hal/efuse_hal.h"
@@ -54,6 +55,7 @@ static inline void ecc_ll_power_up(void)
{ {
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
} }
static inline void ecc_ll_power_down(void) static inline void ecc_ll_power_down(void)
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,6 +12,7 @@
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
#include "soc/pcr_reg.h" #include "soc/pcr_reg.h"
#include "esp_fault.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -52,6 +53,7 @@ static inline void ecc_ll_power_up(void)
{ {
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD); REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD) == 0);
} }
static inline void ecc_ll_power_down(void) static inline void ecc_ll_power_down(void)
@@ -12,6 +12,7 @@
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
#include "soc/pcr_reg.h" #include "soc/pcr_reg.h"
#include "esp_fault.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -50,9 +51,11 @@ static inline void ecc_ll_reset_register(void)
static inline void ecc_ll_power_up(void) static inline void ecc_ll_power_up(void)
{ {
/* Power up the ECC peripheral (default state is power-down) */ /* Power up the ECC peripheral (default state is power-up) */
REG_CLR_BIT(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_LP_EN); REG_CLR_BIT(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_LP_EN);
REG_CLR_BIT(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_FORCE_CTRL); REG_SET_BIT(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_FORCE_CTRL);
ESP_FAULT_ASSERT(REG_GET_BIT(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_LP_EN) == 0 &&
REG_GET_BIT(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_FORCE_CTRL) != 0);
} }
static inline void ecc_ll_power_down(void) static inline void ecc_ll_power_down(void)
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,8 +12,10 @@
#include "hal/efuse_hal.h" #include "hal/efuse_hal.h"
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/hp_sys_clkrst_struct.h" #include "soc/hp_sys_clkrst_struct.h"
#include "soc/hp_system_reg.h"
#include "soc/chip_revision.h" #include "soc/chip_revision.h"
#include "hal/config.h" #include "hal/config.h"
#include "esp_fault.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -65,8 +67,20 @@ static inline void ecc_ll_reset_register(void)
ecc_ll_reset_register(__VA_ARGS__); \ ecc_ll_reset_register(__VA_ARGS__); \
} while(0) } while(0)
static inline void ecc_ll_power_up(void) {} static inline void ecc_ll_power_up(void)
static inline void ecc_ll_power_down(void) {} {
/* Power up the ECC peripheral (default state is power-up) */
REG_CLR_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_PD);
REG_CLR_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_FORCE_PD);
ESP_FAULT_ASSERT(REG_GET_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_FORCE_PD) == 0);
}
static inline void ecc_ll_power_down(void)
{
/* Power down the ECC peripheral */
REG_CLR_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_FORCE_PU);
REG_SET_BIT(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_PD);
}
static inline void ecc_ll_enable_interrupt(void) static inline void ecc_ll_enable_interrupt(void)
{ {
@@ -11,6 +11,8 @@
#include "hal/ecc_types.h" #include "hal/ecc_types.h"
#include "soc/ecc_mult_reg.h" #include "soc/ecc_mult_reg.h"
#include "soc/hp_sys_clkrst_struct.h" #include "soc/hp_sys_clkrst_struct.h"
#include "soc/hp_system_reg.h"
#include "esp_fault.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -62,8 +64,21 @@ static inline void ecc_ll_reset_register(void)
ecc_ll_reset_register(__VA_ARGS__); \ ecc_ll_reset_register(__VA_ARGS__); \
} while(0) } while(0)
static inline void ecc_ll_power_up(void) {} static inline void ecc_ll_power_up(void)
static inline void ecc_ll_power_down(void) {} {
/* Power up the ECC peripheral (default state is power-up) */
REG_CLR_BIT(HP_SYSTEM_ECC_MEM_LP_CTRL_REG, HP_SYSTEM_ECC_MEM_LP_EN);
REG_SET_BIT(HP_SYSTEM_ECC_MEM_LP_CTRL_REG, HP_SYSTEM_ECC_MEM_LP_FORCE_CTRL);
/* Anti-FI: confirm the clears took effect. */
ESP_FAULT_ASSERT(REG_GET_BIT(HP_SYSTEM_ECC_MEM_LP_CTRL_REG, HP_SYSTEM_ECC_MEM_LP_EN) == 0 &&
REG_GET_BIT(HP_SYSTEM_ECC_MEM_LP_CTRL_REG, HP_SYSTEM_ECC_MEM_LP_FORCE_CTRL) != 0);
}
static inline void ecc_ll_power_down(void)
{
/* Power down the ECC peripheral */
REG_SET_BIT(HP_SYSTEM_ECC_MEM_LP_CTRL_REG, HP_SYSTEM_ECC_MEM_LP_EN);
}
static inline void ecc_ll_enable_interrupt(void) static inline void ecc_ll_enable_interrupt(void)
{ {
@@ -207,6 +207,10 @@ static void test_ecc_point_mul_inner_constant_time(void)
uint32_t max_time = 0, min_time = UINT32_MAX; uint32_t max_time = 0, min_time = UINT32_MAX;
int loop_count = 10; int loop_count = 10;
/* Warm-up: the first call is otherwise an I-cache / branch-predictor
* outlier that dominates max_time and thus creating deviations */
ecc_point_mul(scalar_le, x_le, y_le, ECC_P256_SIZE_BYTES, 0, x_res_le, y_res_le);
for (int i = 0; i < loop_count; i++) { for (int i = 0; i < loop_count; i++) {
ccomp_timer_start(); ccomp_timer_start();
ecc_point_mul(scalar_le, x_le, y_le, ECC_P256_SIZE_BYTES, 0, x_res_le, y_res_le); ecc_point_mul(scalar_le, x_le, y_le, ECC_P256_SIZE_BYTES, 0, x_res_le, y_res_le);
@@ -230,6 +234,9 @@ static void test_ecc_point_mul_inner_constant_time(void)
min_time = UINT32_MAX; min_time = UINT32_MAX;
total_elapsed_time = 0; total_elapsed_time = 0;
/* Warm-up — see comment on the P256 loop. */
ecc_point_mul(scalar_le, x_le, y_le, ECC_P192_SIZE_BYTES, 0, x_res_le, y_res_le);
for (int i = 0; i < loop_count; i++) { for (int i = 0; i < loop_count; i++) {
ccomp_timer_start(); ccomp_timer_start();
ecc_point_mul(scalar_le, x_le, y_le, ECC_P192_SIZE_BYTES, 0, x_res_le, y_res_le); ecc_point_mul(scalar_le, x_le, y_le, ECC_P192_SIZE_BYTES, 0, x_res_le, y_res_le);
@@ -255,6 +262,9 @@ static void test_ecc_point_mul_inner_constant_time(void)
min_time = UINT32_MAX; min_time = UINT32_MAX;
total_elapsed_time = 0; total_elapsed_time = 0;
/* Warm-up — see comment on the P256 loop. */
ecc_point_mul(scalar_le, x_le, y_le, ECC_P384_SIZE_BYTES, 0, x_res_le, y_res_le);
for (int i = 0; i < loop_count; i++) { for (int i = 0; i < loop_count; i++) {
ccomp_timer_start(); ccomp_timer_start();
ecc_point_mul(scalar_le, x_le, y_le, ECC_P384_SIZE_BYTES, 0, x_res_le, y_res_le); ecc_point_mul(scalar_le, x_le, y_le, ECC_P384_SIZE_BYTES, 0, x_res_le, y_res_le);
+4
View File
@@ -59,6 +59,10 @@ if(CONFIG_ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP)
list(APPEND sources "patches/esp_rom_cache_writeback_esp32c5_esp32c61_esp32h4.c") list(APPEND sources "patches/esp_rom_cache_writeback_esp32c5_esp32c61_esp32h4.c")
endif() endif()
if(CONFIG_ESP_ROM_ECDSA_VERIFY_PATCH)
list(APPEND sources "patches/esp_rom_ecdsa.c")
endif()
idf_component_register(SRCS ${sources} idf_component_register(SRCS ${sources}
INCLUDE_DIRS ${include_dirs} INCLUDE_DIRS ${include_dirs}
PRIV_REQUIRES ${private_required_comp} PRIV_REQUIRES ${private_required_comp}
@@ -119,6 +119,10 @@ config ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP
bool bool
default y default y
config ESP_ROM_ECDSA_VERIFY_PATCH
bool
default y
config ESP_ROM_BOOTLOADER_OFFSET_FLASH config ESP_ROM_BOOTLOADER_OFFSET_FLASH
hex hex
default 0x2000 default 0x2000
@@ -35,5 +35,6 @@
#define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access. #define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access.
#define ESP_ROM_DELAY_US_PATCH (1) // ROM ets_delay_us needs patch for U-mode operation #define ESP_ROM_DELAY_US_PATCH (1) // ROM ets_delay_us needs patch for U-mode operation
#define ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP (1) // ROM supports the secure boot fast wakeup feature #define ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP (1) // ROM supports the secure boot fast wakeup feature
#define ESP_ROM_ECDSA_VERIFY_PATCH (1) // ROM ets_ecdsa_verify API requires a software patch
#define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader #define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader
#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter #define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter
+1 -1
View File
@@ -412,7 +412,7 @@ esp_rom_km_huk_risk = 0x40000898;
/* Functions */ /* Functions */
ets_emsa_pss_verify = 0x4000089c; ets_emsa_pss_verify = 0x4000089c;
ets_rsa_pss_verify = 0x400008a0; ets_rsa_pss_verify = 0x400008a0;
ets_ecdsa_verify = 0x400008a4; _rom_ets_ecdsa_verify = 0x400008a4;
ets_secure_boot_verify_bootloader_with_keys = 0x400008a8; ets_secure_boot_verify_bootloader_with_keys = 0x400008a8;
ets_secure_boot_verify_signature = 0x400008ac; ets_secure_boot_verify_signature = 0x400008ac;
ets_secure_boot_read_key_digests = 0x400008b0; ets_secure_boot_read_key_digests = 0x400008b0;
@@ -107,6 +107,10 @@ config ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY
bool bool
default y default y
config ESP_ROM_ECDSA_VERIFY_PATCH
bool
default y
config ESP_ROM_DELAY_US_PATCH config ESP_ROM_DELAY_US_PATCH
bool bool
default y default y
@@ -32,6 +32,7 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage. #define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart) #define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)
#define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access. #define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access.
#define ESP_ROM_ECDSA_VERIFY_PATCH (1) // ROM ets_ecdsa_verify API requires a software patch
#define ESP_ROM_DELAY_US_PATCH (1) // ROM ets_delay_us needs patch for U-mode operation #define ESP_ROM_DELAY_US_PATCH (1) // ROM ets_delay_us needs patch for U-mode operation
#define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x0) // Bootloader offset in flash determined by the ROM bootloader #define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x0) // Bootloader offset in flash determined by the ROM bootloader
#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter #define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter
@@ -370,7 +370,7 @@ ets_efuse_usb_device_disabled = 0x40000808;
***************************************/ ***************************************/
/* Functions */ /* Functions */
ets_ecdsa_verify = 0x40000810; _rom_ets_ecdsa_verify = 0x40000810;
ets_secure_boot_verify_bootloader_with_keys = 0x40000814; ets_secure_boot_verify_bootloader_with_keys = 0x40000814;
ets_secure_boot_verify_signature = 0x40000818; ets_secure_boot_verify_signature = 0x40000818;
ets_secure_boot_read_key_digests = 0x4000081c; ets_secure_boot_read_key_digests = 0x4000081c;
@@ -115,6 +115,10 @@ config ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP
bool bool
default y default y
config ESP_ROM_ECDSA_VERIFY_PATCH
bool
default y
config ESP_ROM_BOOTLOADER_OFFSET_FLASH config ESP_ROM_BOOTLOADER_OFFSET_FLASH
hex hex
default 0x0 default 0x0
@@ -34,4 +34,5 @@
#define ESP_ROM_NO_USB_SERIAL_OUTPUT_API (1) // ROM does not export the usb-serial-jtag write char function #define ESP_ROM_NO_USB_SERIAL_OUTPUT_API (1) // ROM does not export the usb-serial-jtag write char function
#define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access. #define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access.
#define ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP (1) // ROM supports the secure boot fast wakeup feature #define ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP (1) // ROM supports the secure boot fast wakeup feature
#define ESP_ROM_ECDSA_VERIFY_PATCH (1) // ROM ets_ecdsa_verify API requires a software patch
#define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x0) // Bootloader offset in flash determined by the ROM bootloader #define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x0) // Bootloader offset in flash determined by the ROM bootloader
+1 -1
View File
@@ -361,7 +361,7 @@ ets_efuse_secure_boot_fast_wake_enabled = 0x40000830;
/* Functions */ /* Functions */
ets_emsa_pss_verify = 0x40000834; ets_emsa_pss_verify = 0x40000834;
ets_rsa_pss_verify = 0x40000838; ets_rsa_pss_verify = 0x40000838;
ets_ecdsa_verify = 0x4000083c; _rom_ets_ecdsa_verify = 0x4000083c;
ets_secure_boot_verify_bootloader_with_keys = 0x40000840; ets_secure_boot_verify_bootloader_with_keys = 0x40000840;
ets_secure_boot_verify_signature = 0x40000844; ets_secure_boot_verify_signature = 0x40000844;
ets_secure_boot_read_key_digests = 0x40000848; ets_secure_boot_read_key_digests = 0x40000848;
@@ -71,6 +71,10 @@ config ESP_ROM_RAM_APP_NEEDS_MMU_INIT
bool bool
default y default y
config ESP_ROM_ECDSA_VERIFY_PATCH
bool
default y
config ESP_ROM_BOOTLOADER_OFFSET_FLASH config ESP_ROM_BOOTLOADER_OFFSET_FLASH
hex hex
default 0x2000 default 0x2000
@@ -23,5 +23,6 @@
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage. #define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_WDT_INIT_PATCH (1) // ROM version does not configure the clock #define ESP_ROM_WDT_INIT_PATCH (1) // ROM version does not configure the clock
#define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init #define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init
#define ESP_ROM_ECDSA_VERIFY_PATCH (1) // ROM ets_ecdsa_verify API requires a software patch
#define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader #define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader
#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter #define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter
+1 -1
View File
@@ -385,7 +385,7 @@ esp_rom_recover_key = 0x400007cc;
***************************************/ ***************************************/
/* Functions */ /* Functions */
ets_ecdsa_verify = 0x400007d0; _rom_ets_ecdsa_verify = 0x400007d0;
ets_secure_boot_verify_bootloader_with_keys = 0x400007d4; ets_secure_boot_verify_bootloader_with_keys = 0x400007d4;
ets_secure_boot_verify_signature = 0x400007d8; ets_secure_boot_verify_signature = 0x400007d8;
ets_secure_boot_read_key_digests = 0x400007dc; ets_secure_boot_read_key_digests = 0x400007dc;
@@ -87,6 +87,10 @@ config ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY
bool bool
default y default y
config ESP_ROM_ECDSA_VERIFY_PATCH
bool
default y
config ESP_ROM_BOOTLOADER_OFFSET_FLASH config ESP_ROM_BOOTLOADER_OFFSET_FLASH
hex hex
default 0x2000 default 0x2000
@@ -27,5 +27,6 @@
#define ESP_ROM_CLIC_INT_TYPE_PATCH (1) // ROM api esprv_intc_int_set_type configuring edge type interrupt (old revisions) #define ESP_ROM_CLIC_INT_TYPE_PATCH (1) // ROM api esprv_intc_int_set_type configuring edge type interrupt (old revisions)
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart) #define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)
#define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access. #define ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY (1) // ROM mem/str functions are not optimized well for misaligned memory access.
#define ESP_ROM_ECDSA_VERIFY_PATCH (1) // ROM ets_ecdsa_verify API requires a software patch
#define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader #define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader
#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, need map parameter #define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, need map parameter
@@ -450,7 +450,7 @@ esp_rom_km_huk_risk = 0x4fc0071c;
/* Functions */ /* Functions */
ets_emsa_pss_verify = 0x4fc00720; ets_emsa_pss_verify = 0x4fc00720;
ets_rsa_pss_verify = 0x4fc00724; ets_rsa_pss_verify = 0x4fc00724;
ets_ecdsa_verify = 0x4fc00728; _rom_ets_ecdsa_verify = 0x4fc00728;
ets_secure_boot_verify_bootloader_with_keys = 0x4fc0072c; ets_secure_boot_verify_bootloader_with_keys = 0x4fc0072c;
ets_secure_boot_verify_signature = 0x4fc00730; ets_secure_boot_verify_signature = 0x4fc00730;
ets_secure_boot_read_key_digests = 0x4fc00734; ets_secure_boot_read_key_digests = 0x4fc00734;
+1 -1
View File
@@ -448,7 +448,7 @@ esp_rom_km_huk_risk = 0x4fc00710;
/* Functions */ /* Functions */
ets_emsa_pss_verify = 0x4fc00714; ets_emsa_pss_verify = 0x4fc00714;
ets_rsa_pss_verify = 0x4fc00718; ets_rsa_pss_verify = 0x4fc00718;
ets_ecdsa_verify = 0x4fc0071c; _rom_ets_ecdsa_verify = 0x4fc0071c;
ets_secure_boot_verify_bootloader_with_keys = 0x4fc00720; ets_secure_boot_verify_bootloader_with_keys = 0x4fc00720;
ets_secure_boot_verify_signature = 0x4fc00724; ets_secure_boot_verify_signature = 0x4fc00724;
ets_secure_boot_read_key_digests = 0x4fc00728; ets_secure_boot_read_key_digests = 0x4fc00728;
@@ -91,6 +91,10 @@ config ESP_ROM_PRINTS_LOCKUP_STATUS
bool bool
default y default y
config ESP_ROM_ECDSA_VERIFY_PATCH
bool
default y
config ESP_ROM_BOOTLOADER_OFFSET_FLASH config ESP_ROM_BOOTLOADER_OFFSET_FLASH
hex hex
default 0x2000 default 0x2000
@@ -29,5 +29,6 @@
#define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information #define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart) #define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)
#define ESP_ROM_PRINTS_LOCKUP_STATUS (1) // ROM bootloader already prints CPU lockup diagnostic status #define ESP_ROM_PRINTS_LOCKUP_STATUS (1) // ROM bootloader already prints CPU lockup diagnostic status
#define ESP_ROM_ECDSA_VERIFY_PATCH (1) // ROM ets_ecdsa_verify API requires a software patch
#define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader #define ESP_ROM_BOOTLOADER_OFFSET_FLASH (0x2000) // Bootloader offset in flash determined by the ROM bootloader
#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, need map parameter #define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, need map parameter
@@ -467,7 +467,7 @@ esp_rom_recover_key = 0x2f8008b8;
/* Functions */ /* Functions */
ets_emsa_pss_verify = 0x2f8008bc; ets_emsa_pss_verify = 0x2f8008bc;
ets_rsa_pss_verify = 0x2f8008c0; ets_rsa_pss_verify = 0x2f8008c0;
ets_ecdsa_verify = 0x2f8008c4; _rom_ets_ecdsa_verify = 0x2f8008c4;
ets_secure_boot_verify_bootloader_with_keys = 0x2f8008c8; ets_secure_boot_verify_bootloader_with_keys = 0x2f8008c8;
ets_secure_boot_verify_signature = 0x2f8008cc; ets_secure_boot_verify_signature = 0x2f8008cc;
ets_secure_boot_read_key_digests = 0x2f8008d0; ets_secure_boot_read_key_digests = 0x2f8008d0;
+128
View File
@@ -0,0 +1,128 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "esp_rom_caps.h"
#if ESP_ROM_ECDSA_VERIFY_PATCH
#include "soc/soc_caps.h"
#include "esp_fault.h"
#include "rom/ecdsa.h"
#define VALID_MAGIC_OK 0x6A6A6A6AU
#define VALID_MAGIC_FAIL 0x95959595U
static const uint32_t ecdsa_n_p192[6] = {
0xb4d22831U, 0x146bc9b1U, 0x99def836U, 0xffffffffU, 0xffffffffU, 0xffffffffU,
};
static const uint32_t ecdsa_n_p256[8] = {
0xfc632551U, 0xf3b9cac2U, 0xa7179e84U, 0xbce6faadU, 0xffffffffU, 0xffffffffU, 0x00000000U, 0xffffffffU,
};
#if SOC_ECDSA_SUPPORT_CURVE_P384
static const uint32_t ecdsa_n_p384[12] = {
0xccc52973U, 0xecec196aU, 0x48b0a77aU, 0x581a0db2U, 0xf4372ddfU, 0xc7634d81U,
0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU,
};
#endif
static uint32_t ecdsa_mpi_isZero(const uint32_t *mpi, int num_words)
{
uint32_t bits = 0;
for (int i = 0; i < num_words; ++i) {
bits |= mpi[i];
}
return (bits == 0);
}
static int ecdsa_mpi_cmp_unsafe(const uint32_t *left, const uint32_t *right, int num_words)
{
for (int i = num_words - 1; i >= 0; --i) {
if (left[i] > right[i]) {
return 1;
} else if (left[i] < right[i]) {
return -1;
}
}
return 0;
}
static bool ecdsa_scalars_in_range(const uint32_t *r, const uint32_t *s, const uint32_t *n, int num_words, uint32_t *result)
{
volatile uint32_t verdict = VALID_MAGIC_FAIL;
if (ecdsa_mpi_isZero(r, num_words) == 0 && ecdsa_mpi_cmp_unsafe(n, r, num_words) == 1 && ecdsa_mpi_isZero(s, num_words) == 0
&& ecdsa_mpi_cmp_unsafe(n, s, num_words) == 1) {
verdict = VALID_MAGIC_OK;
}
if (verdict != VALID_MAGIC_OK) {
return false;
}
ESP_FAULT_ASSERT(verdict == VALID_MAGIC_OK);
*result = VALID_MAGIC_OK;
return true;
}
extern int _rom_ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig,
ECDSA_CURVE curve_id, const uint8_t *image_digest,
uint8_t *verified_digest);
int ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig,
ECDSA_CURVE curve_id, const uint8_t *image_digest,
uint8_t *verified_digest)
{
int words;
int bytes;
const uint32_t *n;
if (curve_id == ECDSA_CURVE_P256) {
words = 8;
bytes = 32;
n = ecdsa_n_p256;
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (curve_id == ECDSA_CURVE_P384) {
words = 12;
bytes = 48;
n = ecdsa_n_p384;
}
#endif
else {
// curve_id == ECDSA_CURVE_P192
words = 6;
bytes = 24;
n = ecdsa_n_p192;
}
uint32_t r[12] = { 0 };
uint32_t s[12] = { 0 };
memcpy(r, &sig[0], bytes);
memcpy(s, &sig[bytes], bytes);
uint32_t ret_status = VALID_MAGIC_FAIL;
bool ok = ecdsa_scalars_in_range(r, s, n, words, &ret_status);
if (!ok || ret_status != VALID_MAGIC_OK) {
return 0;
}
ESP_FAULT_ASSERT(ok && ret_status == VALID_MAGIC_OK);
int ret = _rom_ets_ecdsa_verify(key, sig, curve_id, image_digest, verified_digest);
if (ret == 1) {
ESP_FAULT_ASSERT(ret_status == VALID_MAGIC_OK);
int sig_diff = (memcmp(r, &sig[0], bytes) | memcmp(s, &sig[bytes], bytes));
ESP_FAULT_ASSERT(sig_diff == 0);
ESP_FAULT_ASSERT(ret == 1);
return ret;
}
return 0;
}
#endif /* ESP_ROM_ECDSA_VERIFY_PATCH */
@@ -99,6 +99,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
// UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling // UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling
// it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM.
@@ -83,6 +83,8 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
CLEAR_PERI_REG_MASK(PCR_REGDMA_CONF_REG, PCR_REGDMA_RST_EN); CLEAR_PERI_REG_MASK(PCR_REGDMA_CONF_REG, PCR_REGDMA_RST_EN);
// UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling // UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling
@@ -100,6 +100,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
// UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling // UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling
// it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM.
@@ -82,6 +82,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
// UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling // UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling
// it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM.
@@ -85,6 +85,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN); CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
// UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling // UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling
// it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM.
@@ -85,6 +85,8 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN); CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_LP_EN);
SET_PERI_REG_MASK(PCR_ECC_MEM_LP_CTRL_REG, PCR_ECC_MEM_FORCE_CTRL);
// UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling // UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling
// it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM.
@@ -131,6 +131,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_KM); CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_KM);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_RSA); CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_RSA);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_SHA); CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_SHA);
CLEAR_PERI_REG_MASK(HP_SYSTEM_ECC_PD_CTRL_REG, HP_SYSTEM_ECC_MEM_FORCE_PD);
#if CONFIG_ESP32P4_REV_MIN_FULL < 101 #if CONFIG_ESP32P4_REV_MIN_FULL < 101
if (efuse_hal_chip_revision() < 101) { if (efuse_hal_chip_revision() < 101) {
@@ -48,6 +48,9 @@ void esp_system_reset_modules_on_exit(void)
esp_rom_output_tx_wait_idle(i); esp_rom_output_tx_wait_idle(i);
} }
} }
CLEAR_PERI_REG_MASK(HP_SYSTEM_ECC_MEM_LP_CTRL_REG, HP_SYSTEM_ECC_MEM_LP_EN);
SET_PERI_REG_MASK(HP_SYSTEM_ECC_MEM_LP_CTRL_REG, HP_SYSTEM_ECC_MEM_LP_FORCE_CTRL);
} }
static void IRAM_ATTR __attribute__((noinline, noreturn)) esp_restart_noos_inner(void) static void IRAM_ATTR __attribute__((noinline, noreturn)) esp_restart_noos_inner(void)
@@ -112,6 +112,14 @@ void esp_tee_configure_region_protection(void);
*/ */
void esp_tee_configure_apm_protection(void); void esp_tee_configure_apm_protection(void);
/**
* @brief Reset the crypto peripherals to a clean state.
*
* Mirrors esp_system_reset_modules_on_exit() in the non-TEE path.
* Intended to be called from the TEE panic handler before a software reset.
*/
void esp_tee_soc_reset_crypto_peripherals(void);
/** /**
* @brief Switch to the REE app after TEE initialization is complete * @brief Switch to the REE app after TEE initialization is complete
* *
@@ -25,7 +25,8 @@ endif()
# SoC specific implementation for TEE # SoC specific implementation for TEE
list(APPEND srcs "soc/${target}/esp_tee_secure_sys_cfg.c" list(APPEND srcs "soc/${target}/esp_tee_secure_sys_cfg.c"
"soc/${target}/esp_tee_pmp_pma_prot_cfg.c" "soc/${target}/esp_tee_pmp_pma_prot_cfg.c"
"soc/${target}/esp_tee_apm_prot_cfg.c") "soc/${target}/esp_tee_apm_prot_cfg.c"
"soc/${target}/esp_tee_crypto_reset.c")
list(APPEND srcs "soc/common/esp_tee_apm_intr.c") list(APPEND srcs "soc/common/esp_tee_apm_intr.c")
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -18,6 +18,7 @@
#include "hal/cache_ll.h" #include "hal/cache_ll.h"
#include "hal/cache_hal.h" #include "hal/cache_hal.h"
#include "hal/apm_hal.h" #include "hal/apm_hal.h"
#include "soc/soc_caps.h"
#if SOC_INT_PLIC_SUPPORTED #if SOC_INT_PLIC_SUPPORTED
#include "soc/plic_reg.h" #include "soc/plic_reg.h"
@@ -56,6 +57,12 @@ static void tee_panic_end(void)
esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
} }
// Reset crypto peripherals before the panic-induced reset so the next boot
// sees them in a clean state. The SoC-specific implementation mirrors
// esp_system_reset_modules_on_exit() in the non-TEE path using register-level
// accesses.
esp_tee_soc_reset_crypto_peripherals();
// Generate system reset // Generate system reset
esp_rom_software_reset_system(); esp_rom_software_reset_system();
} }
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/pcr_reg.h"
#include "esp_tee.h"
void esp_tee_soc_reset_crypto_peripherals(void)
{
SET_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
CLEAR_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
SET_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
SET_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
SET_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
SET_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
SET_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
}
@@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/pcr_reg.h"
#include "esp_tee.h"
void esp_tee_soc_reset_crypto_peripherals(void)
{
SET_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
SET_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
SET_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
SET_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
SET_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
}
@@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/pcr_reg.h"
#include "esp_tee.h"
void esp_tee_soc_reset_crypto_peripherals(void)
{
SET_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
SET_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
}
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/pcr_reg.h"
#include "esp_tee.h"
void esp_tee_soc_reset_crypto_peripherals(void)
{
SET_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
SET_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
SET_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
SET_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
SET_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
SET_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
}
@@ -18,6 +18,7 @@
#include "mbedtls/bignum.h" #include "mbedtls/bignum.h"
#include "esp_assert.h" #include "esp_assert.h"
#include "esp_fault.h"
#include "esp_crypto_lock.h" #include "esp_crypto_lock.h"
#include "esp_crypto_periph_clk.h" #include "esp_crypto_periph_clk.h"
@@ -353,13 +354,22 @@ static psa_status_t check_ecdsa_signature_range(const uint8_t *signature, size_t
goto cleanup; goto cleanup;
} }
/* 1 <= scalar <= n-1: equivalently scalar > 0 and scalar < n. */ /* 1 <= scalar <= n-1: that is, scalar > 0 and scalar < n. */
if (mbedtls_mpi_cmp_int(&r, 0) <= 0 || #define RANGE_OK 0x6A6A6A6AU
mbedtls_mpi_cmp_mpi(&r, &grp.N) >= 0 || #define RANGE_FAIL 0x95959595U
mbedtls_mpi_cmp_int(&s, 0) <= 0 || volatile uint32_t verdict = RANGE_FAIL;
mbedtls_mpi_cmp_mpi(&s, &grp.N) >= 0) { if (mbedtls_mpi_cmp_int(&r, 0) > 0 &&
mbedtls_mpi_cmp_mpi(&r, &grp.N) < 0 &&
mbedtls_mpi_cmp_int(&s, 0) > 0 &&
mbedtls_mpi_cmp_mpi(&s, &grp.N) < 0) {
verdict = RANGE_OK;
}
if (verdict != RANGE_OK) {
goto cleanup; goto cleanup;
} }
ESP_FAULT_ASSERT(verdict == RANGE_OK);
#undef RANGE_OK
#undef RANGE_FAIL
status = PSA_SUCCESS; status = PSA_SUCCESS;
@@ -562,6 +572,8 @@ psa_status_t esp_ecdsa_transparent_verify_hash_complete(esp_ecdsa_transparent_ve
return PSA_ERROR_INVALID_SIGNATURE; return PSA_ERROR_INVALID_SIGNATURE;
} }
ESP_FAULT_ASSERT(ret == 0);
return PSA_SUCCESS; return PSA_SUCCESS;
} }
@@ -10,6 +10,9 @@
#include <inttypes.h> #include <inttypes.h>
#include <esp_log.h> #include <esp_log.h>
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "mbedtls/private/ecp.h"
#include "mbedtls/private/bignum.h"
#include "psa/crypto.h" #include "psa/crypto.h"
#include "psa_crypto_driver_esp_ecdsa_contexts.h" #include "psa_crypto_driver_esp_ecdsa_contexts.h"
#include "psa_crypto_driver_esp_ecdsa.h" #include "psa_crypto_driver_esp_ecdsa.h"
@@ -334,6 +337,16 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP384R1", "[mbe
#define ECDSA_RANGE_CHECK_REJECT_STATUS PSA_ERROR_INVALID_SIGNATURE #define ECDSA_RANGE_CHECK_REJECT_STATUS PSA_ERROR_INVALID_SIGNATURE
#endif #endif
/* Curve order N in big-endian, taken from mbedtls instead of a hard-coded table. */
static void ecdsa_get_curve_order_be(mbedtls_ecp_group_id id, uint8_t *n_be, size_t len)
{
mbedtls_ecp_group grp;
mbedtls_ecp_group_init(&grp);
TEST_ASSERT_EQUAL(0, mbedtls_ecp_group_load(&grp, id));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_write_binary(&grp.N, n_be, len));
mbedtls_ecp_group_free(&grp);
}
TEST_CASE("mbedtls ECDSA signature verification rejects out-of-range r, s on SECP256R1", "[mbedtls]") TEST_CASE("mbedtls ECDSA signature verification rejects out-of-range r, s on SECP256R1", "[mbedtls]")
{ {
#if SOC_ECDSA_SUPPORTED #if SOC_ECDSA_SUPPORTED
@@ -341,24 +354,17 @@ TEST_CASE("mbedtls ECDSA signature verification rejects out-of-range r, s on SEC
TEST_IGNORE_MESSAGE("ECDSA is not supported"); TEST_IGNORE_MESSAGE("ECDSA is not supported");
} }
#endif #endif
/* Case A: r = 0, s = 0 -- caught by 'r > 0' / 's > 0' check. */
static const uint8_t zero32[32] = { 0 }; static const uint8_t zero32[32] = { 0 };
test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, uint8_t p256_n_be[32];
zero32, zero32, ecdsa_get_curve_order_be(MBEDTLS_ECP_DP_SECP256R1, p256_n_be, sizeof(p256_n_be));
ecdsa256_pub_x, ecdsa256_pub_y,
ECDSA_RANGE_CHECK_REJECT_STATUS);
/* Case B: r = N (SECP256R1 curve order), s = valid -- caught by 'r < N' check. */ test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, zero32, zero32, ecdsa256_pub_x, ecdsa256_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=0, s=0 */
static const uint8_t p256_n_be[32] = { test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, zero32, p256_n_be, ecdsa256_pub_x, ecdsa256_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=0, s=N */
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, p256_n_be, zero32, ecdsa256_pub_x, ecdsa256_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=N, s=0 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, p256_n_be, p256_n_be, ecdsa256_pub_x, ecdsa256_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=N, s=N */
0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_r, zero32, ecdsa256_pub_x, ecdsa256_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=valid, s=0 */
0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_r, p256_n_be, ecdsa256_pub_x, ecdsa256_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=valid, s=N */
}; test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, p256_n_be, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=N, s=valid */
test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha,
p256_n_be, ecdsa256_s,
ecdsa256_pub_x, ecdsa256_pub_y,
ECDSA_RANGE_CHECK_REJECT_STATUS);
} }
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384 #ifdef SOC_ECDSA_SUPPORT_CURVE_P384
@@ -369,26 +375,17 @@ TEST_CASE("mbedtls ECDSA signature verification rejects out-of-range r, s on SEC
TEST_IGNORE_MESSAGE("ECDSA is not supported"); TEST_IGNORE_MESSAGE("ECDSA is not supported");
} }
#endif #endif
/* Case A: r = 0, s = 0 */
static const uint8_t zero48[48] = { 0 }; static const uint8_t zero48[48] = { 0 };
test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, uint8_t p384_n_be[48];
zero48, zero48, ecdsa_get_curve_order_be(MBEDTLS_ECP_DP_SECP384R1, p384_n_be, sizeof(p384_n_be));
ecdsa384_pub_x, ecdsa384_pub_y,
ECDSA_RANGE_CHECK_REJECT_STATUS);
/* Case B: r = N (SECP384R1 curve order), s = valid */ test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, zero48, zero48, ecdsa384_pub_x, ecdsa384_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=0, s=0 */
static const uint8_t p384_n_be[48] = { test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, zero48, p384_n_be, ecdsa384_pub_x, ecdsa384_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=0, s=N */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, p384_n_be, zero48, ecdsa384_pub_x, ecdsa384_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=N, s=0 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, p384_n_be, p384_n_be, ecdsa384_pub_x, ecdsa384_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=N, s=N */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_r, zero48, ecdsa384_pub_x, ecdsa384_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=valid, s=0 */
0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_r, p384_n_be, ecdsa384_pub_x, ecdsa384_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=valid, s=N */
0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, p384_n_be, ecdsa384_s, ecdsa384_pub_x, ecdsa384_pub_y, ECDSA_RANGE_CHECK_REJECT_STATUS); /* r=N, s=valid */
0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73,
};
test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha,
p384_n_be, ecdsa384_s,
ecdsa384_pub_x, ecdsa384_pub_y,
ECDSA_RANGE_CHECK_REJECT_STATUS);
} }
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */