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

This commit adds testcases in crypto/hal and mbedtls testapps.
This commit is contained in:
nilesh.kale
2025-05-23 14:23:17 +05:30
parent ae221cb24f
commit 68f06a94bd
25 changed files with 919 additions and 213 deletions

View File

@@ -19,7 +19,7 @@ idf_component_register(SRCS "${srcs}"
PRIV_INCLUDE_DIRS "private_include" PRIV_INCLUDE_DIRS "private_include"
# mbedtls is public requirements because esp_tls.h # mbedtls is public requirements because esp_tls.h
# includes mbedtls header files. # includes mbedtls header files.
REQUIRES mbedtls REQUIRES mbedtls efuse
PRIV_REQUIRES ${priv_req}) PRIV_REQUIRES ${priv_req})
if(CONFIG_ESP_TLS_USING_WOLFSSL) if(CONFIG_ESP_TLS_USING_WOLFSSL)

View File

@@ -28,6 +28,22 @@
extern "C" { extern "C" {
#endif #endif
/**
* @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 more significant bits store the high key block number.
*/
#define ESP_TLS_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 ESP_TLS_ECDSA_EXTRACT_KEY_BLOCKS(combined_blk, blk_high, blk_low) do { \
(blk_high) = ((combined_blk) >> 4) & 0xF; \
(blk_low) = (combined_blk) & 0xF; \
} while(0)
/** /**
* @brief ESP-TLS Connection State * @brief ESP-TLS Connection State
*/ */
@@ -169,7 +185,7 @@ 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. If two blocks are used to store the key, then the macro ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. */
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 +329,7 @@ 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. If two blocks are used to store the key, then the macro ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. */
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,9 @@
#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 "esp_efuse.h"
#include "esp_efuse_chip.h"
#include "ecdsa/ecdsa_alt.h" #include "ecdsa/ecdsa_alt.h"
#endif #endif
@@ -48,6 +51,78 @@ static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki);
static const char *TAG = "esp-tls-mbedtls"; static const char *TAG = "esp-tls-mbedtls";
static mbedtls_x509_crt *global_cacert = NULL; static mbedtls_x509_crt *global_cacert = NULL;
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
/**
* @brief Determine the ECDSA curve group ID based on the efuse block's key purpose
*
* This function reads the key purpose from the specified efuse block and returns the appropriate
* ECDSA curve group ID. 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 both high and low key blocks when supported.
* For SECP192R1 and SECP256R1 curves, it checks the single block.
* For generic ECDSA key purpose, it defaults to SECP256R1.
*
* @param[in] efuse_blk The efuse block(s) to check (can be combined for 384-bit keys)
*
* @return
* - MBEDTLS_ECP_DP_SECP192R1 if block has P192 key purpose
* - MBEDTLS_ECP_DP_SECP256R1 if block has P256 key purpose or generic ECDSA key purpose
* - MBEDTLS_ECP_DP_SECP384R1 if blocks have P384 key purposes
* - MBEDTLS_ECP_DP_NONE if block has invalid or unsupported key purpose
*/
static mbedtls_ecp_group_id esp_tls_get_curve_from_efuse_block(uint8_t efuse_blk)
{
#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES
esp_efuse_purpose_t key_purpose;
// For P384, we need to check both blocks
if (efuse_blk > 0xF) { // Combined blocks for P384
#if SOC_ECDSA_SUPPORT_CURVE_P384
int high_blk, low_blk;
MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk);
esp_efuse_purpose_t high_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)high_blk);
esp_efuse_purpose_t low_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk);
if (low_purpose == ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_L && high_purpose == ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_H) {
return MBEDTLS_ECP_DP_SECP384R1;
}
// If we reach here, the key purposes don't match P384 requirements
ESP_LOGE(TAG, "Efuse blocks %d,%d have invalid P384 key purposes: low=%d, high=%d",
low_blk, high_blk, low_purpose, high_purpose);
return MBEDTLS_ECP_DP_NONE;
#else
// P384 not supported but combined blocks provided
ESP_LOGE(TAG, "P384 curve not supported but combined efuse blocks provided: %d", efuse_blk);
return MBEDTLS_ECP_DP_NONE;
#endif
} else { // Single block for P192 or P256
key_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)efuse_blk);
switch (key_purpose) {
case ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P192:
return MBEDTLS_ECP_DP_SECP192R1;
case ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256:
return MBEDTLS_ECP_DP_SECP256R1;
default:
ESP_LOGE(TAG, "Efuse block %d has unsupported key purpose %d", efuse_blk, key_purpose);
return MBEDTLS_ECP_DP_NONE;
}
}
#else /* SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
// For generic ECDSA key purpose, default to P256
esp_efuse_purpose_t key_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)efuse_blk);
if (key_purpose == ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY) {
return MBEDTLS_ECP_DP_SECP256R1;
}
#endif /* !SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
ESP_LOGE(TAG, "Efuse block %d has invalid key purpose", efuse_blk);
return MBEDTLS_ECP_DP_NONE;
}
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
#if CONFIG_NEWLIB_NANO_FORMAT #if CONFIG_NEWLIB_NANO_FORMAT
#define NEWLIB_NANO_SSIZE_T_COMPAT_FORMAT "X" #define NEWLIB_NANO_SSIZE_T_COMPAT_FORMAT "X"
#define NEWLIB_NANO_SIZE_T_COMPAT_FORMAT PRIu32 #define NEWLIB_NANO_SIZE_T_COMPAT_FORMAT PRIu32
@@ -561,10 +636,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 the efuse block's key purpose
mbedtls_ecp_group_id grp_id = esp_tls_get_curve_from_efuse_block(tls->ecdsa_efuse_blk);
if (grp_id == MBEDTLS_ECP_DP_NONE) {
ESP_LOGE(TAG, "Failed to determine curve group ID from efuse block %d", tls->ecdsa_efuse_blk);
return ESP_ERR_INVALID_ARG;
}
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);
@@ -1012,13 +1095,29 @@ 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_tls_get_curve_from_efuse_block(tls->ecdsa_efuse_blk);
if (grp_id == MBEDTLS_ECP_DP_NONE) {
ESP_LOGE(TAG, "Failed to determine curve group ID from efuse block %d", tls->ecdsa_efuse_blk);
return ESP_ERR_INVALID_ARG;
}
// Create dynamic ciphersuite array based on curve
static int ecdsa_peripheral_supported_ciphersuites[4] = {0}; // Max 4 elements
int ciphersuite_count = 0;
#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 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;
}
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

