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)→ 二级引导/应用镜像 → 应用配置与密钥。每一级只信任下一级的公钥或哈希,形成“逐级背书”。只要根信任不被攻破,整条链的可信性就能成立。
三、启动阶段划分
以 MCUboot 为例,一次典型的安全启动可划分为四个阶段:
- 上电复位与 Boot ROM 阶段:CPU 从固定地址取指,Boot ROM 校验一级引导头部与签名,检查安全启动使能位。
- 一级引导(MCUboot)阶段:初始化时钟、Flash、串口等,读取镜像槽(slot0/slot1)元数据,验证镜像哈希与签名,决定启动哪个槽。
- 镜像跳转阶段:将控制权交给应用镜像入口,完成向量表重定位与内存保护配置。
- 应用运行阶段:应用可继续验证外部资源、密钥或配置,形成更长的信任链。
MCUboot 的镜像头部包含 magic、load_addr、img_size、flags、版本号以及 TLV 区域中的哈希与签名。验证流程可简化为:
读取 image header
→ 校验 magic 与 img_size
→ 计算镜像体 SHA-256
→ 与 TLV 中的 hash 比对
→ 用公钥验证签名
→ 检查版本与安全计数器
→ 通过则跳转,否则进入恢复/回滚
四、威胁模型与常见攻击面
安全启动的威胁模型通常假设攻击者具备以下能力之一:物理接触设备、可读写外部 Flash、可注入故障、可监听总线。基于此,常见攻击面如下表:
| 攻击面 | 典型攻击 | 防护手段 |
|---|---|---|
| Boot ROM | 故障注入跳过校验 | 冗余校验、随机延迟、电压/时钟监测 |
| 外部 Flash | 替换镜像、回滚旧版本 | 签名验证、安全计数器、防回滚版本号 |
| 调试接口 | SWD/JTAG 读取密钥 | 熔断调试口、读保护、安全启动使能位 |
| 通信总线 | 中间人替换升级包 | 端到端签名、加密传输、会话密钥 |
| 密钥存储 | 提取私钥伪造镜像 | 密钥放入安全区、加密存储、不导出 |
| 回滚与降级 | 刷入含漏洞旧固件 | 单调计数器、最低版本策略 |
下图展示了从根信任到应用运行的信任链传递,以及各阶段对应的主要攻击面:
五、案例与场景:一次失败的启动
假设某设备使用 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
六、复盘与设计要点
设计安全启动时,建议按以下清单逐项确认:
- 根信任是否固化在不可修改的存储中?
- 每一级验证是否覆盖完整镜像体,而非仅头部?
- 是否启用防回滚机制,安全计数器是否单调递增?
- 调试接口在产品阶段是否已关闭或受保护?
- 验证失败后的行为是否明确:回滚、恢复还是停机?
- 密钥生命周期是否覆盖生成、烧录、轮换与吊销?
安全启动的价值不在于“永远不被攻破”,而在于把攻击成本提高到不可接受的程度,并让每一次启动都成为一次可审计、可验证的信任决策。理解信任链、根信任与攻击面,是后续掌握 MCUboot 镜像格式、签名流程与升级策略的前提。