diff --git a/components/esp_hal_security/esp32c5/include/hal/ecdsa_ll.h b/components/esp_hal_security/esp32c5/include/hal/ecdsa_ll.h index 57466e861fe..031df896ddb 100644 --- a/components/esp_hal_security/esp32c5/include/hal/ecdsa_ll.h +++ b/components/esp_hal_security/esp32c5/include/hal/ecdsa_ll.h @@ -153,7 +153,7 @@ 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_ENA_REG, ECDSA_PREP_DONE_INT_CLR, 1); + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_PREP_DONE_INT_CLR, 1); break; case ECDSA_INT_SHA_RELEASE: REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_SHA_RELEASE_INT_CLR, 1); diff --git a/components/esp_hal_security/esp32c61/include/hal/ecdsa_ll.h b/components/esp_hal_security/esp32c61/include/hal/ecdsa_ll.h index 3c63ad90f10..75b507127dc 100644 --- a/components/esp_hal_security/esp32c61/include/hal/ecdsa_ll.h +++ b/components/esp_hal_security/esp32c61/include/hal/ecdsa_ll.h @@ -153,7 +153,7 @@ 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_ENA_REG, ECDSA_PREP_DONE_INT_CLR, 1); + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_PREP_DONE_INT_CLR, 1); break; case ECDSA_INT_SHA_RELEASE: REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_SHA_RELEASE_INT_CLR, 1); diff --git a/components/esp_hal_security/esp32h21/include/hal/ecdsa_ll.h b/components/esp_hal_security/esp32h21/include/hal/ecdsa_ll.h index 095e01b88c9..9aedb455d2d 100644 --- a/components/esp_hal_security/esp32h21/include/hal/ecdsa_ll.h +++ b/components/esp_hal_security/esp32h21/include/hal/ecdsa_ll.h @@ -149,7 +149,7 @@ 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_ENA_REG, ECDSA_PREP_DONE_INT_CLR, 1); + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_PREP_DONE_INT_CLR, 1); break; case ECDSA_INT_SHA_RELEASE: REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_SHA_RELEASE_INT_CLR, 1); diff --git a/components/esp_hal_security/esp32h4/include/hal/ecdsa_ll.h b/components/esp_hal_security/esp32h4/include/hal/ecdsa_ll.h index f49c2fd3305..6b2e77e01b9 100644 --- a/components/esp_hal_security/esp32h4/include/hal/ecdsa_ll.h +++ b/components/esp_hal_security/esp32h4/include/hal/ecdsa_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,403 @@ extern "C" { #endif +/** + * @brief Memory blocks of ECDSA parameters + */ +typedef enum { + ECDSA_PARAM_R, + ECDSA_PARAM_S, + ECDSA_PARAM_Z, + 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 Get the state of ECDSA peripheral + * + * @return State of ECDSA + */ +static inline uint32_t ecdsa_ll_get_state(void) +{ + return REG_GET_FIELD(ECDSA_STATE_REG, ECDSA_BUSY); +} + +/** + * @brief Enable the bus clock for ECDSA peripheral module + * + * @param true to enable the module, false to disable the module + */ +static inline void ecdsa_ll_enable_bus_clock(bool enable) +{ + PCR.ecdsa_conf.ecdsa_clk_en = enable; +} + +/** + * @brief Reset the ECDSA peripheral module + */ +static inline void ecdsa_ll_reset_register(void) +{ + PCR.ecdsa_conf.ecdsa_rst_en = 1; + PCR.ecdsa_conf.ecdsa_rst_en = 0; + + while (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) { + ; + } +} + +/** + * @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_PREP_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_PREP_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_PREP_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; + case ECDSA_MODE_EXPORT_PUBKEY: + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 2); + 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_SECP192R1: + case ECDSA_CURVE_SECP256R1: + case ECDSA_CURVE_SECP384R1: + case ECDSA_CURVE_SM2: + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_ECC_CURVE, curve); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + return; + } +} + +/** + * @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 signature generation type of ECDSA operation + * + * @param type Type of the ECDSA signature + */ +static inline void ecdsa_ll_set_k_type(ecdsa_sign_type_t type) +{ + switch (type) { + case ECDSA_K_TYPE_TRNG: + REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_K); + break; +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + case ECDSA_K_TYPE_DETERMINISITIC: + REG_SET_BIT(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_K); + break; +#endif + default: + HAL_ASSERT(false && "Unsupported K type"); + 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 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 written + * @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_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_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 Check if the ECDSA operation is successful + * + * @return - 1, if ECDSA operation succeeds + * - 0, otherwise + */ +static inline int ecdsa_ll_get_operation_result(void) +{ + return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_OPERATION_RESULT); +} + +/** + * @brief Check if the ECDSA deterministic mode is supported + */ +static inline bool ecdsa_ll_is_deterministic_mode_supported(void) +{ + return true; +} + /** * @brief Set the ECDSA key block in eFuse * @@ -25,9 +422,27 @@ extern "C" { */ __attribute__((always_inline)) static inline void ecdsa_ll_set_ecdsa_key_blk(ecdsa_curve_t curve, int efuse_blk) { - //ESP32H4 TODO - (void)curve; - (void)efuse_blk; + uint8_t efuse_blk_low = 0; + uint8_t efuse_blk_high = 0; + + switch (curve) { + case ECDSA_CURVE_SECP192R1: + EFUSE.ecdsa.cfg_ecdsa_p192_blk = efuse_blk; + break; + case ECDSA_CURVE_SECP256R1: + EFUSE.ecdsa.cfg_ecdsa_p256_blk = efuse_blk; + break; + case ECDSA_CURVE_SECP384R1: + // ECDSA-p384 uses two efuse blocks to store the key. These two blocks are stored in a single integer + // where the least significant 4 bits store the low key block number and the next 4 more significant bits store the high key block number. + HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, efuse_blk_high, efuse_blk_low); + EFUSE.ecdsa.cfg_ecdsa_p384_h_blk = efuse_blk_high; + EFUSE.ecdsa.cfg_ecdsa_p384_l_blk = efuse_blk_low; + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + break; + } } /** diff --git a/components/esp_hal_security/esp32p4/include/hal/ecdsa_ll.h b/components/esp_hal_security/esp32p4/include/hal/ecdsa_ll.h index b09e1d57b03..d019c8d2428 100644 --- a/components/esp_hal_security/esp32p4/include/hal/ecdsa_ll.h +++ b/components/esp_hal_security/esp32p4/include/hal/ecdsa_ll.h @@ -176,7 +176,7 @@ static inline void ecdsa_ll_clear_intr(ecdsa_ll_intr_type_t type) switch (type) { case ECDSA_INT_CALC_DONE: #if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 - REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_CLR, 1); + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_PREP_DONE_INT_CLR, 1); #else REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_CALC_DONE_INT_CLR, 1); #endif diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/ecdsa.h b/components/esp_rom/esp32h4/include/esp32h4/rom/ecdsa.h index 1d1fc84a01a..37105d203ca 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/ecdsa.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/ecdsa.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,13 +12,13 @@ extern "C" { #endif -//TODO: [ESP32H4] IDF-12259 inherit from verification branch, need check - -#define ETS_DIGEST_LEN 32 /* SHA-256, bytes */ +#define ETS_DIGEST_SHA256_LEN 32 /* SHA-256, bytes */ +#define ETS_DIGEST_SHA384_LEN 48 /* SHA-384, bytes */ typedef enum { ECDSA_CURVE_P192 = 1, - ECDSA_CURVE_P256 = 2 + ECDSA_CURVE_P256 = 2, + ECDSA_CURVE_P384 = 3 } ECDSA_CURVE; int ets_ecdsa_verify(const uint8_t *key, const uint8_t *sig, ECDSA_CURVE curve_id, const uint8_t *digest, uint8_t *verified_digest); diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 53650c720ca..82d664a8d36 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -203,6 +203,10 @@ config SOC_SPI_FLASH_SUPPORTED bool default y +config SOC_ECDSA_SUPPORTED + bool + default y + config SOC_SPIRAM_SUPPORTED bool default y @@ -807,6 +811,26 @@ config SOC_ECC_SUPPORT_CURVE_P384 bool default y +config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY + bool + default y + +config SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + bool + default y + +config SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP + bool + default y + +config SOC_ECDSA_SUPPORT_CURVE_P384 + bool + default y + +config SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES + bool + default y + config SOC_SPI_PERIPH_NUM int default 3 @@ -935,6 +959,14 @@ config SOC_EFUSE_ECDSA_KEY bool default y +config SOC_EFUSE_ECDSA_KEY_P192 + bool + default y + +config SOC_EFUSE_ECDSA_KEY_P384 + bool + default y + config SOC_EFUSE_XTS_AES_KEY_128 bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 497980e3535..efd1a646b6f 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -89,6 +89,7 @@ #define SOC_WDT_SUPPORTED 1 #define SOC_RTC_WDT_SUPPORTED 1 #define SOC_SPI_FLASH_SUPPORTED 1 +#define SOC_ECDSA_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 #define SOC_LIGHT_SLEEP_SUPPORTED 1 #define SOC_DEEP_SLEEP_SUPPORTED 1 @@ -365,6 +366,13 @@ #define SOC_ECC_CONSTANT_TIME_POINT_MUL 1 #define SOC_ECC_SUPPORT_CURVE_P384 (1) +/*--------------------------- ECDSA CAPS ---------------------------------------*/ +#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) +#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1) +#define SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP (1) +#define SOC_ECDSA_SUPPORT_CURVE_P384 (1) +#define SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES (1) /*!< Support individual key purposes for different ECDSA curves (P192, P256, P384) */ + /*-------------------------- SPI CAPS ----------------------------------------*/ #define SOC_SPI_PERIPH_NUM 3 #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 @@ -413,6 +421,8 @@ #define SOC_EFUSE_DIS_ICACHE 0 #define SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK 1 // XTS-AES key purpose not supported for this block #define SOC_EFUSE_ECDSA_KEY 1 +#define SOC_EFUSE_ECDSA_KEY_P192 1 +#define SOC_EFUSE_ECDSA_KEY_P384 1 #define SOC_EFUSE_XTS_AES_KEY_128 1 #define SOC_EFUSE_XTS_AES_KEY_256 1