diff --git a/components/efuse/include/esp_efuse.h b/components/efuse/include/esp_efuse.h index 80db72a608..fa075f91ac 100644 --- a/components/efuse/include/esp_efuse.h +++ b/components/efuse/include/esp_efuse.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -235,7 +235,7 @@ esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint3 /** * @brief Return efuse coding scheme for blocks. * - * Note: The coding scheme is applicable only to 1, 2 and 3 blocks. For 0 block, the coding scheme is always ``NONE``. + * @note The coding scheme is applicable only to 1, 2 and 3 blocks. For 0 block, the coding scheme is always ``NONE``. * * @param[in] blk Block number of eFuse. * @return Return efuse coding scheme for blocks @@ -708,6 +708,12 @@ esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest); * * The burn of a key, protection bits, and a purpose happens in batch mode. * + * @note This API also enables the read protection efuse bit for certain key blocks like XTS-AES, HMAC, ECDSA etc. + * This ensures that the key is only accessible to hardware peripheral. + * + * @note For SoC's with capability `SOC_EFUSE_ECDSA_USE_HARDWARE_K` (e.g., ESP32-H2), this API writes an additional + * efuse bit for ECDSA key purpose to enforce hardware TRNG generated k mode in the peripheral. + * * @param[in] block Block to read purpose for. Must be in range EFUSE_BLK_KEY0 to EFUSE_BLK_KEY_MAX. Key block must be unused (esp_efuse_key_block_unused). * @param[in] purpose Purpose to set for this key. Purpose must be already unset. * @param[in] key Pointer to data to write. @@ -727,6 +733,12 @@ esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpo * * The burn of keys, protection bits, and purposes happens in batch mode. * + * @note This API also enables the read protection efuse bit for certain key blocks like XTS-AES, HMAC, ECDSA etc. + * This ensures that the key is only accessible to hardware peripheral. + * + * @note For SoC's with capability `SOC_EFUSE_ECDSA_USE_HARDWARE_K` (e.g., ESP32-H2), this API writes an additional + * efuse bit for ECDSA key purpose to enforce hardware TRNG generated k mode in the peripheral. + * * @param[in] purposes Array of purposes (purpose[number_of_keys]). * @param[in] keys Array of keys (uint8_t keys[number_of_keys][32]). Each key is 32 bytes long. * @param[in] number_of_keys The number of keys to write (up to 6 keys). diff --git a/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c b/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c index 179966e7fd..0d48b1fd4e 100644 --- a/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c +++ b/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -315,6 +315,12 @@ esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpo purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_UP) { ESP_EFUSE_CHK(esp_efuse_set_key_dis_read(block)); } +#if SOC_EFUSE_ECDSA_USE_HARDWARE_K + if (purpose == ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY) { + // Permanently enable the hardware TRNG supplied k mode (most secure mode) + ESP_EFUSE_CHK(esp_efuse_write_field_bit(ESP_EFUSE_ECDSA_FORCE_USE_HARDWARE_K)); + } +#endif ESP_EFUSE_CHK(esp_efuse_set_key_purpose(block, purpose)); ESP_EFUSE_CHK(esp_efuse_set_keypurpose_dis_write(block)); return esp_efuse_batch_write_commit(); diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 3a96492503..51c4561d7e 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -27,6 +27,7 @@ #include "esp_newlib.h" #include "esp_timer.h" #include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_flash_encrypt.h" #include "esp_secure_boot.h" #include "esp_xt_wdt.h" @@ -348,6 +349,15 @@ static void do_core_init(void) esp_secure_boot_init_checks(); #endif +#if SOC_EFUSE_ECDSA_USE_HARDWARE_K + if (esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, NULL)) { + // ECDSA key purpose block is present and hence permanently enable + // the hardware TRNG supplied k mode (most secure mode) + err = esp_efuse_write_field_bit(ESP_EFUSE_ECDSA_FORCE_USE_HARDWARE_K); + assert(err == ESP_OK && "Failed to enable ECDSA hardware k mode"); + } +#endif + #if CONFIG_SECURE_DISABLE_ROM_DL_MODE err = esp_efuse_disable_rom_download_mode(); assert(err == ESP_OK && "Failed to disable ROM download mode"); diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index f0681dc830..3737e793ba 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -30,22 +30,17 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) ecdsa_ll_set_curve(conf->curve); if (conf->mode != ECDSA_MODE_EXPORT_PUBKEY) { - ecdsa_ll_set_k_mode(conf->k_mode); ecdsa_ll_set_z_mode(conf->sha_mode); } } -void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *k, const uint8_t *hash, +void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, uint8_t *r_out, uint8_t *s_out, uint16_t len) { if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN) { HAL_ASSERT(false && "Incorrect length"); } - if (conf->k_mode == ECDSA_K_USER_PROVIDED && k == NULL) { - HAL_ASSERT(false && "Mismatch in K configuration"); - } - if (conf->sha_mode == ECDSA_Z_USER_PROVIDED && hash == NULL) { HAL_ASSERT(false && "Mismatch in SHA configuration"); } diff --git a/components/hal/esp32h2/include/hal/ecdsa_ll.h b/components/hal/esp32h2/include/hal/ecdsa_ll.h index fc1162603f..3e16b9726c 100644 --- a/components/hal/esp32h2/include/hal/ecdsa_ll.h +++ b/components/hal/esp32h2/include/hal/ecdsa_ll.h @@ -23,7 +23,6 @@ typedef enum { ECDSA_PARAM_R, ECDSA_PARAM_S, ECDSA_PARAM_Z, - ECDSA_PARAM_K, ECDSA_PARAM_QAX, ECDSA_PARAM_QAY } ecdsa_ll_param_t; @@ -190,26 +189,6 @@ static inline void ecdsa_ll_set_curve(ecdsa_curve_t curve) } } -/** - * @brief Set the source of `K` - * - * @param mode Mode of K generation - */ -static inline void ecdsa_ll_set_k_mode(ecdsa_k_mode_t mode) -{ - switch (mode) { - case ECDSA_K_USE_TRNG: - REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_K); - break; - case ECDSA_K_USER_PROVIDED: - REG_SET_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_K); - break; - default: - HAL_ASSERT(false && "Unsupported curve"); - break; - } -} - /** * @brief Set the source of `Z` (SHA message) * @@ -335,7 +314,6 @@ static inline void ecdsa_ll_write_param(ecdsa_ll_param_t param, const uint8_t *b case ECDSA_PARAM_Z: reg = ECDSA_Z_MEM; break; - case ECDSA_PARAM_K: case ECDSA_PARAM_QAX: reg = ECDSA_QAX_MEM; break; @@ -373,7 +351,6 @@ static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uin case ECDSA_PARAM_Z: reg = ECDSA_Z_MEM; break; - case ECDSA_PARAM_K: case ECDSA_PARAM_QAX: reg = ECDSA_QAX_MEM; break; diff --git a/components/hal/esp32p4/include/hal/ecdsa_ll.h b/components/hal/esp32p4/include/hal/ecdsa_ll.h index 1d52bd4f9f..b30b078b41 100644 --- a/components/hal/esp32p4/include/hal/ecdsa_ll.h +++ b/components/hal/esp32p4/include/hal/ecdsa_ll.h @@ -23,7 +23,6 @@ typedef enum { ECDSA_PARAM_R, ECDSA_PARAM_S, ECDSA_PARAM_Z, - ECDSA_PARAM_K, ECDSA_PARAM_QAX, ECDSA_PARAM_QAY } ecdsa_ll_param_t; @@ -199,26 +198,6 @@ static inline void ecdsa_ll_set_curve(ecdsa_curve_t curve) } } -/** - * @brief Set the source of `K` - * - * @param mode Mode of K generation - */ -static inline void ecdsa_ll_set_k_mode(ecdsa_k_mode_t mode) -{ - switch (mode) { - case ECDSA_K_USE_TRNG: - REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_K); - break; - case ECDSA_K_USER_PROVIDED: - REG_SET_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_K); - break; - default: - HAL_ASSERT(false && "Unsupported curve"); - break; - } -} - /** * @brief Set the source of `Z` (SHA message) * @@ -344,7 +323,6 @@ static inline void ecdsa_ll_write_param(ecdsa_ll_param_t param, const uint8_t *b case ECDSA_PARAM_Z: reg = ECDSA_Z_MEM; break; - case ECDSA_PARAM_K: case ECDSA_PARAM_QAX: reg = ECDSA_QAX_MEM; break; @@ -382,7 +360,6 @@ static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uin case ECDSA_PARAM_Z: reg = ECDSA_Z_MEM; break; - case ECDSA_PARAM_K: case ECDSA_PARAM_QAX: reg = ECDSA_QAX_MEM; break; diff --git a/components/hal/include/hal/ecdsa_hal.h b/components/hal/include/hal/ecdsa_hal.h index 9ce048f9e3..9798160019 100644 --- a/components/hal/include/hal/ecdsa_hal.h +++ b/components/hal/include/hal/ecdsa_hal.h @@ -27,7 +27,6 @@ extern "C" { typedef struct { ecdsa_mode_t mode; /* Mode of operation */ ecdsa_curve_t curve; /* Curve to use for operation */ - ecdsa_k_mode_t k_mode; /* Source of K */ 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) */ bool use_km_key; /* Use an ECDSA key from the Key Manager peripheral */ @@ -37,13 +36,12 @@ typedef struct { * @brief Generate ECDSA signature * * @param conf Configuration for ECDSA operation, see ``ecdsa_hal_config_t`` - * @param k Value of K used internally. Set this to NULL if K is generated by hardware * @param hash Hash that is to be signed * @param r_out Buffer that will contain `R` component of ECDSA signature * @param s_out Buffer that will contain `S` component of ECDSA signature * @param len Length of the r_out and s_out buffer (32 bytes for SECP256R1, 24 for SECP192R1) */ -void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *k, const uint8_t *hash, +void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, uint8_t *r_out, uint8_t *s_out, uint16_t len); /** diff --git a/components/hal/include/hal/ecdsa_types.h b/components/hal/include/hal/ecdsa_types.h index fa96fbdee7..8ef5636b49 100644 --- a/components/hal/include/hal/ecdsa_types.h +++ b/components/hal/include/hal/ecdsa_types.h @@ -26,14 +26,6 @@ typedef enum { ECDSA_CURVE_SECP256R1, } ecdsa_curve_t; -/** - * @brief Source of 'K' used internally for generating signature - */ -typedef enum { - ECDSA_K_USE_TRNG, - ECDSA_K_USER_PROVIDED, -} ecdsa_k_mode_t; - /** * @brief Source of SHA message that is to be signed/verified */ 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 6b9c80c8a5..0c2363bdaa 100644 --- a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c +++ b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c @@ -50,7 +50,6 @@ static int test_ecdsa_verify(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_SIGN_VERIFY, - .k_mode = ECDSA_K_USE_TRNG, .sha_mode = ECDSA_Z_USER_PROVIDED, }; @@ -119,7 +118,6 @@ static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_SIGN_GEN, - .k_mode = ECDSA_K_USE_TRNG, .sha_mode = ECDSA_Z_USER_PROVIDED, .use_km_key = use_km_key, }; @@ -144,7 +142,7 @@ static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* ecdsa_enable_and_reset(); do { - ecdsa_hal_gen_signature(&conf, NULL, sha_le, r_le, s_le, len); + ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len); } while(!memcmp(r_le, zeroes, len) || !memcmp(s_le, zeroes, len)); ecdsa_disable(); diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index a4bef4dd5e..c0fc7c793b 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -244,13 +244,12 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_SIGN_GEN, .curve = curve, - .k_mode = ECDSA_K_USE_TRNG, .sha_mode = ECDSA_Z_USER_PROVIDED, .efuse_key_blk = d->MBEDTLS_PRIVATE(n), .use_km_key = 0, //TODO: IDF-7992 }; - ecdsa_hal_gen_signature(&conf, NULL, sha_le, r_le, s_le, len); + ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len); } while (!memcmp(r_le, zeroes, len) || !memcmp(s_le, zeroes, len)); esp_ecdsa_release_hardware(); @@ -470,7 +469,6 @@ static int esp_ecdsa_verify(mbedtls_ecp_group *grp, ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_SIGN_VERIFY, .curve = curve, - .k_mode = ECDSA_K_USE_TRNG, .sha_mode = ECDSA_Z_USER_PROVIDED, }; diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h index 3e27b21551..a8646979a7 100644 --- a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h +++ b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h @@ -24,14 +24,14 @@ extern "C" { * by the peripheral, a flag load_pubkey that is used specify if the public key has to be populated */ typedef struct { - mbedtls_ecp_group_id grp_id; - uint8_t efuse_block; + mbedtls_ecp_group_id grp_id; /*!< MbedTLS ECP group identifier */ + uint8_t efuse_block; /*!< EFuse block id for ECDSA private key */ #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY - bool load_pubkey; + bool load_pubkey; /*!< Export ECDSA public key from the hardware */ #endif } esp_ecdsa_pk_conf_t; //TODO: IDF-7925 (Add a config to select the ecdsa key from the key manager peripheral) -#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY +#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || __DOXYGEN__ /** * @brief Populate the public key buffer of the mbedtls_ecp_keypair context. @@ -45,9 +45,10 @@ typedef struct { * - -1 if invalid efuse block is specified */ int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk); -#endif -#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +#endif // SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || __DOXYGEN__ + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || __DOXYGEN__ /** * @brief Initialize MPI to notify mbedtls_ecdsa_sign to use the private key in efuse @@ -97,7 +98,8 @@ int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk * - -1 otherwise */ int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf); -#endif + +#endif // CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || __DOXYGEN__ #ifdef __cplusplus } diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 1cde3e559f..79d8a0c6b0 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1079,6 +1079,10 @@ config SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK bool default y +config SOC_EFUSE_ECDSA_USE_HARDWARE_K + bool + default y + config SOC_SECURE_BOOT_V2_RSA bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index cd260fbb24..0cbb73fbad 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -441,6 +441,7 @@ #define SOC_EFUSE_SOFT_DIS_JTAG 1 #define SOC_EFUSE_DIS_ICACHE 1 #define SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK 1 // XTS-AES and ECDSA key purposes not supported for this block +#define SOC_EFUSE_ECDSA_USE_HARDWARE_K 1 // Force use hardware TRNG supplied K for ECDSA /*-------------------------- Secure Boot CAPS----------------------------*/ #define SOC_SECURE_BOOT_V2_RSA 1 diff --git a/docs/conf_common.py b/docs/conf_common.py index 05d2bb9748..5136aa61d0 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -209,6 +209,7 @@ conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS, 'SOC_RISCV_COPROC_SUPPORTED':RISCV_COPROC_DOCS, 'SOC_LP_CORE_SUPPORTED':LP_CORE_DOCS, 'SOC_DIG_SIGN_SUPPORTED':['api-reference/peripherals/ds.rst'], + 'SOC_ECDSA_SUPPORTED':['api-reference/peripherals/ecdsa.rst'], 'SOC_HMAC_SUPPORTED':['api-reference/peripherals/hmac.rst'], 'SOC_ASYNC_MEMCPY_SUPPORTED':['api-reference/system/async_memcpy.rst'], 'CONFIG_IDF_TARGET_ARCH_XTENSA':XTENSA_DOCS, diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 99128ba63b..2321f7424e 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -260,6 +260,7 @@ INPUT = \ $(PROJECT_PATH)/components/lwip/include/apps/esp_sntp.h \ $(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \ $(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \ + $(PROJECT_PATH)/components/mbedtls/port/include/ecdsa/ecdsa_alt.h \ $(PROJECT_PATH)/components/mqtt/esp-mqtt/include/mqtt_client.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs_flash.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs.h \ diff --git a/docs/en/api-reference/peripherals/ecdsa.rst b/docs/en/api-reference/peripherals/ecdsa.rst new file mode 100644 index 0000000000..d6e19cf5bc --- /dev/null +++ b/docs/en/api-reference/peripherals/ecdsa.rst @@ -0,0 +1,82 @@ +Elliptic Curve Digital Signature Algorithm (ECDSA) +================================================== + +The Elliptic Curve Digital Signature Algorithm (ECDSA) offers a variant of the Digital Signature Algorithm (DSA) which uses elliptic-curve cryptography. + +{IDF_TARGET_NAME}'s ECDSA peripheral provides a secure and efficient environment for computing ECDSA signatures. It offers fast computations while ensuring the confidentiality of the signing process to prevent information leakage. ECDSA private key used in the signing process is accessible only to the hardware peripheral, and it is not readable by software. + +ECDSA peripheral can help to establish **Secure Device Identity** for TLS mutual authentication and similar use-cases. + +Supported Features +------------------ + +- ECDSA digital signature generation and verification +- Two different elliptic curves, namely P-192 and P-256 (FIPS 186-3 specification) +- Two hash algorithms for message hash in the ECDSA operation, namely SHA-224 and SHA-256 (FIPS PUB 180-4 specification) + + +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 can be programmed externally through ``espefuse.py`` script using: + +.. code:: bash + + espefuse.py burn_key ECDSA_KEY + +.. only:: SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK + + .. note:: + + Five physical eFuse blocks can be used as keys for the ECDSA module: block 4 ~ block 8. E.g., for block 4 (which is the first key block) , the argument should be ``BLOCK_KEY0``. + +.. only:: not SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK + + .. note:: + + Six physical eFuse blocks can be used as keys for the ECDSA module: block 4 ~ block 9. E.g., for block 4 (which is the first key block) , the argument should be ``BLOCK_KEY0``. + + +Alternatively the ECDSA key can also be programmed through the application running on the target. + +Following code snippet uses :cpp:func:`esp_efuse_write_key` to set physical key block 0 in the eFuse with key purpose as :cpp:enumerator:`esp_efuse_purpose_t::ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY`: + +.. code-block:: c + + #include "esp_efuse.h" + + const uint8_t key_data[32] = { ... }; + + esp_err_t status = esp_efuse_write_key(EFUSE_BLK_KEY0, + ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, + key_data, sizeof(key_data)); + + if (status == ESP_OK) { + // written key + } else { + // writing key failed, maybe written already + } + + +Dependency on TRNG +------------------ + +ECDSA peripheral relies on the hardware True Random Number Generator (TRNG) for its internal entropy requirement. During ECDSA signature creation, the algorithm requires a random integer to be generated as specified in the `RFC 6090 `_ section 5.3.2. + +Please ensure that hardware :doc:`RNG <../system/random>` is enabled before starting ECDSA computations (primarily signing) in the application. + +Application Outline +------------------- + +Please refer to the :ref:`ecdsa-peri-with-esp-tls` guide for details on how-to use ECDSA peripheral for establishing a mutually authenticated TLS connection. + +The ECDSA peripheral in mbedTLS stack is integrated by overriding the ECDSA sign and verify APIs. Please note that, the ECDSA peripheral does not support all curves or hash algorithms and hence for cases where the requirements do not meet the hardware, implementation falls back to the software. + +For a particular TLS context, additional APIs have been supplied to populate certain fields (e.g., private key ctx) to differentiate routing to hardware. ESP-TLS layer integrates these APIs internally and hence no additional work is required at the application layer. However, for custom use-cases please refer to API details below. + +API Reference +------------- + +.. include-build-file:: inc/ecdsa_alt.inc diff --git a/docs/en/api-reference/peripherals/index.rst b/docs/en/api-reference/peripherals/index.rst index b2fa160573..bc4212cf6b 100644 --- a/docs/en/api-reference/peripherals/index.rst +++ b/docs/en/api-reference/peripherals/index.rst @@ -12,6 +12,7 @@ Peripherals API :SOC_ANA_CMPR_SUPPORTED: ana_cmpr clk_tree :SOC_DAC_SUPPORTED: dac + :SOC_ECDSA_SUPPORTED: ecdsa :SOC_ETM_SUPPORTED: etm gpio gptimer diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index 241c5d9c49..afe732fe6a 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -203,6 +203,8 @@ The following table shows a typical comparison between WolfSSL and MbedTLS when .. only:: SOC_ECDSA_SUPPORTED + .. _ecdsa-peri-with-esp-tls: + ECDSA Peripheral with ESP-TLS ----------------------------- diff --git a/docs/en/api-reference/system/random.rst b/docs/en/api-reference/system/random.rst index 0e28b99e0b..de7d544804 100644 --- a/docs/en/api-reference/system/random.rst +++ b/docs/en/api-reference/system/random.rst @@ -1,7 +1,7 @@ Random Number Generation ======================== -{IDF_TARGET_RF_NAME: default="Wi-Fi or Bluetooth", esp32s2="Wi-Fi"} +{IDF_TARGET_RF_NAME: default="Wi-Fi or Bluetooth", esp32s2="Wi-Fi", esp32h2="Bluetooth or 802.15.4 Thread/Zigbee", esp32c6="Wi-Fi or Bluetooth or 802.15.4 Thread/Zigbee"} {IDF_TARGET_RF_IS: default="are", esp32s2="is"} {IDF_TARGET_BOOTLOADER_RANDOM_INCOMPATIBLE: default="", esp32="I2S, "} diff --git a/docs/en/security/security.rst b/docs/en/security/security.rst index 521f318951..5ec7f152bd 100644 --- a/docs/en/security/security.rst +++ b/docs/en/security/security.rst @@ -1,6 +1,10 @@ Security ======== +{IDF_TARGET_CIPHER_SCHEME:default="RSA", esp32h2="RSA or ECDSA", esp32p4="RSA or ECDSA"} + +{IDF_TARGET_SIG_PERI:default="DS", esp32h2="DS or ECDSA", esp32p4="DS or ECDSA"} + :link_to_translation:`zh_CN:[中文]` This guide provides an overview of the overall security features available in various Espressif solutions. It is highly recommended to consider this guide while designing the products with the Espressif platform and the ESP-IDF software stack from the **security** perspective. @@ -73,9 +77,19 @@ Flash Encryption Best Practices The Digital Signature peripheral in {IDF_TARGET_NAME} produces hardware-accelerated RSA digital signatures with the assistance of HMAC, without the RSA private key being accessible by software. This allows the private key to be kept secured on the device without anyone other than the device hardware being able to access it. - This peripheral can help to establish the **Secure Device Identity** to the remote endpoint, e.g., in the case of TLS mutual authentication based on the RSA cipher scheme. + .. only:: SOC_ECDSA_SUPPORTED - Please refer to the :doc:`../api-reference/peripherals/ds` for detailed documentation. + {IDF_TARGET_NAME} also supportes ECDSA peripheral for generating hardware-accelerated ECDSA digital signatures. ECDSA private key can be directly programmed in an eFuse block and marked as read protected from the software. + + {IDF_TARGET_SIG_PERI} peripheral can help to establish the **Secure Device Identity** to the remote endpoint, e.g., in the case of TLS mutual authentication based on the {IDF_TARGET_CIPHER_SCHEME} cipher scheme. + + .. only:: not SOC_ECDSA_SUPPORTED + + Please refer to the :doc:`../api-reference/peripherals/ds` for detailed documentation. + + .. only:: SOC_ECDSA_SUPPORTED + + Please refer to the :doc:`../api-reference/peripherals/ecdsa` and :doc:`../api-reference/peripherals/ds` guides for detailed documentation. .. only:: SOC_MEMPROT_SUPPORTED or SOC_CPU_IDRAM_SPLIT_USING_PMP diff --git a/docs/zh_CN/api-reference/peripherals/ecdsa.rst b/docs/zh_CN/api-reference/peripherals/ecdsa.rst new file mode 100644 index 0000000000..5a65a8a8bf --- /dev/null +++ b/docs/zh_CN/api-reference/peripherals/ecdsa.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/peripherals/ecdsa.rst diff --git a/docs/zh_CN/api-reference/peripherals/index.rst b/docs/zh_CN/api-reference/peripherals/index.rst index e6f0399180..51fa665504 100644 --- a/docs/zh_CN/api-reference/peripherals/index.rst +++ b/docs/zh_CN/api-reference/peripherals/index.rst @@ -12,6 +12,7 @@ :SOC_ANA_CMPR_SUPPORTED: ana_cmpr clk_tree :SOC_DAC_SUPPORTED: dac + :SOC_ECDSA_SUPPORTED: ecdsa :SOC_ETM_SUPPORTED: etm gpio gptimer diff --git a/docs/zh_CN/api-reference/protocols/esp_tls.rst b/docs/zh_CN/api-reference/protocols/esp_tls.rst index 369882c7f8..66b136a673 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -203,6 +203,8 @@ MbedTLS 与 WolfSSL 对比 .. only:: SOC_ECDSA_SUPPORTED + .. _ecdsa-peri-with-esp-tls: + 在 ESP-TLS 中使用 ECDSA 外设 -----------------------------