diff --git a/components/esp_hw_support/include/soc/esp32c5/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32c5/esp_crypto_lock.h index 617d0231d8..5b8f392677 100644 --- a/components/esp_hw_support/include/soc/esp32c5/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32c5/esp_crypto_lock.h @@ -75,6 +75,20 @@ void esp_crypto_ecc_lock_acquire(void); */ void esp_crypto_ecc_lock_release(void); +/** + * @brief Acquire lock for ECDSA cryptography peripheral + * + * Internally also locks the ECC and MPI peripheral, as the ECDSA depends on these peripherals + */ +void esp_crypto_ecdsa_lock_acquire(void); + +/** + * @brief Release lock for ECDSA cryptography peripheral + * + * Internally also releases the ECC and MPI peripheral, as the ECDSA depends on these peripherals + */ +void esp_crypto_ecdsa_lock_release(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32c5/esp_crypto_lock.c b/components/esp_hw_support/port/esp32c5/esp_crypto_lock.c index d5192c8589..f61241298c 100644 --- a/components/esp_hw_support/port/esp32c5/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32c5/esp_crypto_lock.c @@ -32,6 +32,9 @@ static _lock_t s_crypto_sha_aes_lock; /* Lock for ECC peripheral */ static _lock_t s_crypto_ecc_lock; +/* Lock for ECDSA peripheral */ +static _lock_t s_crypto_ecdsa_lock; + void esp_crypto_hmac_lock_acquire(void) { _lock_acquire(&s_crypto_hmac_lock); @@ -87,3 +90,15 @@ void esp_crypto_ecc_lock_release(void) { _lock_release(&s_crypto_ecc_lock); } + +void esp_crypto_ecdsa_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecdsa_lock); + esp_crypto_ecc_lock_acquire(); +} + +void esp_crypto_ecdsa_lock_release(void) +{ + esp_crypto_ecc_lock_release(); + _lock_release(&s_crypto_ecdsa_lock); +} diff --git a/components/esp_rom/esp32c5/mp/esp32c5/esp_rom_caps.h b/components/esp_rom/esp32c5/mp/esp32c5/esp_rom_caps.h index 76b76bc17b..3bef0e6e9d 100644 --- a/components/esp_rom/esp32c5/mp/esp32c5/esp_rom_caps.h +++ b/components/esp_rom/esp32c5/mp/esp32c5/esp_rom_caps.h @@ -22,8 +22,6 @@ #define ESP_ROM_HAS_REGI2C_BUG (1) // ROM has the regi2c bug #define ESP_ROM_HAS_NEWLIB (1) // ROM has newlib (at least parts of it) functions included #define ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT (1) // ROM has the newlib normal/full version of formatting functions (as opposed to the nano versions) -// TODO: [ESP32C5] IDF-8618 -// #define ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE (1) // ECO 0 does not have ets_ecdsa_verify symbol, future revision will have it #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_HAS_VERSION (1) // ROM has version/eco information diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index 552fb423af..828be1e555 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -9,6 +9,11 @@ #include "hal/ecdsa_hal.h" #include "hal/efuse_hal.h" +// Need to remove in IDF-8621 +#if CONFIG_IDF_TARGET_ESP32C5 +#include "soc/keymng_reg.h" +#endif + #ifdef SOC_KEY_MANAGER_SUPPORTED #include "hal/key_mgr_hal.h" #endif @@ -22,6 +27,12 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) if (conf->use_km_key == 0) { efuse_hal_set_ecdsa_key(conf->efuse_key_blk); + +// Need to remove in IDF-8621 +#if CONFIG_IDF_TARGET_ESP32C5 + REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 1); +#endif + #if SOC_KEY_MANAGER_SUPPORTED key_mgr_hal_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); #endif diff --git a/components/hal/esp32c5/efuse_hal.c b/components/hal/esp32c5/efuse_hal.c index df9595556d..6a789c0bef 100644 --- a/components/hal/esp32c5/efuse_hal.c +++ b/components/hal/esp32c5/efuse_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/hal/esp32c5/include/hal/ecdsa_ll.h b/components/hal/esp32c5/include/hal/ecdsa_ll.h new file mode 100644 index 0000000000..e88ffb0d0e --- /dev/null +++ b/components/hal/esp32c5/include/hal/ecdsa_ll.h @@ -0,0 +1,443 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 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 "soc/pcr_struct.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_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: +#if !CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_ENA, 0); +#else + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 0); +#endif + 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: +#if !CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_ENA, 0); +#else + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 0); +#endif + 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: +#if !CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_CLR, 0); +#else + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_CLR, 0); +#endif + 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_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 `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 loop number value that is used for deterministic derivation of K + * + * @param loop_number Loop number for deterministic K + */ +static inline void ecdsa_ll_set_deterministic_loop(uint16_t loop_number) +{ + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_LOOP, loop_number); +} + +/** + * @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 k value is greater than the curve order. + * + * @return 0, k value is not greater than the curve order. In this case, the k value is the set k value. + * @return 1, k value is greater than than the curve order. In this case, the k value is the set (k mod n). + */ +static inline int ecdsa_ll_check_k_value(void) +{ + return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_K_VALUE_WARNING); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c5/include/hal/efuse_hal.h b/components/hal/esp32c5/include/hal/efuse_hal.h index 19c8ea42fa..e70ae36182 100644 --- a/components/hal/esp32c5/include/hal/efuse_hal.h +++ b/components/hal/esp32c5/include/hal/efuse_hal.h @@ -16,7 +16,6 @@ extern "C" { #endif - /** * @brief get chip version */ diff --git a/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in index f73769d906..bbb1f156f5 100644 --- a/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in @@ -135,6 +135,10 @@ config SOC_SPI_FLASH_SUPPORTED bool default y +config SOC_ECDSA_SUPPORTED + bool + default y + config SOC_LIGHT_SLEEP_SUPPORTED bool default y @@ -483,6 +487,10 @@ config SOC_SHA_SUPPORT_SHA256 bool default y +config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY + bool + default y + config SOC_SPI_PERIPH_NUM int default 2 diff --git a/components/soc/esp32c5/beta3/include/soc/soc_caps.h b/components/soc/esp32c5/beta3/include/soc/soc_caps.h index 03053b6e87..2acb52cafd 100644 --- a/components/soc/esp32c5/beta3/include/soc/soc_caps.h +++ b/components/soc/esp32c5/beta3/include/soc/soc_caps.h @@ -73,7 +73,7 @@ // #define SOC_WDT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8650 #define SOC_SPI_FLASH_SUPPORTED 1 // TODO: [ESP32C5] IDF-8715 // #define SOC_BITSCRAMBLER_SUPPORTED 1 // TODO: [ESP32C5] IDF-8711 -// #define SOC_ECDSA_SUPPORTED 1 // TODO: [ESP32C5] IDF-8618 +#define SOC_ECDSA_SUPPORTED 1 // #define SOC_KEY_MANAGER_SUPPORTED 1 // TODO: [ESP32C5] IDF-8621 // #define SOC_HUK_SUPPORTED 1 // TODO: [ESP32C5] IDF-8617 #define SOC_LIGHT_SLEEP_SUPPORTED 1 @@ -376,7 +376,7 @@ #define SOC_SHA_SUPPORT_SHA256 (1) /*--------------------------- ECDSA CAPS ---------------------------------------*/ -// #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) +#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) /*-------------------------- Sigma Delta Modulator CAPS -----------------*/ // #define SOC_SDM_GROUPS 1U diff --git a/components/soc/esp32c5/mp/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/mp/include/soc/Kconfig.soc_caps.in index 3c4508d030..c3d90ac794 100644 --- a/components/soc/esp32c5/mp/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/mp/include/soc/Kconfig.soc_caps.in @@ -99,6 +99,10 @@ config SOC_SPI_FLASH_SUPPORTED bool default y +config SOC_ECDSA_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y @@ -463,6 +467,10 @@ config SOC_SHA_SUPPORT_SHA256 bool default y +config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY + bool + default y + config SOC_SPI_PERIPH_NUM int default 2 diff --git a/components/soc/esp32c5/mp/include/soc/soc_caps.h b/components/soc/esp32c5/mp/include/soc/soc_caps.h index f68cbad6a4..3ddc963377 100644 --- a/components/soc/esp32c5/mp/include/soc/soc_caps.h +++ b/components/soc/esp32c5/mp/include/soc/soc_caps.h @@ -69,7 +69,7 @@ // #define SOC_WDT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8650 #define SOC_SPI_FLASH_SUPPORTED 1 // TODO: [ESP32C5] IDF-8715 // #define SOC_BITSCRAMBLER_SUPPORTED 1 // TODO: [ESP32C5] IDF-8711 -// #define SOC_ECDSA_SUPPORTED 1 // TODO: [ESP32C5] IDF-8618 +#define SOC_ECDSA_SUPPORTED 1 // #define SOC_KEY_MANAGER_SUPPORTED 1 // TODO: [ESP32C5] IDF-8621 // #define SOC_HUK_SUPPORTED 1 // TODO: [ESP32C5] IDF-8617 // #define SOC_MODEM_CLOCK_SUPPORTED 1 // TODO: [ESP32C5] IDF-8845 @@ -376,7 +376,7 @@ #define SOC_SHA_SUPPORT_SHA256 (1) /*--------------------------- ECDSA CAPS ---------------------------------------*/ -// #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) +#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) /*-------------------------- Sigma Delta Modulator CAPS -----------------*/ // #define SOC_SDM_GROUPS 1U