实战指南:硬件级 RSA 私钥保护与 PSA Crypto 集成)
ESP-IDF RSA 数字签名外设RSA_DS实战指南硬件级 RSA 私钥保护与 PSA Crypto 集成【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf导读本文以 ESP-IDF 官方文档 ds.rst 为骨架系统讲解 RSA 数字签名外设RSA_DS的原理、密钥配置流程、ESP-IDF 低层 APIesp_ds_sign系列与 PSA Crypto RSA_DS 驱动的使用方法。RSA_DS 让 RSA 私钥以密文形式存放于 flashHMAC 密钥烧录于 eFuse 且可读保护签名计算全程在硬件内完成软件永远接触不到解密密钥。读完本文你将掌握如何生成并加密 RSA 私钥参数、如何烧录 HMAC 密钥、如何用阻塞/非阻塞 API 完成硬件签名、如何通过 PSA 标准 APIpsa_sign_hash/psa_asymmetric_decrypt使用 RSA_DS以及如何为 TLS 双向认证配置该外设。RSA_DS 是什么硬件完成、密钥永不出芯片RSA 数字签名外设RSA Digital Signature Peripheral简称 RSA_DS为基于 RSA 的消息签名提供硬件加速。与纯软件 RSA 相比它的核心价值在于密钥隔离签名的私钥参数以 AES 加密的形式存放在 flash 中用于派生 AES 密钥的 HMAC 输入密钥烧录在 eFuse 中并可通过 eFuse 读保护阻止软件读取。整个签名流程在硬件内部完成因此无论是 RSA 参数的解密密钥还是 HMAC 派生函数的输入密钥在签名计算过程中都无法被软件观测到。调用签名时软件只需指定三个要素参见 esp_ds.h用于 HMAC 的 eFuse key block IDhmac_key_id_t加密 RSA 私钥参数在 flash 中的位置const esp_ds_data_t *data待签名的消息。在支持 Key Manager 的新款芯片上SOC_KEY_MANAGER_SUPPORTEDRSA_DS 还可以使用存放在 Key Manager 中的密钥AES 密钥可直接以ESP_KEY_MGR_DS_KEY类型部署到 Key Manager从而替代 eFuse key block。安全模型与数据流HMAC 派生 AES 加密 eFuse 读保护RSA_DS 的安全模型由三层密钥体系构成层次载体作用HMAC 输入密钥256 位eFuse key block可读保护作为 HMAC 密钥派生函数KDF的输入AES 加密密钥256 位由 HMAC 在硬件内派生不可见解密 flash 中存放的 RSA 私钥参数RSA 私钥参数flashAES-CBC 加密存储签名运算使用的 Y指数、M模数等私钥参数在 esp_ds_data_t 中组织为rsa_lengthRSA 长度、iv[4]128 位初始化向量、c[ESP_DS_C_LEN]AES-CBC 加密后的参数密文。从 esp_ds.h 的注释可以还原密文c的明文布局操作数 YRSA 指数、MRSA 模数、r_bar各占最大 RSA 位长操作数 MD消息摘要256 位操作数 M 与 L各 32 位操作数 beta填充值64 位。因此ESP_DS_C_LEN的计算公式为(3 × 最大RSA位长 256 32 32 64) / 8字节——这就是文档中提到esp_ds_data_t约 12001600 字节视芯片的SOC_RSA_MAX_BIT_LEN而定的原因。源码还通过_Static_assert强制保证esp_ds_data_t与 ROM 中的ets_ds_data_t内存布局完全一致二者通过裸指针转换使用见 esp_ds.c。签名运算本身为硬件实现的模幂运算Z X^Y mod M其中 Z 为签名、X 为输入消息、Y 与 M 为私钥参数。密钥生成与参数加密运行前的一站式准备在使用 RSA_DS 之前必须在软件侧在芯片上或主机上完成 HMAC 密钥与 RSA 私钥的创建和存储。ESP-IDF 为此提供两个关键 API见 esp_ds.hesp_efuse_write_block将 256 位 HMAC 密钥烧写入 eFuse key blockesp_hmac_calculate以 HMAC 作为密钥派生函数加密 RSA 私钥参数。该函数使用 HMAC 外设的 upstream 模式对给定消息计算 SHA-256 HMAC输出 32 字节结果见 esp_hmac.h并要求对应 eFuse key block 的 purpose 字段设为 HMAC upstream purpose 值。加密私钥参数的完整流程可直接调用esp_ds_encrypt_params完成// 1) 准备明文私钥参数注意Y、M、Rb、M_prime 均须为小端格式 esp_ds_p_data_t p_data { .Y { ... }, // RSA 指数exp长度等于 RSA 私钥位长 .M { ... }, // RSA 模数modulus长度等于 RSA 私钥位长 .Rb { ... }, // RSA r 逆操作数 .M_prime 0, // RSA M prime 操作数 .length 64, // RSA 长度32 位字为单位2048 位即 64 字 }; // 2) 随机生成 16 字节 IV 与 32 字节 HMAC 密钥 uint8_t iv[ESP_DS_IV_LEN]; // 128 位 IV uint8_t hmac_key[ESP_DS_DATA_KEY_SIZE]; // 32 字节 esp_fill_random(iv, sizeof(iv)); esp_fill_random(hmac_key, sizeof(hmac_key)); // 3) 加密 RSA 参数 esp_ds_data_t data {0}; esp_err_t err esp_ds_encrypt_params(data, iv, p_data, hmac_key); // err ESP_OK 后data 即可写入 flash 持久化 // 4) 将 HMAC 密钥烧入 eFuse烧录后务必彻底擦除内存中的密钥副本 err esp_efuse_write_block(ESP_EFUSE_KEY_BLOCK_1, hmac_key, 0, ESP_DS_DATA_KEY_SIZE * 8);实现细节见 esp_ds.cesp_ds_encrypt_params内部会锁定并启用 AES、SHA、RSA 与 HMAC 外设计算HMAC_SHA256(key, iv)派生 AES 密钥再用 AES-CBC 加密各操作数。文档明确指出这一加密过程并非必须在本芯片上完成——在外部设备上完成加密、再把密文烧入 flash 同样可行。完成加密后明文私钥参数与 HMAC 密钥的软件副本必须彻底删除这是整个安全模型成立的前提。参数加密还提供带密钥类型参数的变体esp_ds_encrypt_params_using_key_typeESP_DS_KEY_HMAC/ESP_DS_KEY_AES见 esp_ds.h后者面向 Key Manager 场景——AES 密钥由 DS 外设内部使用以解密加密的 RSA 参数。RSA 长度支持 1024/2048/3072/4096 位由枚举esp_digital_signature_length_t定义(bits/32) - 1形式对应 RSA_LENGTH 寄存器值见 esp_ds.h。低层 API阻塞式与非阻塞式签名由于签名计算需要一定时间ESP-IDF 提供两种调用风格详见 esp_ds.h阻塞式esp_ds_sign简单直接调用后一直阻塞到签名完成。其内部通过vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS)10 ms 轮询见 esp_ds.c等待硬件完成是esp_ds_start_signesp_ds_finish_sign的封装二者不可并行使用。非阻塞式三步曲若软件在签名期间需要做其他事情esp_ds_context_t *ctx NULL; esp_err_t err esp_ds_start_sign(message, data, key_id, ctx); // ... 做其他事情 ... while (esp_ds_is_busy()) { // 周期性检查硬件是否完成 } uint8_t signature[256]; // 长度 (rsa_length 1) * 4 字节 err esp_ds_finish_sign(signature, ctx);三个 API 的职责与注意点esp_ds_start_sign启动签名并返回esp_ds_context_t上下文。它会锁定 HMAC、SHA、AES 与 RSA 组件因此必须及时调用esp_ds_finish_sign释放见 esp_ds.hesp_ds_is_busy返回外设是否忙碌仅在调用过esp_ds_start_sign后有效esp_ds_finish_sign取出签名结果并校验内嵌的消息摘要与填充。esp_ds_sign/esp_ds_start_sign计算的是裸 RSA 签名Z X^Y mod M必须自行转换成 TLS 等协议所需的格式如 PKCS#1 v1.5 或 PSS。两条硬性约束消息长度固定消息长度须为(data-rsa_length 1) * 4字节且为小端格式无自动填充对任意长度消息签名时输入通常是对真实消息哈希后、按所需长度补齐的结果即message padding(hash(inputMsg))。填充须由调用方自行完成。错误码esp_ds.h返回值注释包括ESP_ERR_INVALID_ARG参数为空或 rsa_length 越界、ESP_ERR_NO_MEM上下文分配失败、ESP_ERR_HW_CRYPTO_DS_HMAC_FAILHMAC 派生解密密钥失败、ESP_ERR_HW_CRYPTO_DS_INVALID_KEYHMAC 密钥传递问题、ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST消息摘要不匹配签名无效通常意味着加密的 RSA 参数被篡改或 flash 出错、ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING消息填充错误但因摘要匹配签名仍可读出。通过 PSA Crypto 驱动使用 RSA_DSRSA_DS 外设还通过PSA Crypto RSA_DS driver暴露为标准 PSA 接口可执行 PKCS#1 v1.5 / PSS 签名以及 PKCS#1 v1.5 / OAEP 解密。启用方式在Component configmbedTLS中开启CONFIG_MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL。该配置项为 bool默认关闭default n依赖SOC_DIG_SIGN_SUPPORTED其 help 文本说明其作用是“启用硬件 RSA 数字签名外设加速”见 mbedtls/Kconfig。PSA 驱动涉及的上下文结构定义在 psa_crypto_driver_esp_rsa_ds_contexts.hesp_ds_data_ctx_t持有esp_ds_data_t *esp_ds_data加密密钥数据、efuse_key_ideFuse block ID如 0/1、rsa_length_bitsRSA 私钥位长如 2048esp_rsa_ds_opaque_key_t包含ds_data_ctx指针在 Key Manager 芯片上还包含key_recovery_info指针。典型使用步骤文档与测试用例 test_ds_sign_and_decrypt.c 相互印证#include psa/crypto.h #include psa_crypto_driver_esp_rsa_ds.h // ds_ctx 指向 esp_ds_data_ctx_t例如来自 esp_secure_cert_mgr 或 NVS esp_ds_data_ctx_t *ds_ctx ...; esp_rsa_ds_opaque_key_t rsa_ds_opaque_key { .ds_data_ctx ds_ctx, }; psa_key_attributes_t attrs PSA_KEY_ATTRIBUTES_INIT; psa_set_key_type(attrs, PSA_KEY_TYPE_RSA_KEY_PAIR); psa_set_key_bits(attrs, ds_ctx-rsa_length_bits); psa_set_key_usage_flags(attrs, PSA_KEY_USAGE_SIGN_HASH); psa_set_key_algorithm(attrs, PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)); psa_set_key_lifetime(attrs, PSA_KEY_LIFETIME_ESP_RSA_DS_VOLATILE); psa_key_id_t key_id; psa_status_t status psa_import_key(attrs, (const uint8_t *)rsa_ds_opaque_key, sizeof(rsa_ds_opaque_key), key_id); psa_reset_key_attributes(attrs); if (status ! PSA_SUCCESS) { // handle error } // 对哈希签名例如消息的 SHA-256 uint8_t hash[32] { ... }; uint8_t signature[256]; size_t sig_len; status psa_sign_hash(key_id, PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256), hash, sizeof(hash), signature, sizeof(signature), sig_len); psa_destroy_key(key_id);要点导入前需确保创建密钥时已设置esp_ds_data_t的rsa_length字段通过esp_ds_encrypt_params或 RSA_DS 预置工具驱动会从ds_ctx-rsa_length_bits读取位长签名用法标志设为PSA_KEY_USAGE_SIGN_HASH若需解密则结合PSA_KEY_USAGE_DECRYPT并调用psa_asymmetric_decrypt()驱动头文件中PSA_KEY_LOCATION_ESP_RSA_DS定义为0x800003并基于它构造出持久与易失两种 key lifetime 宏见 psa_crypto_driver_esp_rsa_ds.h。驱动还提供了esp_rsa_ds_opaque_sign_hash_start/complete/abort、esp_rsa_ds_opaque_signature_sign_hash、esp_rsa_ds_opaque_asymmetric_decrypt、esp_rsa_ds_opaque_set_session_timeout以及持久化键缓冲的格式化/解析辅助函数esp_rsa_ds_format_persistent_key_buffer/esp_rsa_ds_parse_persistent_key_buffer供自定义 PSA ITS 后端集成使用。易失 vs 持久两种 PSA Key 生命周期驱动支持两种 RSA_DS key lifetime详见 psa_crypto_driver_esp_rsa_ds_contexts.h 与文档说明PSA_KEY_LIFETIME_ESP_RSA_DS_VOLATILE易失PSA key slot 中只保存指向调用方esp_ds_data_ctx_t及 Key Manager 恢复信息的指针不深拷贝大块数据。当esp_ds_data_t约 12001600 字节视芯片而定已通过esp_secure_cert_mgr以 mmap 方式映射到 flash 时可避免不必要的内存拷贝。要求被引用的缓冲区必须保持有效直到调用psa_destroy_key。PSA_KEY_LIFETIME_ESP_RSA_DS持久在psa_import_key时深拷贝加密密钥材料到 PSA key slot并由 PSA 连同其他密钥属性一并持久化到 NVS。psa_import_key返回后调用方即可释放导入缓冲区后续psa_sign_hash/psa_asymmetric_decrypt会自动从 NVS 取回数据。适合希望密钥跨重启存活、而不必每次启动都从外部存储重新加载esp_ds_data_ctx_t的应用。为 TLS 连接配置 RSA_DS 外设在将 RSA_DS 用于 TLS 连接例如 TLS 客户端认证之前需要完成如下 4 步配置详见{IDF_TARGET_NAME} Technical Reference Manual的 RSA_DS 章节随机生成 256 位Initialization VectorIV随机生成 256 位HMAC_KEY依据客户端 RSA 私钥与上两步的参数计算出加密后的私钥参数将 256 位HMAC_KEY烧录到 eFuse使其只能被 RSA_DS 外设读取。开发阶段可使用esp-secure-cert-tool工具自动完成上述配置。配置得到的加密私钥参数应存储于 flash应用通过esp_secure_cert_mgr组件提供的 API 读取 RSA_DS 数据如 NVS 分区或安全证书分区。随后即可借助 ESP-TLS 的 digital signature 支持将 RSA_DS 用于 TLS 双向认证场景——ESP-TLS 会在握手签名时调用 RSA_DS 驱动完成私钥操作。SSL 双向认证示例文档说明原先位于examples/protocols/mqtt/ssl_ds的 SSL 双向认证示例现已随独立的espressif/mqtt组件发布。按该组件文档拉取 SSL RSA_DS 示例并与 ESP-MQTT 一起编译即可。示例继续使用mqtt_client由 ESP-MQTT 实现连接test.mosquitto.org进行双向认证 TLSTLS 部分由 ESP-TLS 处理——通过它可以看到 RSA_DS 与 mbedTLS/ESP-TLS 全链路协作的真实用法。Key Manager 支持新款芯片在SOC_KEY_MANAGER_SUPPORTED的芯片上RSA_DS 还支持基于 Key Manager 的密钥部署AES 加密密钥可直接以ESP_KEY_MGR_DS_KEY类型部署到 Key Manager。当esp_ds_data_ctx_t::efuse_key_id与esp_rsa_ds_opaque_key_t::key_recovery_info同时被设置时ESP-DS PSA 驱动优先使用 Key Manager 中的 DS key而非 eFuse 中的 DS key。相应的实现条件编译可见 esp_ds.c 对SOC_KEY_MANAGER_DS_KEY_DEPLOY的引用以及驱动上下文中SOC_KEY_MANAGER_SUPPORTED保护下的key_recovery_info字段。测试与验证仓库提供了完整的 RSA_DS 验证用例test_ds_sign_and_decrypt.c 覆盖了 PSA 导入 opaque key 后执行psa_sign_hashPKCS#1 v1.5 与 PSS与psa_asymmetric_decryptPKCS#1 v1.5 与 OAEP的完整路径并在 sdkconfig.ci.ds_rsa 中配置了CONFIG_MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL可作为应用侧集成 RSA_DS 时的参考模板。总结RSA_DS 是 ESP-IDF 中硬件级保护 RSA 私钥的标准方案eFuse 读保护的 HMAC 密钥 硬件内派生的 AES 密钥 flash 中的密文参数构成“软件不可见”的私钥使用链路。开发时先通过esp_efuse_write_block/esp_hmac_calculate/esp_ds_encrypt_params完成预置再根据需求选择低层 APIesp_ds_sign阻塞式或esp_ds_start_sign非阻塞式或开启CONFIG_MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL走标准 PSA 接口获得签名/解密能力最终可无缝接入 ESP-TLS 双向认证场景。【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考