From 68f06a94bd26864657434c780d6cf94b8c76eef0 Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Fri, 23 May 2025 14:23:17 +0530 Subject: [PATCH 1/3] feat: add ecdsa-p384 testcases and relative support for ESP32C5 ECO2 This commit adds testcases in crypto/hal and mbedtls testapps. --- components/esp-tls/CMakeLists.txt | 2 +- components/esp-tls/esp_tls.h | 20 +- components/esp-tls/esp_tls_mbedtls.c | 111 +++++++- .../esp_http_client/include/esp_http_client.h | 2 +- .../include/esp_https_server.h | 2 +- components/hal/ecdsa_hal.c | 21 +- components/hal/esp32c5/include/hal/efuse_ll.h | 10 + components/hal/include/hal/ecdsa_hal.h | 2 +- components/hal/include/hal/ecdsa_types.h | 17 +- components/hal/include/hal/efuse_hal.h | 3 +- components/hal/test_apps/crypto/README.md | 2 +- .../test_apps/crypto/main/Kconfig.projbuild | 2 +- .../crypto/main/ecdsa/ecdsa384_priv_key.pem | 6 + .../crypto/main/ecdsa/ecdsa_params.h | 87 ++++-- .../test_apps/crypto/main/ecdsa/test_ecdsa.c | 252 ++++++++++++------ .../test_apps/crypto/main/hal_crypto_common.h | 20 +- components/mbedtls/port/ecdsa/ecdsa_alt.c | 245 ++++++++++++++--- .../mbedtls/port/include/ecdsa/ecdsa_alt.h | 23 +- .../mbedtls/test_apps/ecdsa_key_p384.pem | 6 + .../test_apps/main/test_mbedtls_ecdsa.c | 202 +++++++++++--- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c5/include/soc/soc_caps.h | 3 +- .../tcp_transport/include/esp_transport_ssl.h | 2 +- docs/en/api-reference/peripherals/ecdsa.rst | 44 +++ .../zh_CN/api-reference/peripherals/ecdsa.rst | 44 +++ 25 files changed, 919 insertions(+), 213 deletions(-) create mode 100644 components/hal/test_apps/crypto/main/ecdsa/ecdsa384_priv_key.pem create mode 100644 components/mbedtls/test_apps/ecdsa_key_p384.pem diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt index 3809b6473b..f2d01bc272 100644 --- a/components/esp-tls/CMakeLists.txt +++ b/components/esp-tls/CMakeLists.txt @@ -19,7 +19,7 @@ idf_component_register(SRCS "${srcs}" PRIV_INCLUDE_DIRS "private_include" # mbedtls is public requirements because esp_tls.h # includes mbedtls header files. - REQUIRES mbedtls + REQUIRES mbedtls efuse PRIV_REQUIRES ${priv_req}) if(CONFIG_ESP_TLS_USING_WOLFSSL) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 99c52a46b5..9d0bd63f39 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -28,6 +28,22 @@ extern "C" { #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 */ @@ -169,7 +185,7 @@ 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. 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 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 */ - 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 atecc608a chip */ diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index af789dc3f8..dcd3514fda 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -22,6 +22,9 @@ #include "esp_check.h" #include "mbedtls/esp_mbedtls_dynamic.h" #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +#include "mbedtls/ecp.h" +#include "esp_efuse.h" +#include "esp_efuse_chip.h" #include "ecdsa/ecdsa_alt.h" #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 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 #define NEWLIB_NANO_SSIZE_T_COMPAT_FORMAT "X" #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 #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN 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 = { - .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); @@ -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"); 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 - 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 - }; + 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"); mbedtls_ssl_conf_ciphersuites(&tls->conf, ecdsa_peripheral_supported_ciphersuites); diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index b707a22c03..f057b373b3 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -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) */ #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. 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 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..a7b143c72e 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -100,7 +100,7 @@ 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. 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; /** Transport Mode (default secure) */ diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index 2c7f607d7c..a8a5cb4e47 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 3053286a5b..e978b69498 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..5aed889dd5 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 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 } #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 6438ede5a5..a1ed078b74 100644 --- a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c +++ b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c @@ -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; - 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 */ @@ -86,51 +97,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; @@ -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, .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 */ @@ -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(); } #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(); @@ -227,30 +268,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) @@ -265,13 +301,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)); } } @@ -280,7 +315,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); } } @@ -289,23 +324,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 @@ -316,7 +351,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); } } @@ -325,7 +360,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 */ @@ -336,30 +371,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 bb3c1623e3..ae7fc8ef1c 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(); @@ -97,10 +127,90 @@ 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) +{ +#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) { /* 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]; @@ -113,14 +223,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; + 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 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]; @@ -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) { 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; } } @@ -196,7 +315,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; } @@ -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; 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; + 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; } } @@ -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; 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; + 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; } } @@ -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; } - 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; @@ -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_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]; @@ -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; } - 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; } @@ -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) { 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; } } @@ -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; 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; @@ -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; } - 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; } @@ -877,23 +1029,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; } @@ -953,9 +1117,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..72bd48605a 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" { @@ -19,6 +20,22 @@ extern "C" { #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 * @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 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 * - 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 +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. * 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 MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in this header file. * * @return - 0 if successful * - -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. * 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 MBEDTLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in this header file. * * @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..aa7f1bbc0a 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 = 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 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 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 = 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 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 ad32bd89e7..74256c6dd9 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 1cacb6a7bf..acfb529f9e 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..d26e6b3333 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -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. * * @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); #endif diff --git a/docs/en/api-reference/peripherals/ecdsa.rst b/docs/en/api-reference/peripherals/ecdsa.rst index 0e872df586..e646d7d255 100644 --- a/docs/en/api-reference/peripherals/ecdsa.rst +++ b/docs/en/api-reference/peripherals/ecdsa.rst @@ -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. +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: .. code:: bash diff --git a/docs/zh_CN/api-reference/peripherals/ecdsa.rst b/docs/zh_CN/api-reference/peripherals/ecdsa.rst index 9783176b5e..899f766620 100644 --- a/docs/zh_CN/api-reference/peripherals/ecdsa.rst +++ b/docs/zh_CN/api-reference/peripherals/ecdsa.rst @@ -22,6 +22,50 @@ ECDSA 外设可以为 TLS 双向身份验证等用例建立 **安全设备身份 在 {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 的值为 4,extracted_block_high 的值为 5 + ECDSA 密钥可以通过 ``idf.py`` 脚本在外部编程。以下是关于编程 ECDSA 密钥的示例: .. code:: bash From 08e781c876a0d139a246a206913ebfcb3d4ae774 Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Mon, 14 Jul 2025 13:49:36 +0530 Subject: [PATCH 2/3] feat: added new config member to provide ecdsa curve type --- components/esp-tls/esp_tls.h | 11 ++ components/esp-tls/esp_tls_mbedtls.c | 120 ++++++------------ .../esp-tls/private_include/esp_tls_private.h | 2 + components/esp_http_client/CMakeLists.txt | 2 +- components/esp_http_client/esp_http_client.c | 2 + .../esp_http_client/include/esp_http_client.h | 2 + .../include/esp_https_server.h | 4 + .../esp_https_server/src/https_server.c | 1 + .../tcp_transport/include/esp_transport_ssl.h | 8 ++ components/tcp_transport/transport_ssl.c | 6 + .../protocols/esp_http_client.rst | 14 ++ docs/en/api-reference/protocols/esp_tls.rst | 3 +- docs/en/api-reference/protocols/mqtt.rst | 3 + .../protocols/esp_http_client.rst | 14 ++ .../zh_CN/api-reference/protocols/esp_tls.rst | 3 +- docs/zh_CN/api-reference/protocols/mqtt.rst | 3 + 16 files changed, 114 insertions(+), 84 deletions(-) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 9d0bd63f39..dd97ec97d7 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -112,6 +112,13 @@ 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 */ + ESP_TLS_ECDSA_CURVE_SECP384R1, /*!< Use SECP384R1 curve */ +} esp_tls_ecdsa_curve_t; /** * @brief ESP-TLS configuration parameters @@ -187,6 +194,8 @@ typedef struct esp_tls_cfg { 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. */ + 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 blocking mode after tls session is established */ @@ -331,6 +340,8 @@ typedef struct esp_tls_cfg_server { 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. */ + 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 dcd3514fda..6cb9c2a87f 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -51,78 +51,6 @@ static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki); static const char *TAG = "esp-tls-mbedtls"; 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 #define NEWLIB_NANO_SSIZE_T_COMPAT_FORMAT "X" #define NEWLIB_NANO_SIZE_T_COMPAT_FORMAT PRIu32 @@ -133,6 +61,34 @@ static mbedtls_ecp_group_id esp_tls_get_curve_from_efuse_block(uint8_t efuse_blk #define NEWLIB_NANO_SIZE_T_COMPAT_CAST(size_t_var) size_t_var #endif +#if 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) +{ + if (grp_id == NULL) { + return ESP_ERR_INVALID_ARG; + } + + 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: + ESP_LOGE(TAG, "Invalid ECDSA curve specified: %d", curve); + 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) { @@ -636,11 +592,11 @@ 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 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; + // 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 = { @@ -833,6 +789,7 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral; tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk; + tls->ecdsa_curve = cfg->ecdsa_curve; esp_tls_pki_t pki = { .public_cert = &tls->servercert, .pk_key = &tls->serverkey, @@ -1080,6 +1037,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral; tls->ecdsa_efuse_blk = cfg->ecdsa_key_efuse_blk; + tls->ecdsa_curve = cfg->ecdsa_curve; esp_tls_pki_t pki = { .public_cert = &tls->clientcert, .pk_key = &tls->clientkey, @@ -1096,10 +1054,10 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t return esp_ret; } - 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; + 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 diff --git a/components/esp-tls/private_include/esp_tls_private.h b/components/esp-tls/private_include/esp_tls_private.h index cb7be6ce8f..8bba630972 100644 --- a/components/esp-tls/private_include/esp_tls_private.h +++ b/components/esp-tls/private_include/esp_tls_private.h @@ -15,6 +15,7 @@ #include #include "esp_err.h" #include "esp_tls_errors.h" +#include "esp_tls.h" #ifdef CONFIG_ESP_TLS_USING_MBEDTLS #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" @@ -67,6 +68,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/CMakeLists.txt b/components/esp_http_client/CMakeLists.txt index 4a353e33ca..ebdcc4ef08 100644 --- a/components/esp_http_client/CMakeLists.txt +++ b/components/esp_http_client/CMakeLists.txt @@ -1,5 +1,5 @@ if(NOT ${IDF_TARGET} STREQUAL "linux") - set(req lwip esp_event) + set(req lwip esp_event esp-tls) else() set(req linux esp_event) endif() diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index a5e0c7f6d1..fac636d1c7 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -928,6 +928,8 @@ 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) { esp_transport_ssl_set_client_key_ecdsa_peripheral(ssl, config->ecdsa_key_efuse_blk); + // 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 f057b373b3..2acb9d448f 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -11,6 +11,7 @@ #include "sdkconfig.h" #include "esp_err.h" #include +#include "esp_tls.h" #ifdef __cplusplus extern "C" { @@ -179,6 +180,7 @@ typedef struct { #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. 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 */ + esp_tls_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 a7b143c72e..20ec2624b8 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -103,6 +103,9 @@ struct httpd_ssl_config { /*!< 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; + /*!< 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 +189,7 @@ typedef struct httpd_ssl_config httpd_ssl_config_t; .prvtkey_len = 0, \ .use_ecdsa_peripheral = false, \ .ecdsa_key_efuse_blk = 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..6cadd1eac9 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -333,6 +333,7 @@ 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; + (*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/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index d26e6b3333..194c132e74 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -97,6 +97,14 @@ void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char * @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); + +/** + * @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..d02ce219e9 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -421,6 +421,12 @@ 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; } + +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/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index 870c508aa1..770b553ee9 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -44,6 +44,20 @@ 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 = /* efuse block with ecdsa private key */, + .ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // or ESP_TLS_ECDSA_CURVE_SECP384R1 + }; + HTTPS Request ------------- diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index b6937144cd..85734a5482 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -217,7 +217,7 @@ 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. + To use ECDSA peripheral with ESP-TLS, set :cpp:member:`esp_tls_cfg_t::use_ecdsa_peripheral` to `true`, set :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` to the eFuse block ID in which ECDSA private key is stored, and set :cpp:member:`esp_tls_cfg_t::ecdsa_curve` to specify the ECDSA curve to use. 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. @@ -227,6 +227,7 @@ To enable the secure element support, and use it in your project for TLS connect esp_tls_cfg_t cfg = { .use_ecdsa_peripheral = true, .ecdsa_key_efuse_blk = /* efuse block with ecdsa private key */, + .ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // or ESP_TLS_ECDSA_CURVE_SECP384R1 }; .. note:: diff --git a/docs/en/api-reference/protocols/mqtt.rst b/docs/en/api-reference/protocols/mqtt.rst index cde304e340..57e1e76b3e 100644 --- a/docs/en/api-reference/protocols/mqtt.rst +++ b/docs/en/api-reference/protocols/mqtt.rst @@ -156,6 +156,9 @@ It is possible to set authentication parameters through the :cpp:class:`authenti * :cpp:member:`certificate ` and :cpp:member:`key `: mutual authentication with TLS, and both can be provided in PEM or DER format * :cpp:member:`use_secure_element `: use secure element (ATECC608A) interfaced to ESP32 series * :cpp:member:`ds_data `: use Digital Signature Peripheral available in some Espressif devices + * :cpp:member:`use_ecdsa_peripheral `: use ECDSA Peripheral available in some Espressif devices + * :cpp:member:`ecdsa_key_efuse_blk `: eFuse block containing ECDSA private key + * :cpp:member:`ecdsa_curve `: ECDSA curve to use (ESP_TLS_ECDSA_CURVE_SECP256R1 or ESP_TLS_ECDSA_CURVE_SECP384R1) Session ^^^^^^^^^^^ 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..b0419ba557 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,20 @@ 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 = /* 存储 ECDSA 私钥的 eFuse 块 */, + .ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // 或 ESP_TLS_ECDSA_CURVE_SECP384R1 + }; + 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..8a066ed3b5 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -217,7 +217,7 @@ 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。 + 在 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,并将 :cpp:member:`esp_tls_cfg_t::ecdsa_curve` 设置为指定要使用的 ECDSA 曲线。 这样就可以使用 ECDSA 外设进行私钥操作。由于客户私钥已经存储在 eFuse 中,因此无需将其传递给 :cpp:type:`esp_tls_cfg_t`。 @@ -227,6 +227,7 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须 esp_tls_cfg_t cfg = { .use_ecdsa_peripheral = true, .ecdsa_key_efuse_blk = /* 存储 ECDSA 私钥的 eFuse 块 */, + .ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // 或 ESP_TLS_ECDSA_CURVE_SECP384R1 }; .. note:: diff --git a/docs/zh_CN/api-reference/protocols/mqtt.rst b/docs/zh_CN/api-reference/protocols/mqtt.rst index 27d36416ba..17a736a7e8 100644 --- a/docs/zh_CN/api-reference/protocols/mqtt.rst +++ b/docs/zh_CN/api-reference/protocols/mqtt.rst @@ -156,6 +156,9 @@ ESP-MQTT 库将始终重新传输未确认的 QoS 1 和 2 发布消息,以避 * * :cpp:member:`certificate ` 和 :cpp:member:`key `:进行双向 TLS 身份验证,PEM 或 DER 格式均可 * :cpp:member:`use_secure_element `:使用 ESP32 系列中的安全元素 (ATECC608A) * :cpp:member:`ds_data `:使用某些乐鑫设备的数字签名外设 + * :cpp:member:`use_ecdsa_peripheral `:使用某些乐鑫设备中可用的 ECDSA 外设 + * :cpp:member:`ecdsa_key_efuse_blk `:包含 ECDSA 私钥的 eFuse 块 + * :cpp:member:`ecdsa_curve `:要使用的 ECDSA 曲线(ESP_TLS_ECDSA_CURVE_SECP256R1 或 ESP_TLS_ECDSA_CURVE_SECP384R1) 会话 ^^^^^^^^^^^^ From dedc9889ded68117088ecc06b3723a295e787153 Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Mon, 21 Jul 2025 15:40:52 +0530 Subject: [PATCH 3/3] feat: added config member to store block number for hign part of ecdsa key --- components/esp-tls/CMakeLists.txt | 2 +- components/esp-tls/esp_tls.h | 27 +++----- components/esp-tls/esp_tls_mbedtls.c | 28 ++++---- .../esp-tls/private_include/esp_tls_private.h | 1 - components/esp_http_client/CMakeLists.txt | 2 +- components/esp_http_client/esp_http_client.c | 5 ++ .../esp_http_client/include/esp_http_client.h | 17 ++++- .../include/esp_https_server.h | 10 ++- .../esp_https_server/src/https_server.c | 3 + components/hal/include/hal/ecdsa_types.h | 2 +- components/mbedtls/port/ecdsa/ecdsa_alt.c | 64 +++++++------------ .../mbedtls/port/include/ecdsa/ecdsa_alt.h | 22 +------ .../test_apps/main/test_mbedtls_ecdsa.c | 6 +- .../tcp_transport/include/esp_transport_ssl.h | 14 +++- components/tcp_transport/transport_ssl.c | 10 +++ docs/en/api-reference/peripherals/ecdsa.rst | 43 ++++--------- .../protocols/esp_http_client.rst | 5 +- docs/en/api-reference/protocols/esp_tls.rst | 9 ++- docs/en/api-reference/protocols/mqtt.rst | 3 - .../zh_CN/api-reference/peripherals/ecdsa.rst | 43 ++++--------- .../protocols/esp_http_client.rst | 5 +- .../zh_CN/api-reference/protocols/esp_tls.rst | 7 +- docs/zh_CN/api-reference/protocols/mqtt.rst | 3 - 23 files changed, 146 insertions(+), 185 deletions(-) diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt index f2d01bc272..3809b6473b 100644 --- a/components/esp-tls/CMakeLists.txt +++ b/components/esp-tls/CMakeLists.txt @@ -19,7 +19,7 @@ idf_component_register(SRCS "${srcs}" PRIV_INCLUDE_DIRS "private_include" # mbedtls is public requirements because esp_tls.h # includes mbedtls header files. - REQUIRES mbedtls efuse + REQUIRES mbedtls PRIV_REQUIRES ${priv_req}) if(CONFIG_ESP_TLS_USING_WOLFSSL) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index dd97ec97d7..cbcb31681f 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -28,22 +28,6 @@ extern "C" { #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 */ @@ -117,7 +101,10 @@ typedef enum { */ 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; /** @@ -192,7 +179,9 @@ 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 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. */ + 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) */ @@ -338,7 +327,9 @@ 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. If two blocks are used to store the key, then the macro ESP_TLS_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. */ + 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) */ diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 6cb9c2a87f..874866a18a 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -23,8 +23,6 @@ #include "mbedtls/esp_mbedtls_dynamic.h" #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #include "mbedtls/ecp.h" -#include "esp_efuse.h" -#include "esp_efuse_chip.h" #include "ecdsa/ecdsa_alt.h" #endif @@ -61,7 +59,7 @@ static mbedtls_x509_crt *global_cacert = NULL; #define NEWLIB_NANO_SIZE_T_COMPAT_CAST(size_t_var) size_t_var #endif -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +#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 @@ -70,10 +68,6 @@ static mbedtls_x509_crt *global_cacert = NULL; */ static esp_err_t esp_tls_ecdsa_curve_to_mbedtls_group_id(esp_tls_ecdsa_curve_t curve, mbedtls_ecp_group_id *grp_id) { - if (grp_id == NULL) { - return ESP_ERR_INVALID_ARG; - } - switch (curve) { case ESP_TLS_ECDSA_CURVE_SECP256R1: *grp_id = MBEDTLS_ECP_DP_SECP256R1; @@ -82,7 +76,6 @@ static esp_err_t esp_tls_ecdsa_curve_to_mbedtls_group_id(esp_tls_ecdsa_curve_t c *grp_id = MBEDTLS_ECP_DP_SECP384R1; break; default: - ESP_LOGE(TAG, "Invalid ECDSA curve specified: %d", curve); return ESP_ERR_INVALID_ARG; } return ESP_OK; @@ -788,7 +781,11 @@ 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, @@ -1036,7 +1033,11 @@ 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, @@ -1064,6 +1065,12 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t static int ecdsa_peripheral_supported_ciphersuites[4] = {0}; // Max 4 elements int ciphersuite_count = 0; + if (grp_id == MBEDTLS_ECP_DP_SECP384R1) { + ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; + } else { + ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; + } + #if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 if (grp_id == MBEDTLS_ECP_DP_SECP384R1) { ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384; @@ -1071,11 +1078,6 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256; } #endif - 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"); 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 8bba630972..728b538d13 100644 --- a/components/esp-tls/private_include/esp_tls_private.h +++ b/components/esp-tls/private_include/esp_tls_private.h @@ -15,7 +15,6 @@ #include #include "esp_err.h" #include "esp_tls_errors.h" -#include "esp_tls.h" #ifdef CONFIG_ESP_TLS_USING_MBEDTLS #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" diff --git a/components/esp_http_client/CMakeLists.txt b/components/esp_http_client/CMakeLists.txt index ebdcc4ef08..4a353e33ca 100644 --- a/components/esp_http_client/CMakeLists.txt +++ b/components/esp_http_client/CMakeLists.txt @@ -1,5 +1,5 @@ if(NOT ${IDF_TARGET} STREQUAL "linux") - set(req lwip esp_event esp-tls) + set(req lwip esp_event) else() set(req linux esp_event) endif() diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index fac636d1c7..7a9a28fdec 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 @@ -927,7 +928,11 @@ 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); } diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index 2acb9d448f..04b2239f4b 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -11,7 +11,6 @@ #include "sdkconfig.h" #include "esp_err.h" #include -#include "esp_tls.h" #ifdef __cplusplus extern "C" { @@ -98,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 */ @@ -179,8 +189,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. 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 */ - esp_tls_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */ + 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 20ec2624b8..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,10 +100,13 @@ struct httpd_ssl_config { /** Use ECDSA peripheral to use private key */ bool use_ecdsa_peripheral; - /*!< 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 */ + /** 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; - /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */ + /** 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) */ @@ -189,6 +192,7 @@ 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, \ diff --git a/components/esp_https_server/src/https_server.c b/components/esp_https_server/src/https_server.c index 6cadd1eac9..5ae7213072 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -333,6 +333,9 @@ 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."); diff --git a/components/hal/include/hal/ecdsa_types.h b/components/hal/include/hal/ecdsa_types.h index 5aed889dd5..4a4be050bf 100644 --- a/components/hal/include/hal/ecdsa_types.h +++ b/components/hal/include/hal/ecdsa_types.h @@ -50,7 +50,7 @@ typedef enum { /** * @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 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)) diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index ae7fc8ef1c..a6474ea5b9 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -148,60 +148,44 @@ static void esp_ecdsa_release_hardware(void) */ 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 - esp_efuse_purpose_t expected_purpose; - esp_efuse_purpose_t actual_purpose; +#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_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; - } + expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P192; 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; - } + expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256; 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; - } + 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, "Invalid ECDSA curve id"); + 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 */ - // 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); + 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; } -#endif /* !SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */ return 0; } @@ -224,7 +208,7 @@ int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk) bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; if (!use_km_key) { int high_blk, low_blk; - MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, 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"); @@ -339,7 +323,7 @@ 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) { int high_blk, low_blk; - MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, 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"); @@ -380,7 +364,7 @@ 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) { int high_blk, low_blk; - MBEDTLS_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, 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"); diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h index 72bd48605a..b2b8f3a65a 100644 --- a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h +++ b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h @@ -20,22 +20,6 @@ extern "C" { #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 * @note Contains configuration information like the efuse key block that should be used as the private key, @@ -67,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 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. + * 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 @@ -87,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 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. + * 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 @@ -103,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 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. + * 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/main/test_mbedtls_ecdsa.c b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c index aa7f1bbc0a..71823376a1 100644 --- a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c +++ b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c @@ -375,7 +375,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_ke #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); + 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 */ @@ -444,7 +444,7 @@ 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); + 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 */ @@ -532,7 +532,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][efuse_key]" #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); + 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 */ diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index 194c132e74..4dcd5c1338 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -94,10 +94,22 @@ 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. 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 + * @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. * diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index d02ce219e9..517f0982fb 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -422,6 +422,16 @@ void esp_transport_ssl_set_client_key_ecdsa_peripheral(esp_transport_handle_t t, 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); diff --git a/docs/en/api-reference/peripherals/ecdsa.rst b/docs/en/api-reference/peripherals/ecdsa.rst index e646d7d255..6a9570d432 100644 --- a/docs/en/api-reference/peripherals/ecdsa.rst +++ b/docs/en/api-reference/peripherals/ecdsa.rst @@ -25,46 +25,27 @@ On {IDF_TARGET_NAME}, the ECDSA module works with a secret key burnt into an eFu ECDSA Key Storage ^^^^^^^^^^^^^^^^^ -ECDSA private keys are stored in eFuse key blocks. The number of key blocks required depends on the curve size: +.. only:: SOC_ECDSA_SUPPORT_CURVE_P384 -- **P-192 and P-256 curves**: Require one eFuse key block (256 bits) -- **P-384 curve**: Requires two eFuse key blocks (512 bits total) + ECDSA private keys are stored in eFuse key blocks. The number of key blocks required depends on the curve size: -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: + - **P-256 curve**: Require one eFuse key block (256 bits) + - **P-384 curve**: Requires two eFuse key blocks (512 bits total) -- **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``) + For curves requiring two key blocks (like P-384), configure the following fields: -You can also extract the individual block numbers using the corresponding extract macro: + - 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 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 + 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. -Here is an example of how to use these macros: +.. only:: not SOC_ECDSA_SUPPORT_CURVE_P384 -.. code-block:: c + ECDSA private keys are stored in eFuse key blocks. One eFuse key block (256 bits) is required for P-256 curve. - #include "ecdsa/ecdsa_alt.h" + Configure the following field: - // 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 + - 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: diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index 770b553ee9..e463eb95b4 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -54,8 +54,9 @@ The ECDSA peripheral can be used for the underlying TLS connection in the HTTP c esp_http_client_config_t cfg = { /* other configurations options */ .use_ecdsa_peripheral = true, - .ecdsa_key_efuse_blk = /* efuse block with ecdsa private key */, - .ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // or ESP_TLS_ECDSA_CURVE_SECP384R1 + .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 }; diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index 85734a5482..0e5c9a0420 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -217,17 +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`, set :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` to the eFuse block ID in which ECDSA private key is stored, and set :cpp:member:`esp_tls_cfg_t::ecdsa_curve` to specify the ECDSA curve to use. - - 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_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // or ESP_TLS_ECDSA_CURVE_SECP384R1 + .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/en/api-reference/protocols/mqtt.rst b/docs/en/api-reference/protocols/mqtt.rst index 57e1e76b3e..cde304e340 100644 --- a/docs/en/api-reference/protocols/mqtt.rst +++ b/docs/en/api-reference/protocols/mqtt.rst @@ -156,9 +156,6 @@ It is possible to set authentication parameters through the :cpp:class:`authenti * :cpp:member:`certificate ` and :cpp:member:`key `: mutual authentication with TLS, and both can be provided in PEM or DER format * :cpp:member:`use_secure_element `: use secure element (ATECC608A) interfaced to ESP32 series * :cpp:member:`ds_data `: use Digital Signature Peripheral available in some Espressif devices - * :cpp:member:`use_ecdsa_peripheral `: use ECDSA Peripheral available in some Espressif devices - * :cpp:member:`ecdsa_key_efuse_blk `: eFuse block containing ECDSA private key - * :cpp:member:`ecdsa_curve `: ECDSA curve to use (ESP_TLS_ECDSA_CURVE_SECP256R1 or ESP_TLS_ECDSA_CURVE_SECP384R1) Session ^^^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/peripherals/ecdsa.rst b/docs/zh_CN/api-reference/peripherals/ecdsa.rst index 899f766620..e85ff51032 100644 --- a/docs/zh_CN/api-reference/peripherals/ecdsa.rst +++ b/docs/zh_CN/api-reference/peripherals/ecdsa.rst @@ -25,46 +25,27 @@ ECDSA 外设可以为 TLS 双向身份验证等用例建立 **安全设备身份 ECDSA 密钥存储 ^^^^^^^^^^^^^^ -ECDSA 私钥存储在 eFuse 密钥块中。所需的密钥块数量取决于曲线大小: +.. only:: SOC_ECDSA_SUPPORT_CURVE_P384 -- **P-192 和 P-256 曲线**:需要一个 eFuse 密钥块(256 位) -- **P-384 曲线**:需要两个 eFuse 密钥块(总共 512 位) + ECDSA 私钥存储在 eFuse 密钥块中。所需的密钥块数量取决于曲线大小: -使用 P-384 曲线或其他需要两个密钥块的曲线时,必须使用相应的宏将两个密钥块编号组合为一个整数,以便 ECDSA 外设能够识别: + - **P-256 曲线**:需要一个 eFuse 密钥块(256 位) + - **P-384 曲线**:需要两个 eFuse 密钥块(总共 512 位) -- **对于 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`` 中) + 对于需要两个密钥块的曲线(如 P-384),配置以下字段: -你还可以使用相应的提取宏来获取各个密钥块编号: + - 将 :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk` 设置为低块号 + - 将 :cpp:member:`esp_tls_cfg_t::ecdsa_key_efuse_blk_high` 设置为高块号 -- **对于 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` 宏 + 对于单块曲线(如 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 -.. code-block:: c + ECDSA 私钥存储在 eFuse 密钥块中。一个 eFuse 密钥块(256 位)是 P-256 曲线所需的。 - #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 的值为 4,extracted_block_high 的值为 5 + - 将 :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 密钥的示例: 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 b0419ba557..5a6ff5852a 100644 --- a/docs/zh_CN/api-reference/protocols/esp_http_client.rst +++ b/docs/zh_CN/api-reference/protocols/esp_http_client.rst @@ -54,8 +54,9 @@ ECDSA 外设可用于 HTTP 客户端连接中的底层 TLS 连接。详细内容 esp_http_client_config_t cfg = { /* other configurations options */ .use_ecdsa_peripheral = true, - .ecdsa_key_efuse_blk = /* 存储 ECDSA 私钥的 eFuse 块 */, - .ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // 或 ESP_TLS_ECDSA_CURVE_SECP384R1 + .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 曲线 }; diff --git a/docs/zh_CN/api-reference/protocols/esp_tls.rst b/docs/zh_CN/api-reference/protocols/esp_tls.rst index 8a066ed3b5..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,并将 :cpp:member:`esp_tls_cfg_t::ecdsa_curve` 设置为指定要使用的 ECDSA 曲线。 - 这样就可以使用 ECDSA 外设进行私钥操作。由于客户私钥已经存储在 eFuse 中,因此无需将其传递给 :cpp:type:`esp_tls_cfg_t`。 .. code-block:: c @@ -226,8 +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_curve = ESP_TLS_ECDSA_CURVE_SECP256R1, // 或 ESP_TLS_ECDSA_CURVE_SECP384R1 + .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:: diff --git a/docs/zh_CN/api-reference/protocols/mqtt.rst b/docs/zh_CN/api-reference/protocols/mqtt.rst index 17a736a7e8..27d36416ba 100644 --- a/docs/zh_CN/api-reference/protocols/mqtt.rst +++ b/docs/zh_CN/api-reference/protocols/mqtt.rst @@ -156,9 +156,6 @@ ESP-MQTT 库将始终重新传输未确认的 QoS 1 和 2 发布消息,以避 * * :cpp:member:`certificate ` 和 :cpp:member:`key `:进行双向 TLS 身份验证,PEM 或 DER 格式均可 * :cpp:member:`use_secure_element `:使用 ESP32 系列中的安全元素 (ATECC608A) * :cpp:member:`ds_data `:使用某些乐鑫设备的数字签名外设 - * :cpp:member:`use_ecdsa_peripheral `:使用某些乐鑫设备中可用的 ECDSA 外设 - * :cpp:member:`ecdsa_key_efuse_blk `:包含 ECDSA 私钥的 eFuse 块 - * :cpp:member:`ecdsa_curve `:要使用的 ECDSA 曲线(ESP_TLS_ECDSA_CURVE_SECP256R1 或 ESP_TLS_ECDSA_CURVE_SECP384R1) 会话 ^^^^^^^^^^^^