@@ -178,7 +178,7 @@ 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. If two blocks are used to store the key, then the macro ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in esp_tls.h */
#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

@@ -100,7 +100,7 @@ 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. If two blocks are used to store the key, then the macro ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in esp_tls.h */
uint8_t ecdsa_key_efuse_blk; uint8_t ecdsa_key_efuse_blk;
/** Transport Mode (default secure) */ /** Transport Mode (default secure) */

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 more significant 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

@@ -59,22 +59,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; conf.curve = ECDSA_CURVE_SECP192R1;
} else { len = 24;
conf.curve = ECDSA_CURVE_SECP192R1; break;
len = 24; 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 */
@@ -86,51 +97,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;
@@ -142,19 +155,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; 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_2; conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1;
} }
len = 32; len = 24;
} else { break;
conf.curve = ECDSA_CURVE_SECP192R1; case ECDSA_CURVE_SECP256R1:
if (use_km_key == 0) { conf.curve = ECDSA_CURVE_SECP256R1;
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; if (use_km_key == 0) {
} conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_2;
len = 24; }
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 */
@@ -182,43 +210,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.curve = ECDSA_CURVE_SECP192R1;
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_2; if (use_km_key == 0) {
} conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1;
*len = 32; }
} else { *len = 24;
conf.curve = ECDSA_CURVE_SECP192R1; break;
if (use_km_key == 0) { case ECDSA_CURVE_SECP256R1:
conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; conf.curve = ECDSA_CURVE_SECP256R1;
} if (use_km_key == 0) {
*len = 24; 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();
@@ -227,30 +268,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)
@@ -265,13 +301,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));
} }
} }
@@ -280,7 +315,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);
} }
} }
@@ -289,23 +324,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
@@ -316,7 +351,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);
} }
} }
@@ -325,7 +360,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 */
@@ -336,30 +371,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();
@@ -97,10 +127,90 @@ 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)
{
#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES
esp_efuse_purpose_t expected_purpose;
esp_efuse_purpose_t actual_purpose;
switch (grp_id) {
case MBEDTLS_ECP_DP_SECP192R1:
expected_purpose = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P192;
actual_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)efuse_blk);
if (actual_purpose != expected_purpose) {
ESP_LOGE(TAG, "Efuse block %d has purpose %d, expected %d", efuse_blk, actual_purpose, expected_purpose);
return MBEDTLS_ERR_ECP_INVALID_KEY;
}
break;
case MBEDTLS_ECP_DP_SECP256R1:
expected_purpose = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256;
actual_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)efuse_blk);
if (actual_purpose != expected_purpose) {
ESP_LOGE(TAG, "Efuse block %d has purpose %d, expected %d", efuse_blk, actual_purpose, expected_purpose);
return MBEDTLS_ERR_ECP_INVALID_KEY;
}
break;
#if SOC_ECDSA_SUPPORT_CURVE_P384
case MBEDTLS_ECP_DP_SECP384R1:
int high_blk, low_blk;
MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk);
// For P384, we need to check both blocks
esp_efuse_purpose_t high_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)high_blk);
esp_efuse_purpose_t low_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk);
if (high_purpose != ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_H) {
ESP_LOGE(TAG, "Efuse block %d has purpose %d, expected P384_H (%d)",
high_blk, high_purpose, ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_H);
return MBEDTLS_ERR_ECP_INVALID_KEY;
}
if (low_purpose != ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_L) {
ESP_LOGE(TAG, "Efuse block %d has purpose %d, expected P384_L (%d)",
low_blk, low_purpose, ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_L);
return MBEDTLS_ERR_ECP_INVALID_KEY;
}
break;
#endif
default:
ESP_LOGE(TAG, "Invalid ECDSA curve id");
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#else /* SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
// For generic ECDSA key purpose, validate the single block (efuse_blk)
esp_efuse_purpose_t actual_purpose = esp_efuse_get_key_purpose((esp_efuse_block_t)efuse_blk);
if (actual_purpose != ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY) {
ESP_LOGE(TAG, "Efuse block %d has purpose %d, expected ECDSA_KEY (%d)",
efuse_blk, actual_purpose, ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY);
return MBEDTLS_ERR_ECP_INVALID_KEY;
}
#endif /* !SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
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];
@@ -113,14 +223,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;
MBEDTLS_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];
@@ -128,18 +240,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;
} }
} }
@@ -196,7 +315,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;
} }
@@ -215,8 +338,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"); MBEDTLS_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;
} }
} }
@@ -253,8 +379,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"); MBEDTLS_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;
} }
} }
@@ -285,7 +414,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;
@@ -314,10 +442,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];
@@ -325,17 +452,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;
} }
@@ -343,10 +482,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;
} }
} }
@@ -422,10 +562,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;
@@ -522,17 +662,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;
} }
@@ -877,23 +1029,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;
} }
@@ -953,9 +1117,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" {
@@ -19,6 +20,22 @@ extern "C" {
#define USE_ECDSA_KEY_FROM_KEY_MANAGER INT_MAX #define USE_ECDSA_KEY_FROM_KEY_MANAGER INT_MAX
/* ECDSA key block combination macros - aliases to HAL macros */
/**
* @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 more significant bits store the high key block number.
* @note example: HAL_ECDSA_COMBINE_KEY_BLOCKS(blk_high, blk_low)
*/
#define MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS HAL_ECDSA_COMBINE_KEY_BLOCKS
/**
* @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
* @note example: HAL_ECDSA_EXTRACT_KEY_BLOCKS(combined_blk, blk_high, blk_low)
*/
#define MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS HAL_ECDSA_EXTRACT_KEY_BLOCKS
/** /**
* @brief ECDSA private key context initialization config structure * @brief ECDSA private key context initialization config structure
* @note Contains configuration information like the efuse key block that should be used as the private key, * @note Contains configuration information like the efuse key block that should be used as the private key,
@@ -50,7 +67,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 MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in this header file.
* @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 +87,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 MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in this header file.
* *
* @return - 0 if successful * @return - 0 if successful
* - -1 otherwise * - -1 otherwise
@@ -86,7 +103,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 MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in this header file.
* *
* @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 = MBEDTLS_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 = MBEDTLS_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 = MBEDTLS_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

@@ -444,7 +444,8 @@
#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1)
#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,7 +94,7 @@ 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] efuse_blk. The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in esp_tls.h
*/ */
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);
#endif #endif

