2. 安全启动基础

安全启动(Secure Boot)不是某一个单独的功能,而是一套贯穿芯片上电到应用运行的完整性验证机制。它的核心目标可以概括为一句话:确保设备每一次启动时,执行的每一段代码都是经过授权、未被篡改的。在 MCUboot 的语境下,安全启动通过“信任链”把不可变的硬件信任根逐级传递到可升级的固件镜像,从而在开放升级能力的同时守住安全底线。

一、安全启动的定义与本质

安全启动的本质是验证与执行的绑定:任何一段代码在被 CPU 执行之前,必须先由上一级可信代码验证其完整性和真实性。完整性通常用哈希(如 SHA-256)保证,真实性用数字签名(如 ECDSA-P256、RSA-2048/3072)保证。验证通过才跳转执行,验证失败则拒绝启动或进入恢复模式。

需要区分两个容易混淆的概念:

  • 安全启动:关注“能不能启动”,即镜像是否可信。
  • 安全升级:关注“能不能换镜像”,即新镜像是否可信且可回滚。

MCUboot 同时覆盖这两者,但本章聚焦启动阶段的信任建立过程。

二、信任链与根信任

信任链(Chain of Trust)是一条从“绝对可信”到“逐级可信”的验证路径。链的起点是根信任(Root of Trust, RoT),它必须满足三个条件:不可修改、不可绕过、可被验证。在 MCU 上,根信任通常由以下几部分构成:

  • Boot ROM:芯片出厂固化代码,负责最初始的验证。
  • eFuse / OTP:存储公钥哈希或根公钥,一次性写入不可更改。
  • 安全启动使能位:锁定调试接口、禁止降级等策略。

信任链的典型传递顺序是:Boot ROM → 一级引导(如 MCUboot)→ 二级引导/应用镜像 → 应用配置与密钥。每一级只信任下一级的公钥或哈希,形成“逐级背书”。只要根信任不被攻破,整条链的可信性就能成立。

根信任不是“一段代码”,而是“代码 + 存储 + 策略”的组合。缺少 eFuse 中的公钥哈希,Boot ROM 就无法判断一级引导是否被替换。

三、启动阶段划分

以 MCUboot 为例,一次典型的安全启动可划分为四个阶段:

  1. 上电复位与 Boot ROM 阶段:CPU 从固定地址取指,Boot ROM 校验一级引导头部与签名,检查安全启动使能位。
  2. 一级引导(MCUboot)阶段:初始化时钟、Flash、串口等,读取镜像槽(slot0/slot1)元数据,验证镜像哈希与签名,决定启动哪个槽。
  3. 镜像跳转阶段:将控制权交给应用镜像入口,完成向量表重定位与内存保护配置。
  4. 应用运行阶段:应用可继续验证外部资源、密钥或配置,形成更长的信任链。

MCUboot 的镜像头部包含 magic、load_addr、img_size、flags、版本号以及 TLV 区域中的哈希与签名。验证流程可简化为:

读取 image header
  → 校验 magic 与 img_size
  → 计算镜像体 SHA-256
  → 与 TLV 中的 hash 比对
  → 用公钥验证签名
  → 检查版本与安全计数器
  → 通过则跳转,否则进入恢复/回滚

四、威胁模型与常见攻击面

安全启动的威胁模型通常假设攻击者具备以下能力之一:物理接触设备、可读写外部 Flash、可注入故障、可监听总线。基于此,常见攻击面如下表:

攻击面典型攻击防护手段
Boot ROM故障注入跳过校验冗余校验、随机延迟、电压/时钟监测
外部 Flash替换镜像、回滚旧版本签名验证、安全计数器、防回滚版本号
调试接口SWD/JTAG 读取密钥熔断调试口、读保护、安全启动使能位
通信总线中间人替换升级包端到端签名、加密传输、会话密钥
密钥存储提取私钥伪造镜像密钥放入安全区、加密存储、不导出
回滚与降级刷入含漏洞旧固件单调计数器、最低版本策略

下图展示了从根信任到应用运行的信任链传递,以及各阶段对应的主要攻击面:

安全启动信任链与攻击面 根信任 RoT Boot ROM + eFuse 公钥哈希 / 使能位 一级引导 MCUboot 验证镜像哈希与签名 选择 slot0 / slot1 应用镜像 向量表重定位 资源与密钥校验 验证 验证 攻击面:故障注入 电压/时钟毛刺跳过校验 攻击面:镜像替换 外部 Flash 篡改 / 回滚 攻击面:调试接口 SWD/JTAG 读取密钥 启动阶段划分 ① Boot ROM 取指 / 校验一级引导 ② MCUboot 哈希 / 签名 / 选槽 ③ 镜像跳转 向量表 / 内存保护 ④ 应用运行 资源 / 密钥校验

五、案例与场景:一次失败的启动

假设某设备使用 MCUboot,slot0 为当前运行镜像,slot1 为待升级镜像。升级后重启,MCUboot 验证 slot1 失败,可能原因包括:

  • 镜像签名与 eFuse 中公钥哈希不匹配;
  • 镜像体在传输中被截断,SHA-256 不一致;
  • 安全计数器要求版本不低于当前值,而新镜像版本更低;
  • TLV 区域缺失或格式错误,导致签名无法解析。

此时 MCUboot 会拒绝跳转,并根据配置回滚到 slot0 或进入串口恢复模式。日志中通常能看到类似输出:

[boot] Image 1: magic OK, size 0x1A000
[boot] Image 1: hash mismatch
[boot] Image 1: signature verification failed
[boot] Boot failed, swapping back to slot 0
[boot] Jumping to slot 0 @ 0x08008000
常见误区:认为“加了签名就等于安全启动”。实际上,如果公钥没有烧录到 eFuse/OTP,攻击者可以同时替换镜像和公钥,信任链在根上就断了。

六、复盘与设计要点

设计安全启动时,建议按以下清单逐项确认:

  1. 根信任是否固化在不可修改的存储中?
  2. 每一级验证是否覆盖完整镜像体,而非仅头部?
  3. 是否启用防回滚机制,安全计数器是否单调递增?
  4. 调试接口在产品阶段是否已关闭或受保护?
  5. 验证失败后的行为是否明确:回滚、恢复还是停机?
  6. 密钥生命周期是否覆盖生成、烧录、轮换与吊销?

安全启动的价值不在于“永远不被攻破”,而在于把攻击成本提高到不可接受的程度,并让每一次启动都成为一次可审计、可验证的信任决策。理解信任链、根信任与攻击面,是后续掌握 MCUboot 镜像格式、签名流程与升级策略的前提。