# 安全性

[English]

## Mbed TLS

从 ESP-IDF v6.0 开始，一些已废弃的 mbedtls 头文件已被移除，例如 `esp32/aes.h`、`esp32/sha.h`、`esp32s2/aes.h`、`esp32s2/sha.h` 和 `esp32s2/gcm.h`。请改为分别包含 `aes/esp_aes.h`、`sha/sha_core.h` 和 `aes/esp_aes_gcm.h`。

SHA 模块头文件 `sha/sha_dma.h` 和 `sha/sha_block.h` 也已废弃并被移除，请改为包含 `sha/sha_core.h`。

### PSA Crypto 迁移

在 ESP-IDF v6.0 中，多个 ESP-IDF 组件已完成从传统 Mbed TLS 加密 API（例如 `mbedtls_sha*_*()`、`mbedtls_md*_*()` 等）向 PSA Crypto API 的迁移。

此次迁移使 ESP-IDF 与将 PSA Crypto 作为主要加密接口的 Mbed TLS v4.x 保持同步，并能够在支持时通过 PSA 驱动程序启用 ESP-IDF 硬件加速功能。

#### Mbed TLS v4.0 迁移

ESP-IDF v6.0 已升级至 Mbed TLS v4.0，PSA Crypto 成为主要加密接口 （TF-PSA-Crypto 提供加密功能，Mbed TLS 侧重于 TLS 和 X.509）。此变更可能直接影响使用 Mbed TLS 加密原语、TLS 配置或 Mbed TLS 内部/私有声明的应用程序。

- 重大变更：在 Mbed TLS v4.0 中，大多数传统加密 API 已被移除，PSA Crypto 成为主要接口。如果应用直接使用传统的 `mbedtls_*` 加密原语，则无法直接兼容，需迁移到 PSA Crypto API。

- 重大变更：在执行任何加密操作之前（包括解析密钥/证书或启动 TLS 握手等操作），必须调用 `psa_crypto_init()`。ESP-IDF 在常规启动过程中会初始化 PSA，因此大多数应用保持兼容；但对于早于常规启动流程运行的代码，需显式调用 `psa_crypto_init()`。

- 重大变更：`esp_ecdsa_load_pubkey()`、`esp_ecdsa_privkey_load_mpi()`、`esp_ecdsa_privkey_load_pk_context()`、`esp_ecdsa_set_pk_context()`、`esp_ecdsa_tee_load_pubkey()` 和 `esp_ecdsa_tee_set_pk_context()` 已被弃用并移除。旧的 `esp_ecdsa_pk_conf_t` 配置已被 `esp_ecdsa_opaque_key_t` 取代，后者支持由 ECDSA 硬件提供的不透明密钥。应用程序可以配置该结构体并通过 `psa_import_key()` 导入，从而使用标准 PSA Crypto API 启用所有 ECDSA 操作。

- 重大变更：原需应用提供 RNG 回调（`f_rng`、`p_rng`）的 API，在 Mbed TLS v4.0 中已改为使用 PSA RNG。使用旧函数原型的代码将无法直接兼容，需要更新为新的 API 定义（例如 X.509 写入 API、SSL cookie 设置以及 SSL ticket 设置）。

- 重大变更：TLS 1.2 / DTLS 1.2 的互操作性可能受到影响，因为 Mbed TLS v4.0 移除了对基于有限域 DHE、无前向保密的 RSA 密钥交换（以及静态 ECDH）的支持。如果对等端需要使用已移除的密码套件，TLS 连接将不兼容并可能失败；需相应更新服务器或客户端的密码套件配置。

- 重大变更：证书或对等端中使用的椭圆曲线位数小于 250 位（例如 secp192r1/secp224r1）已不再受支持。