View File

@@ -22,6 +22,50 @@ 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
^^^^^^^^^^^^^^^^^
ECDSA private keys are stored in eFuse key blocks. The number of key blocks required depends on the curve size:
- **P-192 and P-256 curves**: Require one eFuse key block (256 bits)
- **P-384 curve**: Requires two eFuse key blocks (512 bits total)
When using the P-384 curve or any other curves that require two key blocks, you must use the appropriate macro to combine the block numbers into a single integer that the ECDSA peripheral can understand:
- **For mbedTLS applications**: Use :c:macro:`MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS` macro (defined in ``ecdsa/ecdsa_alt.h``)
- **For HAL applications**: Use :c:macro:`HAL_ECDSA_COMBINE_KEY_BLOCKS` macro (defined in ``hal/ecdsa_types.h``)
- **For ESP-TLS applications**: Use :c:macro:`ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS` macro (defined in ``esp_tls.h``)
You can also extract the individual block numbers using the corresponding extract macro:
- **For mbedTLS applications**: Use :c:macro:`MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS` macro
- **For HAL applications**: Use :c:macro:`HAL_ECDSA_EXTRACT_KEY_BLOCKS` macro
- **For ESP-TLS applications**: Use :c:macro:`ESP_TLS_ECDSA_EXTRACT_KEY_BLOCKS` macro
Here is an example of how to use these macros:
.. code-block:: c
#include "ecdsa/ecdsa_alt.h"
// Example: Using P-384 curve which requires two key blocks
// Assuming you want to use key blocks 4 and 5
uint8_t block_low = 4; // Lower key block
uint8_t block_high = 5; // Higher key block
// Combine the two block numbers into a single integer
// Note: First parameter is high block, second parameter is low block
uint16_t combined_blocks = MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS(block_high, block_low);
// Use the combined_blocks value in your ECDSA operations
// This value can be passed to mbedTLS ECDSA functions
// To extract the individual block numbers later
uint8_t extracted_block_low, extracted_block_high;
MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS(combined_blocks, &extracted_block_high, &extracted_block_low);
// extracted_block_low will be 4, extracted_block_high will be 5
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

