4. 回滚保护核心概念

在安全固件升级体系中,回滚保护是防止攻击者把设备降级到存在已知漏洞的旧版本的关键机制。它并不是单一技术,而是一组围绕“版本不可逆”建立的概念组合:版本号用于标识固件新旧,防回滚计数器用于记录设备已经接受过的最高安全版本,单调计数器保证该记录只能增加不能减少,安全存储则保证这些记录不被篡改或擦除。理解这四者的关系,是掌握 TF-M 安全升级与回滚保护的基础。

一、核心原理:为什么“旧版本”反而是威胁

很多人直觉认为升级只是功能迭代,旧版本最多是功能少,不会更危险。但在安全视角下,旧固件往往意味着:已公开的 CVE 漏洞、已泄露的调试密钥、已被绕过的签名校验逻辑,甚至包含攻击者已经掌握的通信协议缺陷。攻击者若能通过物理接口、调试口或降级升级包,把设备从已修复的 v2.3 刷回存在漏洞的 v1.8,就相当于绕过了所有后续安全修复。因此,回滚保护的目标不是“阻止升级”,而是阻止安全版本号下降。

TF-M 将固件版本与安全计数器绑定:每次成功升级后,设备不仅保存新镜像,还会把“已接受的最低安全版本”提升到新版本。之后任何低于该版本的镜像,即使签名合法,也会被拒绝安装或拒绝启动。

二、四个关键概念及其关系

  • 版本号(Version Number):描述固件发布次序的标识,通常为 major.minor.patch 或单调递增整数。它本身只是“标签”,若可被随意修改,则不具备安全意义。
  • 防回滚计数器(Anti-Rollback Counter):设备侧记录“当前允许的最低安全版本”的计数器。升级到新版本时,该计数器被提升;尝试安装更低版本时,该计数器触发拒绝。
  • 单调计数器(Monotonic Counter):一种只能递增、不能递减或复位的硬件/安全存储结构。它是防回滚计数器的物理基础,保证攻击者无法通过擦写、掉电或恢复出厂设置把计数改小。
  • 安全存储(Secure Storage):存放版本元数据、计数器值、镜像哈希和签名状态的受保护区域。TF-M 中通常由 ITS(Internal Trusted Storage)或受保护的 OTP/eFuse 承担。
回滚保护的本质公式:
可安装条件 = 镜像签名有效 AND 镜像安全版本 ≥ 设备防回滚计数器当前值
其中防回滚计数器由单调计数器保证只增不减。

三、回滚攻击的典型路径与防护点

回滚攻击并不总是“破解签名”,更多时候是绕过版本判断。常见路径包括:

  1. 重放旧镜像:攻击者保留一份旧版合法签名镜像,在设备升级后重新刷入。防护点是升级前比较版本号与防回滚计数器。
  2. 篡改版本元数据:直接修改镜像头中的版本号,使其看起来更高。防护点是版本元数据必须纳入签名覆盖范围,并由安全存储校验。
  3. 擦除或复位计数器:通过调试口、故障注入或掉电攻击把单调计数器改小。防护点是使用 OTP/eFuse 或受硬件保护的单调计数器。
  4. 双槽回退:在 A/B 双槽升级中,诱导设备从旧槽启动。防护点是启动时校验槽内镜像版本不低于防回滚计数器。
  5. 降级恢复出厂:利用恢复模式刷入旧固件。防护点是恢复模式同样执行版本检查,不能绕过安全策略。
注意:仅依赖镜像内的版本号字段是危险的。如果版本号没有与安全存储中的防回滚计数器联动,攻击者只需改一个字节即可绕过。版本号必须被签名保护,计数器必须单调。

四、参数与存储位置对照

对象 作用 典型存储位置 是否可回退
固件版本号 标识镜像新旧 镜像头 / 签名元数据 字段可写,但受签名保护
防回滚计数器 记录允许的最低安全版本 安全存储 / ITS 只能提升
单调计数器 提供不可逆递增语义 OTP / eFuse / 安全外设 不可回退
镜像哈希与签名 验证镜像完整性与来源 签名区 / 安全存储 随镜像更新
槽位状态 标记 active/pending/confirmed 安全存储 可切换,但受版本约束

五、TF-M 中的配置与日志示例

在 TF-M 的升级流程中,版本与计数器通常通过清单(manifest)和镜像元数据传递。下面是一个简化的版本元数据示例:

{
  "image_id": "TFM_SP_BOOT",
  "version": "2.3.1",
  "security_counter": 7,
  "signature": "ecdsa-p256:...",
  "hash": "sha256:..."
}

启动或升级校验时,引导程序会执行类似逻辑:

if (image.security_counter < device.anti_rollback_counter) {
    reject_image("rollback detected");
    log_event("SECURITY: rollback attempt blocked");
} else {
    accept_image();
    device.anti_rollback_counter = image.security_counter;
}

典型日志如下:

[BOOT] image version=2.3.1 counter=7
[BOOT] device anti-rollback counter=7
[BOOT] version check passed
[BOOT] image confirmed, counter updated to 7

六、案例场景:一次被阻止的降级

某设备当前运行 v2.3.1,防回滚计数器为 7。攻击者获取了厂商早期发布的 v1.8 合法签名镜像,试图通过调试口刷入。引导程序读取镜像元数据后发现 security_counter=3,小于设备当前值 7,于是拒绝安装并记录安全事件。即使攻击者修改镜像头把版本号改成 9,由于版本号在签名覆盖范围内,签名校验会失败;即使攻击者尝试擦除安全存储,单调计数器位于 OTP 区域,无法回退。最终降级失败。

七、常见误区与复盘

  • 误区一:有签名就不需要回滚保护。签名只证明镜像来源合法,不证明它是最新安全版本。旧镜像同样可以有合法签名。
  • 误区二:版本号写在镜像里就够了。镜像内字段必须被签名覆盖,并且要与设备侧防回滚计数器比较。
  • 误区三:软件变量也能做单调计数器。普通 Flash 变量可被擦除或回滚,必须依赖 OTP、eFuse 或安全外设。
  • 误区四:恢复模式可以绕过检查。恢复模式是攻击面之一,必须执行同样的版本策略。
  • 复盘要点:升级流程中要同时校验签名、哈希、版本号和防回滚计数器;计数器更新必须与镜像确认原子化,避免掉电导致状态不一致。
回滚保护核心概念与攻击路径 镜像侧(Image) 版本号 version = 2.3.1 安全计数器 counter = 7 签名 + 哈希保护 引导校验逻辑 签名 / 哈希校验 counter ≥ 设备防回滚值? 通过则更新计数器 设备侧安全存储 防回滚计数器 = 7 单调计数器(OTP/eFuse) 只增不减,不可擦除 提交镜像 读取/更新 回滚攻击路径与防护点 重放旧镜像 防护:版本比较 篡改版本元数据 防护:签名覆盖 擦除/复位计数器 防护:OTP/eFuse 双槽回退启动 防护:启动校验 核心结论:签名有效 ≠ 可安装;版本必须 ≥ 防回滚计数器,且计数器不可回退 版本号 + 防回滚计数器 + 单调计数器 + 安全存储 = 完整回滚保护链

总结来看,回滚保护不是某一个单独模块,而是一条从镜像元数据、签名校验、版本比较、单调计数器到安全存储的完整信任链。版本号提供语义,防回滚计数器提供策略,单调计数器提供不可逆性,安全存储提供抗篡改能力。四者缺一不可,任何一环被绕过,降级攻击就可能成功。因此在 TF-M 安全固件升级设计中,必须把回滚保护作为与签名校验同等重要的安全目标来对待。