- 注意：

  - 避免依赖 Mbed TLS 的私有声明（例如 `mbedtls/private/` 目录下的头文件，或通过 `MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS` / `MBEDTLS_ALLOW_PRIVATE_ACCESS` 启用的声明）。这些私有接口可能未经通知即发生变更。

  - PSA Crypto 迁移 (TF-PSA-Crypto) 可能会增加 flash 占用，具体取决于启用的功能。以下示例可作为参考：

    示例 | 非 PSA 构建（字节） | PSA 迁移（字节） | 差值（字节） | 差值（%）
    --- | --- | --- | --- | ---
    protocols/esp_http_client | 609041 | 646293 | 37252 | 5.76
    protocols/https_server | 871021 | 898717 | 27696 | 3.08
    protocols/http_server/simple | 785825 | 826909 | 41084 | 4.97

#### 默认配置更改

- 注意：默认的 Mbed TLS 配置在 ESP-IDF v6.0 中已收紧，以提升安全性并降低资源占用：

  - `MBEDTLS_ARIA_C` 默认禁用。依赖 ARIA 的应用必须在 `menuconfig` (Component config -> mbedTLS) 中显式启用，或通过自定义 `components/mbedtls/config/mbedtls_preset_default.conf` 来启用。

  - 默认禁用 `secp192r1`，这与证书和 TLS 中移除对 250 位以下椭圆曲线的支持策略保持一致。如果某个应用在 TLS／证书之外仍然需要旧版曲线支持，则必须显式启用该功能（例如通过定义 `PSA_WANT_ECC_SECP_R1_192=1`），并验证其兼容性。注意：该旧版支持可能会在下一次 ESP-IDF 小版本更新中被禁用。

- `MBEDTLS_THREADING_C` 默认启用。这为 PSA Crypto 密钥管理 API 和 `psa_crypto_init()` 提供了线程安全。当在多线程环境中使用 PSA Crypto 时（例如，并发的 TLS 连接、证书操作，或任何可能从不同线程调用密码运算的场景），建议保持此配置为启用状态。对于仅从单个线程调用 PSA 函数的应用程序，不受此更改影响，并且如果需要，可以选择禁用线程支持。

- `MBEDTLS_THREADING_PTHREAD` 默认启用。这使得 Mbed TLS 能够使用 pthread 原语来实现线程支持。

- `MBEDTLS_THREADING_ALT` 默认禁用。这会禁止 Mbed TLS 使用替代线程原语来实现线程支持。

#### 参考文档

- Mbed TLS 4.0 迁移指南

- TF-PSA-Crypto 1.0 迁移指南

- TF-PSA-Crypto PSA 过渡说明

#### 上游 Mbed TLS PSA 说明

部分应用程序此前可能访问的数据结构和内部状态，在使用基于 PSA 的 Mbed TLS 版本时已不可用。如果应用依赖直接访问 Mbed TLS 的内部状态（例如以结构体字段形式访问熵/DRBG 上下文），请迁移到受支持的公共 API。

#### ESP-IDF 中的 PSA 持久化存储 (ITS)

ESP-IDF 提供了基于 NVS 的 PSA 内部可信存储 (ITS) 实现，因此无需文件系统即可使用 PSA 持久化存储。如果应用使用 PSA 持久化密钥/存储，请确保在首次使用前 NVS 已就绪并初始化完毕。

#### 已移除的弃用 API (Mbed TLS / crypto)

以下废弃函数已被移除：

- `esp_aes_encrypt()` – 请使用 `esp_internal_aes_encrypt()` 代替。

- `esp_aes_decrypt()` – 请使用 `esp_internal_aes_decrypt()` 代替。

- `esp_crypto_shared_gdma_start()` – 请使用 `esp_crypto_shared_gdma_start_axi_ahb()` 代替。

注意，新的 AES 函数返回错误代码以提供更好的错误处理，与返回 void 的旧函数不同。

## 数字签名 (DS) 外设

现已通过 PSA Crypto RSA DS 驱动程序 使用 DS 外设，而不是采用旧版 Mbed TLS RSA 签名/解密的替代实现。面向应用的流程（从安全证书／NVS 获取 DS 上下文，传递给 ESP-TLS，或用于签名／解密）保持不变，仅内部实现改为使用 PSA 驱动。

