Merge branch 'feature/add_ecdsa_p384_support_and_testcases' into 'master'

feat: add ecdsa-p384 testcases and relative support for ESP32C5 ECO2

Closes IDF-13008 and IDF-12630

See merge request espressif/esp-idf!38857
This commit is contained in:
Mahavir Jain
2025-08-14 12:33:25 +05:30
32 changed files with 917 additions and 220 deletions

View File

@@ -96,6 +96,16 @@ typedef enum {
ESP_TLS_DYN_BUF_STRATEGY_MAX, /*!< to indicate max */ ESP_TLS_DYN_BUF_STRATEGY_MAX, /*!< to indicate max */
} esp_tls_dyn_buf_strategy_t; } esp_tls_dyn_buf_strategy_t;
/**
* @brief ECDSA curve options for TLS connections
*/
typedef enum {
ESP_TLS_ECDSA_CURVE_SECP256R1 = 0, /*!< Use SECP256R1 curve */
#if SOC_ECDSA_SUPPORT_CURVE_P384
ESP_TLS_ECDSA_CURVE_SECP384R1, /*!< Use SECP384R1 curve */
#endif
ESP_TLS_ECDSA_CURVE_MAX, /*!< to indicate max */
} esp_tls_ecdsa_curve_t;
/** /**
* @brief ESP-TLS configuration parameters * @brief ESP-TLS configuration parameters
@@ -169,7 +179,11 @@ typedef struct esp_tls_cfg {
bool use_ecdsa_peripheral; /*!< Use the ECDSA peripheral for the private key operations */ bool use_ecdsa_peripheral; /*!< Use the ECDSA peripheral for the private key operations */
uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where the ECDSA key is stored */ uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where ECDSA key is stored. For SECP384R1 curve, if two blocks are used, set this to the low block and use ecdsa_key_efuse_blk_high for the high block. */
uint8_t ecdsa_key_efuse_blk_high; /*!< The high efuse block for ECDSA key (used only for SECP384R1 curve). If not set (0), only ecdsa_key_efuse_blk is used. */
esp_tls_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */
bool non_block; /*!< Configure non-blocking mode. If set to true the bool non_block; /*!< Configure non-blocking mode. If set to true the
underneath socket will be configured in non underneath socket will be configured in non
@@ -313,7 +327,11 @@ typedef struct esp_tls_cfg_server {
bool use_ecdsa_peripheral; /*!< Use ECDSA peripheral to use private key */ bool use_ecdsa_peripheral; /*!< Use ECDSA peripheral to use private key */
uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where ECDSA key is stored */ uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where ECDSA key is stored. For SECP384R1 curve, if two blocks are used, set this to the low block and use ecdsa_key_efuse_blk_high for the high block. */
uint8_t ecdsa_key_efuse_blk_high; /*!< The high efuse block for ECDSA key (used only for SECP384R1 curve). If not set (0), only ecdsa_key_efuse_blk is used. */
esp_tls_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */
bool use_secure_element; /*!< Enable this option to use secure element or bool use_secure_element; /*!< Enable this option to use secure element or
atecc608a chip */ atecc608a chip */

View File

