3. 安全启动与信任链
在TF-M量产安全体系中,安全启动不是单一功能,而是一条从芯片上电到安全服务可用的完整信任链。信任链的核心思想是:每一级启动阶段在将控制权交给下一级之前,必须先验证下一级镜像的完整性与真实性,验证通过后才允许执行。这样,信任从不可变的硬件信任根逐级传递,最终覆盖TF-M安全分区与安全服务。
一、信任链的层级结构
典型TF-M启动链由三个主要阶段构成:BL1(不可变ROM引导)、BL2(可更新引导)和TF-M运行时。BL1通常固化在芯片ROM中,作为硬件信任根,负责验证BL2镜像;BL2位于可更新Flash区域,负责验证TF-M镜像及安全分区;TF-M启动后,再验证非安全应用或安全服务的加载。每一级都持有下一级的公钥哈希或签名信息,形成逐级信任传递。
二、镜像验证机制
镜像验证是信任链的技术核心。TF-M通常采用“签名+哈希”的双重校验方式:首先计算镜像的哈希值,确认数据未被篡改;然后使用公钥验证签名,确认镜像来源可信。公钥本身通过哈希固化在上一级镜像或OTP中,形成不可篡改的信任锚点。
以BL2验证TF-M镜像为例,典型流程如下:
- BL2读取TF-M镜像头部,获取镜像长度、版本号、签名算法标识。
- 计算镜像主体的SHA-256哈希值。
- 使用内置的TF-M公钥验证镜像签名,确认哈希值与签名匹配。
- 检查镜像版本号是否不低于安全计数器记录的最低版本。
- 全部通过后,将控制权跳转到TF-M入口。
/* 伪代码:BL2 验证 TF-M 镜像 */
int verify_tfm_image(uint8_t *img, size_t len) {
uint8_t hash[32];
sha256(img, len, hash);
if (!ecdsa_verify(tfm_pubkey, img_signature, hash)) {
log_security_event(VERIFY_SIG_FAIL);
return -1;
}
if (img_version < get_min_version()) {
log_security_event(VERIFY_ROLLBACK);
return -1;
}
return 0;
}
三、回滚保护与防降级策略
回滚保护用于防止攻击者将设备降级到存在已知漏洞的旧版本固件。TF-M通常使用安全计数器(NV Counter)实现:每次成功升级后,计数器递增并写入OTP或受保护的非易失存储区。启动时,BL2将镜像版本号与计数器当前值比较,若镜像版本低于计数器值,则拒绝启动。
| 保护机制 | 实现位置 | 关键参数 | 失败后果 |
|---|---|---|---|
| 签名验证 | BL1/BL2 | 公钥哈希、签名算法 | 停止启动,记录事件 |
| 完整性校验 | BL1/BL2/TF-M | SHA-256 哈希 | 拒绝执行,进入恢复 |
| 回滚保护 | BL2 | NV Counter、版本号 | 拒绝降级启动 |
| 防降级策略 | BL2/TF-M | 最低版本阈值 | 阻止旧版镜像运行 |
四、典型场景与误区复盘
场景:某设备在OTA升级后无法启动。排查发现,新固件版本号为2,但安全计数器已递增到3。BL2在启动时检测到镜像版本低于计数器值,触发回滚保护,拒绝启动。解决方案是重新签发版本号不低于3的固件,或通过恢复模式重置计数器(需授权)。
常见误区:
- 只做哈希校验不做签名验证:哈希只能防篡改,不能防伪造。攻击者可替换镜像并重新计算哈希。
- 公钥存储在可写区域:信任锚点必须固化在ROM或OTP中,否则信任链从根上被破坏。
- 忽略版本号与计数器的同步:升级时只更新镜像版本,忘记递增计数器,导致回滚保护失效。
- 验证失败后继续启动:部分实现为了“兼容性”在验证失败后仍跳转执行,这完全违背安全启动原则。
总结来说,从BL1到BL2再到TF-M的信任链,是TF-M量产安全的基石。只有每一级都严格执行“验证后再执行”,并配合回滚保护与防降级策略,才能确保设备在整个生命周期内只运行可信固件,抵御降级攻击与固件篡改。