Files
2026-07-13 13:04:25 +08:00

422 lines
16 KiB
ReStructuredText
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Mbed TLS
========
:link_to_translation:`en:[English]`
`Mbed TLS <https://github.com/Mbed-TLS/mbedtls>`_ 是一个 C 代码库,用于实现加密基元、X.509 证书操作以及 SSL/TLS 和 DTLS 协议。该库代码占用空间小,适合嵌入式系统使用。
.. note::
ESP-IDF 使用的 Mbed TLS `复刻仓库 <https://github.com/espressif/mbedtls>`_ 中包含对原生 Mbed TLS 的补丁。这些补丁与某些模块的硬件例程有关,如 ``bignum (MPI)````ECC``。
Mbed TLS 通过提供以下内容支持 TLS 1.2、TLS 1.3 和 DTLS 1.2 通信:
- TCP/IP 通信功能:监听、连接、接收、读/写。
- SSL/TLS 通信功能:初始化、握手、读/写。
- X.509 功能:CRT、CRL 和密钥处理
- 随机数生成
- 哈希
- 加密/解密
.. note::
Mbed TLS v3.x.x 系列仅支持 TLS 1.2 和 TLS 1.3 协议。对 SSL 3.0、TLS 1.0/1.1 和 DTLS 1.0 的支持已被删除(弃用)。从 Mbed TLS v3.6.0 版本开始完全支持 TLS 1.3,在此版本之前,某些功能仍处于试验状态。有关更多详细信息,请参阅 :component_file:`Mbed TLS ChangeLog <mbedtls/mbedtls/ChangeLog>`。
Mbed TLS 文档
------------------
Mbed TLS 文档请参阅以下(上游)指针:
- `API Reference`_
- `Knowledge Base`_
ESP-IDF 的 Mbed TLS 支持
------------------------------
请在 `此处 <https://github.com/espressif/mbedtls/wiki#mbed-tls-support-in-esp-idf>`__ 查找 ESP-IDF 不同分支上的 Mbed TLS 版本信息。
.. note::
参考 :ref:`migration_guide_mbedtls` 从 Mbed TLS 2.x 版本迁移到 3.0 及以上版本。
预设配置
^^^^^^^^
ESP-IDF 为 Mbed TLS 提供了基于预设的配置系统,用于简化设置并为不同的应用场景提供优化后的初始配置。这套系统可以和现有的手动配置方式一同使用,先提供基础配置,然后可通过 menuconfig 或其他配置文件对其进行自定义。
.. list-table::
:header-rows: 1
:widths: 15 25 35
:align: center
* - 预设
- 使用场景
- 主要特性
* - **默认**
- 通用应用
- • 支持 TLS 1.2 和 1.3
• 启用证书包
• 硬件加速
• 支持完整的加密算法套件
* - **最小化**
- 资源受限应用
- • 仅 TLS 1.2 客户端
• RSA 和 PSK 密钥交换
• AES-128 CBC/CTR 模式
• 基本的 X.509 解析
* - **蓝牙 (BT)**
- 蓝牙应用
- • 针对低功耗蓝牙安全性需求进行优化
• 支持 ECC P-256 曲线
• 最小的 TLS 开销
• 蓝牙特定算法
使用预设配置
^^^^^^^^^^^^
预设配置是 mbedTLS 配置的 **起点**,你可以直接使用,也可以借助 ESP-IDF 提供的标准配置方式对其进一步自定义。
要使用预设配置,请在调用 ``project()`` **之前**,先在项目的 ``CMakeLists.txt`` 文件中添加以下代码:
.. code-block:: cmake
# 包含默认预设(适用于大多数应用)
list(APPEND sdkconfig_defaults $ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_default.conf)
# 适用于资源受限的应用
list(APPEND sdkconfig_defaults $ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_minimal.conf)
# 适用于蓝牙应用
list(APPEND sdkconfig_defaults $ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_bt.conf)
# 标准的 ESP-IDF 项目设置
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(my_project)
.. note::
预设配置存放于 ``components/mbedtls/config/`` 中,你可以自定义预设配置或将其作为基础模板使用。
自定义预设配置
^^^^^^^^^^^^^^
在应用预设后,你可以使用以下任一种方法进一步自定义配置:
**方法 1:使用 menuconfig(推荐)**
.. code-block:: bash
# 在 CMakeLists.txt 中应用预设后
idf.py menuconfig
前往 ``Component Config`` > ``mbedTLS`` 修改设置,你的更改将覆盖预设的默认值。
**方法 2:通过其他配置文件**
也可以通过创建其他配置文件,将预设与自定义的配置相结合:
.. code-block:: cmake
# 基于最小预设,添加自定义设置
list(APPEND SDKCONFIG_DEFAULTS
$ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_minimal.conf
${CMAKE_CURRENT_SOURCE_DIR}/my_custom_mbedtls.conf
)
从手动配置迁移
^^^^^^^^^^^^^^
预设系统对手动配置进行了补充。假设目前你手动配置了 mbedTLS:
**选项 1:保留当前配置**
当前的手动配置无需任何更改即可工作。
**选项 2:迁移到预设并对其进行自定义**
1. **选择基础预设**,该预设最接近你当前的配置。
2.``CMakeLists.txt``**应用预设**
3. **使用 menuconfig** 调整设置,匹配需求。
4. **全面测试** 以确保功能完整。
配置类别
^^^^^^^^
新的 mbedTLS 配置系统按逻辑进行分类,便于查找:
**核心配置**
包括内存分配、线程和调试选项的基本 mbedTLS 设置。
**TLS 协议配置**
TLS/DTLS 协议版本、模式(客户端/服务器)和特定协议的功能。
**对称加密算法**
块密码(AES、ARIA 等)、加密算法模式(CBC、GCM 等)和对称密码学。
**非对称加密算法**
RSA、ECC 和其他公钥密码学算法。
**哈希函数**
消息摘要算法(SHA-256、SHA-512 等)和 HMAC。
**硬件加速**
为加密操作提供 ESP32 专用的硬件加速支持。
**证书支持**
X.509 证书解析、验证和证书包管理。
PSA ITS 自定义存储后端
-----------------------
ESP-IDF 的 PSA 内部可信存储 (Internal Trusted Storage, ITS) 实现默认使用 NVS 作为持久化 PSA Crypto 密钥的存储后端。自定义存储后端功能允许将保留范围内的 PSA 密钥 ID 路由到用户提供的存储实现,而其他密钥继续使用 NVS。
适用场景包括:
- 某些密钥需要存储在不同的文件系统中(如 FATFS、SPIFFS、littlefs
- 密钥需要硬件保护的加密存储(例如通过 TEE 安全存储)
- 不同类别的密钥需要使用不同的存储分区
启用自定义后端
^^^^^^^^^^^^^^^
通过 ``menuconfig````Component Config`` > ``mbedTLS`` 中启用该功能:
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_STORAGE_BACKEND`:启用自定义存储后端
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MIN`:自定义密钥 ID 范围的起始值(默认 ``0x30000000``
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MAX`:自定义密钥 ID 范围的结束值(默认 ``0x3FFFFFFF``
配置范围内的 PSA 密钥 ID 会被路由到已注册的后端。其他所有密钥 ID(以及随机种子等 PSA 内部数据)继续使用默认的 NVS 后端。
实现自定义后端
^^^^^^^^^^^^^^^
实现 ``esp_psa_its_custom_ops_t`` 回调结构体,并在使用自定义范围内的 PSA Crypto 密钥之前进行注册:
.. code-block:: c
#include "esp_psa_its.h"
static psa_status_t my_set(void *ctx, const psa_storage_uid_t uid,
const uint32_t data_length, const void *p_data,
const psa_storage_create_flags_t create_flags)
{
/* 存储 uid 对应的 blob */
}
static psa_status_t my_get(void *ctx, const psa_storage_uid_t uid,
const uint32_t data_offset, const uint32_t data_length,
void *p_data, size_t *p_data_length)
{
/* 读取 uid 对应的 blob */
}
static psa_status_t my_get_info(void *ctx, const psa_storage_uid_t uid,
struct psa_storage_info_t *p_info)
{
/* 返回 uid 对应 blob 的大小和标志位 */
}
static psa_status_t my_remove(void *ctx, const psa_storage_uid_t uid)
{
/* 删除 uid 对应的 blob */
}
static esp_psa_its_custom_ops_t my_ops = {
.set = my_set,
.get = my_get,
.get_info = my_get_info,
.remove = my_remove,
.ctx = NULL, /* 可选的用户上下文 */
};
/* 在使用自定义范围内的 PSA 密钥之前注册 */
esp_psa_its_register_custom_backend(&my_ops);
回调函数的签名与 PSA ITS API 保持一致。每个回调接收原始的 ``psa_storage_uid_t``\ (而非字符串),允许实现根据数值型密钥 ID 进行路由决策。``ctx`` 指针会作为第一个参数传递给每个回调。
.. note::
只有持久化密钥会经过 ITS 层。PSA 要求持久化密钥必须调用 ``psa_set_key_id()``,因此应用程序始终可以控制分配哪些密钥 ID,进而决定它们落在哪个范围内。
如有需要,后端实现需自行处理 ``psa_storage_create_flags_t`` 的语义。
处理 PSA 密钥文件格式
^^^^^^^^^^^^^^^^^^^^^^
通过 ``psa_its_set()`` / ``psa_its_get()`` 传输的字节流采用 Mbed TLS `存储规范 <https://github.com/Mbed-TLS/TF-PSA-Crypto/blob/development/docs/architecture/mbed-crypto-storage-specification.md>`__\ 中描述的 PSA 持久密钥文件格式。原样存储该 blob 的后端无需查看其内容;在写入时剥离头部以节省空间,或在读取时合成 blob 的后端(例如,将预配置的硬件密钥暴露为持久 PSA 密钥)则需要自行构造或解析。
为此,ESP-IDF 在 ``esp_psa_key_file.h`` 中提供以下辅助函数:
- :cpp:func:`esp_psa_key_file_pack` —— 将 ``psa_key_attributes_t`` 结构和原始密钥字节封装为密钥 blob。
- :cpp:func:`esp_psa_key_file_unpack` —— 将密钥 blob 解析回属性以及指向密钥字节段的指针。
- :cpp:func:`esp_psa_key_file_size` —— 根据给定的密钥字节长度返回 blob 的总大小。
这些辅助函数直接实现规范文档中描述的字节布局,不依赖任何 Mbed TLS 内部函数。例如,仅存储内部密钥字节的后端可以在读取时重建 blob:
.. code-block:: c
#include "esp_psa_key_file.h"
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attr, key_data_len * 8);
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attr, PSA_ALG_CBC_NO_PADDING);
size_t blob_size = esp_psa_key_file_size(key_data_len);
uint8_t *blob = calloc(1, blob_size);
size_t written = 0;
esp_psa_key_file_pack(&attr, key_data, key_data_len, blob, blob_size, &written);
/* blob 现在包含完整的 PSA 持久密钥文件;按 psa_its_get() 的 offset/length
* 参数将所请求的窗口复制到 p_data。 */
完整的可运行示例(使用自定义 NVS 命名空间作为自定义后端)请参考 :example:`security/psa_its_custom_backend`
应用示例
--------
ESP-IDF 中的示例使用 :doc:`/api-reference/protocols/esp_tls`,为访问常用的 TLS 功能提供了简化的 API 接口。
参考示例 :example:`protocols/https_server/simple` (简单的 HTTPS 服务器)和 :example:`protocols/https_request` (发起 HTTPS 请求)了解更多信息。
如需直接使用 Mbed TLS API,请参考示例 :example:`protocols/https_mbedtls`。该示例演示了如何用 Mbed TLS 创建 HTTPS 连接。具体做法是配置安全的套接字,并使用证书包进行验证。
:example:`protocols/smtp_client` 示例演示了如何使用 Mbed TLS API,通过带有 STARTTLS 的 SMTP 发送电子邮件(包括附件)。
重要配置
--------
Mbed TLS 配置系统支持预设配置。``Component Config`` > ``mbedTLS`` 中的部分重要配置选项如下所示。点击 :ref:`此处 <CONFIG_MBEDTLS_MEM_ALLOC_MODE>` 获取完整配置选项列表。
**核心配置:**
.. list::
:SOC_SHA_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_SHA`:支持硬件 SHA 加速
:SOC_AES_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_AES`:支持硬件 AES 加速
:SOC_MPI_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_MPI`:支持硬件 MPI(大数)加速
:SOC_ECC_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_ECC`:支持硬件 ECC 加速
- :ref:`CONFIG_MBEDTLS_MEM_ALLOC_MODE`:内存分配策略(内部/外部/自定义)
- :ref:`CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN`:用于内存优化的非对称输入/输出片段长度
- :ref:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`:启用动态 TX/RX buffer 分配
- :ref:`CONFIG_MBEDTLS_DEBUG`:启用 mbedTLS 调试(有助于调试)
**TLS 协议配置:**
.. list::
- :ref:`CONFIG_MBEDTLS_TLS_ENABLED`:启用 TLS 协议支持
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_2`:支持 TLS 1.2(推荐)
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_3`:支持 TLS 1.3(最新标准)
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_DTLS`:支持基于 UDP 的 DTLS
- :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS`:支持 TLS 会话恢复(客户端会话票据)
- :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS`:支持 TLS 会话恢复(服务器会话票据)
- :ref:`CONFIG_MBEDTLS_SSL_ALPN`:支持应用层协议协商
- :ref:`CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION`:支持服务器名称指示 (SNI)
**证书支持:**
.. list::
- :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE`:支持受信任的根证书包(详情请参阅 :doc:`/api-reference/protocols/esp_crt_bundle`
- :ref:`CONFIG_MBEDTLS_X509_USE_C`:启用 X.509 证书支持
- :ref:`CONFIG_MBEDTLS_PEM_PARSE_C`:读取并解析 PEM 格式的证书
- :ref:`CONFIG_MBEDTLS_PEM_WRITE_C`:编写 PEM 格式的证书
- :ref:`CONFIG_MBEDTLS_X509_CRT_PARSE_C`:解析 X.509 证书
- :ref:`CONFIG_MBEDTLS_X509_CRL_PARSE_C`:解析 X.509 证书吊销列表
**加密算法:**
.. list::
- :ref:`CONFIG_MBEDTLS_AES_C`:支持 AES 块密码
- :ref:`CONFIG_MBEDTLS_RSA_C`RSA 公钥密码系统
- :ref:`CONFIG_MBEDTLS_ECP_C`:支持椭圆曲线密码学
- :ref:`CONFIG_MBEDTLS_ECDSA_C`:椭圆曲线数字签名算法
- :ref:`CONFIG_MBEDTLS_ECDH_C`:椭圆曲线 Diffie-Hellman 密钥交换
- :ref:`CONFIG_MBEDTLS_SHA256_C`SHA-256 哈希函数
- :ref:`CONFIG_MBEDTLS_SHA512_C`SHA-512 哈希函数
- :ref:`CONFIG_MBEDTLS_GCM_C`Galois/Counter 模式用于认证加密
.. note::
新的配置结构将各项配置按照“核心配置”、“TLS 协议配置”、“对称加密算法”、“非对称加密算法”、“哈希函数”和“硬件加速”等类别进行分类,便于查找和管理配置。
调试 mbedTLS
^^^^^^^^^^^^
为启用调试,请添加以下配置:
.. code-block:: kconfig
CONFIG_MBEDTLS_DEBUG=y
CONFIG_MBEDTLS_DEBUG_LEVEL=3
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
性能优化
^^^^^^^^
为获得最佳性能,请尽可能 **启用硬件加速**
.. code-block:: kconfig
CONFIG_MBEDTLS_HARDWARE_AES=y
CONFIG_MBEDTLS_HARDWARE_SHA=y
CONFIG_MBEDTLS_HARDWARE_MPI=y
CONFIG_MBEDTLS_HARDWARE_ECC=y
性能和内存调整
--------------
.. _reducing_ram_usage_mbedtls:
减少内存使用
^^^^^^^^^^^^^^
下表展示了在不同配置下,用 Mbed TLS 作为 SSL/TLS 库运行示例 :example:`protocols/https_request` (启用服务器验证)时,内存的实际使用情况。
.. list-table::
:header-rows: 1
:widths: 25 60 30
:align: center
* - Mbed TLS 测试
- 相关配置
- 堆使用(近似值)
* - 默认
- NA
- 42196 B
* - 启用 SSL 动态 buffer 长度
- :ref:`CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH`
- 42120 B
* - 禁用保留对端证书
- :ref:`CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE`
- 38533 B
* - 启用动态 TX/RX buffer
- :ref:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`
:ref:`CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA`
::ref:`CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT`
- 22013 B
.. note::
这些值会随着配置选项和 Mbed TLS 版本的变化而变化。
.. note::
:ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` 默认启用。如果无需支持交叉签名证书链,禁用该选项可将 TLS 握手期间的堆内存峰值降低约 1 KB,但代价是 flash 中的证书包体积会增大。详情请参阅 :doc:`/api-reference/protocols/esp_crt_bundle`
减小固件大小
^^^^^^^^^^^^^^^^^^
``Component Config`` > ``mbedTLS`` 配置中,多个 Mbed TLS 功能已默认启用。如无需使用,可以禁用以减小固件大小。详情请参阅 :ref:`最小化固件大小 <minimizing_binary_mbedtls>`
.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.5/
.. _`Knowledge Base`: https://mbed-tls.readthedocs.io/en/latest/kb/