@@ -22,6 +22,7 @@
#include "esp_check.h" #include "esp_check.h"
#include "mbedtls/esp_mbedtls_dynamic.h" #include "mbedtls/esp_mbedtls_dynamic.h"
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
#include "mbedtls/ecp.h"
#include "ecdsa/ecdsa_alt.h" #include "ecdsa/ecdsa_alt.h"
#endif #endif
@@ -58,6 +59,29 @@ static mbedtls_x509_crt *global_cacert = NULL;
#define NEWLIB_NANO_SIZE_T_COMPAT_CAST(size_t_var) size_t_var #define NEWLIB_NANO_SIZE_T_COMPAT_CAST(size_t_var) size_t_var
#endif #endif
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
/**
* @brief Convert ESP-TLS ECDSA curve enum to mbedTLS group ID
* @param curve ESP-TLS ECDSA curve enum value
* @param grp_id Pointer to store the converted mbedTLS group ID
* @return ESP_OK on success, ESP_ERR_INVALID_ARG on invalid curve
*/
static esp_err_t esp_tls_ecdsa_curve_to_mbedtls_group_id(esp_tls_ecdsa_curve_t curve, mbedtls_ecp_group_id *grp_id)
{
switch (curve) {
case ESP_TLS_ECDSA_CURVE_SECP256R1:
*grp_id = MBEDTLS_ECP_DP_SECP256R1;
break;
case ESP_TLS_ECDSA_CURVE_SECP384R1:
*grp_id = MBEDTLS_ECP_DP_SECP384R1;
break;
default:
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}
#endif
/* This function shall return the error message when appropriate log level has been set, otherwise this function shall do nothing */ /* This function shall return the error message when appropriate log level has been set, otherwise this function shall do nothing */
static void mbedtls_print_error_msg(int error) static void mbedtls_print_error_msg(int error)
{ {
@@ -561,10 +585,18 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
#endif #endif
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
if (tls->use_ecdsa_peripheral) { if (tls->use_ecdsa_peripheral) {
// Determine the curve group ID based on user preference
mbedtls_ecp_group_id grp_id;
esp_err_t esp_ret = esp_tls_ecdsa_curve_to_mbedtls_group_id(tls->ecdsa_curve, &grp_id);
if (esp_ret != ESP_OK) {
return esp_ret;
}
esp_ecdsa_pk_conf_t conf = { esp_ecdsa_pk_conf_t conf = {
.grp_id = MBEDTLS_ECP_DP_SECP256R1, .grp_id = grp_id,
.efuse_block = tls->ecdsa_efuse_blk, .efuse_block = tls->ecdsa_efuse_blk,
}; };
ret = esp_ecdsa_set_pk_context(pki->pk_key, &conf); ret = esp_ecdsa_set_pk_context(pki->pk_key, &conf);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize pk context for ecdsa peripheral with the key stored in efuse block %d", tls->ecdsa_efuse_blk); ESP_LOGE(TAG, "Failed to initialize pk context for ecdsa peripheral with the key stored in efuse block %d", tls->ecdsa_efuse_blk);
@@ -749,7 +781,12 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls)
} else if (cfg->use_ecdsa_peripheral) { } else if (cfg->use_ecdsa_peripheral) {
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral; tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral;
#if SOC_ECDSA_SUPPORT_CURVE_P384
tls->ecdsa_efuse_blk = HAL_ECDSA_COMBINE_KEY_BLOCKS(cfg->ecdsa_key_efuse_blk_high, cfg->ecdsa_key_efuse_blk);
#else
tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk; tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk;
#endif
tls->ecdsa_curve = cfg->ecdsa_curve;
esp_tls_pki_t pki = { esp_tls_pki_t pki = {
.public_cert = &tls->servercert, .public_cert = &tls->servercert,
.pk_key = &tls->serverkey, .pk_key = &tls->serverkey,
@@ -996,7 +1033,12 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
} else if (cfg->use_ecdsa_peripheral) { } else if (cfg->use_ecdsa_peripheral) {
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral; tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral;
#if SOC_ECDSA_SUPPORT_CURVE_P384
tls->ecdsa_efuse_blk = HAL_ECDSA_COMBINE_KEY_BLOCKS(cfg->ecdsa_key_efuse_blk_high, cfg->ecdsa_key_efuse_blk);
#else
tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk; tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk;
#endif
tls->ecdsa_curve = cfg->ecdsa_curve;
esp_tls_pki_t pki = { esp_tls_pki_t pki = {
.public_cert = &tls->clientcert, .public_cert = &tls->clientcert,
.pk_key = &tls->clientkey, .pk_key = &tls->clientkey,
@@ -1012,13 +1054,30 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
ESP_LOGE(TAG, "Failed to set client pki context"); ESP_LOGE(TAG, "Failed to set client pki context");
return esp_ret; return esp_ret;
} }
static const int ecdsa_peripheral_supported_ciphersuites[] = {
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, mbedtls_ecp_group_id grp_id;
esp_ret = esp_tls_ecdsa_curve_to_mbedtls_group_id(tls->ecdsa_curve, &grp_id);
if (esp_ret != ESP_OK) {
return esp_ret;
}
// Create dynamic ciphersuite array based on curve
static int ecdsa_peripheral_supported_ciphersuites[4] = {0}; // Max 4 elements
int ciphersuite_count = 0;
if (grp_id == MBEDTLS_ECP_DP_SECP384R1) {
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
} else {
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
}
#if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 #if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3
MBEDTLS_TLS1_3_AES_128_GCM_SHA256, if (grp_id == MBEDTLS_ECP_DP_SECP384R1) {
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384;
} else {
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256;
}
#endif #endif
0
};
ESP_LOGD(TAG, "Set the ciphersuites list"); ESP_LOGD(TAG, "Set the ciphersuites list");
mbedtls_ssl_conf_ciphersuites(&tls->conf, ecdsa_peripheral_supported_ciphersuites); mbedtls_ssl_conf_ciphersuites(&tls->conf, ecdsa_peripheral_supported_ciphersuites);

View File

@@ -67,6 +67,7 @@ struct esp_tls {
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
bool use_ecdsa_peripheral; /*!< Use the ECDSA peripheral for the private key operations. */ bool use_ecdsa_peripheral; /*!< Use the ECDSA peripheral for the private key operations. */
uint8_t ecdsa_efuse_blk; /*!< The efuse block number where the ECDSA key is stored. */ uint8_t ecdsa_efuse_blk; /*!< The efuse block number where the ECDSA key is stored. */
esp_tls_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */
#endif #endif
#if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 && CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS #if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 && CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS
unsigned char *client_session; /*!< Pointer for the serialized client session ticket context. */ unsigned char *client_session; /*!< Pointer for the serialized client session ticket context. */

View File

@@ -36,6 +36,7 @@ ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_TLS_VER_ANY == (int)ESP_TLS_VER_ANY, "Enu
ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_TLS_VER_MAX <= (int)ESP_TLS_VER_TLS_MAX, "HTTP client supported TLS is not supported in esp-tls"); ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_TLS_VER_MAX <= (int)ESP_TLS_VER_TLS_MAX, "HTTP client supported TLS is not supported in esp-tls");
ESP_STATIC_ASSERT((int)HTTP_TLS_DYN_BUF_RX_STATIC == (int)ESP_TLS_DYN_BUF_RX_STATIC, "Enum mismatch in esp_http_client and esp-tls"); ESP_STATIC_ASSERT((int)HTTP_TLS_DYN_BUF_RX_STATIC == (int)ESP_TLS_DYN_BUF_RX_STATIC, "Enum mismatch in esp_http_client and esp-tls");
ESP_STATIC_ASSERT((int)HTTP_TLS_DYN_BUF_STRATEGY_MAX <= (int)ESP_TLS_DYN_BUF_STRATEGY_MAX, "HTTP client supported TLS is not supported in esp-tls"); ESP_STATIC_ASSERT((int)HTTP_TLS_DYN_BUF_STRATEGY_MAX <= (int)ESP_TLS_DYN_BUF_STRATEGY_MAX, "HTTP client supported TLS is not supported in esp-tls");
ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_ECDSA_CURVE_MAX <= (int)ESP_TLS_ECDSA_CURVE_MAX, "HTTP client supported ECDSA curve is not supported in esp-tls");
#if CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT == -1 #if CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT == -1
#define ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT portMAX_DELAY #define ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT portMAX_DELAY
@@ -917,7 +918,13 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
} }
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
if (config->use_ecdsa_peripheral) { if (config->use_ecdsa_peripheral) {
#if SOC_ECDSA_SUPPORT_CURVE_P384
esp_transport_ssl_set_client_key_ecdsa_peripheral_extended(ssl, config->ecdsa_key_efuse_blk, config->ecdsa_key_efuse_blk_high);
#else
esp_transport_ssl_set_client_key_ecdsa_peripheral(ssl, config->ecdsa_key_efuse_blk); esp_transport_ssl_set_client_key_ecdsa_peripheral(ssl, config->ecdsa_key_efuse_blk);
#endif
// Set the ECDSA curve
esp_transport_ssl_set_ecdsa_curve(ssl, config->ecdsa_curve);
} }
#endif #endif
if (config->client_key_password && config->client_key_password_len > 0) { if (config->client_key_password && config->client_key_password_len > 0) {

View File

@@ -97,6 +97,17 @@ typedef enum {
typedef esp_err_t (*http_event_handle_cb)(esp_http_client_event_t *evt); typedef esp_err_t (*http_event_handle_cb)(esp_http_client_event_t *evt);
/**
* @brief ECDSA curve options for TLS connections
*/
typedef enum {
ESP_HTTP_CLIENT_ECDSA_CURVE_SECP256R1 = 0, /*!< Use SECP256R1 curve */
#if SOC_ECDSA_SUPPORT_CURVE_P384
ESP_HTTP_CLIENT_ECDSA_CURVE_SECP384R1, /*!< Use SECP384R1 curve */
#endif
ESP_HTTP_CLIENT_ECDSA_CURVE_MAX, /*!< to indicate max */
} esp_http_client_ecdsa_curve_t;
/** /**
* @brief HTTP method * @brief HTTP method
*/ */
@@ -194,7 +205,9 @@ typedef struct {
esp_http_client_proto_ver_t tls_version; /*!< TLS protocol version of the connection, e.g., TLS 1.2, TLS 1.3 (default - no preference) */ esp_http_client_proto_ver_t tls_version; /*!< TLS protocol version of the connection, e.g., TLS 1.2, TLS 1.3 (default - no preference) */
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
bool use_ecdsa_peripheral; /*!< Use ECDSA peripheral to use private key. */ bool use_ecdsa_peripheral; /*!< Use ECDSA peripheral to use private key. */
uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where ECDSA key is stored. */ uint8_t ecdsa_key_efuse_blk; /*!< The efuse block where ECDSA key is stored. For SECP384R1 curve, if two blocks are used, set this to the low block and use ecdsa_key_efuse_blk_high for the high block. */
uint8_t ecdsa_key_efuse_blk_high; /*!< The high efuse block for ECDSA key (used only for SECP384R1 curve). If not set (0), only ecdsa_key_efuse_blk is used. */
esp_http_client_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */
#endif #endif
const char *user_agent; /*!< The User Agent string to send with HTTP requests */ const char *user_agent; /*!< The User Agent string to send with HTTP requests */
esp_http_client_method_t method; /*!< HTTP Method */ esp_http_client_method_t method; /*!< HTTP Method */

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -100,9 +100,15 @@ struct httpd_ssl_config {
/** Use ECDSA peripheral to use private key */ /** Use ECDSA peripheral to use private key */
bool use_ecdsa_peripheral; bool use_ecdsa_peripheral;
/** The efuse block where ECDSA key is stored */ /** The efuse block where ECDSA key is stored. For SECP384R1 curve, if two blocks are used, set this to the low block and use ecdsa_key_efuse_blk_high for the high block. */
uint8_t ecdsa_key_efuse_blk; uint8_t ecdsa_key_efuse_blk;
/** The high efuse block for ECDSA key (used only for SECP384R1 curve). If not set (0), only ecdsa_key_efuse_blk is used. */
uint8_t ecdsa_key_efuse_blk_high;
/** ECDSA curve to use (SECP256R1 or SECP384R1) */
esp_tls_ecdsa_curve_t ecdsa_curve;
/** Transport Mode (default secure) */ /** Transport Mode (default secure) */
httpd_ssl_transport_mode_t transport_mode; httpd_ssl_transport_mode_t transport_mode;
@@ -186,6 +192,8 @@ typedef struct httpd_ssl_config httpd_ssl_config_t;
.prvtkey_len = 0, \ .prvtkey_len = 0, \
.use_ecdsa_peripheral = false, \ .use_ecdsa_peripheral = false, \
.ecdsa_key_efuse_blk = 0, \ .ecdsa_key_efuse_blk = 0, \
.ecdsa_key_efuse_blk_high = 0, \
.ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, \
.transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \ .transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \
.port_secure = 443, \ .port_secure = 443, \
.port_insecure = 80, \ .port_insecure = 80, \

View File

@@ -333,6 +333,10 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
(*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral; (*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral;
(*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk; (*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk;
#if SOC_ECDSA_SUPPORT_CURVE_P384
(*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk_high = config->ecdsa_key_efuse_blk_high;
#endif
(*ssl_ctx)->tls_cfg->ecdsa_curve = config->ecdsa_curve;
#else #else
ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig."); ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig.");
ret = ESP_ERR_NOT_SUPPORTED; ret = ESP_ERR_NOT_SUPPORTED;

View File

@@ -22,6 +22,9 @@
#define ECDSA_HAL_P192_COMPONENT_LEN 24 #define ECDSA_HAL_P192_COMPONENT_LEN 24
#define ECDSA_HAL_P256_COMPONENT_LEN 32 #define ECDSA_HAL_P256_COMPONENT_LEN 32
#if SOC_ECDSA_SUPPORT_CURVE_P384
#define ECDSA_HAL_P384_COMPONENT_LEN 48
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) static void configure_ecdsa_periph(ecdsa_hal_config_t *conf)
{ {
@@ -134,7 +137,11 @@ __attribute__((optimize("O0"))) static void ecdsa_hal_gen_signature_with_counter
void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash,
uint8_t *r_out, uint8_t *s_out, uint16_t len) uint8_t *r_out, uint8_t *s_out, uint16_t len)
{ {
if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN) { if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN
#if SOC_ECDSA_SUPPORT_CURVE_P384
&& len != ECDSA_HAL_P384_COMPONENT_LEN
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
) {
HAL_ASSERT(false && "Incorrect length"); HAL_ASSERT(false && "Incorrect length");
} }
@@ -165,7 +172,11 @@ void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash,
int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, const uint8_t *r, const uint8_t *s, 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) 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) { if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN
#if SOC_ECDSA_SUPPORT_CURVE_P384
&& len != ECDSA_HAL_P384_COMPONENT_LEN
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
) {
HAL_ASSERT(false && "Incorrect length"); HAL_ASSERT(false && "Incorrect length");
} }
@@ -201,7 +212,11 @@ int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, co
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t *pub_y, uint16_t len) void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t *pub_y, uint16_t len)
{ {
if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN) { if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN
#if SOC_ECDSA_SUPPORT_CURVE_P384
&& len != ECDSA_HAL_P384_COMPONENT_LEN
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
) {
HAL_ASSERT(false && "Incorrect length"); HAL_ASSERT(false && "Incorrect length");
} }

View File

@@ -96,6 +96,9 @@ __attribute__((always_inline)) static inline uint32_t efuse_ll_get_chip_ver_pkg(
__attribute__((always_inline)) static inline void efuse_ll_set_ecdsa_key_blk(ecdsa_curve_t curve, int efuse_blk) __attribute__((always_inline)) static inline void efuse_ll_set_ecdsa_key_blk(ecdsa_curve_t curve, int efuse_blk)
{ {
uint8_t efuse_blk_low = 0;
uint8_t efuse_blk_high = 0;
switch (curve) { switch (curve) {
case ECDSA_CURVE_SECP192R1: case ECDSA_CURVE_SECP192R1:
EFUSE.ecdsa.cfg_ecdsa_p192_blk = efuse_blk; EFUSE.ecdsa.cfg_ecdsa_p192_blk = efuse_blk;
@@ -103,6 +106,13 @@ __attribute__((always_inline)) static inline void efuse_ll_set_ecdsa_key_blk(ecd
case ECDSA_CURVE_SECP256R1: case ECDSA_CURVE_SECP256R1:
EFUSE.ecdsa.cfg_ecdsa_p256_blk = efuse_blk; EFUSE.ecdsa.cfg_ecdsa_p256_blk = efuse_blk;
break; 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: default:
HAL_ASSERT(false && "Unsupported curve"); HAL_ASSERT(false && "Unsupported curve");
break; break;

View File

@@ -40,7 +40,7 @@ typedef struct {
ecdsa_mode_t mode; /* Mode of operation */ ecdsa_mode_t mode; /* Mode of operation */
ecdsa_curve_t curve; /* Curve to use for operation */ ecdsa_curve_t curve; /* Curve to use for operation */
ecdsa_sha_mode_t sha_mode; /* Source of SHA that needs to be signed */ ecdsa_sha_mode_t sha_mode; /* Source of SHA that needs to be signed */
int efuse_key_blk; /* Efuse block to use as ECDSA key (The purpose of the efuse block must be ECDSA_KEY) */ int efuse_key_blk; /*!< The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h */
bool use_km_key; /* Use an ECDSA key from the Key Manager peripheral */ bool use_km_key; /* Use an ECDSA key from the Key Manager peripheral */
ecdsa_sign_type_t sign_type; /* Type of signature generation */ ecdsa_sign_type_t sign_type; /* Type of signature generation */
uint16_t loop_number; /* Determines the loop number value in deterministic derivation algorithm to derive K. uint16_t loop_number; /* Determines the loop number value in deterministic derivation algorithm to derive K.

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -48,6 +48,21 @@ typedef enum {
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
} ecdsa_sign_type_t; } ecdsa_sign_type_t;
/**
* @brief Macro to combine two key blocks into a single integer
* @note Least significant 4 bits stores block number of the low key block, and the next 4 bits store the high key block number.
*/
#define HAL_ECDSA_COMBINE_KEY_BLOCKS(blk_high, blk_low) (((blk_high) << 4) | (blk_low))
/**
* @brief Macro to extract high and low key block numbers from a combined integer
* @note Extracts high block from bits 4-7 and low block from bits 0-3
*/
#define HAL_ECDSA_EXTRACT_KEY_BLOCKS(combined_blk, blk_high, blk_low) do { \
(blk_high) = ((combined_blk) >> 4) & 0xF; \
(blk_low) = (combined_blk) & 0xF; \
} while(0)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -82,7 +82,8 @@ uint32_t efuse_hal_get_chip_ver_pkg(void);
* @note The efuse block must be burnt with key purpose ECDSA_KEY * @note The efuse block must be burnt with key purpose ECDSA_KEY
* *
* @param curve ECDSA curve type * @param curve ECDSA curve type
* @param efuse_key_blk Efuse key block number (Must be in [EFUSE_BLK_KEY0...EFUSE_BLK_KEY_MAX - 1] range) * @param efuse_key_blk If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h
* Each efuse key block number (Must be in [EFUSE_BLK_KEY0...EFUSE_BLK_KEY_MAX - 1] range).
*/ */
void efuse_hal_set_ecdsa_key(ecdsa_curve_t curve, int efuse_key_blk); void efuse_hal_set_ecdsa_key(ecdsa_curve_t curve, int efuse_key_blk);
#endif #endif

View File

@@ -106,7 +106,7 @@ espefuse.py -p $ESPPORT burn_key BLOCK_KEY2 main/ds/keys/4096/ds_key3.bin HMAC_D
# Burning the ECDSA keys # Burning the ECDSA keys
By default, ECDSA tests are disabled. You can enable it after disabling HMAC tests using `idf.py menuconfig -> Test App Configuration -> Enable ECDSA Peripheral test cases` By default, ECDSA tests are disabled. You can enable it after disabling HMAC & DS tests using `idf.py menuconfig -> Test App Configuration -> Enable ECDSA Peripheral test cases`
The ECDSA tests need some ECDSA keys to be burned in the `BLOCK_KEY3` and `BLOCK_KEY4` of the efuses. As this verification application is independent of the efuse component, the user needs to manually burn the keys and their key purposes using `espefuse.py`. The ECDSA tests need some ECDSA keys to be burned in the `BLOCK_KEY3` and `BLOCK_KEY4` of the efuses. As this verification application is independent of the efuse component, the user needs to manually burn the keys and their key purposes using `espefuse.py`.

View File

@@ -22,7 +22,7 @@ menu "Test App Configuration"
Enabling this option includes HMAC Peripheral related test cases in the build for supported targets. Enabling this option includes HMAC Peripheral related test cases in the build for supported targets.
config CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS config CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS
depends on SOC_ECDSA_SUPPORTED && !CRYPTO_TEST_APP_ENABLE_HMAC_TESTS depends on SOC_ECDSA_SUPPORTED && !CRYPTO_TEST_APP_ENABLE_HMAC_TESTS && !CRYPTO_TEST_APP_ENABLE_DS_TESTS
bool "Enable ECDSA Peripheral test cases" bool "Enable ECDSA Peripheral test cases"
default n default n
help help

View File

@@ -0,0 +1,6 @@
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAlJNNxsYfk5Ljs1S+0A+F0bsbCBOYvEkGgHLe2GX8BZWvF/UcBQ/MC
qw2m/lFnDx+gBwYFK4EEACKhZANiAASuwiuzzbIJKY3lHflvXsUZx1txuxUGfudz
LZ6X0dM0DAfhk37MxXHli3veGelbkUX37qyRhGShPfNCznxwgfHRTBzEus0gR0hM
/KCjgiryPZfgI0t41sLOf4bJ1q6tvyk=
-----END EC PRIVATE KEY-----

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -20,27 +20,20 @@ const uint8_t ecc_p192_k[] = {
0x75, 0x87, 0xbb, 0x6f, 0x80, 0x34, 0x8d, 0x5e 0x75, 0x87, 0xbb, 0x6f, 0x80, 0x34, 0x8d, 0x5e
}; };
uint8_t sha[] = {
0x0c, 0xaa, 0x08, 0xb4, 0xf0, 0x89, 0xd3, 0x45,
0xbb, 0x55, 0x98, 0xd9, 0xc2, 0xe9, 0x65, 0x5d,
0x7e, 0xa3, 0xa9, 0xc3, 0xcd, 0x69, 0xb1, 0xcf,
0x91, 0xbe, 0x58, 0x10, 0xfe, 0x80, 0x65, 0x6e
};
/* Little endian */ /* Little endian */
uint8_t ecdsa256_r[] = { uint8_t ecdsa256_r[] = {
0xff, 0x94, 0xf7, 0x5a, 0xce, 0x81, 0x05, 0xfc, 0x23, 0xc0, 0x94, 0xe5, 0x49, 0x17, 0xf4, 0x30,
0x98, 0x17, 0xd5, 0x0a, 0x94, 0x53, 0xab, 0x54, 0x10, 0xa4, 0xa0, 0x53, 0x28, 0x8b, 0x87, 0xde,
0xa8, 0x21, 0x8b, 0xe6, 0xf2, 0x6e, 0xa0, 0x7b, 0xfc, 0x58, 0x9e, 0x64, 0x0b, 0x27, 0xe3, 0xb4,
0x20, 0x36, 0x27, 0xd2, 0x60, 0x5d, 0xa3, 0x2e 0x46, 0x6c, 0x24, 0x64, 0x0f, 0xe1, 0x3e, 0x97
}; };
/* Little endian */ /* Little endian */
uint8_t ecdsa256_s[] = { uint8_t ecdsa256_s[] = {
0x50, 0x78, 0x0e, 0x41, 0xe3, 0x03, 0xd2, 0x5b, 0x98, 0x16, 0xf0, 0x9a, 0x8a, 0xf1, 0x8c, 0x8f,
0xaf, 0x74, 0x31, 0xb8, 0x74, 0xc9, 0xb3, 0x89, 0x3b, 0xcb, 0x75, 0x78, 0x71, 0xc9, 0x98, 0x67,
0x8d, 0xb5, 0x40, 0x3e, 0x5b, 0x2a, 0x4b, 0xe2, 0x86, 0xf3, 0x05, 0x0c, 0x5a, 0xe3, 0x8d, 0xec,
0x5e, 0xf8, 0x96, 0xd4, 0xf9, 0x22, 0xf9, 0xb4 0x55, 0x6f, 0x3b, 0xab, 0xd5, 0x1b, 0xae, 0xb1
}; };
/* Little endian */ /* Little endian */
@@ -61,16 +54,16 @@ uint8_t ecdsa256_pub_y[] = {
/* Little endian */ /* Little endian */
uint8_t ecdsa192_r[] = { uint8_t ecdsa192_r[] = {
0x9f, 0xee, 0xb7, 0x4f, 0x09, 0xd5, 0xc8, 0x42, 0x9c, 0xd0, 0xbc, 0x89, 0xbe, 0x77, 0x7e, 0x87,
0x2c, 0x74, 0xe7, 0xaa, 0x6d, 0xe2, 0xe1, 0x1c, 0x00, 0xfc, 0x20, 0x07, 0x2f, 0x2d, 0x46, 0xef,
0xb7, 0x26, 0x75, 0xb2, 0x2f, 0x18, 0x8a, 0x2b 0xa2, 0x81, 0x29, 0x68, 0x95, 0x29, 0xc8, 0x90
}; };
/* Little endian */ /* Little endian */
uint8_t ecdsa192_s[] = { uint8_t ecdsa192_s[] = {
0x12, 0x5b, 0x30, 0x24, 0x59, 0x24, 0xeb, 0xf6, 0x46, 0x46, 0x2b, 0xfa, 0x9e, 0x0e, 0xb2, 0x74,
0x2f, 0x06, 0x60, 0xa8, 0xff, 0xa5, 0xed, 0xce, 0x57, 0xd6, 0xb2, 0xea, 0xbd, 0x76, 0xc1, 0x3b,
0xb6, 0xa5, 0x28, 0xf4, 0x05, 0xb4, 0x74, 0x1a 0x11, 0x8a, 0x5b, 0xb6, 0xc5, 0x84, 0xb1, 0x1e
}; };
/* Little endian */ /* Little endian */
@@ -86,3 +79,53 @@ uint8_t ecdsa192_pub_y[] = {
0xde, 0xc2, 0xdc, 0x74, 0xf3, 0xfd, 0x09, 0x74, 0xde, 0xc2, 0xdc, 0x74, 0xf3, 0xfd, 0x09, 0x74,
0xbe, 0xc4, 0xbc, 0x65, 0xcb, 0x76, 0xfc, 0x85 0xbe, 0xc4, 0xbc, 0x65, 0xcb, 0x76, 0xfc, 0x85
}; };
/* Big endian */
uint8_t sha[] = {
0x98, 0xca, 0xea, 0x85, 0x7b, 0x03, 0x5e, 0xc0,
0xe3, 0xc3, 0x39, 0x29, 0xef, 0xf1, 0xf1, 0x25,
0x00, 0x19, 0xe7, 0x11, 0xc3, 0x3d, 0x84, 0x42,
0x38, 0x79, 0x10, 0xef, 0xb2, 0x9b, 0xd2, 0x63,
0xed, 0xfe, 0x04, 0xce, 0x66, 0x89, 0xd0, 0xa4,
0xb2, 0x60, 0xb2, 0x38, 0x93, 0xa6, 0x27, 0x14
};
/* Little endian */
uint8_t ecdsa384_r[] = {
0xbb, 0x6e, 0x80, 0x35, 0x09, 0x36, 0x31, 0xc5,
0x59, 0x0a, 0x89, 0x82, 0x22, 0xa7, 0x5f, 0xfb,
0x35, 0x6a, 0x4b, 0xf0, 0x4a, 0x20, 0x3a, 0x9d,
0xbe, 0x6f, 0xf0, 0xa9, 0xd7, 0x2e, 0x2d, 0x6b,
0x04, 0x7f, 0x75, 0x14, 0xf8, 0xc6, 0x18, 0xe6,
0x81, 0xb6, 0x08, 0x08, 0xaf, 0xe3, 0x24, 0x1a,
};
/* Little endian */
uint8_t ecdsa384_s[] = {
0x94, 0x61, 0xf9, 0xa8, 0xcd, 0x7a, 0x3c, 0x23,
0xd8, 0x12, 0x3e, 0x33, 0x29, 0xa9, 0x9b, 0xe9,
0x85, 0x5b, 0x34, 0xb9, 0xdc, 0xc2, 0x90, 0x87,
0x71, 0x7c, 0x89, 0xa2, 0x94, 0x5f, 0x4e, 0x47,
0x5f, 0xa7, 0xe4, 0x20, 0x4e, 0xf7, 0x36, 0x6e,
0xe4, 0x62, 0x94, 0x41, 0x8c, 0x30, 0x81, 0x38,
};
/* Little endian */
uint8_t ecdsa384_pub_x[] = {
0x45, 0x91, 0x5b, 0xe9, 0x19, 0xde, 0x7b, 0x8b,
0xe5, 0x71, 0xc5, 0xcc, 0x7e, 0x93, 0xe1, 0x07,
0x0c, 0x34, 0xd3, 0xd1, 0x97, 0x9e, 0x2d, 0x73,
0xe7, 0x7e, 0x06, 0x15, 0xbb, 0x71, 0x5b, 0xc7,
0x19, 0xc5, 0x5e, 0x6f, 0xf9, 0x1d, 0xe5, 0x8d,
0x29, 0x09, 0xb2, 0xcd, 0xb3, 0x2b, 0xc2, 0xae,
};
/* Little endian */
uint8_t ecdsa384_pub_y[] = {
0x29, 0xbf, 0xad, 0xae, 0xd6, 0xc9, 0x86, 0x7f,
0xce, 0xc2, 0xd6, 0x78, 0x4b, 0x23, 0xe0, 0x97,
0x3d, 0xf2, 0x2a, 0x82, 0xa3, 0xa0, 0xfc, 0x4c,
0x48, 0x47, 0x20, 0xcd, 0xba, 0xc4, 0x1c, 0x4c,
0xd1, 0xf1, 0x81, 0x70, 0x7c, 0xce, 0x42, 0xf3,
0x3d, 0xa1, 0x64, 0x84, 0x91, 0xac, 0xee, 0xf7,
};

View File

@@ -63,22 +63,33 @@ static void ecc_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len
} }
} }
int test_ecdsa_verify(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y) int test_ecdsa_verify(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y)
{ {
uint16_t len; uint16_t len = 0;
uint8_t sha_le[32]; uint8_t sha_le[48];
ecdsa_hal_config_t conf = { ecdsa_hal_config_t conf = {
.mode = ECDSA_MODE_SIGN_VERIFY, .mode = ECDSA_MODE_SIGN_VERIFY,
.sha_mode = ECDSA_Z_USER_PROVIDED, .sha_mode = ECDSA_Z_USER_PROVIDED,
}; };
if (is_p256) { switch (curve) {
conf.curve = ECDSA_CURVE_SECP256R1; case ECDSA_CURVE_SECP192R1:
len = 32;
} else {
conf.curve = ECDSA_CURVE_SECP192R1; conf.curve = ECDSA_CURVE_SECP192R1;
len = 24; len = 24;
break;
case ECDSA_CURVE_SECP256R1:
conf.curve = ECDSA_CURVE_SECP256R1;
len = 32;
break;
#if SOC_ECDSA_SUPPORT_CURVE_P384
case ECDSA_CURVE_SECP384R1:
conf.curve = ECDSA_CURVE_SECP384R1;
len = 48;
break;
#endif
default:
break;
} }
/* Set HASH */ /* Set HASH */
@@ -90,51 +101,53 @@ int test_ecdsa_verify(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le,
return ret; return ret;
} }
static void test_ecdsa_corrupt_data(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y) static void test_ecdsa_corrupt_data(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y)
{ {
int len; int len = 0;
if (is_p256) { switch (curve) {
len = 32; case ECDSA_CURVE_SECP192R1: len = 24; break;
} else { case ECDSA_CURVE_SECP256R1: len = 32; break;
len = 24; #if SOC_ECDSA_SUPPORT_CURVE_P384
case ECDSA_CURVE_SECP384R1: len = 48; break;
#endif
default: break;
} }
// Randomly select a bit and corrupt its corresponding value // Randomly select a bit and corrupt its corresponding value
uint16_t r_bit = esp_random() % len * 8; uint16_t r_bit = esp_random() % (len * 8);
printf("Corrupting SHA bit %d...\n", r_bit); printf("Corrupting SHA bit %d...\n", r_bit);
sha[r_bit / 8] ^= 1 << (r_bit % 8); sha[r_bit / 8] ^= 1 << (r_bit % 8);
TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y)); TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(curve, sha, r_le, s_le, pub_x, pub_y));
sha[r_bit / 8] ^= 1 << (r_bit % 8); sha[r_bit / 8] ^= 1 << (r_bit % 8);
printf("Corrupting R bit %d...\n", r_bit); printf("Corrupting R bit %d...\n", r_bit);
r_le[r_bit / 8] ^= 1 << (r_bit % 8); r_le[r_bit / 8] ^= 1 << (r_bit % 8);
TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y)); TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(curve, sha, r_le, s_le, pub_x, pub_y));
r_le[r_bit / 8] ^= 1 << (r_bit % 8); r_le[r_bit / 8] ^= 1 << (r_bit % 8);
printf("Corrupting S bit %d...\n", r_bit); printf("Corrupting S bit %d...\n", r_bit);
s_le[r_bit / 8] ^= 1 << (r_bit % 8); s_le[r_bit / 8] ^= 1 << (r_bit % 8);
TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y)); TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(curve, sha, r_le, s_le, pub_x, pub_y));
s_le[r_bit / 8] ^= 1 << (r_bit % 8); s_le[r_bit / 8] ^= 1 << (r_bit % 8);
printf("Corrupting pub_x bit %d...\n", r_bit); printf("Corrupting pub_x bit %d...\n", r_bit);
pub_x[r_bit / 8] ^= 1 << (r_bit % 8); pub_x[r_bit / 8] ^= 1 << (r_bit % 8);
TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y)); TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(curve, sha, r_le, s_le, pub_x, pub_y));
pub_x[r_bit / 8] ^= 1 << (r_bit % 8); pub_x[r_bit / 8] ^= 1 << (r_bit % 8);
printf("Corrupting pub_y bit %d...\n", r_bit); printf("Corrupting pub_y bit %d...\n", r_bit);
pub_y[r_bit / 8] ^= 1 << (r_bit % 8); pub_y[r_bit / 8] ^= 1 << (r_bit % 8);
TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y)); TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(curve, sha, r_le, s_le, pub_x, pub_y));
pub_y[r_bit / 8] ^= 1 << (r_bit % 8); pub_y[r_bit / 8] ^= 1 << (r_bit % 8);
} }
void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type) void test_ecdsa_sign(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type)
{ {
uint8_t sha_le[32] = {0}; uint8_t sha_le[48] = {0};
uint8_t zeroes[32] = {0}; uint8_t zeroes[48] = {0};
uint16_t len; uint16_t len = 0;
#if !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP #if !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP
uint16_t det_loop_number = 1; uint16_t det_loop_number = 1;
@@ -146,19 +159,34 @@ void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, b
.use_km_key = use_km_key, .use_km_key = use_km_key,
.sign_type = k_type, .sign_type = k_type,
}; };
switch (curve) {
if (is_p256) { case ECDSA_CURVE_SECP192R1:
conf.curve = ECDSA_CURVE_SECP256R1;
if (use_km_key == 0) {
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_2;
}
len = 32;
} else {
conf.curve = ECDSA_CURVE_SECP192R1; conf.curve = ECDSA_CURVE_SECP192R1;
if (use_km_key == 0) { if (use_km_key == 0) {
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1;
} }
len = 24; len = 24;
break;
case ECDSA_CURVE_SECP256R1:
conf.curve = ECDSA_CURVE_SECP256R1;
if (use_km_key == 0) {
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_2;
}
len = 32;
break;
#if SOC_ECDSA_SUPPORT_CURVE_P384
case ECDSA_CURVE_SECP384R1:
conf.curve = ECDSA_CURVE_SECP384R1;
if (use_km_key == 0) {
// Store two key blocks in a single 8-bit integer
// Most significant 4 bits for first block where, lower 4 bits for second block
conf.efuse_key_blk = HAL_ECDSA_COMBINE_KEY_BLOCKS(EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_3, EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_4);
}
len = 48;
break;
#endif
default:
break;
} }
/* Set HASH */ /* Set HASH */
@@ -186,43 +214,56 @@ void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, b
process_again |= !ecdsa_hal_det_signature_k_check(); process_again |= !ecdsa_hal_det_signature_k_check();
} }
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */
} while(process_again); } while(process_again);
ecdsa_disable(); ecdsa_disable();
} }
void test_ecdsa_sign_and_verify(bool is_p256, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type) void test_ecdsa_sign_and_verify(ecdsa_curve_t curve, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type)
{ {
uint8_t r_le[32] = {0}; uint8_t r_le[48] = {0};
uint8_t s_le[32] = {0}; uint8_t s_le[48] = {0};
test_ecdsa_sign(curve, sha, r_le, s_le, use_km_key, k_type);
test_ecdsa_sign(is_p256, sha, r_le, s_le, use_km_key, k_type); TEST_ASSERT_EQUAL(0, test_ecdsa_verify(curve, sha, r_le, s_le, pub_x, pub_y));
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(is_p256, sha, r_le, s_le, pub_x, pub_y));
} }
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
void test_ecdsa_export_pubkey_inner(bool is_p256, uint8_t *exported_pub_x, uint8_t *exported_pub_y, bool use_km_key, uint16_t *len) void test_ecdsa_export_pubkey_inner(ecdsa_curve_t curve, uint8_t *exported_pub_x, uint8_t *exported_pub_y, bool use_km_key, uint16_t *len)
{ {
uint8_t zeroes[48] = {0};
uint8_t zeroes[32] = {0};
ecdsa_hal_config_t conf = { ecdsa_hal_config_t conf = {
.mode = ECDSA_MODE_EXPORT_PUBKEY, .mode = ECDSA_MODE_EXPORT_PUBKEY,
.use_km_key = use_km_key, .use_km_key = use_km_key,
}; };
if (is_p256) { switch (curve) {
conf.curve = ECDSA_CURVE_SECP256R1; case ECDSA_CURVE_SECP192R1:
if (use_km_key == 0) {
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_2;
}
*len = 32;
} else {
conf.curve = ECDSA_CURVE_SECP192R1; conf.curve = ECDSA_CURVE_SECP192R1;
if (use_km_key == 0) { if (use_km_key == 0) {
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1;
} }
*len = 24; *len = 24;
break;
case ECDSA_CURVE_SECP256R1:
conf.curve = ECDSA_CURVE_SECP256R1;
if (use_km_key == 0) {
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_2;
}
*len = 32;
break;
#if SOC_ECDSA_SUPPORT_CURVE_P384
case ECDSA_CURVE_SECP384R1:
conf.curve = ECDSA_CURVE_SECP384R1;
if (use_km_key == 0) {
// Store two key blocks in a single 8-bit integer
// Most significant 4 bits for first block where, lower 4 bits for second block
conf.efuse_key_blk = HAL_ECDSA_COMBINE_KEY_BLOCKS(EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_3, EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_4);
}
*len = 48;
break;
#endif
default:
break;
} }
ecdsa_enable_and_reset(); ecdsa_enable_and_reset();
@@ -231,30 +272,25 @@ void test_ecdsa_export_pubkey_inner(bool is_p256, uint8_t *exported_pub_x, uint8
do { do {
ecdsa_hal_export_pubkey(&conf, exported_pub_x, exported_pub_y, *len); ecdsa_hal_export_pubkey(&conf, exported_pub_x, exported_pub_y, *len);
process_again = !ecdsa_hal_get_operation_result() process_again = !ecdsa_hal_get_operation_result()
|| !memcmp(exported_pub_x, zeroes, *len) || !memcmp(exported_pub_x, zeroes, *len)
|| !memcmp(exported_pub_y, zeroes, *len); || !memcmp(exported_pub_y, zeroes, *len);
} while (process_again); } while (process_again);
ecdsa_disable(); ecdsa_disable();
} }
void test_ecdsa_export_pubkey(ecdsa_curve_t curve, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key)
void test_ecdsa_export_pubkey(bool is_p256, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key)
{ {
uint8_t pub_x[32] = {0}; uint8_t pub_x[48] = {0};
uint8_t pub_y[32] = {0}; uint8_t pub_y[48] = {0};
uint16_t len; uint16_t len;
test_ecdsa_export_pubkey_inner(is_p256, pub_x, pub_y, use_km_key, &len); test_ecdsa_export_pubkey_inner(curve, pub_x, pub_y, use_km_key, &len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa_pub_x, pub_x, len); TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa_pub_x, pub_x, len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa_pub_y, pub_y, len); TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa_pub_y, pub_y, len);
} }
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
TEST_GROUP(ecdsa); TEST_GROUP(ecdsa);
TEST_SETUP(ecdsa) TEST_SETUP(ecdsa)
@@ -269,13 +305,12 @@ TEST_TEAR_DOWN(ecdsa)
test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL)); test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
} }
TEST(ecdsa, ecdsa_SECP192R1_signature_verification) TEST(ecdsa, ecdsa_SECP192R1_signature_verification)
{ {
if (!esp_efuse_is_ecdsa_p192_curve_supported()) { if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
} else { } else {
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y)); TEST_ASSERT_EQUAL(0, test_ecdsa_verify(ECDSA_CURVE_SECP192R1, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y));
} }
} }
@@ -284,7 +319,7 @@ TEST(ecdsa, ecdsa_SECP192R1_sign_and_verify)
if (!esp_efuse_is_ecdsa_p192_curve_supported()) { if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
} else { } else {
test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_TRNG); test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_TRNG);
} }
} }
@@ -293,23 +328,23 @@ TEST(ecdsa, ecdsa_SECP192R1_corrupt_signature)
if (!esp_efuse_is_ecdsa_p192_curve_supported()) { if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
} else { } else {
test_ecdsa_corrupt_data(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y); test_ecdsa_corrupt_data(ECDSA_CURVE_SECP192R1, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y);
} }
} }
TEST(ecdsa, ecdsa_SECP256R1_signature_verification) TEST(ecdsa, ecdsa_SECP256R1_signature_verification)
{ {
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y)); TEST_ASSERT_EQUAL(0, test_ecdsa_verify(ECDSA_CURVE_SECP256R1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y));
} }
TEST(ecdsa, ecdsa_SECP256R1_sign_and_verify) TEST(ecdsa, ecdsa_SECP256R1_sign_and_verify)
{ {
test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_TRNG); test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_TRNG);
} }
TEST(ecdsa, ecdsa_SECP256R1_corrupt_signature) TEST(ecdsa, ecdsa_SECP256R1_corrupt_signature)
{ {
test_ecdsa_corrupt_data(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y); test_ecdsa_corrupt_data(ECDSA_CURVE_SECP256R1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y);
} }
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE #ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
@@ -320,7 +355,7 @@ TEST(ecdsa, ecdsa_SECP192R1_det_sign_and_verify)
} else if (!esp_efuse_is_ecdsa_p192_curve_supported()) { } else if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
} else { } else {
test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC); test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
} }
} }
@@ -329,7 +364,7 @@ TEST(ecdsa, ecdsa_SECP256R1_det_sign_and_verify)
if (!ecdsa_ll_is_deterministic_mode_supported()) { if (!ecdsa_ll_is_deterministic_mode_supported()) {
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported."); ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
} else { } else {
test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC); test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
} }
} }
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
@@ -340,30 +375,81 @@ TEST(ecdsa, ecdsa_SECP192R1_export_pubkey)
if (!esp_efuse_is_ecdsa_p192_curve_supported()) { if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
} else { } else {
test_ecdsa_export_pubkey(0, ecdsa192_pub_x, ecdsa192_pub_y, 0); test_ecdsa_export_pubkey(ECDSA_CURVE_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, 0);
} }
} }
TEST(ecdsa, ecdsa_SECP256R1_export_pubkey) TEST(ecdsa, ecdsa_SECP256R1_export_pubkey)
{ {
test_ecdsa_export_pubkey(1, ecdsa256_pub_x, ecdsa256_pub_y, 0); test_ecdsa_export_pubkey(ECDSA_CURVE_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, 0);
} }
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
TEST(ecdsa, ecdsa_SECP384R1_signature_verification)
{
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(ECDSA_CURVE_SECP384R1, sha, ecdsa384_r, ecdsa384_s, ecdsa384_pub_x, ecdsa384_pub_y));
}
TEST(ecdsa, ecdsa_SECP384R1_sign_and_verify)
{
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, ECDSA_K_TYPE_TRNG);
}
TEST(ecdsa, ecdsa_SECP384R1_corrupt_signature)
{
test_ecdsa_corrupt_data(ECDSA_CURVE_SECP384R1, sha, ecdsa384_r, ecdsa384_s, ecdsa384_pub_x, ecdsa384_pub_y);
}
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
TEST(ecdsa, ecdsa_SECP384R1_det_sign_and_verify)
{
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
}
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
TEST(ecdsa, ecdsa_SECP384R1_export_pubkey)
{
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP384R1, ecdsa384_pub_x, ecdsa384_pub_y, 0);
}
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
TEST_GROUP_RUNNER(ecdsa) TEST_GROUP_RUNNER(ecdsa)
{ {
/* SECP192R1 test cases */
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_signature_verification) RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_signature_verification)
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_sign_and_verify) RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_sign_and_verify)
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_corrupt_signature) RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_corrupt_signature)
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_det_sign_and_verify)
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_export_pubkey)
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
/* SECP256R1 test cases */
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_signature_verification) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_signature_verification)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_sign_and_verify) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_sign_and_verify)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_corrupt_signature) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_corrupt_signature)
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE #ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_det_sign_and_verify)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_det_sign_and_verify) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_det_sign_and_verify)
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_export_pubkey)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_export_pubkey) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_export_pubkey)
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
/* SECP384R1 test cases */
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
RUN_TEST_CASE(ecdsa, ecdsa_SECP384R1_signature_verification)
RUN_TEST_CASE(ecdsa, ecdsa_SECP384R1_sign_and_verify)
RUN_TEST_CASE(ecdsa, ecdsa_SECP384R1_corrupt_signature)
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
RUN_TEST_CASE(ecdsa, ecdsa_SECP384R1_det_sign_and_verify)
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
RUN_TEST_CASE(ecdsa, ecdsa_SECP384R1_export_pubkey)
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -10,14 +10,16 @@
#define DS_KEY_BLOCK_2 1 #define DS_KEY_BLOCK_2 1
#define DS_KEY_BLOCK_3 2 #define DS_KEY_BLOCK_3 2
/*
* HMAC and ECDSA testcases cannot run together as block used for burning keys are overlapped
*/
// efuse key blocks for ECDSA
#define ECDSA_KEY_BLOCK_1 3
#define ECDSA_KEY_BLOCK_2 4
// efuse key blocks for HMAC // efuse key blocks for HMAC
#define HMAC_KEY_BLOCK_1 4 #define HMAC_KEY_BLOCK_1 4
#define HMAC_KEY_BLOCK_2 5 #define HMAC_KEY_BLOCK_2 5
/*
* ECDSA and other peripheral testcases cannot run together as block used for burning keys are overlapped
*/
// efuse key blocks for ECDSA
#define ECDSA_KEY_BLOCK_1 0
#define ECDSA_KEY_BLOCK_2 1
#define ECDSA_KEY_BLOCK_3 2
#define ECDSA_KEY_BLOCK_4 3

