ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Flipper Zero 固件中 Mbed TLS PSA Crypto 实现结构剖析:核心-驱动分层设计与新增算法的标准流程

Flipper Zero 固件中 Mbed TLS PSA Crypto 实现结构剖析:核心-驱动分层设计与新增算法的标准流程 Flipper Zero 固件中 Mbed TLS PSA Crypto 实现结构剖析核心-驱动分层设计与新增算法的标准流程【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware本文以 Flipper Zero 固件仓库中随 Mbed TLS 附带的架构文档psa-crypto-implementation-structure.md为主体讲解 Mbed TLS PSA Cryptography API 参考实现的核心 PSA 驱动分层架构、驱动分发的代码生成机制与密钥创建生命周期并完整继承原文档中新增加密机制的文件修改清单与实操指南。读完后你将能够理解一次psa_xxx调用从 API 入口到软件驱动的完整路径掌握PSA_WANT/MBEDTLS_PSA_BUILTIN/MBEDTLS_PSA_ACCEL三套宏的协作关系并了解这套 Mbed TLS 在 Flipper Zero 固件中的实际编译与裁剪方式。一、背景PSA Cryptography API 与 PSA 驱动接口Mbed TLS 库提供了 PSA Cryptography API 规范接口的参考实现。该规范定义了一套面向加密操作的统一 C 接口而其配套规范——PSA 驱动接口PSA driver interface——则定义了加密处理器驱动的接入接口使同一套 API 之下可以共存纯软件实现、硬件加速器与安全元件Secure Element后端。Mbed TLS 的 PSA Crypto 实现的整体组织一句话概括就是由一个核心core加上一组 PSA 驱动构成其中软件加密操作本身也被组织为 PSA 驱动的形式通过 PSA 驱动接口与核心交互。原文档给出的设计动机Rationale包括四点用同一个 C 接口同时访问软件与硬件加密实现可以缩减核心代码规模及其调用图复杂度核心及其对软件/硬件实现的分发逻辑因此更容易测试与验证将软件加密实现组织为驱动促进了这些实现的模块化与硬件能力一样软件加密功能也可以用 PSA 驱动接口定义的 JSON 驱动描述文件来描述配合 JSON 驱动描述文件PSA 驱动规范定义了一个驱动被纳入 Mbed TLS PSA Crypto 实现所需的交付物这为集成第三方或替代性软件加密实现提供了天然的框架。这一设计的直接收益是核心代码永远不执行具体加密运算所有运算都被推送到某个驱动因此验证工作可以集中在API 语义 驱动接口两层而不是每一种算法各写一套边界检查。二、核心Core的职责与标准调用骨架Mbed TLS PSA 核心实现了 PSA Cryptography API 规范定义的全部 API但它自身不执行任何加密操作完全依赖 PSA 驱动来完成实际运算。核心负责三件事密钥存储key store管理密钥槽位、生命周期与持久化详见 psa-keystore-design.md参数校验与翻译检查 PSA API 的入参并将其翻译为对 PSA 驱动接口的合法调用参数分发dispatching把加密操作分发到合适的 PSA 驱动。因此一个典型的 PSA 加密 API 实现遵循如下骨架原文档示例psa_status_t psa_api( ... ) { psa_status_t status; /* Pre driver interface call processing: validation of arguments, building * of arguments for the call to the driver interface, ... */ ... /* Call to the driver interface */ status psa_driver_wrapper_entry_point( ... ); if( status ! PSA_SUCCESS ) return( status ); /* Post driver interface call processing: validation of the values returned * by the driver, finalization of the values to return to the caller, * clean-up in case of error ... */ }大多数 PSA API 的代码结构与上述布局精确一致。但为了适配更多样的硬件设计部分 API 会包含多次驱动接口调用。原文档举的例子是为了同时容纳能校验 MAC与只能计算 MAC两类硬件加速器psa_mac_verify()可以先调用psa_driver_wrapper_mac_verify()失败后再回退到psa_driver_wrapper_mac_compute()。在仓库中可以看到这一分发模式的实际形态psa_crypto.c 中psa_mac_setup()根据is_sign分发到psa_driver_wrapper_mac_sign_setup()或psa_driver_wrapper_mac_verify_setup()约 L2655后续 finish/compute 路径分别调用psa_driver_wrapper_mac_verify_finish()、psa_driver_wrapper_mac_compute()约 L2803/L2847/L5954/L7229与文档描述一致。2.1 驱动包装函数由构建系统生成psa_driver_wrapper_entry_point()系列函数的实现不是手写的而是构建系统依据各个 PSA 驱动的 JSON 驱动描述文件生成的产物分为两部分静态实现生成在头文件psa_crypto_driver_wrappers.h中非静态实现生成在 C 文件psa_crypto_driver_wrappers_no_static.c中原型声明在psa_crypto_driver_wrappers_no_static.h。仓库中这三个文件均已生成并位于 library/ 目录psa_crypto_driver_wrappers.h、psa_crypto_driver_wrappers_no_static.c模板源头是 psa_crypto_driver_wrappers.h.jinja 与 psa_crypto_driver_wrappers_no_static.c.jinja对应的生成脚本是 generate_psa_wrappers.py。生成的头文件中可以看到驱动按编译开关注册的特征/* BEGIN-driver headers */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include test/drivers/test_driver.h #endif /* Headers for p256 transparent driver */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) #include ../3rdparty/p256-m/p256-m_driver_entrypoints.h #endif这些psa_driver_wrapper_*()函数负责把操作分发到加速器驱动、安全元件驱动以及纯软件实现三者之上。2.2 纯 C 编译器即可构建PSA_WANT 条件编译一个值得注意的工程特性是该实现允许仅用 C 编译器构建整个库其手段是随源码附带一个对应纯软件实现的生成文件该文件中各驱动入口点及其代码都被基于PSA_WANT_xyz宏的条件编译指令所保护。这样库中只编译并包含所需的加密操作即可实现按需裁剪。详细的条件包含规则见 PSA 机制的条件包含文档。三、密钥创建的生命周期start / finish / fail 三段式核心中的密钥创建实现围绕三个内部函数组织psa_start_key_creation()、psa_finish_key_creation()与psa_fail_key_creation()。密钥创建类 PSA API——即psa_import_key()、psa_generate_key()、psa_key_derivation_output_key()与psa_copy_key()——统一遵循如下序列检查输入参数调用psa_start_key_creation()分配密钥槽位、按指定密钥属性初始化槽位若为易失性volatile密钥则分配一个易失性密钥标识生成或拷贝密钥材料到槽位其中包含为密钥材料分配缓冲内存调用psa_finish_key_creation()主要职责是把持久密钥persistent key写入持久存储。第 3 步或第 4 步发生任何错误时调用psa_fail_key_creation()进行清理清零并释放该槽位特别是密钥材料——将曾存放密钥材料的 RAM 内存重置为零、释放已分配缓冲区。这种先占槽、后写材料、最后落盘失败即擦除的模式保证密钥材料在 RAM 中只以最短时间内驻留。在仓库源码中psa_crypto.c 可见psa_start_key_creation()的具体实现先通过psa_validate_key_attributes()校验属性再在可选项下的互斥保护中调用psa_reserve_free_key_slot()预留空闲槽位psa_finish_key_creation()紧随其后定义于 L1901 附近与文档描述的四步序列一一对应。四、PSA 驱动命名约定与文件组织Mbed TLS 的 PSA 驱动是驱动意义上的驱动——它符合 PSA 驱动接口规范但并不是驱动某块硬件的实际设备驱动而是纯软件实现的加密操作。其文件与函数命名遵循严格约定驱动 C 文件命名为psa_crypto_driver_name.c头文件为psa_crypto_driver_name.h实现某个驱动入口点PSA 驱动接口规范中定义的函数命名为mbedtls_psa_driver_name_entry_point()。原文档以 RSA 驱动为例psa_crypto_rsa.c 与 psa_crypto_rsa.h 就是实现 RSA 加密操作的 Mbed TLS PSA 驱动文件该驱动实现了包括 import_key 在内的多个入口点其中 import_key 入口点的实现函数名为mbedtls_psa_rsa_import_key()——在仓库中该函数定义于 psa_crypto_rsa.c。同一目录下还有 psa_crypto_ecp.c椭圆曲线、psa_crypto_ffdh.c有限域 Diffie-Hellman、psa_crypto_mac.cHMAC 等 MAC、psa_crypto_hash.c、psa_crypto_cipher.c、psa_crypto_aead.c 等均可按上述命名约定对号入座。五、新增一个加密机制标准操作流程原文档的核心实操价值在于给出新增算法或密钥类型时的文件修改清单。以下完整保留该清单路径转换为以 Mbed TLS 仓库根为基准的相对路径引用时在 Flipper 固件中需加上lib/mbedtls/前缀。新增算法或密钥类型时需要修改的文件PSA Crypto API 草案如尚未完成——见PSA 标准化一节include/psa/crypto_values.h或include/psa/crypto_extra.h——见新函数与宏一节include/psa/crypto_config.h、tests/include/test/drivers/crypto_config_test_driver_extension.h——见预处理器符号一节偶尔需要library/check_crypto_config.h——见预处理器符号一节include/mbedtls/config_psa.h——见预处理器符号一节library/psa_crypto.c、library/psa_crypto_*.[hc]——见机制的实现一节include/psa/crypto_builtin_*.h——见半透明数据结构一节tests/suites/test_suite_psa_crypto_metadata.data——见新函数与宏一节若新增PSA_IS_xxx宏tests/suites/test_suite_psa_crypto_metadata.function——见新函数与宏一节tests/suites/test_suite_psa_crypto*.data、tests/suites/test_suite_psa_crypto*.function——见单元测试一节framework/scripts/mbedtls_framework/crypto_knowledge.py、framework/scripts/mbedtls_framework/asymmetric_key_data.py——见单元测试一节ChangeLog.d/*.txt——变更日志条目新增 API 函数时需要修改的文件include/psa/crypto.h和include/psa/crypto_sizes.h或include/psa/crypto_extra.h——见新函数与宏一节library/psa_crypto.c、scripts/data_files/driver_templates/*.jinja——见机制的实现一节若新增有状态函数include/psa/crypto_struct.h、include/psa/crypto_builtin_*.h、include/psa/crypto_driver_contexts_*.h——见半透明数据结构一节tests/suites/test_suite_psa_crypto.data、tests/suites/test_suite_psa_crypto.function、tests/suites/test_suite_psa_crypto_driver_wrappers.*——见单元测试一节文档同时强调这只是基本指引某些情况下无需改动清单中全部文件某些情况下可能还需要改动其他文件。以上清单中提到的文件在当前仓库中均已实际存在例如 check_crypto_config.h、crypto_config_test_driver_extension.h、crypto_knowledge.py可作为动手修改前的对照物。5.1 PSA 标准化通常如果某个加密机制在 Mbed TLS 中有足够的需求那么把它纳入正式 PSA Cryptography 规范的需求也足够充分。因此实现新机制的第一步应当是向 Arm 的 PSA Cryptography 工作组working group提出标准化请求。截至原文档撰写时Mbed TLS 中所有可通过psa_xxxAPI 访问的加密机制都是现行或即将发布的 PSA 标准Mbed TLS 同时实现了一些 PSA API 扩展提供额外的集成定制或额外的密钥策略key policies。Mbed TLS 还常规性地实现尚未纳入已发布 PSA 标准、但已列入未来版本计划的机制——Mbed TLS 的实现正是对这些未来 PSA 标准可行性的验证PSA Cryptography 工作组与 Mbed TLS 开发团队在新接口制定过程中保持沟通。5.2 新函数与宏如果新机制需要新函数这些函数应当遵循 PSA Cryptography API 规范中的设计指南并按标准化状态分头放置属于现行或将要发布 API 的函数声明在include/psa/crypto.h结构体访问器除外后者定义在include/psa/crypto_struct.h带输出缓冲区的函数在include/psa/crypto_sizes.h中有配套的足够输出大小宏常量算法标识、密钥类型标识等及其配套解构宏如PSA_IS_xxx()定义在include/psa/crypto_values.h不打算标准化、或草案标准仍可能大幅演进的函数与宏声明在include/psa/crypto_extra.h。PSA 规范为某些常量类别同时定义了名字和数值算法PSA_ALG_xxx、密钥类型PSA_KEY_TYPE_xxx、ECC 曲线族PSA_ECC_FAMILY_xxx、DH 群族PSA_DH_FAMILY_xxx。若 Mbed TLS 定义的算法或密钥类型不属于现行或即将发布的 PSA 标准应选择设置了VENDOR标志的数值若 Mbed TLS 定义的 ECC 曲线或 DH 群族不属于标准则应定义一个 vendor 密钥类型族标识符仅与该 vendor 密钥类型配合使用。此外每个新常量必须在 test_suite_psa_crypto_metadata.data 中有测试用例验证PSA_IS_xxx宏对新常量的行为正确新的PSA_IS_xxx宏必须声明在test_suite_psa_crypto_metadata.function中。5.3 预处理器符号PSA_WANT / BUILTIN / ACCEL 三层协作每个加密机制都是可选的应用可在构建时选择。对每个特性PSA_ttt_xxx应用可见性当预处理器符号PSA_WANT_ttt_xxx被定义时该特性对应用可见。该符号的设置方式取决于配置模式若MBEDTLS_PSA_CRYPTO_CONFIG未启用基于 Mbed TLS 中可用的机制由 config_psa.h 中的代码从mbedtls/mbedtls_config.h推断得出若MBEDTLS_PSA_CRYPTO_CONFIG已启用在应用配置文件include/psa/crypto_config.h或MBEDTLS_PSA_CRYPTO_CONFIG_FILE再叠加MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE中显式设置同时config_psa.h中的代码负责反推出所需的底层MBEDTLS_xxx符号。实现来源对透明密钥不在安全元件中的密钥特性由 Mbed TLS 实现当且仅当定义了MBEDTLS_PSA_BUILTIN_ttt_xxx由加速器驱动实现当且仅当定义了MBEDTLS_PSA_ACCEL_ttt_xxx。MBEDTLS_PSA_BUILTIN_ttt_xxx常量在config_psa.h中根据应用请求PSA_WANT_ttt_xxx与加速器驱动声明MBEDTLS_PSA_ACCEL_ttt_xxx计算得出。分发测试为测试驱动分发代码crypto_config_test_driver_extension.h 会额外设置一组MBEDTLS_PSA_ACCEL_xxx符号使同一套测试能在软件 测试驱动两种后端上运行分发逻辑。机制之间存在依赖关系。例如没有分组密码就无法做 GCM没有 RSA 密钥就无法做 RSA-PSS。当机制 A 依赖机制 B 时config_psa.h保证启用 A 时必然启用 B当 A 只要求集合 {B1, B2, B3, ...} 中至少一个、但无理由强制选中其中特定某一个时由应用自行选择 Bi此时 check_crypto_config.h 提供编译期约束确保至少一个 Bi 被启用。更多细节参见 条件包含文档。5.4 机制的实现四层结构一个加密操作函数的通用实现结构分为四层API 函数定义在library/psa_crypto.c。入口点执行与软件实现还是驱动实现无关的通用检查并在密钥存储中查找密钥驱动分发代码位于 driver_templates 目录的 Jinja 模板psa_crypto_driver_wrappers.h.jinja、psa_crypto_driver_wrappers_no_static.c.jinja及它们包含的文件内建实现built-in位于library/psa_crypto_*.c函数声明在对应.h中。这些文件通常包含在其他地方定义的基础构件之上实现的运算模式。例如HMAC 实现在 psa_crypto_mac.c而它依赖的底层哈希函数实现在library/sha*.c与library/md*.c基础加密构件位于library/*.c。实现新算法或密钥类型时通常要改动library/psa_crypto.c例如缓冲区大小计算、算法/密钥类型兼容性判断与内建实现但不需要改动驱动分发代码——这正是生成式分发机制的价值所在。5.5 半透明数据结构Translucent data structures某些机制需要在多次函数调用之间保持状态。密钥及类密钥数据存放在由 PSA 内部管理的密钥存储中其他状态例如多部件操作 multipart 的状态则存放在由调用方分配的结构体中。由于操作结构体大小必须在编译期可知调用方可能在栈上分配它们这些结构体被定义在公开头文件中按归属拆分include/psa/crypto_struct.h与底层实现无关的部分include/psa/crypto_builtin_*Mbed TLS 内建实现特有部分仓库中可见 crypto_builtin_primitives.h、crypto_builtin_composites.h 等include/psa/crypto_driver_*.h驱动实现的结构体如 crypto_driver_contexts_composites.h。5.6 单元测试自动生成 手工补充一批单元测试由 generate_psa_tests.py 基于crypto_values.h与crypto_extra.h中声明的算法和密钥类型自动生成覆盖尝试用不支持的密钥类型创建密钥尝试用无效或不支持的密钥类型 × 算法组合执行操作持久密钥的存储与取回。新增密钥类型或算法时需要同步维护两个知识文件framework/scripts/mbedtls_framework/crypto_knowledge.py包含密钥类型、密钥尺寸与算法之间兼容性的知识framework/scripts/mbedtls_framework/asymmetric_key_data.py包含非对称密钥类型的有效密钥数据。其余内容需要手工测试可写在tests/suites/test_suite_psa_crypto.data或其他文件中原文档此处文件名test_sutie_psa_crypto.data为笔误实际为 test_suite_psa_crypto.data。需要手工覆盖的情形包括但不限于非穷尽列表已知答案测试Known answer tests潜在边界情形如数据小于/等于/大于块大小、非对称加密中数值等于零非法密钥尺寸或格式错误非法数据尺寸或格式错误、输出缓冲区过小、无效填充新函数错误的函数调用序列、驱动分发在tests/suites/test_suite_psa_crypto_driver_wrappers.*中密钥派生算法输入步骤序列的变化、输出尺寸的变化。六、这套 Mbed TLS 在 Flipper Zero 固件中如何被裁剪使用以上架构描述的是 Mbed TLS 的完整 PSA Crypto 实现而 Flipper Zero 固件对这份 vendored 副本做了显著裁剪。从构建脚本 mbedtls.scons 可以看到固件只编译了一组低级原语源文件aes.c、bignum.c、bignum_core.c、ecdsa.c、ecp.c、ecp_curves.c、md.c、md5.c、platform_util.c、ripemd160.c、sha1.c、sha256.c、des.cPSA 核心psa_crypto.c与psa_crypto_*.c内建驱动均不在固件编译范围内。配置通过MBEDTLS_CONFIG_FILEmbedtls_cfg.h指向 mbedtls_cfg.h该文件头部注释明确说明它是与 Flipper Zero 固件和应用相关的 mbedtls 配置子集若需要更多特性可用fap_private_libs在自己的应用中引入完整 mbedtls 库。编译参数还特意加上了-mword-relocations与-mlong-calls注释为Required for lib to be linkable with .faps即保证该静态库可被 Flash 应用.fap链接。从源码结构看固件内应用如 NFC 辅助模块、U2F 应用直接链接的是 mbedtls 的 AES/ECDSA/SHA 等传统接口而设备级的加密 CLI 服务 crypto_cli.c 则走的是另一条路径——安全加密飞地secure enclave经furi_hal_crypto_enclave_*接口调用 STM32WB 副处理器侧的硬件密钥槽这与本文讨论的 PSA 软件实现是相互独立的两套机制。换句话说本文第一至五节描述的 PSA 核心/驱动架构在 Flipper Zero 固件中主要作为随源码附带的参考实现与二次开发基线存在若开发者在 .fap 应用里通过fap_private_libs引入完整 mbedtls这套架构就完整可用而固件本体则只取其底层构件。理解这一点有助于在固件开发中正确选择加密接口层级避免误判 PSA API 在固件侧的可用性。七、小结Mbed TLS 的 PSA Crypto 实现以核心只做校验与分发、运算一律下沉到驱动为骨架用构建系统生成的psa_driver_wrapper_*()把软件、加速器、安全元件三类后端统一在同一个 C 接口之后并以PSA_WANT宏族实现按需编译。密钥创建的 start/finish/fail 三段式保证了密钥材料的最短驻留与失败擦除。新增机制时按标准化 → 头文件常量/宏 → 预处理器符号 → 四层实现 → 半透明结构 → 自动生成 手工测试的流程推进即可在不触碰分发代码的前提下安全扩展。在 Flipper Zero 固件仓库中这套实现可通过lib/mbedtls/目录完整研读而固件本体对它的裁剪方式见 mbedtls.scons 与 mbedtls_cfg.h则展示了嵌入式场景下全量架构文档 最小构建子集的实际落地形态。【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表