# ECDSA 数字签名外设 (ECDSA_DS)

[English]

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

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

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

## 支持的特性

- ECDSA 数字签名生成和验证

- 两种不同的椭圆曲线，P-192 和 P-256（FIPS 186-3 规范）

- ECDSA 操作中哈希消息的两种哈希算法，SHA-224 和 SHA-256（FIPS PUB 180-4 规范）

## ESP32-H21 上的 ECDSA_DS

在 ESP32-H21 上，ECDSA_DS 模块使用烧录到 eFuse 块中的密钥。

密码模块外的任何资源都不可访问此密钥（默认模式），从而避免密钥泄露。

### ECDSA 密钥存储

ECDSA 私钥存储在 eFuse 密钥块中。一个 eFuse 密钥块（256 位）是 P-256 曲线所需的。

配置以下字段：

- 将 `esp_tls_cfg_t::ecdsa_key_efuse_blk` 设置为块号，将 `esp_tls_cfg_t::ecdsa_key_efuse_blk_high` 保持为 0 或不赋值。

ECDSA 密钥可以通过 `idf.py` 脚本在外部编程。以下是关于编程 ECDSA 密钥的示例：

使用 eFuse 存储 ECDSA 密钥：

    idf.py efuse-burn-key <BLOCK_NUM> </path/to/ecdsa_private_key.pem> ECDSA_KEY

备注

六个物理 eFuse 块可作为 ECDSA_DS 模块的密钥：块 4 ~ 块 9。例如，对于块 4（第一个密钥块），参数为 `BLOCK_KEY0`。

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

使用 eFuse 存储 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
    }

## ECDSA 曲线配置

ESP32-H21 的 ECDSA_DS 外设支持 ECDSA-P192 和 ECDSA-P256 两种曲线操作，但默认仅启用 ECDSA-P256 操作。可以通过以下配置项启用 ECDSA-P192 操作：

- CONFIG_ESP_ECDSA_ENABLE_P192_CURVE 启用对 ECDSA-P192 曲线操作的支持，使设备可以同时执行 192 位和 256 位的 ECDSA 曲线操作。但请注意，如果 eFuse 写保护期间已永久禁用 ECDSA-P192 操作，则启用该配置项也无法重新启用该功能。

- `esp_efuse_enable_ecdsa_p192_curve_mode()` 可用于以编程方式启用 ECDSA-P192 曲线操作。它会向 eFuse 写入相应值，从而使设备支持 P-192 和 P-256 曲线操作。但请注意，若对应的 eFuse 区域已被写保护，则此 API 将调用失败。

## 生成确定性签名

ESP32-H21 的 ECDSA_DS 外设还支持使用确定性推导参数 K 来生成确定性签名，详见 RFC 6979 第 3.2 节。

## 生成非确定性签名

### 对 TRNG 的依赖

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

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

## 应用程序概述

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

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

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

## API 参考

### Header File

- components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa_contexts.h

- This header file can be included with:

  >     #include "psa_crypto_driver_esp_ecdsa_contexts.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

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。