View File

@@ -27,6 +27,7 @@
#include "hal/ecdsa_ll.h" #include "hal/ecdsa_ll.h"
#include "hal/ecdsa_hal.h" #include "hal/ecdsa_hal.h"
#include "esp_efuse.h" #include "esp_efuse.h"
#include "esp_efuse_chip.h"
#endif #endif
#if SOC_ECC_SUPPORTED #if SOC_ECC_SUPPORTED
#include "hal/ecc_ll.h" #include "hal/ecc_ll.h"
@@ -37,8 +38,24 @@
#define ECDSA_KEY_MAGIC (short) 0xECD5A #define ECDSA_KEY_MAGIC (short) 0xECD5A
#define ECDSA_KEY_MAGIC_TEE (short) 0xA5DCE #define ECDSA_KEY_MAGIC_TEE (short) 0xA5DCE
#define ECDSA_SHA_LEN 32
/* Key lengths for different ECDSA curves */
#define ECDSA_KEY_LEN_P192 24
#define ECDSA_KEY_LEN_P256 32
#define ECDSA_KEY_LEN_P384 48
#if SOC_ECDSA_SUPPORT_CURVE_P384
#define MAX_ECDSA_COMPONENT_LEN 48
#define MAX_ECDSA_SHA_LEN 48
#else
#define MAX_ECDSA_COMPONENT_LEN 32 #define MAX_ECDSA_COMPONENT_LEN 32
#define MAX_ECDSA_SHA_LEN 32
#endif
#define ECDSA_SHA_LEN 32
#if SOC_ECDSA_SUPPORT_CURVE_P384
#define ECDSA_SHA_LEN_P384 48
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM #if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM
#include "esp_timer.h" #include "esp_timer.h"
@@ -67,6 +84,19 @@
__attribute__((unused)) static const char *TAG = "ecdsa_alt"; __attribute__((unused)) static const char *TAG = "ecdsa_alt";
#if SOC_ECDSA_SUPPORTED #if SOC_ECDSA_SUPPORTED
/**
* @brief Check if the extracted efuse blocks are valid
*
* @param high_blk High efuse block number
* @param low_blk Low efuse block number
* @return true if both blocks are valid, false otherwise
*/
static inline bool is_efuse_blk_valid(int high_blk, int low_blk)
{
return (high_blk >= EFUSE_BLK0 && high_blk < EFUSE_BLK_MAX &&
low_blk >= EFUSE_BLK0 && low_blk < EFUSE_BLK_MAX);
}
static void esp_ecdsa_acquire_hardware(void) static void esp_ecdsa_acquire_hardware(void)
{ {
esp_crypto_ecdsa_lock_acquire(); esp_crypto_ecdsa_lock_acquire();
@@ -101,10 +131,74 @@ static void esp_ecdsa_release_hardware(void)
} }
#endif /* SOC_ECDSA_SUPPORTED */ #endif /* SOC_ECDSA_SUPPORTED */
#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
/**
* @brief Validate if the efuse block(s) have the appropriate ECDSA key purpose for the given curve
*
* This function validates that the provided efuse block(s) have been programmed with the appropriate
* ECDSA key purpose for the specified curve type. It handles both curve-specific key purposes
* (when SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES is defined) and generic ECDSA key purpose.
*
* For SECP384R1 curve, it checks for both high and low key blocks when supported.
* For SECP192R1 and SECP256R1 curves, it validates the single block.
*
* @param[in] grp_id The ECP group ID (curve type) to validate the key purpose for
* @param[in] efuse_blk The efuse block(s) to validate (can be combined for 384-bit keys)
*
* @return
* - 0 on success (block(s) have correct purpose)
* - MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input parameters are invalid
* - MBEDTLS_ERR_ECP_INVALID_KEY if block(s) don't have appropriate key purpose
*/
static int esp_ecdsa_validate_efuse_block(mbedtls_ecp_group_id grp_id, int efuse_blk)
{
int low_blk = efuse_blk;
esp_efuse_purpose_t expected_key_purpose_low;
#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES
#if SOC_ECDSA_SUPPORT_CURVE_P384
int high_blk;
HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk);
esp_efuse_purpose_t expected_key_purpose_high;
#endif
switch (grp_id) {
case MBEDTLS_ECP_DP_SECP192R1:
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P192;
break;
case MBEDTLS_ECP_DP_SECP256R1:
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256;
break;
#if SOC_ECDSA_SUPPORT_CURVE_P384
case MBEDTLS_ECP_DP_SECP384R1:
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_L;
expected_key_purpose_high = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_H;
break;
#endif
default:
ESP_LOGE(TAG, "Unsupported ECDSA curve ID: %d", grp_id);
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#else /* SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY;
#endif /* !SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
if (expected_key_purpose_low != esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk)
#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && SOC_ECDSA_SUPPORT_CURVE_P384
|| expected_key_purpose_high != esp_efuse_get_key_purpose((esp_efuse_block_t)high_blk)
#endif
) {
ESP_LOGE(TAG, "Key burned in efuse has incorrect purpose");
return MBEDTLS_ERR_ECP_INVALID_KEY;
}
return 0;
}
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
static void __attribute__((unused)) ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) static void __attribute__((unused)) 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*/ /* When the size is 24 bytes, it should be padded with 0 bytes*/
memset(le_point, 0x0, 32); memset(le_point, 0x0, len);
for(int i = 0; i < len; i++) { for(int i = 0; i < len; i++) {
le_point[i] = be_point[len - i - 1]; le_point[i] = be_point[len - i - 1];
@@ -117,14 +211,16 @@ int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk)
int ret = -1; int ret = -1;
bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false;
if (!use_km_key) { if (!use_km_key) {
if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { int high_blk, low_blk;
HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk);
if (!is_efuse_blk_valid(high_blk, low_blk)) {
ESP_LOGE(TAG, "Invalid efuse block selected"); ESP_LOGE(TAG, "Invalid efuse block selected");
return ret; return ret;
} }
} }
ecdsa_curve_t curve; ecdsa_curve_t curve;
esp_efuse_block_t blk;
uint16_t len; uint16_t len;
uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0};
uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN];
@@ -132,18 +228,25 @@ int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk)
if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP192R1) { if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP192R1) {
curve = ECDSA_CURVE_SECP192R1; curve = ECDSA_CURVE_SECP192R1;
len = 24; len = ECDSA_KEY_LEN_P192;
} else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) { } else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) {
curve = ECDSA_CURVE_SECP256R1; curve = ECDSA_CURVE_SECP256R1;
len = 32; len = ECDSA_KEY_LEN_P256;
} else { }
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP384R1) {
curve = ECDSA_CURVE_SECP384R1;
len = ECDSA_KEY_LEN_P384;
}
#endif
else {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
if (!use_km_key) { if (!use_km_key) {
if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, &blk)) { ret = esp_ecdsa_validate_efuse_block(keypair->MBEDTLS_PRIVATE(grp).id, efuse_blk);
ESP_LOGE(TAG, "No efuse block with purpose ECDSA_KEY found"); if (ret != 0) {
return MBEDTLS_ERR_ECP_INVALID_KEY; return ret;
} }
} }
@@ -200,7 +303,11 @@ static int validate_ecdsa_pk_input(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_con
return ret; return ret;
} }
if (conf->grp_id != MBEDTLS_ECP_DP_SECP192R1 && conf->grp_id != MBEDTLS_ECP_DP_SECP256R1) { if (conf->grp_id != MBEDTLS_ECP_DP_SECP192R1 && conf->grp_id != MBEDTLS_ECP_DP_SECP256R1
#if SOC_ECDSA_SUPPORT_CURVE_P384
&& conf->grp_id != MBEDTLS_ECP_DP_SECP384R1
#endif
) {
ESP_LOGE(TAG, "Invalid EC curve group id mentioned in esp_ecdsa_pk_conf_t"); ESP_LOGE(TAG, "Invalid EC curve group id mentioned in esp_ecdsa_pk_conf_t");
return ret; return ret;
} }
@@ -219,8 +326,11 @@ int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk)
bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false;
if (!use_km_key) { if (!use_km_key) {
if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { int high_blk, low_blk;
ESP_LOGE(TAG, "Invalid efuse block"); HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk);
if (!is_efuse_blk_valid(high_blk, low_blk)) {
ESP_LOGE(TAG, "Invalid efuse block selected");
return -1; return -1;
} }
} }
@@ -257,8 +367,11 @@ int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk
bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false;
if (!use_km_key) { if (!use_km_key) {
if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { int high_blk, low_blk;
ESP_LOGE(TAG, "Invalid efuse block"); HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk);
if (!is_efuse_blk_valid(high_blk, low_blk)) {
ESP_LOGE(TAG, "Invalid efuse block selected");
return -1; return -1;
} }
} }
@@ -289,7 +402,6 @@ int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *c
efuse_key_block = conf->efuse_block; efuse_key_block = conf->efuse_block;
} }
if ((ret = esp_ecdsa_privkey_load_pk_context(key_ctx, efuse_key_block)) != 0) { if ((ret = esp_ecdsa_privkey_load_pk_context(key_ctx, efuse_key_block)) != 0) {
ESP_LOGE(TAG, "Loading private key context failed, esp_ecdsa_privkey_load_pk_context() returned %d", ret); ESP_LOGE(TAG, "Loading private key context failed, esp_ecdsa_privkey_load_pk_context() returned %d", ret);
return ret; return ret;
@@ -318,10 +430,9 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s
ecdsa_sign_type_t k_type) ecdsa_sign_type_t k_type)
{ {
ecdsa_curve_t curve; ecdsa_curve_t curve;
esp_efuse_block_t blk;
uint16_t len; uint16_t len;
uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0};
uint8_t sha_le[ECDSA_SHA_LEN]; uint8_t sha_le[MAX_ECDSA_SHA_LEN];
uint8_t r_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t r_le[MAX_ECDSA_COMPONENT_LEN];
uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t s_le[MAX_ECDSA_COMPONENT_LEN];
@@ -329,17 +440,29 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
if (msg_len != ECDSA_SHA_LEN) { if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && msg_len != ECDSA_SHA_LEN) ||
(grp->id == MBEDTLS_ECP_DP_SECP256R1 && msg_len != ECDSA_SHA_LEN)
#if SOC_ECDSA_SUPPORT_CURVE_P384
|| (grp->id == MBEDTLS_ECP_DP_SECP384R1 && msg_len != ECDSA_SHA_LEN_P384)
#endif
) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { if (grp->id == MBEDTLS_ECP_DP_SECP192R1) {
curve = ECDSA_CURVE_SECP192R1; curve = ECDSA_CURVE_SECP192R1;
len = 24; len = ECDSA_KEY_LEN_P192;
} else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) {
curve = ECDSA_CURVE_SECP256R1; curve = ECDSA_CURVE_SECP256R1;
len = 32; len = ECDSA_KEY_LEN_P256;
} else { }
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (grp->id == MBEDTLS_ECP_DP_SECP384R1) {
curve = ECDSA_CURVE_SECP384R1;
len = ECDSA_KEY_LEN_P384;
}
#endif
else {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
@@ -347,10 +470,11 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s
if (d->MBEDTLS_PRIVATE(n) == (unsigned short) USE_ECDSA_KEY_FROM_KEY_MANAGER) { if (d->MBEDTLS_PRIVATE(n) == (unsigned short) USE_ECDSA_KEY_FROM_KEY_MANAGER) {
use_km_key = true; use_km_key = true;
} }
if (!use_km_key) { if (!use_km_key) {
if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, &blk)) { int ret = esp_ecdsa_validate_efuse_block(grp->id, d->MBEDTLS_PRIVATE(n));
ESP_LOGE(TAG, "No efuse block with purpose ECDSA_KEY found"); if (ret != 0) {
return MBEDTLS_ERR_ECP_INVALID_KEY; return ret;
} }
} }
@@ -426,10 +550,10 @@ int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, const char *tee_key_
esp_tee_sec_storage_type_t key_type; esp_tee_sec_storage_type_t key_type;
if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) { if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) {
len = 32; len = ECDSA_KEY_LEN_P256;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;
} else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP192R1) { } else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP192R1) {
len = 24; len = ECDSA_KEY_LEN_P192;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1; key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1;
} else { } else {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
@@ -526,17 +650,29 @@ static int esp_ecdsa_tee_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mp
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
if (msg_len != ECDSA_SHA_LEN) { if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && msg_len != ECDSA_SHA_LEN) ||
(grp->id == MBEDTLS_ECP_DP_SECP256R1 && msg_len != ECDSA_SHA_LEN)
#if SOC_ECDSA_SUPPORT_CURVE_P384
|| (grp->id == MBEDTLS_ECP_DP_SECP384R1 && msg_len != ECDSA_SHA_LEN_P384)
#endif
) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { if (grp->id == MBEDTLS_ECP_DP_SECP256R1) {
len = 32; len = ECDSA_KEY_LEN_P256;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;
} else if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { } else if (grp->id == MBEDTLS_ECP_DP_SECP192R1) {
len = 24; len = ECDSA_KEY_LEN_P192;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1; key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1;
} else { }
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (grp->id == MBEDTLS_ECP_DP_SECP384R1) {
len = ECDSA_KEY_LEN_P384;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1;
}
#endif
else {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
@@ -881,23 +1017,35 @@ static int esp_ecdsa_verify(mbedtls_ecp_group *grp,
uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t s_le[MAX_ECDSA_COMPONENT_LEN];
uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN];
uint8_t qy_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t qy_le[MAX_ECDSA_COMPONENT_LEN];
uint8_t sha_le[ECDSA_SHA_LEN]; uint8_t sha_le[MAX_ECDSA_SHA_LEN];
if (!grp || !buf || !Q || !r || !s) { if (!grp || !buf || !Q || !r || !s) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
if (blen != ECDSA_SHA_LEN) { if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && blen != ECDSA_SHA_LEN) ||
(grp->id == MBEDTLS_ECP_DP_SECP256R1 && blen != ECDSA_SHA_LEN)
#if SOC_ECDSA_SUPPORT_CURVE_P384
|| (grp->id == MBEDTLS_ECP_DP_SECP384R1 && blen != ECDSA_SHA_LEN_P384)
#endif
) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { if (grp->id == MBEDTLS_ECP_DP_SECP192R1) {
curve = ECDSA_CURVE_SECP192R1; curve = ECDSA_CURVE_SECP192R1;
len = 24; len = ECDSA_KEY_LEN_P192;
} else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) {
curve = ECDSA_CURVE_SECP256R1; curve = ECDSA_CURVE_SECP256R1;
len = 32; len = ECDSA_KEY_LEN_P256;
} else { }
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (grp->id == MBEDTLS_ECP_DP_SECP384R1) {
curve = ECDSA_CURVE_SECP384R1;
len = ECDSA_KEY_LEN_P384;
}
#endif
else {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
} }
@@ -957,9 +1105,12 @@ int __wrap_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
const mbedtls_mpi *s, const mbedtls_mpi *s,
mbedtls_ecdsa_restart_ctx *rs_ctx) mbedtls_ecdsa_restart_ctx *rs_ctx)
{ {
if (((grp->id == MBEDTLS_ECP_DP_SECP192R1 && esp_efuse_is_ecdsa_p192_curve_supported()) if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && blen == ECDSA_SHA_LEN && esp_efuse_is_ecdsa_p192_curve_supported()) ||
|| (grp->id == MBEDTLS_ECP_DP_SECP256R1 && esp_efuse_is_ecdsa_p256_curve_supported())) (grp->id == MBEDTLS_ECP_DP_SECP256R1 && blen == ECDSA_SHA_LEN && esp_efuse_is_ecdsa_p256_curve_supported())
&& blen == ECDSA_SHA_LEN) { #if SOC_ECDSA_SUPPORT_CURVE_P384
|| (grp->id == MBEDTLS_ECP_DP_SECP384R1 && blen == ECDSA_SHA_LEN_P384)
#endif
) {
return esp_ecdsa_verify(grp, buf, blen, Q, r, s); return esp_ecdsa_verify(grp, buf, blen, Q, r, s);
} else { } else {
return __real_mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, rs_ctx); return __real_mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, rs_ctx);

