From 483c51b3c8ab95500a87c76866c1f2a8ebb73983 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Fri, 12 Jun 2026 15:02:44 +0530 Subject: [PATCH] fix(mbedtls): validate ECDSA signature range and harden ECC memory power-down Co-Authored-By: Ashish Sharma --- .../port/soc/esp32c5/system_internal.c | 1 + .../port/soc/esp32c6/system_internal.c | 2 ++ .../port/soc/esp32c61/system_internal.c | 1 + .../port/soc/esp32h2/system_internal.c | 1 + .../port/soc/esp32p4/system_internal.c | 1 + components/hal/esp32c5/include/hal/ecc_ll.h | 9 ++++++++- components/hal/esp32c6/include/hal/ecc_ll.h | 4 +++- components/hal/esp32c61/include/hal/ecc_ll.h | 6 ++++-- components/hal/esp32h2/include/hal/ecc_ll.h | 4 +++- components/hal/esp32p4/include/hal/ecc_ll.h | 20 ++++++++++++++++--- components/mbedtls/port/ecdsa/ecdsa_alt.c | 18 ++++++++++++++--- 11 files changed, 56 insertions(+), 11 deletions(-) diff --git a/components/esp_system/port/soc/esp32c5/system_internal.c b/components/esp_system/port/soc/esp32c5/system_internal.c index f03a9ba3d81..c84e4e6b342 100644 --- a/components/esp_system/port/soc/esp32c5/system_internal.c +++ b/components/esp_system/port/soc/esp32c5/system_internal.c @@ -99,6 +99,7 @@ void esp_system_reset_modules_on_exit(void) 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); + 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 // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. diff --git a/components/esp_system/port/soc/esp32c6/system_internal.c b/components/esp_system/port/soc/esp32c6/system_internal.c index a811b0cb124..9c41c634e37 100644 --- a/components/esp_system/port/soc/esp32c6/system_internal.c +++ b/components/esp_system/port/soc/esp32c6/system_internal.c @@ -80,6 +80,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_RSA_CONF_REG, PCR_RSA_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); // UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling diff --git a/components/esp_system/port/soc/esp32c61/system_internal.c b/components/esp_system/port/soc/esp32c61/system_internal.c index 20eddb5481e..fba9db1881f 100644 --- a/components/esp_system/port/soc/esp32c61/system_internal.c +++ b/components/esp_system/port/soc/esp32c61/system_internal.c @@ -97,6 +97,7 @@ void esp_system_reset_modules_on_exit(void) 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); + 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 // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. diff --git a/components/esp_system/port/soc/esp32h2/system_internal.c b/components/esp_system/port/soc/esp32h2/system_internal.c index 88c6e8511e3..1a86e86ff18 100644 --- a/components/esp_system/port/soc/esp32h2/system_internal.c +++ b/components/esp_system/port/soc/esp32h2/system_internal.c @@ -79,6 +79,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_RSA_CONF_REG, PCR_RSA_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 // it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM. diff --git a/components/esp_system/port/soc/esp32p4/system_internal.c b/components/esp_system/port/soc/esp32p4/system_internal.c index f4aa3a8d023..0e198d28659 100644 --- a/components/esp_system/port/soc/esp32p4/system_internal.c +++ b/components/esp_system/port/soc/esp32p4/system_internal.c @@ -127,6 +127,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_RSA); 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 (efuse_hal_chip_revision() < 101) { diff --git a/components/hal/esp32c5/include/hal/ecc_ll.h b/components/hal/esp32c5/include/hal/ecc_ll.h index 54c7b8bc2d9..9563fcc612a 100644 --- a/components/hal/esp32c5/include/hal/ecc_ll.h +++ b/components/hal/esp32c5/include/hal/ecc_ll.h @@ -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 */ @@ -12,6 +12,7 @@ #include "soc/ecc_mult_reg.h" #include "soc/pcr_struct.h" #include "soc/pcr_reg.h" +#include "esp_fault.h" #ifdef __cplusplus extern "C" { @@ -47,11 +48,17 @@ static inline void ecc_ll_reset_register(void) 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) { /* 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_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) diff --git a/components/hal/esp32c6/include/hal/ecc_ll.h b/components/hal/esp32c6/include/hal/ecc_ll.h index d144dbff297..fc0861b3148 100644 --- a/components/hal/esp32c6/include/hal/ecc_ll.h +++ b/components/hal/esp32c6/include/hal/ecc_ll.h @@ -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 */ @@ -12,6 +12,7 @@ #include "soc/ecc_mult_reg.h" #include "soc/pcr_struct.h" #include "soc/pcr_reg.h" +#include "esp_fault.h" #ifdef __cplusplus 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_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) diff --git a/components/hal/esp32c61/include/hal/ecc_ll.h b/components/hal/esp32c61/include/hal/ecc_ll.h index 9e56f188b8d..b82dd0cf946 100644 --- a/components/hal/esp32c61/include/hal/ecc_ll.h +++ b/components/hal/esp32c61/include/hal/ecc_ll.h @@ -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 */ @@ -12,6 +12,7 @@ #include "soc/ecc_mult_reg.h" #include "soc/pcr_struct.h" #include "soc/pcr_reg.h" +#include "esp_fault.h" #ifdef __cplusplus extern "C" { @@ -49,9 +50,10 @@ static inline void ecc_ll_reset_register(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_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) diff --git a/components/hal/esp32h2/include/hal/ecc_ll.h b/components/hal/esp32h2/include/hal/ecc_ll.h index c57200f6273..9db578ed305 100644 --- a/components/hal/esp32h2/include/hal/ecc_ll.h +++ b/components/hal/esp32h2/include/hal/ecc_ll.h @@ -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 */ @@ -12,6 +12,7 @@ #include "soc/ecc_mult_reg.h" #include "soc/pcr_struct.h" #include "soc/pcr_reg.h" +#include "esp_fault.h" #include "soc/chip_revision.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_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) diff --git a/components/hal/esp32p4/include/hal/ecc_ll.h b/components/hal/esp32p4/include/hal/ecc_ll.h index 0286d737b4b..a97ad8d107a 100644 --- a/components/hal/esp32p4/include/hal/ecc_ll.h +++ b/components/hal/esp32p4/include/hal/ecc_ll.h @@ -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 */ @@ -12,8 +12,10 @@ #include "hal/efuse_hal.h" #include "soc/ecc_mult_reg.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/hp_system_reg.h" #include "soc/chip_revision.h" #include "hal/config.h" +#include "esp_fault.h" #ifdef __cplusplus extern "C" { @@ -59,8 +61,20 @@ static inline void ecc_ll_reset_register(void) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define ecc_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; ecc_ll_reset_register(__VA_ARGS__) -static inline void ecc_ll_power_up(void) {} -static inline void ecc_ll_power_down(void) {} +static inline void ecc_ll_power_up(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) { diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index 1a1207ccbe2..681b8fdd998 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -7,6 +7,7 @@ #include "esp_err.h" #include "esp_log.h" +#include "esp_fault.h" #include "hal/ecdsa_types.h" #include "ecdsa/ecdsa_alt.h" @@ -1080,11 +1081,22 @@ static int esp_ecdsa_verify(mbedtls_ecp_group *grp, return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } - if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 || - mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0 ) - { + /* 1 <= scalar <= n-1: that is, scalar > 0 and scalar < n. */ + #define RANGE_OK 0x6A6A6A6AU + #define RANGE_FAIL 0x95959595U + volatile uint32_t verdict = RANGE_FAIL; + 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) { return MBEDTLS_ERR_ECP_VERIFY_FAILED; } + ESP_FAULT_ASSERT(verdict == RANGE_OK); + #undef RANGE_OK + #undef RANGE_FAIL ecdsa_be_to_le(buf, sha_le, len);