- 破坏性变更：已移除旧版 DS 集成，并由 PSA RSA DS 驱动程序取代。

- 迁移：

  - 针对 TLS (ESP-TLS)： 启用 `CONFIG_ESP_TLS_USE_DS_PERIPHERAL`，并在 `esp_tls_cfg_t` 中将 `esp_ds_data_ctx_t` 作为 `ds_data` 传入。详见 ESP-TLS 文档 中的 ESP-TLS 的数字签名 章节。

  - 用于直接使用（在应用代码中进行签名／解密）： 启用 `CONFIG_MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL`，使用 `psa_import_key()` 并指定 `PSA_KEY_LIFETIME_ESP_RSA_DS_VOLATILE` 导入 `esp_rsa_ds_opaque_key_t`，然后使用 `psa_sign_hash()` 或 `psa_asymmetric_decrypt()`。参见 数字签名 (DS) 文档中的章节 通过 PSA Crypto 使用 DS 外设。

## HMAC 外设

现已通过 PSA Crypto HMAC 驱动程序 使用 HMAC 外设，而不是使用旧版 `esp_hmac_calculate()` API。应用需要填写 `esp_hmac_opaque_key_t` 结构体，并通过 `psa_import_key()` API 使用 `PSA_KEY_LIFETIME_ESP_HMAC` 生命周期属性将其导入。然后可以使用 `psa_mac_compute()` API 计算 HMAC。

## BluFi

BluFi（基于 BLE 的 Wi-Fi 配网）功能受到 ESP-IDF v6.0 中 Mbed TLS v4.x / PSA Crypto 迁移的影响。

- 重大变更：BluFi 协议版本已更新（`BTC_BluFi_SUB_VER` 从 `0x03` 升级至 `0x04`）。ESP-IDF 使用的 BluFi 安全协商实现也同步更新为基于 PSA Crypto 的方案（参考更新后的 `examples/bluetooth/BluFi` 示例）。

- 影响：基于旧版 BluFi 加密/协议实现构建的现有 BluFi 客户端应用（例如手机 App），可能无法再与使用 ESP-IDF v6.0 构建的设备互通。通常表现为在配网时出现 BluFi 协商或连接失败。

- 必要操作：请同步更新两端应用：

  - 将设备固件升级至 ESP-IDF v6.0。

  - 将 BluFi 客户端应用更新至兼容 ESP-IDF v6.0 新版 BluFi 协议和安全协商的版本。

## 引导加载程序支持

已弃用的 API

以下函数已被弃用：

- `esp_flash_encryption_enabled()` 已被弃用。请使用 `esp_efuse_is_flash_encryption_enabled()` 代替。需要依赖的组件由 `bootloader_support` 替换为 `efuse`。

安全启动中的 ECDSA 曲线选择

- 在 ESP-IDF v6.0 中，用于安全启动的 ECDSA 应为 NISTP256/NISTP384 曲线。

- 对旧版 NISTP192 的支持已弃用，仅当通过 `CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_192_BITS` 显式启用时方可使用。

- 对旧版 NISTP192 的支持可能会在下一个 ESP-IDF 版本中被移除，因此强烈建议迁移至 NISTP256/NISTP384。

已移除的废弃 API

以下废弃函数已被移除：

- `esp_secure_boot_verify_signature_block()` – 请使用 `esp_secure_boot_verify_ecdsa_signature_block()` 代替。

## NVS 安全方案

- 当 SoC 具备 HMAC 外设并启用了 flash 加密时，如果同时还启用了 NVS 加密，则默认会选择基于 HMAC 的 NVS 加密方案，而不是基于 flash 加密的方案。如果你的应用程序之前使用基于 flash 加密的方案，则需要通过 `menuconfig` 或项目的 `sdkconfig` 文件，手动将 NVS 加密方案从 HMAC 配置为 flash 加密（即设置 `CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC=y`）。

## Mbed TLS v4.1 迁移

### 引导加载程序支持

- 从 Mbed TLS 4.1 开始，已移除对旧版 NISTP192 的支持。

此文档对您有帮助吗？

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

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