View File

@@ -12,6 +12,7 @@
#include "mbedtls/pk.h" #include "mbedtls/pk.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "hal/ecdsa_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -50,7 +51,7 @@ typedef struct {
* *
* @param keypair The mbedtls ECP key-pair structure * @param keypair The mbedtls ECP key-pair structure
* @param efuse_blk The efuse key block that should be used as the private key. * @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 * The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h.
* @return - 0 if successful * @return - 0 if successful
* - MBEDTLS_ERR_ECP_BAD_INPUT_DATA if invalid ecp group id specified * - MBEDTLS_ERR_ECP_BAD_INPUT_DATA if invalid ecp group id specified
* - MBEDTLS_ERR_ECP_INVALID_KEY if efuse block with purpose ECDSA_KEY is not found * - MBEDTLS_ERR_ECP_INVALID_KEY if efuse block with purpose ECDSA_KEY is not found
@@ -70,7 +71,7 @@ int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk);
* @param key The MPI in which this functions stores the hardware context. * @param key The MPI in which this functions stores the hardware context.
* This must be uninitialized * This must be uninitialized
* @param efuse_blk The efuse key block that should be used as the private key. * @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 * The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h.
* *
* @return - 0 if successful * @return - 0 if successful
* - -1 otherwise * - -1 otherwise
@@ -86,7 +87,7 @@ int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk);
* @param key_ctx The context in which this functions stores the hardware context. * @param key_ctx The context in which this functions stores the hardware context.
* This must be uninitialized * This must be uninitialized
* @param efuse_blk The efuse key block that should be used as the private key. * @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 * The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h.
* *
* @return - 0 if successful * @return - 0 if successful
* - -1 otherwise * - -1 otherwise

