1. 课程导入
在 ARMv8-M 架构逐步成为物联网主控芯片主流选择的今天,安全能力不再只是“加一个加密库”那么简单。Trusted Firmware-M(简称 TF-M)正是为了解决这一层问题而出现的开源参考实现:它把安全启动、安全存储、密码学服务、安全分区调度等能力,统一收敛到一颗 MCU 内部,并通过 PSA(Platform Security Architecture)规范对外提供标准化接口。本课程的目标,是带领大家从“会用 TF-M”走向“能开发 TF-M 安全分区与服务”。
一、TF-M 的定位:MCU 上的安全服务运行时
TF-M 运行在支持 TrustZone 的 Cortex-M 处理器上,通常位于安全侧(Secure Processing Environment,SPE),与运行在非安全侧(NSPE)的应用或 RTOS 通过 PSA Client API 交互。它的核心价值可以概括为三点:
- 隔离:借助 TrustZone 硬件隔离,把安全资产与非安全代码物理隔开,非安全侧无法直接访问安全内存与外设。
- 服务化:把安全能力封装为“安全分区(Secure Partition)”,每个分区提供一组 PSA RoT 服务,如 ITS、Crypto、Attestation、Firmware Update。
- 可移植:通过平台抽象层(Platform)与硬件抽象层(HAL),使同一套安全服务能适配不同厂商的芯片。
换句话说,TF-M 不是“一个库”,而是一个安全服务运行时 + 分区调度框架 + 标准化接口的组合体。理解这一点,是后续开发安全分区的前提。
二、学习目标:从使用者到开发者
本课程围绕“安全分区与服务开发”展开,学完后你应当能够:
- 说清 TF-M 的启动流程、SPE/NSPE 划分以及 PSA 接口调用路径;
- 读懂 TF-M 的构建系统(CMake + Kconfig)与目录结构,能独立编译一个目标平台;
- 基于 Manifest 编写一个自定义安全分区,并实现其服务接口;
- 掌握分区间的 IPC 通信、内存映射与中断处理机制;
- 能够对安全分区进行调试、日志分析与常见故障定位。
三、整体框架:一张图看懂 TF-M 的分层与数据流
下图展示了 TF-M 的典型分层结构:非安全应用通过 PSA API 发起请求,经 IPC 进入安全侧,由分区管理器调度到具体安全分区,最终访问硬件资源或返回结果。请重点观察“请求路径”与“服务边界”两条线。
四、核心原理:请求如何穿过安全边界
当非安全应用调用 psa_crypto_init() 或 psa_its_set() 时,实际发生的过程如下:
- NSPE 侧调用 PSA Client API,触发 SVC(Supervisor Call)异常;
- CPU 切换到安全状态,进入 TF-M 的 SPM(Secure Partition Manager);
- SPM 根据请求的服务 ID,通过 IPC 机制把消息投递给对应安全分区;
- 安全分区执行服务逻辑,必要时访问硬件或调用其他分区;
- 结果沿原路径返回 NSPE,非安全侧拿到 PSA 状态码与数据。
这条路径中,Manifest 文件决定了分区的服务列表、内存布局与优先级,是开发安全分区时最先要写的“契约”。
五、案例场景:一个智能门锁的安全需求拆解
假设我们要为一款智能门锁开发安全功能,需求包括:指纹模板安全存储、开锁指令签名验证、设备身份证明。对应到 TF-M 框架:
| 安全需求 | 对应 TF-M 服务 | 开发动作 |
|---|---|---|
| 指纹模板加密存储 | ITS + Crypto | 调用 PSA ITS API,密钥由 Crypto 分区管理 |
| 开锁指令签名验证 | Crypto(ECDSA) | 使用 PSA Crypto 验签接口,公钥存于安全侧 |
| 设备身份证明 | Attestation | 生成初始证明令牌,供云端核验 |
| 固件安全升级 | FWU | 配置镜像签名与回滚策略 |
可以看到,大部分需求可以直接复用 TF-M 内置分区;只有当业务逻辑特殊(如自定义门锁协议解析)时,才需要新增自定义安全分区。
六、常见误区与复盘建议
误区二:忽略 Manifest 与链接脚本的对应关系,导致分区内存越界或启动失败。
误区三:调试时只看 NSPE 日志,不打开 TF-M 的
TFM_SPM_LOG_LEVEL,难以定位 IPC 超时问题。
建议在每完成一个分区后,做一次“三查”:查 Manifest 服务声明、查分区栈与堆大小、查 PSA 状态码返回值。这三步能覆盖大部分初期问题。
# 典型构建命令示例
cmake -S . -B build -DTFM_PLATFORM=arm/mps2/an521 \
-DTFM_TOOLCHAIN_FILE=toolchain_GNUARM.cmake \
-DCMAKE_BUILD_TYPE=Debug
cmake --build build -- install