feat(hal): enable ecdsa support in esp32h4

This commit is contained in:
nilesh.kale
2026-01-30 10:54:04 +05:30
parent b9a394e75e
commit f400c78d42
8 changed files with 470 additions and 13 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
}
/**

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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