View File

@@ -0,0 +1,6 @@
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAlJNNxsYfk5Ljs1S+0A+F0bsbCBOYvEkGgHLe2GX8BZWvF/UcBQ/MC
qw2m/lFnDx+gBwYFK4EEACKhZANiAASuwiuzzbIJKY3lHflvXsUZx1txuxUGfudz
LZ6X0dM0DAfhk37MxXHli3veGelbkUX37qyRhGShPfNCznxwgfHRTBzEus0gR0hM
/KCjgiryPZfgI0t41sLOf4bJ1q6tvyk=
-----END EC PRIVATE KEY-----

View File

@@ -44,6 +44,22 @@
#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 SOC_ECDSA_SUPPORT_CURVE_P384
#define MAX_ECDSA_COMPONENT_LEN 48
#define MAX_HASH_LEN 48
#else /* !SOC_ECDSA_SUPPORT_CURVE_P384 */
#define MAX_ECDSA_COMPONENT_LEN 32
#define MAX_HASH_LEN 32
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#define HASH_LEN 32
#if SOC_ECDSA_SUPPORT_CURVE_P384
#define HASH_LEN_P384 48
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#define ECDSA_P192_HASH_COMPONENT_LEN 24
#define ECDSA_P256_HASH_COMPONENT_LEN 32
__attribute__((unused)) static const char * TAG = "mbedtls_test"; __attribute__((unused)) static const char * TAG = "mbedtls_test";
/* /*
@@ -51,52 +67,94 @@ __attribute__((unused)) static const char * TAG = "mbedtls_test";
*/ */
const uint8_t sha[] = { const uint8_t sha[] = {
0x0c, 0xaa, 0x08, 0xb4, 0xf0, 0x89, 0xd3, 0x45, 0x98, 0xca, 0xea, 0x85, 0x7b, 0x03, 0x5e, 0xc0,
0xbb, 0x55, 0x98, 0xd9, 0xc2, 0xe9, 0x65, 0x5d, 0xe3, 0xc3, 0x39, 0x29, 0xef, 0xf1, 0xf1, 0x25,
0x7e, 0xa3, 0xa9, 0xc3, 0xcd, 0x69, 0xb1, 0xcf, 0x00, 0x19, 0xe7, 0x11, 0xc3, 0x3d, 0x84, 0x42,
0x91, 0xbe, 0x58, 0x10, 0xfe, 0x80, 0x65, 0x6e 0x38, 0x79, 0x10, 0xef, 0xb2, 0x9b, 0xd2, 0x63,
0xed, 0xfe, 0x04, 0xce, 0x66, 0x89, 0xd0, 0xa4,
0xb2, 0x60, 0xb2, 0x38, 0x93, 0xa6, 0x27, 0x14
}; };
#if CONFIG_MBEDTLS_HARDWARE_ECC || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY #if CONFIG_MBEDTLS_HARDWARE_ECC || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY
/* Big endian */
uint8_t ecdsa384_r[] = {
0x1a, 0x24, 0xe3, 0xaf, 0x08, 0x08, 0xb6, 0x81,
0xe6, 0x18, 0xc6, 0xf8, 0x14, 0x75, 0x7f, 0x04,
0x6b, 0x2d, 0x2e, 0xd7, 0xa9, 0xf0, 0x6f, 0xbe,
0x9d, 0x3a, 0x20, 0x4a, 0xf0, 0x4b, 0x6a, 0x35,
0xfb, 0x5f, 0xa7, 0x22, 0x82, 0x89, 0x0a, 0x59,
0xc5, 0x31, 0x36, 0x09, 0x35, 0x80, 0x6e, 0xbb,
};
/* Big endian */
uint8_t ecdsa384_s[] = {
0x38, 0x81, 0x30, 0x8c, 0x41, 0x94, 0x62, 0xe4,
0x6e, 0x36, 0xf7, 0x4e, 0x20, 0xe4, 0xa7, 0x5f,
0x47, 0x4e, 0x5f, 0x94, 0xa2, 0x89, 0x7c, 0x71,
0x87, 0x90, 0xc2, 0xdc, 0xb9, 0x34, 0x5b, 0x85,
0xe9, 0x9b, 0xa9, 0x29, 0x33, 0x3e, 0x12, 0xd8,
0x23, 0x3c, 0x7a, 0xcd, 0xa8, 0xf9, 0x61, 0x94,
};
/* Big endian */
const uint8_t ecdsa384_pub_x[] = {
0xae, 0xc2, 0x2b, 0xb3, 0xcd, 0xb2, 0x09, 0x29,
0x8d, 0xe5, 0x1d, 0xf9, 0x6f, 0x5e, 0xc5, 0x19,
0xc7, 0x5b, 0x71, 0xbb, 0x15, 0x06, 0x7e, 0xe7,
0x73, 0x2d, 0x9e, 0x97, 0xd1, 0xd3, 0x34, 0x0c,
0x07, 0xe1, 0x93, 0x7e, 0xcc, 0xc5, 0x71, 0xe5,
0x8b, 0x7b, 0xde, 0x19, 0xe9, 0x5b, 0x91, 0x45,
};
/* Big endian */
const uint8_t ecdsa384_pub_y[] = {
0xf7, 0xee, 0xac, 0x91, 0x84, 0x64, 0xa1, 0x3d,
0xf3, 0x42, 0xce, 0x7c, 0x70, 0x81, 0xf1, 0xd1,
0x4c, 0x1c, 0xc4, 0xba, 0xcd, 0x20, 0x47, 0x48,
0x4c, 0xfc, 0xa0, 0xa3, 0x82, 0x2a, 0xf2, 0x3d,
0x97, 0xe0, 0x23, 0x4b, 0x78, 0xd6, 0xc2, 0xce,
0x7f, 0x86, 0xc9, 0xd6, 0xae, 0xad, 0xbf, 0x29,
};
const uint8_t ecdsa256_r[] = { const uint8_t ecdsa256_r[] = {
0x26, 0x1a, 0x0f, 0xbd, 0xa5, 0xe5, 0x1e, 0xe7, 0x97, 0x3e, 0xe1, 0x0f, 0x64, 0x24, 0x6c, 0x46,
0xb3, 0xc3, 0xb7, 0x09, 0xd1, 0x4a, 0x7a, 0x2a, 0xb4, 0xe3, 0x27, 0x0b, 0x64, 0x9e, 0x58, 0xfc,
0x16, 0x69, 0x4b, 0xaf, 0x76, 0x5c, 0xd4, 0x0e, 0xde, 0x87, 0x8b, 0x28, 0x53, 0xa0, 0xa4, 0x10,
0x93, 0x57, 0xb8, 0x67, 0xf9, 0xa1, 0xe5, 0xe8 0x30, 0xf4, 0x17, 0x49, 0xe5, 0x94, 0xc0, 0x23
}; };
const uint8_t ecdsa256_s[] = { const uint8_t ecdsa256_s[] = {
0x63, 0x59, 0xc0, 0x3b, 0x6a, 0xc2, 0xc4, 0xc4, 0xb1, 0xae, 0x1b, 0xd5, 0xab, 0x3b, 0x6f, 0x55,
0xaf, 0x47, 0x5c, 0xe6, 0x6d, 0x43, 0x3b, 0xa7, 0xec, 0x8d, 0xe3, 0x5a, 0x0c, 0x05, 0xf3, 0x86,
0x91, 0x51, 0x15, 0x62, 0x7e, 0x46, 0x0e, 0x68, 0x67, 0x98, 0xc9, 0x71, 0x78, 0x75, 0xcb, 0x3b,
0x84, 0xce, 0x72, 0xa0, 0xd8, 0x8b, 0x69, 0xd5 0x8f, 0x8c, 0xf1, 0x8a, 0x9a, 0xf0, 0x16, 0x98
}; };
const uint8_t ecdsa256_pub_x[] = { const uint8_t ecdsa256_pub_x[] = {
0xcb, 0x59, 0xde, 0x9c, 0xbb, 0x28, 0xaa, 0xac, 0x4d, 0xdf, 0x64, 0x1f, 0xd8, 0x6e, 0xd4, 0x8b,
0x72, 0x06, 0xc3, 0x43, 0x2a, 0x65, 0x82, 0xcc, 0xa7, 0xca, 0x04, 0xc7, 0x11, 0xb8, 0x45, 0xda,
0x68, 0x01, 0x76, 0x68, 0xfc, 0xec, 0xf5, 0x91, 0x0c, 0xff, 0x5f, 0x7a, 0xce, 0x5a, 0x11, 0xf9,
0xd1, 0x9e, 0xbf, 0xcf, 0x67, 0x7d, 0x7d, 0xbe 0x95, 0x55, 0x08, 0x26, 0x85, 0x88, 0xe9, 0xa8
}; };
const uint8_t ecdsa256_pub_y[] = { const uint8_t ecdsa256_pub_y[] = {
0x00, 0x66, 0x14, 0x74, 0xe0, 0x06, 0x44, 0x66, 0x24, 0xb0, 0x4d, 0xcc, 0xbf, 0xce, 0x9a, 0x6e,
0x6f, 0x3b, 0x8c, 0x3b, 0x2d, 0x05, 0xf6, 0xd5, 0xa0, 0x8a, 0xb6, 0x1a, 0x40, 0xf2, 0x71, 0x6a,
0xb2, 0x5d, 0xe4, 0x85, 0x6c, 0x61, 0x38, 0xc5, 0x50, 0xa8, 0xfd, 0xaa, 0x2c, 0x80, 0xa0, 0xbc,
0xb1, 0x21, 0xde, 0x2b, 0x44, 0xf5, 0x13, 0x62 0x73, 0xa1, 0xe8, 0xec, 0xaf, 0x2c, 0x25, 0x34
}; };
const uint8_t ecdsa192_r[] = { const uint8_t ecdsa192_r[] = {
0x2b, 0x8a, 0x18, 0x2f, 0xb2, 0x75, 0x26, 0xb7, 0x90, 0xc8, 0x29, 0x95, 0x68, 0x29, 0x81, 0xa2,
0x1c, 0xe1, 0xe2, 0x6d, 0xaa, 0xe7, 0x74, 0x2c, 0xef, 0x46, 0x2d, 0x2f, 0x07, 0x20, 0xfc, 0x00,
0x42, 0xc8, 0xd5, 0x09, 0x4f, 0xb7, 0xee, 0x9f 0x87, 0x7e, 0x77, 0xbe, 0x89, 0xbc, 0xd0, 0x9c
}; };
const uint8_t ecdsa192_s[] = { const uint8_t ecdsa192_s[] = {
0x1a, 0x74, 0xb4, 0x5, 0xf4, 0x28, 0xa5, 0xb6, 0x1e, 0xb1, 0x84, 0xc5, 0xb6, 0x5b, 0x8a, 0x11,
0xce, 0xed, 0xa5, 0xff, 0xa8, 0x60, 0x06, 0x2f, 0x3b, 0xc1, 0x76, 0xbd, 0xea, 0xb2, 0xd6, 0x57,
0xf6, 0xeb, 0x24, 0x59, 0x24, 0x30, 0x5b, 0x12 0x74, 0xb2, 0x0e, 0x9e, 0xfa, 0x2b, 0x46, 0x46
}; };
const uint8_t ecdsa192_pub_x[] = { const uint8_t ecdsa192_pub_x[] = {
@@ -114,6 +172,7 @@ const uint8_t ecdsa192_pub_y[] = {
void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *r_comp, const uint8_t *s_comp, void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *r_comp, const uint8_t *s_comp,
const uint8_t *pub_x, const uint8_t *pub_y) const uint8_t *pub_x, const uint8_t *pub_y)
{ {
size_t hash_len = HASH_LEN;
int64_t elapsed_time; int64_t elapsed_time;
mbedtls_mpi r, s; mbedtls_mpi r, s;
@@ -127,15 +186,23 @@ void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8
size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P); size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P);
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&r, r_comp, plen)); TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&r, r_comp, plen));
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&s, s_comp, plen)); TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&s, s_comp, plen));
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), pub_x, plen)); TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), pub_x, plen));
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), pub_y, plen)); TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), pub_y, plen));
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1)); TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1));
if (id == MBEDTLS_ECP_DP_SECP192R1 || id == MBEDTLS_ECP_DP_SECP256R1) {
hash_len = HASH_LEN;
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
hash_len = HASH_LEN_P384;
}
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
ccomp_timer_start(); ccomp_timer_start();
TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), hash, 32, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s)); TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), hash, hash_len, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s));
elapsed_time = ccomp_timer_stop(); elapsed_time = ccomp_timer_stop();
if (id == MBEDTLS_ECP_DP_SECP192R1) { if (id == MBEDTLS_ECP_DP_SECP192R1) {
@@ -143,6 +210,11 @@ void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8
} else if (id == MBEDTLS_ECP_DP_SECP256R1) { } else if (id == MBEDTLS_ECP_DP_SECP256R1) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P256_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P256_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time));
} }
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P384_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time));
}
#endif
mbedtls_mpi_free(&r); mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s); mbedtls_mpi_free(&s);
@@ -161,6 +233,14 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbe
ecdsa256_pub_x, ecdsa256_pub_y); ecdsa256_pub_x, ecdsa256_pub_y);
} }
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
TEST_CASE("mbedtls ECDSA signature verification performance on SECP384R1", "[mbedtls]")
{
test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_r, ecdsa384_s,
ecdsa384_pub_x, ecdsa384_pub_y);
}
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#endif /* CONFIG_MBEDTLS_HARDWARE_ECC */ #endif /* CONFIG_MBEDTLS_HARDWARE_ECC */
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
@@ -170,12 +250,12 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbe
* *
* ecdsa_key_p192.pem must be burnt in efuse block 4 * ecdsa_key_p192.pem must be burnt in efuse block 4
* ecdsa_key_p256.pem must be burnt in efuse block 5 * ecdsa_key_p256.pem must be burnt in efuse block 5
* ecdsa_key_p384.pem must be burnt in efuse block 6 and 7
*/ */
#define SECP192R1_EFUSE_BLOCK 4 // EFUSE_BLK_KEY0 #define SECP192R1_EFUSE_BLOCK 4 // EFUSE_BLK_KEY0
#define SECP256R1_EFUSE_BLOCK 5 // EFUSE_BLK_KEY1 #define SECP256R1_EFUSE_BLOCK 5 // EFUSE_BLK_KEY1
#define SECP384R1_EFUSE_BLOCK_HIGH 6 // EFUSE_BLK_KEY2
#define MAX_ECDSA_COMPONENT_LEN 32 #define SECP384R1_EFUSE_BLOCK_LOW 7 // EFUSE_BLK_KEY3
#define HASH_LEN 32
const uint8_t ecdsa256_sign_pub_x[] = { const uint8_t ecdsa256_sign_pub_x[] = {
0xa2, 0x8f, 0x52, 0x60, 0x20, 0x9b, 0x54, 0x3c, 0xa2, 0x8f, 0x52, 0x60, 0x20, 0x9b, 0x54, 0x3c,
@@ -223,6 +303,7 @@ const uint8_t k1_ecdsa192_encrypt[] = {
void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *pub_x, const uint8_t *pub_y, bool is_deterministic, int efuse_key_block) void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *pub_x, const uint8_t *pub_y, bool is_deterministic, int efuse_key_block)
{ {
size_t hash_len = HASH_LEN;
uint8_t r_be[MAX_ECDSA_COMPONENT_LEN] = {0}; uint8_t r_be[MAX_ECDSA_COMPONENT_LEN] = {0};
uint8_t s_be[MAX_ECDSA_COMPONENT_LEN] = {0}; uint8_t s_be[MAX_ECDSA_COMPONENT_LEN] = {0};
@@ -240,12 +321,26 @@ void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t
} else if (id == MBEDTLS_ECP_DP_SECP256R1) { } else if (id == MBEDTLS_ECP_DP_SECP256R1) {
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
} }
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP384R1);
}
#endif
esp_ecdsa_privkey_load_mpi(&key_mpi, efuse_key_block); esp_ecdsa_privkey_load_mpi(&key_mpi, efuse_key_block);
if (id == MBEDTLS_ECP_DP_SECP192R1 || id == MBEDTLS_ECP_DP_SECP256R1) {
hash_len = HASH_LEN;
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
hash_len = HASH_LEN_P384;
}
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
if (is_deterministic) { if (is_deterministic) {
mbedtls_ecdsa_sign_det_ext(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, HASH_LEN, 0, NULL, NULL); mbedtls_ecdsa_sign_det_ext(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, hash_len, 0, NULL, NULL);
} else { } else {
mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, HASH_LEN, NULL, NULL); mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, hash_len, NULL, NULL);
} }
mbedtls_mpi_write_binary(&r, r_be, MAX_ECDSA_COMPONENT_LEN); mbedtls_mpi_write_binary(&r, r_be, MAX_ECDSA_COMPONENT_LEN);
@@ -253,10 +348,15 @@ void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t
if (id == MBEDTLS_ECP_DP_SECP192R1) { if (id == MBEDTLS_ECP_DP_SECP192R1) {
// Skip the initial zeroes // Skip the initial zeroes
test_ecdsa_verify(id, sha, &r_be[8], &s_be[8], pub_x, pub_y); test_ecdsa_verify(id, sha, &r_be[MAX_HASH_LEN - ECDSA_P192_HASH_COMPONENT_LEN], &s_be[MAX_HASH_LEN - ECDSA_P192_HASH_COMPONENT_LEN], pub_x, pub_y);
} else if (id == MBEDTLS_ECP_DP_SECP256R1) { } else if (id == MBEDTLS_ECP_DP_SECP256R1) {
test_ecdsa_verify(id, sha, &r_be[MAX_HASH_LEN - ECDSA_P256_HASH_COMPONENT_LEN], &s_be[MAX_HASH_LEN - ECDSA_P256_HASH_COMPONENT_LEN], pub_x, pub_y);
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
test_ecdsa_verify(id, sha, r_be, s_be, pub_x, pub_y); test_ecdsa_verify(id, sha, r_be, s_be, pub_x, pub_y);
} }
#endif
mbedtls_mpi_free(&r); mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s); mbedtls_mpi_free(&s);
@@ -272,6 +372,15 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_ke
{ {
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y, false, SECP256R1_EFUSE_BLOCK); test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y, false, SECP256R1_EFUSE_BLOCK);
} }
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][efuse_key]")
{
uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW);
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, efuse_key_block);
}
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#if SOC_KEY_MANAGER_SUPPORTED #if SOC_KEY_MANAGER_SUPPORTED
static void deploy_key_in_key_manager(const uint8_t *k1_encrypted, esp_key_mgr_key_type_t key_type) { static void deploy_key_in_key_manager(const uint8_t *k1_encrypted, esp_key_mgr_key_type_t key_type) {
@@ -332,6 +441,14 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe
} }
} }
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP384R1", "[mbedtls][efuse_key]")
{
uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW);
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, true, efuse_key_block);
}
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#if SOC_KEY_MANAGER_SUPPORTED #if SOC_KEY_MANAGER_SUPPORTED
TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbedtls][key_manager_key]") TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbedtls][key_manager_key]")
{ {
@@ -360,8 +477,8 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
void test_ecdsa_export_pubkey(mbedtls_ecp_group_id id, const uint8_t *pub_x, const uint8_t *pub_y, int efuse_key_block) void test_ecdsa_export_pubkey(mbedtls_ecp_group_id id, const uint8_t *pub_x, const uint8_t *pub_y, int efuse_key_block)
{ {
uint8_t export_pub_x[32] = {0}; uint8_t export_pub_x[48] = {0};
uint8_t export_pub_y[32] = {0}; uint8_t export_pub_y[48] = {0};
int len = 0; int len = 0;
esp_ecdsa_pk_conf_t pk_conf = { esp_ecdsa_pk_conf_t pk_conf = {
@@ -380,6 +497,11 @@ void test_ecdsa_export_pubkey(mbedtls_ecp_group_id id, const uint8_t *pub_x, con
} else if (id == MBEDTLS_ECP_DP_SECP256R1) { } else if (id == MBEDTLS_ECP_DP_SECP256R1) {
len = 32; len = 32;
} }
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
len = 48;
}
#endif
mbedtls_pk_context key_ctx; mbedtls_pk_context key_ctx;
@@ -407,6 +529,14 @@ TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][efuse_key]"
test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP256R1, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y, SECP256R1_EFUSE_BLOCK); test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP256R1, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y, SECP256R1_EFUSE_BLOCK);
} }
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
TEST_CASE("mbedtls ECDSA export public key on SECP384R1", "[mbedtls][efuse_key]")
{
uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW);
test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP384R1, ecdsa384_pub_x, ecdsa384_pub_y, efuse_key_block);
}
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#if SOC_KEY_MANAGER_SUPPORTED #if SOC_KEY_MANAGER_SUPPORTED
TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][key_manager_key]") TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][key_manager_key]")
{ {

View File

@@ -1131,6 +1131,10 @@ config SOC_ECDSA_SUPPORT_CURVE_P384
bool bool
default y default y
config SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES
bool
default y
config SOC_SPI_PERIPH_NUM config SOC_SPI_PERIPH_NUM
int int
default 2 default 2

View File

@@ -445,6 +445,7 @@
#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1) #define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1)
#define SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP (1) #define SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP (1)
#define SOC_ECDSA_SUPPORT_CURVE_P384 (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 ----------------------------------------*/ /*-------------------------- SPI CAPS ----------------------------------------*/
#define SOC_SPI_PERIPH_NUM 2 #define SOC_SPI_PERIPH_NUM 2

View File

@@ -94,9 +94,29 @@ void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char
* @brief Set SSL client key data for mutual authentication when using ECDSA peripheral. * @brief Set SSL client key data for mutual authentication when using ECDSA peripheral.
* *
* @param t ssl transport * @param t ssl transport
* @param[in] efuse_blk Efuse block where ECDSA private key is stored * @param[in] ecdsa_efuse_blk. The efuse block where ECDSA key is stored.
*/ */
void esp_transport_ssl_set_client_key_ecdsa_peripheral(esp_transport_handle_t t, uint8_t ecdsa_efuse_blk); void esp_transport_ssl_set_client_key_ecdsa_peripheral(esp_transport_handle_t t, uint8_t ecdsa_efuse_blk);
#if SOC_ECDSA_SUPPORT_CURVE_P384
/**
* @brief Set SSL client key data for mutual authentication when using ECDSA peripheral with extended key storage.
* This function is used when the ECDSA key requires multiple efuse blocks for storage (e.g., P-384 curve).
*
* @param t ssl transport
* @param[in] ecdsa_efuse_blk The efuse block where the lower part of ECDSA key is stored
* @param[in] ecdsa_efuse_blk_high The efuse block where the upper part of ECDSA key is stored (required for P-384 and larger curves)
*/
void esp_transport_ssl_set_client_key_ecdsa_peripheral_extended(esp_transport_handle_t t, uint8_t ecdsa_efuse_blk, uint8_t ecdsa_efuse_blk_high);
#endif
/**
* @brief Set ECDSA curve for SSL client when using ECDSA peripheral.
*
* @param t ssl transport
* @param[in] curve ECDSA curve to use
*/
void esp_transport_ssl_set_ecdsa_curve(esp_transport_handle_t t, esp_tls_ecdsa_curve_t curve);
#endif #endif
/** /**

View File

@@ -421,6 +421,22 @@ void esp_transport_ssl_set_client_key_ecdsa_peripheral(esp_transport_handle_t t,
ssl->cfg.use_ecdsa_peripheral = true; ssl->cfg.use_ecdsa_peripheral = true;
ssl->cfg.ecdsa_key_efuse_blk = ecdsa_efuse_blk; ssl->cfg.ecdsa_key_efuse_blk = ecdsa_efuse_blk;
} }
#if SOC_ECDSA_SUPPORT_CURVE_P384
void esp_transport_ssl_set_client_key_ecdsa_peripheral_extended(esp_transport_handle_t t, uint8_t ecdsa_efuse_blk, uint8_t ecdsa_efuse_blk_high)
{
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
ssl->cfg.use_ecdsa_peripheral = true;
ssl->cfg.ecdsa_key_efuse_blk = ecdsa_efuse_blk;
ssl->cfg.ecdsa_key_efuse_blk_high = ecdsa_efuse_blk_high;
}
#endif
void esp_transport_ssl_set_ecdsa_curve(esp_transport_handle_t t, esp_tls_ecdsa_curve_t curve)
{
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
ssl->cfg.ecdsa_curve = curve;
}
#endif #endif
void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const char *data, int len) void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const char *data, int len)

View File

@@ -22,6 +22,31 @@ ECDSA on {IDF_TARGET_NAME}
On {IDF_TARGET_NAME}, the ECDSA module works with a secret key burnt into an eFuse block. This eFuse key is made completely inaccessible (default mode) for any resources outside the cryptographic modules, thus avoiding key leakage. On {IDF_TARGET_NAME}, the ECDSA module works with a secret key burnt into an eFuse block. This eFuse key is made completely inaccessible (default mode) for any resources outside the cryptographic modules, thus avoiding key leakage.
ECDSA Key Storage
^^^^^^^^^^^^^^^^^
.. only:: SOC_ECDSA_SUPPORT_CURVE_P384
ECDSA private keys are stored in eFuse key blocks. The number of key blocks required depends on the curve size:
- **P-256 curve**: Require one eFuse key block (256 bits)
- **P-384 curve**: Requires two eFuse key blocks (512 bits total)
For curves requiring two key blocks (like P-384), configure the following fields:
- Set :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` to the low block number
- Set :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk_high` to the high block number
For single-block curves (like P-256), only set :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` and leave :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk_high` as 0 or unassigned.
.. only:: not SOC_ECDSA_SUPPORT_CURVE_P384
ECDSA private keys are stored in eFuse key blocks. One eFuse key block (256 bits) is required for P-256 curve.
Configure the following field:
- Set :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` to the block number and leave :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk_high` as 0 or unassigned.
ECDSA key can be programmed externally through ``idf.py`` script. Here is an example of how to program the ECDSA key: ECDSA key can be programmed externally through ``idf.py`` script. Here is an example of how to program the ECDSA key:
.. code:: bash .. code:: bash

View File

@@ -44,6 +44,21 @@ A secure element (ATECC608) can be also used for the underlying TLS connection i
.use_secure_element = true, .use_secure_element = true,
}; };
Use ECDSA Peripheral for TLS
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ECDSA peripheral can be used for the underlying TLS connection in the HTTP client connection. Please refer to the **ECDSA Peripheral with ESP-TLS** section in the :doc:`ESP-TLS documentation </api-reference/protocols/esp_tls>` for more details. The HTTP client can be configured to use ECDSA peripheral as follows:
.. code-block:: c
esp_http_client_config_t cfg = {
/* other configurations options */
.use_ecdsa_peripheral = true,
.ecdsa_key_efuse_blk = 4, // Low eFuse block for ECDSA key
.ecdsa_key_efuse_blk_high = 5, // High eFuse block for ECDSA key (SECP384R1 only)
.ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP384R1, // set this to ESP_TLS_ECDSA_CURVE_SECP256R1 for SECP256R1 curve
};
HTTPS Request HTTPS Request
------------- -------------

View File

@@ -217,16 +217,16 @@ To enable the secure element support, and use it in your project for TLS connect
ESP-TLS provides support for using the ECDSA peripheral with {IDF_TARGET_NAME}. The use of ECDSA peripheral is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. The ECDSA private key should be present in the eFuse for using the ECDSA peripheral. Please refer to :doc:`ECDSA Guide <../peripherals/ecdsa>` for programming the ECDSA key in the eFuse. ESP-TLS provides support for using the ECDSA peripheral with {IDF_TARGET_NAME}. The use of ECDSA peripheral is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. The ECDSA private key should be present in the eFuse for using the ECDSA peripheral. Please refer to :doc:`ECDSA Guide <../peripherals/ecdsa>` for programming the ECDSA key in the eFuse.
To use ECDSA peripheral with ESP-TLS, set :cpp:member:`esp_tls_cfg_t::use_ecdsa_peripheral` to `true`, and set :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` to the eFuse block ID in which ECDSA private key is stored. This will enable the use of ECDSA peripheral for private key operations. As the client private key is already present in the eFuse, it need not be supplied to the :cpp:type:`esp_tls_cfg_t` structure. Please see the below code snippet for enabling the use of ECDSA peripheral for a given ESP-TLS connection.
This will enable the use of ECDSA peripheral for private key operations. As the client private key is already present in the eFuse, it needs not be supplied to the :cpp:type:`esp_tls_cfg_t` structure.
.. code-block:: c .. code-block:: c
#include "esp_tls.h" #include "esp_tls.h"
esp_tls_cfg_t cfg = { esp_tls_cfg_t cfg = {
.use_ecdsa_peripheral = true, .use_ecdsa_peripheral = true,
.ecdsa_key_efuse_blk = /* efuse block with ecdsa private key */, .ecdsa_key_efuse_blk = 4, // Low eFuse block for ECDSA key
.ecdsa_key_efuse_blk_high = 5, // High eFuse block for ECDSA key (SECP384R1 only)
.ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP384R1, // set this to ESP_TLS_ECDSA_CURVE_SECP256R1 for SECP256R1 curve
}; };
.. note:: .. note::

View File

@@ -22,6 +22,31 @@ ECDSA 外设可以为 TLS 双向身份验证等用例建立 **安全设备身份
在 {IDF_TARGET_NAME} 上ECDSA 模块使用烧录到 eFuse 块中的密钥。密码模块外的任何资源都不可访问此密钥(默认模式),从而避免密钥泄露。 在 {IDF_TARGET_NAME} 上ECDSA 模块使用烧录到 eFuse 块中的密钥。密码模块外的任何资源都不可访问此密钥(默认模式),从而避免密钥泄露。
ECDSA 密钥存储
^^^^^^^^^^^^^^
.. only:: SOC_ECDSA_SUPPORT_CURVE_P384
ECDSA 私钥存储在 eFuse 密钥块中。所需的密钥块数量取决于曲线大小:
- **P-256 曲线**:需要一个 eFuse 密钥块256 位)
- **P-384 曲线**:需要两个 eFuse 密钥块(总共 512 位)
对于需要两个密钥块的曲线(如 P-384配置以下字段
-:cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` 设置为低块号
-:cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk_high` 设置为高块号
对于单块曲线(如 P-256只需设置 :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk`,将 :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk_high` 保持为 0 或不赋值。
.. only:: not SOC_ECDSA_SUPPORT_CURVE_P384
ECDSA 私钥存储在 eFuse 密钥块中。一个 eFuse 密钥块256 位)是 P-256 曲线所需的。
配置以下字段:
-:cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` 设置为块号,将 :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk_high` 保持为 0 或不赋值。
ECDSA 密钥可以通过 ``idf.py`` 脚本在外部编程。以下是关于编程 ECDSA 密钥的示例: ECDSA 密钥可以通过 ``idf.py`` 脚本在外部编程。以下是关于编程 ECDSA 密钥的示例:
.. code:: bash .. code:: bash

View File

@@ -44,6 +44,21 @@ HTTP 基本请求
.use_secure_element = true, .use_secure_element = true,
}; };
为 TLS 使用 ECDSA 外设
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ECDSA 外设可用于 HTTP 客户端连接中的底层 TLS 连接。详细内容请参考 :doc:`ESP-TLS 文档 </api-reference/protocols/esp_tls>` 中的 **ECDSA 外设与 ESP-TLS** 小节。可以按如下方式配置 HTTP 客户端以使用 ECDSA 外设:
.. code-block:: c
esp_http_client_config_t cfg = {
/* other configurations options */
.use_ecdsa_peripheral = true,
.ecdsa_key_efuse_blk = 4, // ECDSA 密钥的低 eFuse 块
.ecdsa_key_efuse_blk_high = 5, // ECDSA 密钥的高 eFuse 块(仅 SECP384R1
.ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP384R1, // 设置为 ESP_TLS_ECDSA_CURVE_SECP256R1 以使用 SECP256R1 曲线
};
HTTPS 请求 HTTPS 请求
----------- -----------

View File

@@ -217,8 +217,6 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须
ESP-TLS 支持在 {IDF_TARGET_NAME} 中使用 ECDSA 外设。使用 ECDSA 外设时ESP-TLS 必须与 MbedTLS 一起作为底层 SSL/TLS 协议栈,并且 ECDSA 的私钥应存储在 eFuse 中。请参考 :doc:`ECDSA 指南 <../peripherals/ecdsa>`,了解如何在 eFuse 中烧写 ECDSA 密钥。 ESP-TLS 支持在 {IDF_TARGET_NAME} 中使用 ECDSA 外设。使用 ECDSA 外设时ESP-TLS 必须与 MbedTLS 一起作为底层 SSL/TLS 协议栈,并且 ECDSA 的私钥应存储在 eFuse 中。请参考 :doc:`ECDSA 指南 <../peripherals/ecdsa>`,了解如何在 eFuse 中烧写 ECDSA 密钥。
在 ESP-TLS 中启用 ECDSA 外设前,请将 :cpp:member:`esp_tls_cfg_t::use_ecdsa_peripheral` 设置为 `true`,并将 :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` 设置为存储了 ECDSA 密钥的 eFuse 块 ID。
这样就可以使用 ECDSA 外设进行私钥操作。由于客户私钥已经存储在 eFuse 中,因此无需将其传递给 :cpp:type:`esp_tls_cfg_t` 这样就可以使用 ECDSA 外设进行私钥操作。由于客户私钥已经存储在 eFuse 中,因此无需将其传递给 :cpp:type:`esp_tls_cfg_t`
.. code-block:: c .. code-block:: c
@@ -226,7 +224,9 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须
#include "esp_tls.h" #include "esp_tls.h"
esp_tls_cfg_t cfg = { esp_tls_cfg_t cfg = {
.use_ecdsa_peripheral = true, .use_ecdsa_peripheral = true,
.ecdsa_key_efuse_blk = /* 存储 ECDSA 钥的 eFuse 块 */, .ecdsa_key_efuse_blk = 4, // ECDSA 钥的 eFuse 块
.ecdsa_key_efuse_blk_high = 5, // ECDSA 密钥的高 eFuse 块(仅 SECP384R1
.ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP384R1, // 设置为 ESP_TLS_ECDSA_CURVE_SECP256R1 以使用 SECP256R1 曲线
}; };
.. note:: .. note::