@@ -22,6 +22,50 @@ ECDSA 外设可以为 TLS 双向身份验证等用例建立 **安全设备身份
在 {IDF_TARGET_NAME} 上ECDSA 模块使用烧录到 eFuse 块中的密钥。密码模块外的任何资源都不可访问此密钥(默认模式),从而避免密钥泄露。 在 {IDF_TARGET_NAME} 上ECDSA 模块使用烧录到 eFuse 块中的密钥。密码模块外的任何资源都不可访问此密钥(默认模式),从而避免密钥泄露。
ECDSA 密钥存储
^^^^^^^^^^^^^^
ECDSA 私钥存储在 eFuse 密钥块中。所需的密钥块数量取决于曲线大小:
- **P-192 和 P-256 曲线**:需要一个 eFuse 密钥块256 位)
- **P-384 曲线**:需要两个 eFuse 密钥块(总共 512 位)
使用 P-384 曲线或其他需要两个密钥块的曲线时,必须使用相应的宏将两个密钥块编号组合为一个整数,以便 ECDSA 外设能够识别:
- **对于 mbedTLS 应用程序**:使用 :c:macro:`MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS` 宏(定义在 ``ecdsa/ecdsa_alt.h`` 中)
- **对于 HAL 应用程序**:使用 :c:macro:`HAL_ECDSA_COMBINE_KEY_BLOCKS` 宏(定义在 ``hal/ecdsa_types.h`` 中)
- **对于 ESP-TLS 应用程序**:使用 :c:macro:`ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS` 宏(定义在 ``esp_tls.h`` 中)
你还可以使用相应的提取宏来获取各个密钥块编号:
- **对于 mbedTLS 应用程序**:使用 :c:macro:`MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS`
- **对于 HAL 应用程序**:使用 :c:macro:`HAL_ECDSA_EXTRACT_KEY_BLOCKS`
- **对于 ESP-TLS 应用程序**:使用 :c:macro:`ESP_TLS_ECDSA_EXTRACT_KEY_BLOCKS`
以下是使用这些宏的示例:
.. code-block:: c
#include "ecdsa/ecdsa_alt.h"
// 示例:使用需要两个密钥块的 P-384 曲线
// 假设要使用密钥块 4 和 5
uint8_t block_low = 4; // 较低编号的密钥块
uint8_t block_high = 5; // 较高编号的密钥块
// 将两个密钥块编号组合成一个整数
// 注意:第一个参数是高位块,第二个参数是低位块
uint16_t combined_blocks = MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS(block_high, block_low);
// 在 ECDSA 操作中使用 combined_blocks 值
// 此值可以传递给 mbedTLS ECDSA 函数
// 之后提取各个密钥块编号
uint8_t extracted_block_low, extracted_block_high;
MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS(combined_blocks, &extracted_block_high, &extracted_block_low);
// extracted_block_low 的值为 4extracted_block_high 的值为 5
ECDSA 密钥可以通过 ``idf.py`` 脚本在外部编程。以下是关于编程 ECDSA 密钥的示例: ECDSA 密钥可以通过 ``idf.py`` 脚本在外部编程。以下是关于编程 ECDSA 密钥的示例:
.. code:: bash .. code:: bash