Mbed TLS

[English]

Mbed TLS 是一个 C 代码库,用于实现加密基元、X.509 证书操作以及 SSL/TLS 和 DTLS 协议。该库代码占用空间小,适合嵌入式系统使用。

备注

ESP-IDF 使用的 Mbed TLS 复刻仓库 中包含对原生 Mbed TLS 的补丁。这些补丁与某些模块的硬件例程有关,如 bignum (MPI)ECC

Mbed TLS 通过提供以下内容支持 TLS 1.2、TLS 1.3 和 DTLS 1.2 通信:

  • TCP/IP 通信功能:监听、连接、接收、读/写。

  • SSL/TLS 通信功能:初始化、握手、读/写。

  • X.509 功能:CRT、CRL 和密钥处理

  • 随机数生成

  • 哈希

  • 加密/解密

备注

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,在此版本之前,某些功能仍处于试验状态。有关更多详细信息,请参阅 Mbed TLS ChangeLog

Mbed TLS 文档

Mbed TLS 文档请参阅以下(上游)指针:

ESP-IDF 的 Mbed TLS 支持

请在 此处 查找 ESP-IDF 不同分支上的 Mbed TLS 版本信息。

备注

参考 Mbed TLS 从 Mbed TLS 2.x 版本迁移到 3.0 及以上版本。

预设配置

ESP-IDF 为 Mbed TLS 提供了基于预设的配置系统,用于简化设置并为不同的应用场景提供优化后的初始配置。这套系统可以和现有的手动配置方式一同使用,先提供基础配置,然后可通过 menuconfig 或其他配置文件对其进行自定义。

预设

使用场景

主要特性

默认

通用应用

  • 支持 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 文件中添加以下代码:

# 包含默认预设(适用于大多数应用)
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)

备注

预设配置存放于 components/mbedtls/config/ 中,你可以自定义预设配置或将其作为基础模板使用。

自定义预设配置

在应用预设后,你可以使用以下任一种方法进一步自定义配置:

方法 1:使用 menuconfig(推荐)

# 在 CMakeLists.txt 中应用预设后
idf.py menuconfig

前往 Component Config > mbedTLS 修改设置,你的更改将覆盖预设的默认值。

方法 2:通过其他配置文件

也可以通过创建其他配置文件,将预设与自定义的配置相结合:

# 基于最小预设,添加自定义设置
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 安全存储)

  • 不同类别的密钥需要使用不同的存储分区

启用自定义后端

通过 menuconfigComponent Config > mbedTLS 中启用该功能:

配置范围内的 PSA 密钥 ID 会被路由到已注册的后端。其他所有密钥 ID(以及随机种子等 PSA 内部数据)继续使用默认的 NVS 后端。

实现自定义后端

实现 esp_psa_its_custom_ops_t 回调结构体,并在使用自定义范围内的 PSA Crypto 密钥之前进行注册:

#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 指针会作为第一个参数传递给每个回调。

备注

只有持久化密钥会经过 ITS 层。PSA 要求持久化密钥必须调用 psa_set_key_id(),因此应用程序始终可以控制分配哪些密钥 ID,进而决定它们落在哪个范围内。

如有需要,后端实现需自行处理 psa_storage_create_flags_t 的语义。

处理 PSA 密钥文件格式

通过 psa_its_set() / psa_its_get() 传输的字节流采用 Mbed TLS 存储规范中描述的 PSA 持久密钥文件格式。原样存储该 blob 的后端无需查看其内容;在写入时剥离头部以节省空间,或在读取时合成 blob 的后端(例如,将预配置的硬件密钥暴露为持久 PSA 密钥)则需要自行构造或解析。

为此,ESP-IDF 在 esp_psa_key_file.h 中提供以下辅助函数:

  • esp_psa_key_file_pack() —— 将 psa_key_attributes_t 结构和原始密钥字节封装为密钥 blob。

  • esp_psa_key_file_unpack() —— 将密钥 blob 解析回属性以及指向密钥字节段的指针。

  • esp_psa_key_file_size() —— 根据给定的密钥字节长度返回 blob 的总大小。

这些辅助函数直接实现规范文档中描述的字节布局,不依赖任何 Mbed TLS 内部函数。例如,仅存储内部密钥字节的后端可以在读取时重建 blob:

#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 命名空间作为自定义后端)请参考 security/psa_its_custom_backend

应用示例

ESP-IDF 中的示例使用 ESP-TLS,为访问常用的 TLS 功能提供了简化的 API 接口。

参考示例 protocols/https_server/simple (简单的 HTTPS 服务器)和 protocols/https_request (发起 HTTPS 请求)了解更多信息。

如需直接使用 Mbed TLS API,请参考示例 protocols/https_mbedtls。该示例演示了如何用 Mbed TLS 创建 HTTPS 连接。具体做法是配置安全的套接字,并使用证书包进行验证。

protocols/smtp_client 示例演示了如何使用 Mbed TLS API,通过带有 STARTTLS 的 SMTP 发送电子邮件(包括附件)。

重要配置

Mbed TLS 配置系统支持预设配置。Component Config > mbedTLS 中的部分重要配置选项如下所示。点击 此处 获取完整配置选项列表。

核心配置:

TLS 协议配置:

证书支持:

加密算法:

备注

新的配置结构将各项配置按照“核心配置”、“TLS 协议配置”、“对称加密算法”、“非对称加密算法”、“哈希函数”和“硬件加速”等类别进行分类,便于查找和管理配置。

调试 mbedTLS

为启用调试,请添加以下配置:

CONFIG_MBEDTLS_DEBUG=y
CONFIG_MBEDTLS_DEBUG_LEVEL=3
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y

性能优化

为获得最佳性能,请尽可能 启用硬件加速

CONFIG_MBEDTLS_HARDWARE_AES=y
CONFIG_MBEDTLS_HARDWARE_SHA=y
CONFIG_MBEDTLS_HARDWARE_MPI=y
CONFIG_MBEDTLS_HARDWARE_ECC=y

性能和内存调整

减少内存使用

下表展示了在不同配置下,用 Mbed TLS 作为 SSL/TLS 库运行示例 protocols/https_request (启用服务器验证)时,内存的实际使用情况。

Mbed TLS 测试

相关配置

堆使用(近似值)

默认

NA

42196 B

启用 SSL 动态 buffer 长度

CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH

42120 B

禁用保留对端证书

CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE

38533 B

启用动态 TX/RX buffer

CONFIG_MBEDTLS_DYNAMIC_BUFFER CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA :CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT

22013 B

备注

这些值会随着配置选项和 Mbed TLS 版本的变化而变化。

减小固件大小

Component Config > mbedTLS 配置中,多个 Mbed TLS 功能已默认启用。如无需使用,可以禁用以减小固件大小。详情请参阅 最小化固件大小


此文档对您有帮助吗?