mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 21:54:33 +02:00
Merge branch 'h2/support-ecdsa' into 'master'
H2: Add support for ECDSA peripheral Closes IDF-6287 See merge request espressif/esp-idf!22663
This commit is contained in:
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -62,7 +62,8 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ESP_EFUSE_KEY_PURPOSE_USER = 0, /**< User purposes (software-only use) */
|
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_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_ALL = 5, /**< HMAC Downstream mode */
|
||||||
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6, /**< JTAG soft enable key (uses HMAC Downstream mode) */
|
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6, /**< JTAG soft enable key (uses HMAC Downstream mode) */
|
||||||
|
@@ -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_1 ||
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 ||
|
purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 ||
|
||||||
#endif //#ifdef SOC_EFUSE_SUPPORT_XTS_AES_256_KEYS
|
#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_ALL ||
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG ||
|
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG ||
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE ||
|
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE ||
|
||||||
|
@@ -27,7 +27,8 @@ extern "C" {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ETS_EFUSE_KEY_PURPOSE_USER = 0,
|
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_XTS_AES_128_KEY = 4,
|
||||||
ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5,
|
ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5,
|
||||||
ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6,
|
ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6,
|
||||||
|
@@ -121,6 +121,10 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
list(APPEND srcs "ecc_hal.c")
|
list(APPEND srcs "ecc_hal.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_SOC_ECDSA_SUPPORTED)
|
||||||
|
list(APPEND srcs "ecdsa_hal.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_SHA_SUPPORTED)
|
if(CONFIG_SOC_SHA_SUPPORTED)
|
||||||
list(APPEND srcs "sha_hal.c")
|
list(APPEND srcs "sha_hal.c")
|
||||||
endif()
|
endif()
|
||||||
|
99
components/hal/ecdsa_hal.c
Normal file
99
components/hal/ecdsa_hal.c
Normal file
@@ -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);
|
||||||
|
}
|
@@ -71,6 +71,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
|
|||||||
return PCR_HMAC_CLK_EN;
|
return PCR_HMAC_CLK_EN;
|
||||||
case PERIPH_DS_MODULE:
|
case PERIPH_DS_MODULE:
|
||||||
return PCR_DS_CLK_EN;
|
return PCR_DS_CLK_EN;
|
||||||
|
case PERIPH_ECDSA_MODULE:
|
||||||
|
return PCR_ECDSA_CLK_EN;
|
||||||
case PERIPH_TEMPSENSOR_MODULE:
|
case PERIPH_TEMPSENSOR_MODULE:
|
||||||
return PCR_TSENS_CLK_EN;
|
return PCR_TSENS_CLK_EN;
|
||||||
// case PERIPH_RNG_MODULE:
|
// case PERIPH_RNG_MODULE:
|
||||||
@@ -139,6 +141,10 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
|
|||||||
case PERIPH_TEMPSENSOR_MODULE:
|
case PERIPH_TEMPSENSOR_MODULE:
|
||||||
return PCR_TSENS_RST_EN;
|
return PCR_TSENS_RST_EN;
|
||||||
case PERIPH_ECC_MODULE:
|
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;
|
return PCR_ECC_RST_EN;
|
||||||
case PERIPH_AES_MODULE:
|
case PERIPH_AES_MODULE:
|
||||||
if (enable == true) {
|
if (enable == true) {
|
||||||
@@ -148,21 +154,25 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
|
|||||||
return PCR_AES_RST_EN;
|
return PCR_AES_RST_EN;
|
||||||
case PERIPH_SHA_MODULE:
|
case PERIPH_SHA_MODULE:
|
||||||
if (enable == true) {
|
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_DS_CONF_REG, PCR_DS_RST_EN);
|
||||||
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_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;
|
return PCR_SHA_RST_EN;
|
||||||
case PERIPH_RSA_MODULE:
|
case PERIPH_RSA_MODULE:
|
||||||
if (enable == true) {
|
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_DS_CONF_REG, PCR_DS_RST_EN);
|
||||||
|
CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
|
||||||
}
|
}
|
||||||
return PCR_RSA_RST_EN;
|
return PCR_RSA_RST_EN;
|
||||||
case PERIPH_HMAC_MODULE:
|
case PERIPH_HMAC_MODULE:
|
||||||
return PCR_HMAC_RST_EN;
|
return PCR_HMAC_RST_EN;
|
||||||
case PERIPH_DS_MODULE:
|
case PERIPH_DS_MODULE:
|
||||||
return PCR_DS_RST_EN;
|
return PCR_DS_RST_EN;
|
||||||
|
case PERIPH_ECDSA_MODULE:
|
||||||
|
return PCR_ECDSA_RST_EN;
|
||||||
// case PERIPH_RNG_MODULE:
|
// case PERIPH_RNG_MODULE:
|
||||||
// return PCR_WIFI_CLK_RNG_EN;
|
// return PCR_WIFI_CLK_RNG_EN;
|
||||||
// case PERIPH_WIFI_MODULE:
|
// case PERIPH_WIFI_MODULE:
|
||||||
@@ -243,6 +253,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
|
|||||||
return PCR_HMAC_CONF_REG;
|
return PCR_HMAC_CONF_REG;
|
||||||
case PERIPH_DS_MODULE:
|
case PERIPH_DS_MODULE:
|
||||||
return PCR_DS_CONF_REG;
|
return PCR_DS_CONF_REG;
|
||||||
|
case PERIPH_ECDSA_MODULE:
|
||||||
|
return PCR_ECDSA_CONF_REG;
|
||||||
case PERIPH_TEMPSENSOR_MODULE:
|
case PERIPH_TEMPSENSOR_MODULE:
|
||||||
return PCR_TSENS_CLK_CONF_REG;
|
return PCR_TSENS_CLK_CONF_REG;
|
||||||
default:
|
default:
|
||||||
@@ -306,6 +318,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
|
|||||||
return PCR_HMAC_CONF_REG;
|
return PCR_HMAC_CONF_REG;
|
||||||
case PERIPH_DS_MODULE:
|
case PERIPH_DS_MODULE:
|
||||||
return PCR_DS_CONF_REG;
|
return PCR_DS_CONF_REG;
|
||||||
|
case PERIPH_ECDSA_MODULE:
|
||||||
|
return PCR_ECDSA_CONF_REG;
|
||||||
case PERIPH_TEMPSENSOR_MODULE:
|
case PERIPH_TEMPSENSOR_MODULE:
|
||||||
return PCR_TSENS_CLK_CONF_REG;
|
return PCR_TSENS_CLK_CONF_REG;
|
||||||
default:
|
default:
|
||||||
|
386
components/hal/esp32h2/include/hal/ecdsa_ll.h
Normal file
386
components/hal/esp32h2/include/hal/ecdsa_ll.h
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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
|
63
components/hal/include/hal/ecdsa_hal.h
Normal file
63
components/hal/include/hal/ecdsa_hal.h
Normal file
@@ -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 <stdint.h>
|
||||||
|
#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
|
46
components/hal/include/hal/ecdsa_types.h
Normal file
46
components/hal/include/hal/ecdsa_types.h
Normal file
@@ -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
|
@@ -235,6 +235,18 @@ if(CONFIG_MBEDTLS_HARDWARE_ECC)
|
|||||||
"${COMPONENT_DIR}/port/ecc/ecc_alt.c")
|
"${COMPONENT_DIR}/port/ecc/ecc_alt.c")
|
||||||
endif()
|
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)
|
if(CONFIG_MBEDTLS_ROM_MD5)
|
||||||
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/md/esp_md.c")
|
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/md/esp_md.c")
|
||||||
endif()
|
endif()
|
||||||
@@ -267,6 +279,10 @@ if(CONFIG_PM_ENABLE)
|
|||||||
target_link_libraries(mbedcrypto PRIVATE idf::esp_pm)
|
target_link_libraries(mbedcrypto PRIVATE idf::esp_pm)
|
||||||
endif()
|
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})
|
target_link_libraries(${COMPONENT_LIB} ${linkage_type} ${mbedtls_targets})
|
||||||
|
|
||||||
if(CONFIG_ESP_TLS_USE_DS_PERIPHERAL)
|
if(CONFIG_ESP_TLS_USE_DS_PERIPHERAL)
|
||||||
|
@@ -455,6 +455,29 @@ menu "mbedTLS"
|
|||||||
help
|
help
|
||||||
Use ROM MD5 in mbedTLS.
|
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
|
config MBEDTLS_ATCA_HW_ECDSA_SIGN
|
||||||
bool "Enable hardware ECDSA sign acceleration when using ATECC608A"
|
bool "Enable hardware ECDSA sign acceleration when using ATECC608A"
|
||||||
default n
|
default n
|
||||||
|
276
components/mbedtls/port/ecdsa/ecdsa_alt.c
Normal file
276
components/mbedtls/port/ecdsa/ecdsa_alt.c
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#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 */
|
63
components/mbedtls/port/include/ecdsa/ecdsa_alt.h
Normal file
63
components/mbedtls/port/include/ecdsa/ecdsa_alt.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#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
|
@@ -224,6 +224,7 @@
|
|||||||
#undef MBEDTLS_ECP_VERIFY_ALT
|
#undef MBEDTLS_ECP_VERIFY_ALT
|
||||||
#undef MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK
|
#undef MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \def MBEDTLS_ENTROPY_HARDWARE_ALT
|
* \def MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||||
*
|
*
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
#define NEWLIB_NANO_COMPAT_CAST(int64_t_var) int64_t_var
|
#define NEWLIB_NANO_COMPAT_CAST(int64_t_var) int64_t_var
|
||||||
#endif
|
#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
|
* All the following values are in big endian format, as required by the mbedTLS APIs
|
||||||
|
@@ -143,6 +143,10 @@ config SOC_ECC_EXTENDED_MODES_SUPPORTED
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config SOC_ECDSA_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_FLASH_ENC_SUPPORTED
|
config SOC_FLASH_ENC_SUPPORTED
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
@@ -38,6 +38,7 @@ typedef enum {
|
|||||||
PERIPH_ECC_MODULE,
|
PERIPH_ECC_MODULE,
|
||||||
PERIPH_HMAC_MODULE,
|
PERIPH_HMAC_MODULE,
|
||||||
PERIPH_DS_MODULE,
|
PERIPH_DS_MODULE,
|
||||||
|
PERIPH_ECDSA_MODULE,
|
||||||
PERIPH_GDMA_MODULE,
|
PERIPH_GDMA_MODULE,
|
||||||
PERIPH_MCPWM0_MODULE,
|
PERIPH_MCPWM0_MODULE,
|
||||||
PERIPH_ETM_MODULE,
|
PERIPH_ETM_MODULE,
|
||||||
|
@@ -61,6 +61,7 @@
|
|||||||
#define SOC_DIG_SIGN_SUPPORTED 1
|
#define SOC_DIG_SIGN_SUPPORTED 1
|
||||||
#define SOC_ECC_SUPPORTED 1
|
#define SOC_ECC_SUPPORTED 1
|
||||||
#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1
|
#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1
|
||||||
|
#define SOC_ECDSA_SUPPORTED 1
|
||||||
#define SOC_FLASH_ENC_SUPPORTED 1
|
#define SOC_FLASH_ENC_SUPPORTED 1
|
||||||
#define SOC_SECURE_BOOT_SUPPORTED 1
|
#define SOC_SECURE_BOOT_SUPPORTED 1
|
||||||
#define SOC_BOD_SUPPORTED 1
|
#define SOC_BOD_SUPPORTED 1
|
||||||
|
Reference in New Issue
Block a user