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