diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 99c52a46b5..cbcb31681f 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -96,6 +96,16 @@ typedef enum { ESP_TLS_DYN_BUF_STRATEGY_MAX, /*!< to indicate max */ } 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 @@ -169,7 +179,11 @@ typedef struct esp_tls_cfg { 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 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 */ - 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 atecc608a chip */ diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index af789dc3f8..874866a18a 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -22,6 +22,7 @@ #include "esp_check.h" #include "mbedtls/esp_mbedtls_dynamic.h" #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +#include "mbedtls/ecp.h" #include "ecdsa/ecdsa_alt.h" #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 #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 */ 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 #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN 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 = { - .grp_id = MBEDTLS_ECP_DP_SECP256R1, + .grp_id = grp_id, .efuse_block = tls->ecdsa_efuse_blk, }; + ret = esp_ecdsa_set_pk_context(pki->pk_key, &conf); 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); @@ -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) { #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN 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; +#endif + tls->ecdsa_curve = cfg->ecdsa_curve; esp_tls_pki_t pki = { .public_cert = &tls->servercert, .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) { #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN 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; +#endif + tls->ecdsa_curve = cfg->ecdsa_curve; esp_tls_pki_t pki = { .public_cert = &tls->clientcert, .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"); 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 - 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 - 0 - }; ESP_LOGD(TAG, "Set the ciphersuites list"); mbedtls_ssl_conf_ciphersuites(&tls->conf, ecdsa_peripheral_supported_ciphersuites); diff --git a/components/esp-tls/private_include/esp_tls_private.h b/components/esp-tls/private_include/esp_tls_private.h index cb7be6ce8f..728b538d13 100644 --- a/components/esp-tls/private_include/esp_tls_private.h +++ b/components/esp-tls/private_include/esp_tls_private.h @@ -67,6 +67,7 @@ struct esp_tls { #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN 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. */ + esp_tls_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */ #endif #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. */ diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 7cb8201659..5e298e39a1 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -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)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)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 #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 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); +#endif + // Set the ECDSA curve + esp_transport_ssl_set_ecdsa_curve(ssl, config->ecdsa_curve); } #endif if (config->client_key_password && config->client_key_password_len > 0) { diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index de1aa8c889..06079629f0 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -97,6 +97,17 @@ typedef enum { 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 */ @@ -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) */ #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN 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 const char *user_agent; /*!< The User Agent string to send with HTTP requests */ esp_http_client_method_t method; /*!< HTTP Method */ diff --git a/components/esp_https_server/include/esp_https_server.h b/components/esp_https_server/include/esp_https_server.h index 6f4e59f1b2..e59052f075 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -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 */ @@ -100,9 +100,15 @@ struct httpd_ssl_config { /** Use ECDSA peripheral to use private key */ 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; + /** 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) */ httpd_ssl_transport_mode_t transport_mode; @@ -186,6 +192,8 @@ typedef struct httpd_ssl_config httpd_ssl_config_t; .prvtkey_len = 0, \ .use_ecdsa_peripheral = false, \ .ecdsa_key_efuse_blk = 0, \ + .ecdsa_key_efuse_blk_high = 0, \ + .ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, \ .transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \ .port_secure = 443, \ .port_insecure = 80, \ diff --git a/components/esp_https_server/src/https_server.c b/components/esp_https_server/src/https_server.c index b3d22e5346..5ae7213072 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -333,6 +333,10 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN (*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral; (*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 ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig."); ret = ESP_ERR_NOT_SUPPORTED; diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index c15c826e49..44b88a66c6 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -22,6 +22,9 @@ #define ECDSA_HAL_P192_COMPONENT_LEN 24 #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) { @@ -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, 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"); } @@ -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, 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"); } @@ -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 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"); } diff --git a/components/hal/esp32c5/include/hal/efuse_ll.h b/components/hal/esp32c5/include/hal/efuse_ll.h index d46c2c9309..7e0ae8f935 100644 --- a/components/hal/esp32c5/include/hal/efuse_ll.h +++ b/components/hal/esp32c5/include/hal/efuse_ll.h @@ -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) { + uint8_t efuse_blk_low = 0; + uint8_t efuse_blk_high = 0; + switch (curve) { case ECDSA_CURVE_SECP192R1: EFUSE.ecdsa.cfg_ecdsa_p192_blk = efuse_blk; @@ -103,6 +106,13 @@ __attribute__((always_inline)) static inline void efuse_ll_set_ecdsa_key_blk(ecd case ECDSA_CURVE_SECP256R1: EFUSE.ecdsa.cfg_ecdsa_p256_blk = efuse_blk; break; + case ECDSA_CURVE_SECP384R1: + // ECDSA-p384 uses two efuse blocks to store the key. These two blocks are stored in a single integer + // where the least significant 4 bits store the low key block number and the next 4 more significant bits store the high key block number. + HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, efuse_blk_high, efuse_blk_low); + EFUSE.ecdsa.cfg_ecdsa_p384_h_blk = efuse_blk_high; + EFUSE.ecdsa.cfg_ecdsa_p384_l_blk = efuse_blk_low; + break; default: HAL_ASSERT(false && "Unsupported curve"); break; diff --git a/components/hal/include/hal/ecdsa_hal.h b/components/hal/include/hal/ecdsa_hal.h index ec654a0b61..41722808cd 100644 --- a/components/hal/include/hal/ecdsa_hal.h +++ b/components/hal/include/hal/ecdsa_hal.h @@ -40,7 +40,7 @@ typedef struct { ecdsa_mode_t mode; /* Mode of operation */ ecdsa_curve_t curve; /* Curve to use for operation */ 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 */ 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. diff --git a/components/hal/include/hal/ecdsa_types.h b/components/hal/include/hal/ecdsa_types.h index 20caf84a1f..4a4be050bf 100644 --- a/components/hal/include/hal/ecdsa_types.h +++ b/components/hal/include/hal/ecdsa_types.h @@ -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 */ @@ -48,6 +48,21 @@ typedef enum { #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ } 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 } #endif diff --git a/components/hal/include/hal/efuse_hal.h b/components/hal/include/hal/efuse_hal.h index b99baa0a0b..c18cdd2d97 100644 --- a/components/hal/include/hal/efuse_hal.h +++ b/components/hal/include/hal/efuse_hal.h @@ -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 * * @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); #endif diff --git a/components/hal/test_apps/crypto/README.md b/components/hal/test_apps/crypto/README.md index 3a5209893e..a9bc97c10f 100644 --- a/components/hal/test_apps/crypto/README.md +++ b/components/hal/test_apps/crypto/README.md @@ -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 -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`. diff --git a/components/hal/test_apps/crypto/main/Kconfig.projbuild b/components/hal/test_apps/crypto/main/Kconfig.projbuild index 3e0c441589..ff8977805f 100644 --- a/components/hal/test_apps/crypto/main/Kconfig.projbuild +++ b/components/hal/test_apps/crypto/main/Kconfig.projbuild @@ -22,7 +22,7 @@ menu "Test App Configuration" Enabling this option includes HMAC Peripheral related test cases in the build for supported targets. 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" default n help diff --git a/components/hal/test_apps/crypto/main/ecdsa/ecdsa384_priv_key.pem b/components/hal/test_apps/crypto/main/ecdsa/ecdsa384_priv_key.pem new file mode 100644 index 0000000000..a87a45dbe1 --- /dev/null +++ b/components/hal/test_apps/crypto/main/ecdsa/ecdsa384_priv_key.pem @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDAlJNNxsYfk5Ljs1S+0A+F0bsbCBOYvEkGgHLe2GX8BZWvF/UcBQ/MC +qw2m/lFnDx+gBwYFK4EEACKhZANiAASuwiuzzbIJKY3lHflvXsUZx1txuxUGfudz +LZ6X0dM0DAfhk37MxXHli3veGelbkUX37qyRhGShPfNCznxwgfHRTBzEus0gR0hM +/KCjgiryPZfgI0t41sLOf4bJ1q6tvyk= +-----END EC PRIVATE KEY----- diff --git a/components/hal/test_apps/crypto/main/ecdsa/ecdsa_params.h b/components/hal/test_apps/crypto/main/ecdsa/ecdsa_params.h index 17f18c64b1..700ae3e828 100644 --- a/components/hal/test_apps/crypto/main/ecdsa/ecdsa_params.h +++ b/components/hal/test_apps/crypto/main/ecdsa/ecdsa_params.h @@ -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 */ @@ -20,27 +20,20 @@ const uint8_t ecc_p192_k[] = { 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 */ uint8_t ecdsa256_r[] = { - 0xff, 0x94, 0xf7, 0x5a, 0xce, 0x81, 0x05, 0xfc, - 0x98, 0x17, 0xd5, 0x0a, 0x94, 0x53, 0xab, 0x54, - 0xa8, 0x21, 0x8b, 0xe6, 0xf2, 0x6e, 0xa0, 0x7b, - 0x20, 0x36, 0x27, 0xd2, 0x60, 0x5d, 0xa3, 0x2e + 0x23, 0xc0, 0x94, 0xe5, 0x49, 0x17, 0xf4, 0x30, + 0x10, 0xa4, 0xa0, 0x53, 0x28, 0x8b, 0x87, 0xde, + 0xfc, 0x58, 0x9e, 0x64, 0x0b, 0x27, 0xe3, 0xb4, + 0x46, 0x6c, 0x24, 0x64, 0x0f, 0xe1, 0x3e, 0x97 }; /* Little endian */ uint8_t ecdsa256_s[] = { - 0x50, 0x78, 0x0e, 0x41, 0xe3, 0x03, 0xd2, 0x5b, - 0xaf, 0x74, 0x31, 0xb8, 0x74, 0xc9, 0xb3, 0x89, - 0x8d, 0xb5, 0x40, 0x3e, 0x5b, 0x2a, 0x4b, 0xe2, - 0x5e, 0xf8, 0x96, 0xd4, 0xf9, 0x22, 0xf9, 0xb4 + 0x98, 0x16, 0xf0, 0x9a, 0x8a, 0xf1, 0x8c, 0x8f, + 0x3b, 0xcb, 0x75, 0x78, 0x71, 0xc9, 0x98, 0x67, + 0x86, 0xf3, 0x05, 0x0c, 0x5a, 0xe3, 0x8d, 0xec, + 0x55, 0x6f, 0x3b, 0xab, 0xd5, 0x1b, 0xae, 0xb1 }; /* Little endian */ @@ -61,16 +54,16 @@ uint8_t ecdsa256_pub_y[] = { /* Little endian */ uint8_t ecdsa192_r[] = { - 0x9f, 0xee, 0xb7, 0x4f, 0x09, 0xd5, 0xc8, 0x42, - 0x2c, 0x74, 0xe7, 0xaa, 0x6d, 0xe2, 0xe1, 0x1c, - 0xb7, 0x26, 0x75, 0xb2, 0x2f, 0x18, 0x8a, 0x2b + 0x9c, 0xd0, 0xbc, 0x89, 0xbe, 0x77, 0x7e, 0x87, + 0x00, 0xfc, 0x20, 0x07, 0x2f, 0x2d, 0x46, 0xef, + 0xa2, 0x81, 0x29, 0x68, 0x95, 0x29, 0xc8, 0x90 }; /* Little endian */ uint8_t ecdsa192_s[] = { - 0x12, 0x5b, 0x30, 0x24, 0x59, 0x24, 0xeb, 0xf6, - 0x2f, 0x06, 0x60, 0xa8, 0xff, 0xa5, 0xed, 0xce, - 0xb6, 0xa5, 0x28, 0xf4, 0x05, 0xb4, 0x74, 0x1a + 0x46, 0x46, 0x2b, 0xfa, 0x9e, 0x0e, 0xb2, 0x74, + 0x57, 0xd6, 0xb2, 0xea, 0xbd, 0x76, 0xc1, 0x3b, + 0x11, 0x8a, 0x5b, 0xb6, 0xc5, 0x84, 0xb1, 0x1e }; /* Little endian */ @@ -86,3 +79,53 @@ uint8_t ecdsa192_pub_y[] = { 0xde, 0xc2, 0xdc, 0x74, 0xf3, 0xfd, 0x09, 0x74, 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, +}; diff --git a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c index 16dfefc473..7e78cacb30 100644 --- a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c +++ b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c @@ -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; - uint8_t sha_le[32]; + uint16_t len = 0; + uint8_t sha_le[48]; ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_SIGN_VERIFY, .sha_mode = ECDSA_Z_USER_PROVIDED, }; - if (is_p256) { - conf.curve = ECDSA_CURVE_SECP256R1; - len = 32; - } else { - conf.curve = ECDSA_CURVE_SECP192R1; - len = 24; + switch (curve) { + case ECDSA_CURVE_SECP192R1: + conf.curve = ECDSA_CURVE_SECP192R1; + 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 */ @@ -90,51 +101,53 @@ int test_ecdsa_verify(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, 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) { - len = 32; - } else { - len = 24; + switch (curve) { + case ECDSA_CURVE_SECP192R1: len = 24; break; + case ECDSA_CURVE_SECP256R1: len = 32; break; +#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 - uint16_t r_bit = esp_random() % len * 8; + uint16_t r_bit = esp_random() % (len * 8); printf("Corrupting SHA bit %d...\n", r_bit); 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); printf("Corrupting R bit %d...\n", r_bit); 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); printf("Corrupting S bit %d...\n", r_bit); 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); printf("Corrupting pub_x bit %d...\n", r_bit); 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); printf("Corrupting pub_y bit %d...\n", r_bit); 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); - } -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 zeroes[32] = {0}; - uint16_t len; + uint8_t sha_le[48] = {0}; + uint8_t zeroes[48] = {0}; + uint16_t len = 0; #if !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP 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, .sign_type = k_type, }; - - if (is_p256) { - 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; - if (use_km_key == 0) { - conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; - } - len = 24; + switch (curve) { + case ECDSA_CURVE_SECP192R1: + conf.curve = ECDSA_CURVE_SECP192R1; + if (use_km_key == 0) { + conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; + } + 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 */ @@ -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(); } #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ - } while(process_again); 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 s_le[32] = {0}; - - test_ecdsa_sign(is_p256, sha, r_le, s_le, use_km_key, k_type); - TEST_ASSERT_EQUAL(0, test_ecdsa_verify(is_p256, sha, r_le, s_le, pub_x, pub_y)); + uint8_t r_le[48] = {0}; + uint8_t s_le[48] = {0}; + test_ecdsa_sign(curve, 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)); } #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[32] = {0}; + uint8_t zeroes[48] = {0}; ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_EXPORT_PUBKEY, .use_km_key = use_km_key, }; - if (is_p256) { - 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; - if (use_km_key == 0) { - conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; - } - *len = 24; + switch (curve) { + case ECDSA_CURVE_SECP192R1: + conf.curve = ECDSA_CURVE_SECP192R1; + if (use_km_key == 0) { + conf.efuse_key_blk = EFUSE_BLK_KEY0 + ECDSA_KEY_BLOCK_1; + } + *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(); @@ -231,30 +272,25 @@ void test_ecdsa_export_pubkey_inner(bool is_p256, uint8_t *exported_pub_x, uint8 do { ecdsa_hal_export_pubkey(&conf, exported_pub_x, exported_pub_y, *len); - process_again = !ecdsa_hal_get_operation_result() || !memcmp(exported_pub_x, zeroes, *len) || !memcmp(exported_pub_y, zeroes, *len); - } while (process_again); ecdsa_disable(); } - -void test_ecdsa_export_pubkey(bool is_p256, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key) +void test_ecdsa_export_pubkey(ecdsa_curve_t curve, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key) { - uint8_t pub_x[32] = {0}; - uint8_t pub_y[32] = {0}; + uint8_t pub_x[48] = {0}; + uint8_t pub_y[48] = {0}; 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_y, pub_y, len); - } #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ - TEST_GROUP(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(ecdsa, ecdsa_SECP192R1_signature_verification) { if (!esp_efuse_is_ecdsa_p192_curve_supported()) { ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); } 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()) { ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); } 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()) { ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); } 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_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_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_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 @@ -320,7 +355,7 @@ TEST(ecdsa, ecdsa_SECP192R1_det_sign_and_verify) } else if (!esp_efuse_is_ecdsa_p192_curve_supported()) { ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); } 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()) { ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported."); } 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 */ @@ -340,30 +375,81 @@ TEST(ecdsa, ecdsa_SECP192R1_export_pubkey) if (!esp_efuse_is_ecdsa_p192_curve_supported()) { ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); } 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_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 */ +#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) { + /* SECP192R1 test cases */ RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_signature_verification) RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_sign_and_verify) 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_sign_and_verify) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_corrupt_signature) #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) #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY - RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_export_pubkey) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_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 */ } diff --git a/components/hal/test_apps/crypto/main/hal_crypto_common.h b/components/hal/test_apps/crypto/main/hal_crypto_common.h index da8b073faa..1626f0a7b1 100644 --- a/components/hal/test_apps/crypto/main/hal_crypto_common.h +++ b/components/hal/test_apps/crypto/main/hal_crypto_common.h @@ -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 */ @@ -10,14 +10,16 @@ #define DS_KEY_BLOCK_2 1 #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 #define HMAC_KEY_BLOCK_1 4 #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 diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index 0fb481ea94..973cf8e114 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -27,6 +27,7 @@ #include "hal/ecdsa_ll.h" #include "hal/ecdsa_hal.h" #include "esp_efuse.h" +#include "esp_efuse_chip.h" #endif #if SOC_ECC_SUPPORTED #include "hal/ecc_ll.h" @@ -37,8 +38,24 @@ #define ECDSA_KEY_MAGIC (short) 0xECD5A #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_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 #include "esp_timer.h" @@ -67,6 +84,19 @@ __attribute__((unused)) static const char *TAG = "ecdsa_alt"; #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) { esp_crypto_ecdsa_lock_acquire(); @@ -101,10 +131,74 @@ static void esp_ecdsa_release_hardware(void) } #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) { /* 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++) { 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; bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; 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"); return ret; } } ecdsa_curve_t curve; - esp_efuse_block_t blk; uint16_t len; uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; 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) { curve = ECDSA_CURVE_SECP192R1; - len = 24; + len = ECDSA_KEY_LEN_P192; } else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) { curve = ECDSA_CURVE_SECP256R1; - len = 32; - } else { + len = ECDSA_KEY_LEN_P256; + } +#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; } if (!use_km_key) { - if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, &blk)) { - ESP_LOGE(TAG, "No efuse block with purpose ECDSA_KEY found"); - return MBEDTLS_ERR_ECP_INVALID_KEY; + ret = esp_ecdsa_validate_efuse_block(keypair->MBEDTLS_PRIVATE(grp).id, efuse_blk); + if (ret != 0) { + return ret; } } @@ -200,7 +303,11 @@ static int validate_ecdsa_pk_input(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_con 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"); 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; if (!use_km_key) { - if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { - ESP_LOGE(TAG, "Invalid efuse block"); + 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"); 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; if (!use_km_key) { - if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { - ESP_LOGE(TAG, "Invalid efuse block"); + 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"); 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; } - 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); 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_curve_t curve; - esp_efuse_block_t blk; uint16_t len; uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; - uint8_t sha_le[ECDSA_SHA_LEN]; + uint8_t sha_le[MAX_ECDSA_SHA_LEN]; uint8_t r_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; } - 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; } if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { curve = ECDSA_CURVE_SECP192R1; - len = 24; + len = ECDSA_KEY_LEN_P192; } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { curve = ECDSA_CURVE_SECP256R1; - len = 32; - } else { + len = ECDSA_KEY_LEN_P256; + } +#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; } @@ -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) { use_km_key = true; } + if (!use_km_key) { - if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, &blk)) { - ESP_LOGE(TAG, "No efuse block with purpose ECDSA_KEY found"); - return MBEDTLS_ERR_ECP_INVALID_KEY; + int ret = esp_ecdsa_validate_efuse_block(grp->id, d->MBEDTLS_PRIVATE(n)); + if (ret != 0) { + 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; 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; } 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; } else { 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; } - 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; } if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { - len = 32; + len = ECDSA_KEY_LEN_P256; key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; } else if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { - len = 24; + len = ECDSA_KEY_LEN_P192; 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; } @@ -881,23 +1017,35 @@ static int esp_ecdsa_verify(mbedtls_ecp_group *grp, uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN]; uint8_t qy_le[MAX_ECDSA_COMPONENT_LEN]; - uint8_t sha_le[ECDSA_SHA_LEN]; + uint8_t sha_le[MAX_ECDSA_SHA_LEN]; if (!grp || !buf || !Q || !r || !s) { 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; } if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { curve = ECDSA_CURVE_SECP192R1; - len = 24; + len = ECDSA_KEY_LEN_P192; } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { curve = ECDSA_CURVE_SECP256R1; - len = 32; - } else { + len = ECDSA_KEY_LEN_P256; + } +#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; } @@ -957,9 +1105,12 @@ int __wrap_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, const mbedtls_mpi *s, mbedtls_ecdsa_restart_ctx *rs_ctx) { - if (((grp->id == MBEDTLS_ECP_DP_SECP192R1 && esp_efuse_is_ecdsa_p192_curve_supported()) - || (grp->id == MBEDTLS_ECP_DP_SECP256R1 && esp_efuse_is_ecdsa_p256_curve_supported())) - && blen == ECDSA_SHA_LEN) { + if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && blen == ECDSA_SHA_LEN && esp_efuse_is_ecdsa_p192_curve_supported()) || + (grp->id == MBEDTLS_ECP_DP_SECP256R1 && blen == ECDSA_SHA_LEN && esp_efuse_is_ecdsa_p256_curve_supported()) +#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); } else { return __real_mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, rs_ctx); diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h index 81e51d7bb5..b2b8f3a65a 100644 --- a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h +++ b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h @@ -12,6 +12,7 @@ #include "mbedtls/pk.h" #include "sdkconfig.h" #include "soc/soc_caps.h" +#include "hal/ecdsa_types.h" #ifdef __cplusplus extern "C" { @@ -50,7 +51,7 @@ typedef struct { * * @param keypair The mbedtls ECP key-pair structure * @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 * - 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 @@ -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. * This must be uninitialized * @param efuse_blk The efuse key block that should be used as the private key. - * The key purpose of this block must be ECDSA_KEY + * 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 * - -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. * This must be uninitialized * @param efuse_blk The efuse key block that should be used as the private key. - * The key purpose of this block must be ECDSA_KEY + * 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 * - -1 otherwise diff --git a/components/mbedtls/test_apps/ecdsa_key_p384.pem b/components/mbedtls/test_apps/ecdsa_key_p384.pem new file mode 100644 index 0000000000..a87a45dbe1 --- /dev/null +++ b/components/mbedtls/test_apps/ecdsa_key_p384.pem @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDAlJNNxsYfk5Ljs1S+0A+F0bsbCBOYvEkGgHLe2GX8BZWvF/UcBQ/MC +qw2m/lFnDx+gBwYFK4EEACKhZANiAASuwiuzzbIJKY3lHflvXsUZx1txuxUGfudz +LZ6X0dM0DAfhk37MxXHli3veGelbkUX37qyRhGShPfNCznxwgfHRTBzEus0gR0hM +/KCjgiryPZfgI0t41sLOf4bJ1q6tvyk= +-----END EC PRIVATE KEY----- diff --git a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c index 8cdc46fc73..71823376a1 100644 --- a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c +++ b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c @@ -44,6 +44,22 @@ #define NEWLIB_NANO_COMPAT_CAST(int64_t_var) int64_t_var #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"; /* @@ -51,52 +67,94 @@ __attribute__((unused)) static const char * TAG = "mbedtls_test"; */ const 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 + 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 }; #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[] = { - 0x26, 0x1a, 0x0f, 0xbd, 0xa5, 0xe5, 0x1e, 0xe7, - 0xb3, 0xc3, 0xb7, 0x09, 0xd1, 0x4a, 0x7a, 0x2a, - 0x16, 0x69, 0x4b, 0xaf, 0x76, 0x5c, 0xd4, 0x0e, - 0x93, 0x57, 0xb8, 0x67, 0xf9, 0xa1, 0xe5, 0xe8 + 0x97, 0x3e, 0xe1, 0x0f, 0x64, 0x24, 0x6c, 0x46, + 0xb4, 0xe3, 0x27, 0x0b, 0x64, 0x9e, 0x58, 0xfc, + 0xde, 0x87, 0x8b, 0x28, 0x53, 0xa0, 0xa4, 0x10, + 0x30, 0xf4, 0x17, 0x49, 0xe5, 0x94, 0xc0, 0x23 }; const uint8_t ecdsa256_s[] = { - 0x63, 0x59, 0xc0, 0x3b, 0x6a, 0xc2, 0xc4, 0xc4, - 0xaf, 0x47, 0x5c, 0xe6, 0x6d, 0x43, 0x3b, 0xa7, - 0x91, 0x51, 0x15, 0x62, 0x7e, 0x46, 0x0e, 0x68, - 0x84, 0xce, 0x72, 0xa0, 0xd8, 0x8b, 0x69, 0xd5 + 0xb1, 0xae, 0x1b, 0xd5, 0xab, 0x3b, 0x6f, 0x55, + 0xec, 0x8d, 0xe3, 0x5a, 0x0c, 0x05, 0xf3, 0x86, + 0x67, 0x98, 0xc9, 0x71, 0x78, 0x75, 0xcb, 0x3b, + 0x8f, 0x8c, 0xf1, 0x8a, 0x9a, 0xf0, 0x16, 0x98 }; const uint8_t ecdsa256_pub_x[] = { - 0xcb, 0x59, 0xde, 0x9c, 0xbb, 0x28, 0xaa, 0xac, - 0x72, 0x06, 0xc3, 0x43, 0x2a, 0x65, 0x82, 0xcc, - 0x68, 0x01, 0x76, 0x68, 0xfc, 0xec, 0xf5, 0x91, - 0xd1, 0x9e, 0xbf, 0xcf, 0x67, 0x7d, 0x7d, 0xbe + 0x4d, 0xdf, 0x64, 0x1f, 0xd8, 0x6e, 0xd4, 0x8b, + 0xa7, 0xca, 0x04, 0xc7, 0x11, 0xb8, 0x45, 0xda, + 0x0c, 0xff, 0x5f, 0x7a, 0xce, 0x5a, 0x11, 0xf9, + 0x95, 0x55, 0x08, 0x26, 0x85, 0x88, 0xe9, 0xa8 }; const uint8_t ecdsa256_pub_y[] = { - 0x00, 0x66, 0x14, 0x74, 0xe0, 0x06, 0x44, 0x66, - 0x6f, 0x3b, 0x8c, 0x3b, 0x2d, 0x05, 0xf6, 0xd5, - 0xb2, 0x5d, 0xe4, 0x85, 0x6c, 0x61, 0x38, 0xc5, - 0xb1, 0x21, 0xde, 0x2b, 0x44, 0xf5, 0x13, 0x62 + 0x24, 0xb0, 0x4d, 0xcc, 0xbf, 0xce, 0x9a, 0x6e, + 0xa0, 0x8a, 0xb6, 0x1a, 0x40, 0xf2, 0x71, 0x6a, + 0x50, 0xa8, 0xfd, 0xaa, 0x2c, 0x80, 0xa0, 0xbc, + 0x73, 0xa1, 0xe8, 0xec, 0xaf, 0x2c, 0x25, 0x34 }; + const uint8_t ecdsa192_r[] = { - 0x2b, 0x8a, 0x18, 0x2f, 0xb2, 0x75, 0x26, 0xb7, - 0x1c, 0xe1, 0xe2, 0x6d, 0xaa, 0xe7, 0x74, 0x2c, - 0x42, 0xc8, 0xd5, 0x09, 0x4f, 0xb7, 0xee, 0x9f + 0x90, 0xc8, 0x29, 0x95, 0x68, 0x29, 0x81, 0xa2, + 0xef, 0x46, 0x2d, 0x2f, 0x07, 0x20, 0xfc, 0x00, + 0x87, 0x7e, 0x77, 0xbe, 0x89, 0xbc, 0xd0, 0x9c }; const uint8_t ecdsa192_s[] = { - 0x1a, 0x74, 0xb4, 0x5, 0xf4, 0x28, 0xa5, 0xb6, - 0xce, 0xed, 0xa5, 0xff, 0xa8, 0x60, 0x06, 0x2f, - 0xf6, 0xeb, 0x24, 0x59, 0x24, 0x30, 0x5b, 0x12 + 0x1e, 0xb1, 0x84, 0xc5, 0xb6, 0x5b, 0x8a, 0x11, + 0x3b, 0xc1, 0x76, 0xbd, 0xea, 0xb2, 0xd6, 0x57, + 0x74, 0xb2, 0x0e, 0x9e, 0xfa, 0x2b, 0x46, 0x46 }; 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, const uint8_t *pub_x, const uint8_t *pub_y) { + size_t hash_len = HASH_LEN; int64_t elapsed_time; 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); 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(&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_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(); - 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(); 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) { 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(&s); @@ -161,6 +233,14 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbe 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 */ #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_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 SECP256R1_EFUSE_BLOCK 5 // EFUSE_BLK_KEY1 - -#define MAX_ECDSA_COMPONENT_LEN 32 -#define HASH_LEN 32 +#define SECP384R1_EFUSE_BLOCK_HIGH 6 // EFUSE_BLK_KEY2 +#define SECP384R1_EFUSE_BLOCK_LOW 7 // EFUSE_BLK_KEY3 const uint8_t ecdsa256_sign_pub_x[] = { 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) { + size_t hash_len = HASH_LEN; uint8_t r_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) { 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); + 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) { - 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 { - 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); @@ -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) { // 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) { + 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); } +#endif mbedtls_mpi_free(&r); 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); } +#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 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 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 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_y[32] = {0}; + uint8_t export_pub_x[48] = {0}; + uint8_t export_pub_y[48] = {0}; int len = 0; 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) { len = 32; } +#if SOC_ECDSA_SUPPORT_CURVE_P384 + else if (id == MBEDTLS_ECP_DP_SECP384R1) { + len = 48; + } +#endif 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); } +#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 TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][key_manager_key]") { diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index e1bb6ba015..5332e01137 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1131,6 +1131,10 @@ config SOC_ECDSA_SUPPORT_CURVE_P384 bool default y +config SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES + bool + default y + config SOC_SPI_PERIPH_NUM int default 2 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 4570f17d22..e20b1f6587 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -444,7 +444,8 @@ #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) #define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1) #define SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP (1) -#define SOC_ECDSA_SUPPORT_CURVE_P384 (1) +#define SOC_ECDSA_SUPPORT_CURVE_P384 (1) +#define SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES (1) /*!< Support individual key purposes for different ECDSA curves (P192, P256, P384) */ /*-------------------------- SPI CAPS ----------------------------------------*/ #define SOC_SPI_PERIPH_NUM 2 diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index 5e4af089ed..4dcd5c1338 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -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. * * @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); + +#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 /** diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index f3ad2b4e22..517f0982fb 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -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.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 void esp_transport_ssl_set_client_cert_data_der(esp_transport_handle_t t, const char *data, int len) diff --git a/docs/en/api-reference/peripherals/ecdsa.rst b/docs/en/api-reference/peripherals/ecdsa.rst index 0e872df586..6a9570d432 100644 --- a/docs/en/api-reference/peripherals/ecdsa.rst +++ b/docs/en/api-reference/peripherals/ecdsa.rst @@ -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. +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: .. code:: bash diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index 870c508aa1..e463eb95b4 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -44,6 +44,21 @@ A secure element (ATECC608) can be also used for the underlying TLS connection i .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 ` 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 ------------- diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index b6937144cd..0e5c9a0420 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -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. - 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 needs not be supplied to the :cpp:type:`esp_tls_cfg_t` structure. + 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. .. code-block:: c #include "esp_tls.h" esp_tls_cfg_t cfg = { .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:: diff --git a/docs/zh_CN/api-reference/peripherals/ecdsa.rst b/docs/zh_CN/api-reference/peripherals/ecdsa.rst index 9783176b5e..e85ff51032 100644 --- a/docs/zh_CN/api-reference/peripherals/ecdsa.rst +++ b/docs/zh_CN/api-reference/peripherals/ecdsa.rst @@ -22,6 +22,31 @@ ECDSA 外设可以为 TLS 双向身份验证等用例建立 **安全设备身份 在 {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 密钥的示例: .. code:: bash diff --git a/docs/zh_CN/api-reference/protocols/esp_http_client.rst b/docs/zh_CN/api-reference/protocols/esp_http_client.rst index e0db0f561b..5a6ff5852a 100644 --- a/docs/zh_CN/api-reference/protocols/esp_http_client.rst +++ b/docs/zh_CN/api-reference/protocols/esp_http_client.rst @@ -44,6 +44,21 @@ HTTP 基本请求 .use_secure_element = true, }; +为 TLS 使用 ECDSA 外设 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +ECDSA 外设可用于 HTTP 客户端连接中的底层 TLS 连接。详细内容请参考 :doc:`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 请求 ----------- diff --git a/docs/zh_CN/api-reference/protocols/esp_tls.rst b/docs/zh_CN/api-reference/protocols/esp_tls.rst index 1d637d58a4..6eaded65ee 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -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 中启用 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`。 .. code-block:: c @@ -226,7 +224,9 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须 #include "esp_tls.h" esp_tls_cfg_t cfg = { .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::