From d345c684ba67af2391b581226b7af21576e40afe Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Thu, 2 Mar 2023 22:40:14 +0530 Subject: [PATCH 1/3] esp32h2: Add support for ECDSA peripheral --- components/hal/CMakeLists.txt | 4 + components/hal/ecdsa_hal.c | 99 +++++ .../hal/esp32h2/include/hal/clk_gate_ll.h | 8 + components/hal/esp32h2/include/hal/ecdsa_ll.h | 386 ++++++++++++++++++ components/hal/include/hal/ecdsa_hal.h | 63 +++ components/hal/include/hal/ecdsa_types.h | 46 +++ .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32h2/include/soc/periph_defs.h | 1 + components/soc/esp32h2/include/soc/soc_caps.h | 1 + 9 files changed, 612 insertions(+) create mode 100644 components/hal/ecdsa_hal.c create mode 100644 components/hal/esp32h2/include/hal/ecdsa_ll.h create mode 100644 components/hal/include/hal/ecdsa_hal.h create mode 100644 components/hal/include/hal/ecdsa_types.h diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index a944c360b3..c37b556c8e 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -121,6 +121,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "ecc_hal.c") endif() + if(CONFIG_SOC_ECDSA_SUPPORTED) + list(APPEND srcs "ecdsa_hal.c") + endif() + if(CONFIG_SOC_SHA_SUPPORTED) list(APPEND srcs "sha_hal.c") endif() diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c new file mode 100644 index 0000000000..4f8e87168d --- /dev/null +++ b/components/hal/ecdsa_hal.c @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/assert.h" +#include "hal/ecdsa_ll.h" +#include "hal/ecdsa_hal.h" + +#define ECDSA_HAL_P192_COMPONENT_LEN 24 +#define ECDSA_HAL_P256_COMPONENT_LEN 32 + +static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) +{ + ecdsa_ll_set_mode(conf->mode); + ecdsa_ll_set_curve(conf->curve); + ecdsa_ll_set_k_mode(conf->k_mode); + ecdsa_ll_set_z_mode(conf->sha_mode); +} + +void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *k, const uint8_t *hash, + uint8_t *r_out, uint8_t *s_out, uint16_t len) +{ + if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN) { + HAL_ASSERT(false && "Incorrect length"); + } + + if (conf->k_mode == ECDSA_K_USER_PROVIDED && k == NULL) { + HAL_ASSERT(false && "Mismatch in K configuration"); + } + + if (conf->sha_mode == ECDSA_Z_USER_PROVIDED && hash == NULL) { + HAL_ASSERT(false && "Mismatch in SHA configuration"); + } + + if (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) { + HAL_ASSERT(false && "Incorrect ECDSA state"); + } + + configure_ecdsa_periph(conf); + + ecdsa_ll_set_stage(ECDSA_STAGE_START_CALC); + + while(ecdsa_ll_get_state() != ECDSA_STATE_LOAD) { + ; + } + + ecdsa_ll_set_stage(ECDSA_STAGE_LOAD_DONE); + + while (ecdsa_ll_get_state() != ECDSA_STATE_GET) { + ; + } + + ecdsa_ll_read_param(ECDSA_PARAM_R, r_out, len); + ecdsa_ll_read_param(ECDSA_PARAM_S, s_out, len); + + ecdsa_ll_set_stage(ECDSA_STAGE_GET_DONE); + + while (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) { + ; + } +} + +int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, const uint8_t *r, const uint8_t *s, + const uint8_t *pub_x, const uint8_t *pub_y, uint16_t len) +{ + if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN) { + HAL_ASSERT(false && "Incorrect length"); + } + + if (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) { + HAL_ASSERT(false && "Incorrect ECDSA state"); + } + + configure_ecdsa_periph(conf); + + ecdsa_ll_set_stage(ECDSA_STAGE_START_CALC); + + while(ecdsa_ll_get_state() != ECDSA_STATE_LOAD) { + ; + } + + ecdsa_ll_write_param(ECDSA_PARAM_Z, hash, len); + ecdsa_ll_write_param(ECDSA_PARAM_R, r, len); + ecdsa_ll_write_param(ECDSA_PARAM_S, s, len); + ecdsa_ll_write_param(ECDSA_PARAM_QAX, pub_x, len); + ecdsa_ll_write_param(ECDSA_PARAM_QAY, pub_y, len); + + ecdsa_ll_set_stage(ECDSA_STAGE_LOAD_DONE); + + while (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) { + ; + } + + int res = ecdsa_ll_get_verification_result(); + + return (res ? 0 : -1); +} diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index 3ffd6c51e0..4a858474bf 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -71,6 +71,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return PCR_HMAC_CLK_EN; case PERIPH_DS_MODULE: return PCR_DS_CLK_EN; + case PERIPH_ECDSA_MODULE: + return PCR_ECDSA_CLK_EN; case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_CLK_EN; // case PERIPH_RNG_MODULE: @@ -163,6 +165,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return PCR_HMAC_RST_EN; case PERIPH_DS_MODULE: return PCR_DS_RST_EN; + case PERIPH_ECDSA_MODULE: + return PCR_ECDSA_RST_EN; // case PERIPH_RNG_MODULE: // return PCR_WIFI_CLK_RNG_EN; // case PERIPH_WIFI_MODULE: @@ -243,6 +247,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return PCR_HMAC_CONF_REG; case PERIPH_DS_MODULE: return PCR_DS_CONF_REG; + case PERIPH_ECDSA_MODULE: + return PCR_ECDSA_CONF_REG; case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_CLK_CONF_REG; default: @@ -306,6 +312,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return PCR_HMAC_CONF_REG; case PERIPH_DS_MODULE: return PCR_DS_CONF_REG; + case PERIPH_ECDSA_MODULE: + return PCR_ECDSA_CONF_REG; case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_CLK_CONF_REG; default: diff --git a/components/hal/esp32h2/include/hal/ecdsa_ll.h b/components/hal/esp32h2/include/hal/ecdsa_ll.h new file mode 100644 index 0000000000..a6931b741a --- /dev/null +++ b/components/hal/esp32h2/include/hal/ecdsa_ll.h @@ -0,0 +1,386 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "hal/assert.h" +#include "soc/ecdsa_reg.h" +#include "hal/ecdsa_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Memory blocks of ECDSA parameters + */ +typedef enum { + ECDSA_PARAM_R, + ECDSA_PARAM_S, + ECDSA_PARAM_Z, + ECDSA_PARAM_K, + ECDSA_PARAM_QAX, + ECDSA_PARAM_QAY +} ecdsa_ll_param_t; + +/** + * @brief Interrupt types in ECDSA + */ +typedef enum { + ECDSA_INT_CALC_DONE, + ECDSA_INT_SHA_RELEASE, +} ecdsa_ll_intr_type_t; + +/** + * @brief Stages of ECDSA operation + */ +typedef enum { + ECDSA_STAGE_START_CALC, + ECDSA_STAGE_LOAD_DONE, + ECDSA_STAGE_GET_DONE +} ecdsa_ll_stage_t; + +/** + * @brief States of ECDSA peripheral + */ +typedef enum { + ECDSA_STATE_IDLE, + ECDSA_STATE_LOAD, + ECDSA_STATE_GET, + ECDSA_STATE_BUSY +} ecdsa_ll_state_t; + +/** + * @brief Types of SHA + */ +typedef enum { + ECDSA_SHA_224, + ECDSA_SHA_256 +} ecdsa_ll_sha_type_t; + +/** + * @brief Operation modes of SHA + */ +typedef enum { + ECDSA_MODE_SHA_START, + ECDSA_MODE_SHA_CONTINUE +} ecdsa_ll_sha_mode_t; + +/** + * @brief Enable interrupt of a given type + * + * @param type Interrupt type + */ +static inline void ecdsa_ll_enable_intr(ecdsa_ll_intr_type_t type) +{ + switch (type) { + case ECDSA_INT_CALC_DONE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 1); + break; + case ECDSA_INT_SHA_RELEASE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 1); + break; + default: + HAL_ASSERT(false && "Unsupported interrupt type"); + break; + } +} + +/** + * @brief Disable interrupt of a given type + * + * @param type Interrupt type + */ +static inline void ecdsa_ll_disable_intr(ecdsa_ll_intr_type_t type) +{ + switch (type) { + case ECDSA_INT_CALC_DONE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 0); + break; + case ECDSA_INT_SHA_RELEASE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 0); + break; + default: + HAL_ASSERT(false && "Unsupported interrupt type"); + break; + } +} + +/** + * @brief Clear interrupt of a given type + * + * @param type Interrupt type + */ +static inline void ecdsa_ll_clear_intr(ecdsa_ll_intr_type_t type) +{ + switch (type) { + case ECDSA_INT_CALC_DONE: + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_CALC_DONE_INT_CLR, 1); + break; + case ECDSA_INT_SHA_RELEASE: + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_SHA_RELEASE_INT_CLR, 1); + break; + default: + HAL_ASSERT(false && "Unsupported interrupt type"); + break; + } +} + +/** + * @brief Set working mode of ECDSA + * + * @param mode Mode of operation + */ +static inline void ecdsa_ll_set_mode(ecdsa_mode_t mode) +{ + switch (mode) { + case ECDSA_MODE_SIGN_VERIFY: + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 0); + break; + case ECDSA_MODE_SIGN_GEN: + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 1); + break; + default: + HAL_ASSERT(false && "Unsupported mode"); + break; + } +} + +/** + * @brief Set curve for ECDSA operation + * + * @param curve ECDSA curve + */ +static inline void ecdsa_ll_set_curve(ecdsa_curve_t curve) +{ + switch (curve) { + case ECDSA_CURVE_SECP256R1: + REG_SET_BIT(ECDSA_CONF_REG, ECDSA_ECC_CURVE); + break; + case ECDSA_CURVE_SECP192R1: + REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_ECC_CURVE); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + return; + } +} + +/** + * @brief Set the source of `K` + * + * @param mode Mode of K generation + */ +static inline void ecdsa_ll_set_k_mode(ecdsa_k_mode_t mode) +{ + switch (mode) { + case ECDSA_K_USE_TRNG: + REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_K); + break; + case ECDSA_K_USER_PROVIDED: + REG_SET_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_K); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + break; + } +} + +/** + * @brief Set the source of `Z` (SHA message) + * + * @param mode Mode of SHA generation + */ +static inline void ecdsa_ll_set_z_mode(ecdsa_ll_sha_mode_t mode) +{ + switch (mode) { + case ECDSA_Z_USE_SHA_PERI: + REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_Z); + break; + case ECDSA_Z_USER_PROVIDED: + REG_SET_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_Z); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + break; + } +} + +/** + * @brief Set the stage of ECDSA operation + * + * @param stage Stage of operation + */ +static inline void ecdsa_ll_set_stage(ecdsa_ll_stage_t stage) +{ + switch (stage) { + case ECDSA_STAGE_START_CALC: + REG_SET_BIT(ECDSA_START_REG, ECDSA_START); + break; + case ECDSA_STAGE_LOAD_DONE: + REG_SET_BIT(ECDSA_START_REG, ECDSA_LOAD_DONE); + break; + case ECDSA_STAGE_GET_DONE: + REG_SET_BIT(ECDSA_START_REG, ECDSA_GET_DONE); + break; + default: + HAL_ASSERT(false && "Unsupported state"); + break; + } +} + +/** + * @brief Get the state of ECDSA peripheral + * + * @return State of ECDSA + */ +static inline ecdsa_ll_state_t ecdsa_ll_get_state(void) +{ + return REG_GET_FIELD(ECDSA_STATE_REG, ECDSA_BUSY); +} + +/** + * @brief Set the SHA type + * + * @param type Type of SHA + */ +static inline void ecdsa_ll_sha_set_type(ecdsa_ll_sha_type_t type) +{ + switch (type) { + case ECDSA_SHA_224: + REG_SET_FIELD(ECDSA_SHA_MODE_REG, ECDSA_SHA_MODE, 1); + break; + case ECDSA_SHA_256: + REG_SET_FIELD(ECDSA_SHA_MODE_REG, ECDSA_SHA_MODE, 2); + break; + default: + HAL_ASSERT(false && "Unsupported type"); + break; + } +} + +/** + * @brief Set the SHA operation mode + * + * @param mode Mode of SHA operation + */ +static inline void ecdsa_ll_sha_set_mode(ecdsa_ll_sha_mode_t mode) +{ + switch (mode) { + case ECDSA_MODE_SHA_START: + REG_SET_BIT(ECDSA_SHA_START_REG, ECDSA_SHA_START); + break; + case ECDSA_MODE_SHA_CONTINUE: + REG_SET_BIT(ECDSA_SHA_CONTINUE_REG, ECDSA_SHA_CONTINUE); + break; + default: + HAL_ASSERT(false && "Unsupported type"); + break; + } +} + +/** + * @brief Check if SHA is busy + * + * @return - true, if SHA is busy + * - false, if SHA is IDLE + */ +static inline bool ecdsa_ll_sha_is_busy(void) +{ + return REG_GET_BIT(ECDSA_SHA_BUSY_REG, ECDSA_SHA_BUSY); +} + +/** + * @brief Write the ECDSA parameter + * + * @param param Parameter to be writen + * @param buf Buffer containing data + * @param len Length of buffer + */ +static inline void ecdsa_ll_write_param(ecdsa_ll_param_t param, const uint8_t *buf, uint16_t len) +{ + uint32_t reg; + uint32_t word; + switch (param) { + case ECDSA_PARAM_R: + reg = ECDSA_R_MEM; + break; + case ECDSA_PARAM_S: + reg = ECDSA_S_MEM; + break; + case ECDSA_PARAM_Z: + reg = ECDSA_Z_MEM; + break; + case ECDSA_PARAM_K: + case ECDSA_PARAM_QAX: + reg = ECDSA_QAX_MEM; + break; + case ECDSA_PARAM_QAY: + reg = ECDSA_QAY_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + for (int i = 0; i < len; i += 4) { + memcpy(&word, buf + i, 4); + REG_WRITE(reg + i, word); + } +} + +/** + * @brief Read the ECDSA parameter + * + * @param param Parameter to be read + * @param buf Buffer where the data will be written + * @param len Length of buffer + */ +static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uint16_t len) +{ + uint32_t reg; + switch (param) { + case ECDSA_PARAM_R: + reg = ECDSA_R_MEM; + break; + case ECDSA_PARAM_S: + reg = ECDSA_S_MEM; + break; + case ECDSA_PARAM_Z: + reg = ECDSA_Z_MEM; + break; + case ECDSA_PARAM_K: + case ECDSA_PARAM_QAX: + reg = ECDSA_QAX_MEM; + break; + case ECDSA_PARAM_QAY: + reg = ECDSA_QAY_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + memcpy(buf, (void *)reg, len); +} + +/** + * @brief Get result of ECDSA verification operation + * + * This is only valid for ECDSA verify mode + * + * @return - 1, if signature verification succeeds + * - 0, otherwise + */ +static inline int ecdsa_ll_get_verification_result(void) +{ + return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_OPERATION_RESULT); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/ecdsa_hal.h b/components/hal/include/hal/ecdsa_hal.h new file mode 100644 index 0000000000..d7244b3dc0 --- /dev/null +++ b/components/hal/include/hal/ecdsa_hal.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The HAL is not public api, don't use in application code. + * See readme.md in soc/README.md + ******************************************************************************/ + +#pragma once + +#include +#include "hal/ecdsa_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ECDSA peripheral config structure + */ +typedef struct { + ecdsa_mode_t mode; /* Mode of operation */ + ecdsa_curve_t curve; /* Curve to use for operation */ + ecdsa_k_mode_t k_mode; /* Source of K */ + ecdsa_sha_mode_t sha_mode; /* Source of SHA that needs to be signed */ +} ecdsa_hal_config_t; + +/** + * @brief Generate ECDSA signature + * + * @param conf Configuration for ECDSA operation, see ``ecdsa_hal_config_t`` + * @param k Value of K used internally. Set this to NULL if K is generated by hardware + * @param hash Hash that is to be signed + * @param r_out Buffer that will contain `R` component of ECDSA signature + * @param s_out Buffer that will contain `S` component of ECDSA signature + * @param len Length of the r_out and s_out buffer (32 bytes for SECP256R1, 24 for SECP192R1) + */ +void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *k, const uint8_t *hash, + uint8_t *r_out, uint8_t *s_out, uint16_t len); + +/** + * @brief Verify given ECDSA signature + * + * @param conf Configuration for ECDSA operation, see ``ecdsa_hal_config_t`` + * @param hash Hash that was signed + * @param r `R` component of ECDSA signature + * @param s `S` component of ECDSA signature + * @param pub_x X coordinate of public key + * @param pub_y Y coordinate of public key + * @param len Length of r and s buffer (32 bytes for SECP256R1, 24 for SECP192R1) + * + * @return - 0, if the signature matches + * - -1, if verification fails + */ +int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, const uint8_t *r, const uint8_t *s, + const uint8_t *pub_x, const uint8_t *pub_y, uint16_t len); +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/ecdsa_types.h b/components/hal/include/hal/ecdsa_types.h new file mode 100644 index 0000000000..fdb2f3d3cf --- /dev/null +++ b/components/hal/include/hal/ecdsa_types.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ECDSA peripheral work modes + */ +typedef enum { + ECDSA_MODE_SIGN_VERIFY, + ECDSA_MODE_SIGN_GEN, +} ecdsa_mode_t; + +/** + * @brief ECDSA curve options + */ +typedef enum { + ECDSA_CURVE_SECP192R1, + ECDSA_CURVE_SECP256R1, +} ecdsa_curve_t; + +/** + * @brief Source of 'K' used internally for generating signature + */ +typedef enum { + ECDSA_K_USE_TRNG, + ECDSA_K_USER_PROVIDED, +} ecdsa_k_mode_t; + +/** + * @brief Source of SHA message that is to be signed/verified + */ +typedef enum { + ECDSA_Z_USE_SHA_PERI, + ECDSA_Z_USER_PROVIDED, +} ecdsa_sha_mode_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index b17065ad6b..8dc02573d7 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -143,6 +143,10 @@ config SOC_ECC_EXTENDED_MODES_SUPPORTED bool default y +config SOC_ECDSA_SUPPORTED + bool + default y + config SOC_FLASH_ENC_SUPPORTED bool default y diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index 2f1789caba..f1b20e2148 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -38,6 +38,7 @@ typedef enum { PERIPH_ECC_MODULE, PERIPH_HMAC_MODULE, PERIPH_DS_MODULE, + PERIPH_ECDSA_MODULE, PERIPH_GDMA_MODULE, PERIPH_MCPWM0_MODULE, PERIPH_ETM_MODULE, diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 263023d90b..58675e9bc7 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -61,6 +61,7 @@ #define SOC_DIG_SIGN_SUPPORTED 1 #define SOC_ECC_SUPPORTED 1 #define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 +#define SOC_ECDSA_SUPPORTED 1 #define SOC_FLASH_ENC_SUPPORTED 1 #define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 From d2940c5ff383c72b2234105cd78ea37df5bbd242 Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Mon, 6 Mar 2023 17:31:38 +0530 Subject: [PATCH 2/3] mbedtls: Add port layer for ECDSA peripheral --- .../efuse/esp32h2/include/esp_efuse_chip.h | 5 +- .../with_key_purposes/esp_efuse_api_key.c | 3 + .../esp_rom/include/esp32h2/rom/efuse.h | 3 +- components/mbedtls/CMakeLists.txt | 16 + components/mbedtls/Kconfig | 23 ++ components/mbedtls/port/ecdsa/ecdsa_alt.c | 276 ++++++++++++++++++ .../mbedtls/port/include/ecdsa/ecdsa_alt.h | 63 ++++ .../mbedtls/port/include/mbedtls/esp_config.h | 1 + .../test_apps/main/test_mbedtls_ecdsa.c | 2 +- 9 files changed, 388 insertions(+), 4 deletions(-) create mode 100644 components/mbedtls/port/ecdsa/ecdsa_alt.c create mode 100644 components/mbedtls/port/include/ecdsa/ecdsa_alt.h diff --git a/components/efuse/esp32h2/include/esp_efuse_chip.h b/components/efuse/esp32h2/include/esp_efuse_chip.h index 9c684ad626..653aef32fb 100644 --- a/components/efuse/esp32h2/include/esp_efuse_chip.h +++ b/components/efuse/esp32h2/include/esp_efuse_chip.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -62,7 +62,8 @@ typedef enum { */ typedef enum { ESP_EFUSE_KEY_PURPOSE_USER = 0, /**< User purposes (software-only use) */ - ESP_EFUSE_KEY_PURPOSE_RESERVED = 1, /**< Reserved */ + ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY = 1, /**< ECDSA private key (Expected in little endian order)*/ + ESP_EFUSE_KEY_PURPOSE_RESERVED = 2, /**< Reserved (Used as a place holder)*/ ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY = 4, /**< XTS_AES_128_KEY (flash/PSRAM encryption) */ ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5, /**< HMAC Downstream mode */ ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6, /**< JTAG soft enable key (uses HMAC Downstream mode) */ diff --git a/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c b/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c index 2af5f863c2..0ae91931f9 100644 --- a/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c +++ b/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c @@ -287,6 +287,9 @@ esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpo purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 || purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 || #endif //#ifdef SOC_EFUSE_SUPPORT_XTS_AES_256_KEYS +#if SOC_ECDSA_SUPPORTED + purpose == ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY || +#endif purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL || purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG || purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE || diff --git a/components/esp_rom/include/esp32h2/rom/efuse.h b/components/esp_rom/include/esp32h2/rom/efuse.h index 6cd9f4b377..dc612dff4b 100644 --- a/components/esp_rom/include/esp32h2/rom/efuse.h +++ b/components/esp_rom/include/esp32h2/rom/efuse.h @@ -27,7 +27,8 @@ extern "C" { typedef enum { ETS_EFUSE_KEY_PURPOSE_USER = 0, - ETS_EFUSE_KEY_PURPOSE_RESERVED = 1, + ETS_EFUSE_KEY_PURPOSE_ECDSA_KEY = 1, + ETS_EFUSE_KEY_PURPOSE_RESERVED = 2, ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY = 4, ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5, ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6, diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 4e758632a5..28556aeed5 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -235,6 +235,18 @@ if(CONFIG_MBEDTLS_HARDWARE_ECC) "${COMPONENT_DIR}/port/ecc/ecc_alt.c") endif() +if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) + target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/ecdsa/ecdsa_alt.c") + + if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign") + endif() + + if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_verify") + endif() +endif() + if(CONFIG_MBEDTLS_ROM_MD5) target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/md/esp_md.c") endif() @@ -267,6 +279,10 @@ if(CONFIG_PM_ENABLE) target_link_libraries(mbedcrypto PRIVATE idf::esp_pm) endif() +if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) + target_link_libraries(mbedcrypto PRIVATE idf::efuse) +endif() + target_link_libraries(${COMPONENT_LIB} ${linkage_type} ${mbedtls_targets}) if(CONFIG_ESP_TLS_USE_DS_PERIPHERAL) diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 7675c0f0a2..0b3d67de11 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -455,6 +455,29 @@ menu "mbedTLS" help Use ROM MD5 in mbedTLS. + config MBEDTLS_HARDWARE_ECDSA_SIGN + bool "Enable ECDSA signing using on-chip ECDSA peripheral" + default n + depends on SOC_ECDSA_SUPPORTED + help + Enable hardware accelerated ECDSA peripheral to sign data + on curve SECP192R1 and SECP256R1 in mbedTLS. + + Note that for signing, the private key has to be burnt in an efuse key block + with key purpose set to ECDSA_KEY. + If no key is burnt, it will report an error + + The key should be burnt in little endian format. espefuse.py utility handles it internally + but care needs to be taken while burning using esp_efuse APIs + + config MBEDTLS_HARDWARE_ECDSA_VERIFY + bool "Enable ECDSA signature verification using on-chip ECDSA peripheral" + default y + depends on SOC_ECDSA_SUPPORTED + help + Enable hardware accelerated ECDSA peripheral to verify signature + on curve SECP192R1 and SECP256R1 in mbedTLS. + config MBEDTLS_ATCA_HW_ECDSA_SIGN bool "Enable hardware ECDSA sign acceleration when using ATECC608A" default n diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c new file mode 100644 index 0000000000..e90f01c584 --- /dev/null +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -0,0 +1,276 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "hal/ecdsa_hal.h" +#include "esp_efuse.h" +#include "mbedtls/ecp.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/platform_util.h" +#include "esp_private/periph_ctrl.h" +#include "ecdsa/ecdsa_alt.h" + +#define ECDSA_KEY_MAGIC 0xECD5A +#define ECDSA_SHA_LEN 32 +#define MAX_ECDSA_COMPONENT_LEN 32 + +__attribute__((unused)) static const char *TAG = "ecdsa_alt"; + +static _lock_t s_crypto_ecdsa_lock; + +static void esp_ecdsa_acquire_hardware(void) +{ + _lock_acquire(&s_crypto_ecdsa_lock); + + periph_module_enable(PERIPH_ECDSA_MODULE); +} + +static void esp_ecdsa_release_hardware(void) +{ + periph_module_disable(PERIPH_ECDSA_MODULE); + + _lock_release(&s_crypto_ecdsa_lock); +} + +static void ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) +{ + /* When the size is 24 bytes, it should be padded with 0 bytes*/ + memset(le_point, 0x0, 32); + + for(int i = 0; i < len; i++) { + le_point[i] = be_point[len - i - 1]; + } +} + +#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk) +{ + if (!key) { + ESP_LOGE(TAG, "Invalid memory"); + return -1; + } + + if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { + ESP_LOGE(TAG, "Invalid efuse block"); + return -1; + } + + mbedtls_mpi_init(key); + + /* We use the mbedtls_mpi struct to pass our own context to hardware ECDSA peripheral + * MPI struct expects `s` to be either 1 or -1, by setting it to 0xECD5A, we ensure that it does + * not collide with a valid MPI. This is done to differentiate between using the private key stored in efuse + * or using the private key provided by software + * + * `n` is used to store the efuse block which should be used as key + */ + key->MBEDTLS_PRIVATE(s) = ECDSA_KEY_MAGIC; + key->MBEDTLS_PRIVATE(n) = efuse_blk; + key->MBEDTLS_PRIVATE(p) = NULL; + + return 0; +} + +int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk) +{ + const mbedtls_pk_info_t *pk_info; + mbedtls_ecp_keypair *keypair; + + if (!key_ctx) { + ESP_LOGE(TAG, "Invalid memory"); + return -1; + } + + if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { + ESP_LOGE(TAG, "Invalid efuse block"); + return -1; + } + + mbedtls_pk_init(key_ctx); + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); + mbedtls_pk_setup(key_ctx, pk_info); + keypair = mbedtls_pk_ec(*key_ctx); + + return esp_ecdsa_privkey_load_mpi(&(keypair->MBEDTLS_PRIVATE(d)), efuse_blk); +} + +static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s, + const mbedtls_mpi *d, const unsigned char* msg, size_t msg_len) +{ + ecdsa_curve_t curve; + esp_efuse_block_t blk; + uint16_t len; + uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; + uint8_t sha_le[ECDSA_SHA_LEN]; + uint8_t r_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; + + if (!grp || !r || !s || !d || !msg) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (msg_len != ECDSA_SHA_LEN) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { + curve = ECDSA_CURVE_SECP192R1; + len = 24; + } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { + curve = ECDSA_CURVE_SECP256R1; + len = 32; + } else { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, &blk)) { + ESP_LOGE(TAG, "No efuse block with purpose ECDSA_KEY found"); + return MBEDTLS_ERR_ECP_INVALID_KEY; + } + + ecdsa_be_to_le(msg, sha_le, len); + + esp_ecdsa_acquire_hardware(); + + do { + ecdsa_hal_config_t conf = { + .mode = ECDSA_MODE_SIGN_GEN, + .curve = curve, + .k_mode = ECDSA_K_USE_TRNG, + .sha_mode = ECDSA_Z_USER_PROVIDED, + }; + + ecdsa_hal_gen_signature(&conf, NULL, sha_le, r_le, s_le, len); + } while (!memcmp(r_le, zeroes, len) || !memcmp(s_le, zeroes, len)); + + esp_ecdsa_release_hardware(); + + mbedtls_mpi_read_binary_le(r, r_le, len); + mbedtls_mpi_read_binary_le(s, s_le, len); + + return 0; +} + +/* + * Compute ECDSA signature of a hashed message; + */ +extern int __real_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + /* + * Check `d` whether it contains the hardware key + */ + if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + // Use hardware ECDSA peripheral + return esp_ecdsa_sign(grp, r, s, d, buf, blen); + } else { + return __real_mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, f_rng, p_rng); + } +} +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ + +#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY +static int esp_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ecdsa_curve_t curve; + uint16_t len; + uint8_t r_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t qy_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t sha_le[ECDSA_SHA_LEN]; + + if (!grp || !buf || !Q || !r || !s) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (blen != ECDSA_SHA_LEN) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { + curve = ECDSA_CURVE_SECP192R1; + len = 24; + } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { + curve = ECDSA_CURVE_SECP256R1; + len = 32; + } else { + 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 ) + { + return MBEDTLS_ERR_ECP_VERIFY_FAILED; + } + + ecdsa_be_to_le(buf, sha_le, len); + + mbedtls_mpi_write_binary_le(&Q->MBEDTLS_PRIVATE(X), qx_le, len); + mbedtls_mpi_write_binary_le(&Q->MBEDTLS_PRIVATE(Y), qy_le, len); + mbedtls_mpi_write_binary_le(r, r_le, len); + mbedtls_mpi_write_binary_le(s, s_le, len); + + esp_ecdsa_acquire_hardware(); + + ecdsa_hal_config_t conf = { + .mode = ECDSA_MODE_SIGN_VERIFY, + .curve = curve, + .k_mode = ECDSA_K_USE_TRNG, + .sha_mode = ECDSA_Z_USER_PROVIDED, + }; + + int ret = ecdsa_hal_verify_signature(&conf, sha_le, r_le, s_le, qx_le, qy_le, len); + + esp_ecdsa_release_hardware(); + + if (ret != 0) { + return MBEDTLS_ERR_ECP_VERIFY_FAILED; + } + + return ret; +} + +/* + * Verify ECDSA signature of hashed message + */ +extern int __real_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s); + +int __wrap_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s); + +int __wrap_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + if (grp->id == MBEDTLS_ECP_DP_SECP192R1 || grp->id == MBEDTLS_ECP_DP_SECP256R1) { + return esp_ecdsa_verify(grp, buf, blen, Q, r, s); + } else { + return __real_mbedtls_ecdsa_verify(grp, buf, blen, Q, r, s); + } +} +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY */ diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h new file mode 100644 index 0000000000..9e2620b312 --- /dev/null +++ b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "sdkconfig.h" +#include "mbedtls/pk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN + +/** + * @brief Initialize MPI to notify mbedtls_ecdsa_sign to use the private key in efuse + * We break the MPI struct of the private key in order to + * differentiate between hardware key and software key + * + * @note Currently, `efuse_blk` is not used internally. + * Hardware will choose the efuse block that has purpose set to ECDSA_KEY. + * In case of multiple ECDSA_KEY burnt in efuse, hardware will choose the + * greater efuse block number as the private key. + * + * @param key The MPI in which this functions stores the hardware context. + * This must be uninitialized + * @param efuse_blk The efuse key block that should be used as the private key. + * The key purpose of this block must be ECDSA_KEY + * + * @return - 0 if successful + * - -1 otherwise + * + */ +int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk); + +/** + * @brief Initialize PK context to notify mbedtls_ecdsa_sign to use the private key in efuse + * We break the MPI struct used to represent the private key `d` in ECP keypair + * in order to differentiate between hardware key and software key + * + * @note Currently, `efuse_blk` is not used internally. + * Hardware will choose the efuse block that has purpose set to ECDSA_KEY. + * In case of multiple ECDSA_KEY burnt in efuse, hardware will choose the + * greater efuse block number as the private key. + * + * @param key_ctx The context in which this functions stores the hardware context. + * This must be uninitialized + * @param efuse_blk The efuse key block that should be used as the private key. + * The key purpose of this block must be ECDSA_KEY + * + * @return - 0 if successful + * - -1 otherwise + */ +int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index 71905d8cb3..ea2efa243a 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -224,6 +224,7 @@ #undef MBEDTLS_ECP_VERIFY_ALT #undef MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK #endif + /** * \def MBEDTLS_ENTROPY_HARDWARE_ALT * diff --git a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c index 70b91b893c..bb6ba9bddd 100644 --- a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c +++ b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c @@ -30,7 +30,7 @@ #define NEWLIB_NANO_COMPAT_CAST(int64_t_var) int64_t_var #endif -#if CONFIG_MBEDTLS_HARDWARE_ECC +#if CONFIG_MBEDTLS_HARDWARE_ECC || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY /* * All the following values are in big endian format, as required by the mbedTLS APIs From e26018d8ee17b33ab61b7a0a0d271a357ac98d21 Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Tue, 21 Mar 2023 10:04:17 +0530 Subject: [PATCH 3/3] h2/clk_gate: Clear reset signal of ECDSA peripheral before enabling SHA, RSA or ECC --- components/hal/esp32h2/include/hal/clk_gate_ll.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index 4a858474bf..08b7894c55 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -141,6 +141,10 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_RST_EN; case PERIPH_ECC_MODULE: + if (enable == true) { + // Clear reset on ECDSA, otherwise ECC is held in reset + CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN); + } return PCR_ECC_RST_EN; case PERIPH_AES_MODULE: if (enable == true) { @@ -150,15 +154,17 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return PCR_AES_RST_EN; case PERIPH_SHA_MODULE: if (enable == true) { - // Clear reset on digital signature and HMAC, otherwise SHA is held in reset + // Clear reset on digital signature, HMAC, and ECDSA, otherwise SHA is held in reset CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN); CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN); + CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN); } return PCR_SHA_RST_EN; case PERIPH_RSA_MODULE: if (enable == true) { - // Clear reset on digital signature, otherwise RSA is held in reset + // Clear reset on digital signature, and ECDSA, otherwise RSA is held in reset CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN); + CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN); } return PCR_RSA_RST_EN; case PERIPH_HMAC_MODULE: