椭圆曲线数字签名算法 (ECDSA)

[English]

椭圆曲线数字签名算法 (ECDSA) 是数字签名算法 (DSA) 基于椭圆曲线密码学的变体。

ESP32-H2 的 ECDSA 外设为计算 ECDSA 签名提供了一个安全高效的环境,不仅能确保签名过程的机密性,防止信息泄露,也提供了快速的计算。在签名过程中使用的 ECDSA 私钥只能由硬件外设访问,软件无法读取。

ECDSA 外设可以为 TLS 双向身份验证等用例建立 安全设备身份认证

支持的特性

  • ECDSA 数字签名生成和验证

  • 两种不同的椭圆曲线,P-192 和 P-256(FIPS 186-3 规范)

  • ECDSA 操作中哈希消息的两种哈希算法,SHA-224 和 SHA-256(FIPS PUB 180-4 规范)

ESP32-H2 上的 ECDSA

在 ESP32-H2 上,ECDSA 模块使用烧录到 eFuse 块中的密钥。密码模块外的任何资源都不可访问此密钥(默认模式),从而避免密钥泄露。

ECDSA 密钥可以通过 espefuse.py 脚本在外部编程:

espefuse.py burn_key <BLOCK_NUM> </path/to/ecdsa_private_key.pem> ECDSA_KEY

备注

五个物理 eFuse 块可作为 ECDSA 模块的密钥:块 4 ~ 块 8。例如,对于块 4(第一个密钥块),参数为 BLOCK_KEY0

另外,ECDSA 密钥也可以通过在目标上运行的应用程序进行编程。

以下代码片段使用 esp_efuse_write_key() 将 eFuse 中的物理密钥块 0 的密钥目的设置为 esp_efuse_purpose_t::ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY:

#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
}

生成非确定性签名

对 TRNG 的依赖

ECDSA 外设依靠硬件真随机数生成器 (TRNG) 来满足其内部熵要求,从而生成非确定性签名。在创建 ECDSA 签名时,算法需要生成一个随机整数,在 RFC 6090 第 5.3.2 节有说明。

在应用程序中启动 ECDSA 计算(主要是签名)之前,请确保硬件 RNG 已经启用。

应用程序概述

有关如何使用 ECDSA 外设建立 TLS 双向身份验证连接的详细信息,请参阅 在 ESP-TLS 中使用 ECDSA 外设 指南。

通过覆盖 ECDSA 签名以及验证 API,可以集成 Mbed TLS 堆栈中的 ECDSA 外设。请注意,ECDSA 外设并不支持所有曲线或哈希算法。因此,在不满足硬件要求时,实现会退回到软件。

对于特定的 TLS 上下文,可用额外的 API 来填充某些字段(例如私钥 ctx),以区分路由到硬件的路径。ESP-TLS 层在内部集成了这些 API,因此在应用程序层不需要额外的操作。对于自定义用例,请参阅以下 API 详细信息。

API 参考

Header File

  • components/mbedtls/port/include/ecdsa/ecdsa_alt.h

  • This header file can be included with:

    #include "ecdsa/ecdsa_alt.h"
    
  • This header file is a part of the API provided by the mbedtls component. To declare that your component depends on mbedtls, add the following to your CMakeLists.txt:

    REQUIRES mbedtls
    

    or

    PRIV_REQUIRES mbedtls
    

Functions

int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk)

Populate the public key buffer of the mbedtls_ecp_keypair context.

参数
  • keypair -- The mbedtls ECP key-pair structure

  • efuse_blk -- The efuse key block that should be used as the private key. The key purpose of this block must be ECDSA_KEY

返回

- 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

  • -1 if invalid efuse block is specified

int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk)

Initialize MPI to notify mbedtls_ecdsa_sign to use the private key in efuse We break the MPI struct of the private key in order to differentiate between hardware key and software key.

参数
  • key -- The MPI in which this functions stores the hardware context. This must be uninitialized

  • efuse_blk -- The efuse key block that should be used as the private key. The key purpose of this block must be ECDSA_KEY

返回

- 0 if successful

  • -1 otherwise

int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk)

Initialize PK context to notify mbedtls_ecdsa_sign to use the private key in efuse We break the MPI struct used to represent the private key d in ECP keypair in order to differentiate between hardware key and software key.

参数
  • key_ctx -- The context in which this functions stores the hardware context. This must be uninitialized

  • efuse_blk -- The efuse key block that should be used as the private key. The key purpose of this block must be ECDSA_KEY

返回

- 0 if successful

  • -1 otherwise

int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf)

Initialize PK context and completely populate mbedtls_ecp_keypair context. We break the MPI struct used to represent the private key d in ECP keypair in order to differentiate between hardware key and software key. We also populate the ECP group field present in the mbedtls_ecp_keypair context. If the ECDSA peripheral of the chip supports exporting the public key, we can also populate the public key buffer of the mbedtls_ecp_keypair context if the load_pubkey flag is set in the esp_ecdsa_pk_conf_t config argument.

参数
  • key_ctx -- The context in which this functions stores the hardware context. This must be uninitialized

  • conf -- ESP-ECDSA private key context initialization config structure

返回

- 0 if successful

  • -1 otherwise

Structures

struct esp_ecdsa_pk_conf_t

ECDSA private key context initialization config structure.

备注

Contains configuration information like the efuse key block that should be used as the private key, EC group ID of the private key and if the export public key operation is supported by the peripheral, a flag load_pubkey that is used specify if the public key has to be populated

Public Members

mbedtls_ecp_group_id grp_id

MbedTLS ECP group identifier

uint8_t efuse_block

EFuse block id for ECDSA private key

bool use_km_key

Use key deployed in the key manager for ECDSA operation. Note: The key must be already deployed by the application and it must be activated for the lifetime of this context

Macros

USE_ECDSA_KEY_FROM_KEY_MANAGER