安全启动与固件防回滚的信任链设计
支持可满 PWM 驱动、额定 16A(峰值 20A)的 AQMD3620NS-A2 这类长期部署设备,固件一旦被篡改,后果可能超出"数据泄露",直接变成设备失控。安全启动要解决三件事:只跑签名固件、不跑旧版本、能被远程核实。
一、信任链的三段
| 阶段 | 信任根 | 校验对象 | 失败行为 |
|---|---|---|---|
| 1. BootROM | 芯片内置(不可改) | 一级 Bootloader 签名 | 停止启动 |
| 2. Bootloader | 一级公钥(固化) | 应用固件签名 + 版本 | 进入恢复模式 |
| 3. 应用 | 自身完整性度量 | 关键参数区/配置区 | 拒绝启动或降级运行 |
关键点是公钥必须固化在不可写区域(OTP/安全区),若公钥可被改写,整条链失效。签名私钥只存在于发布系统,绝不进入设备与代码仓库。
二、防回滚:单调版本计数
攻击者常用"刷回有漏洞的旧固件"绕过修复。仅比对版本号不够(可回退存储),要用不可逆的单调计数:
/* 防回滚:单调计数只增不减,旧固件因计数落后被拒 */
typedef struct {
uint32_t ver; uint32_t mono; } fw_hdr_t;
int rollback_check(const fw_hdr_t *hdr, uint32_t cur_mono)
{
if (hdr->mono < cur_mono) return -1; /* 降级攻击,拒绝 */
return 0;
}
/* 升级成功后推进单调计数(OTP 或带掉电保护的单调存储) */
void mono_advance(uint32_t new_mono)
{
if (new_mono <= mono_read()) return; /* 只允许前进 */
mono_write(new_mono);
}
配套两点:OTA 包头部同时带 ver、mono、签名,三者一致才接受;恢复模式下的固件也要受同一规则约束,否则恢复通道成为绕过口。
三、验签耗时的工程预算
MCU 侧验签不是免费的。取签名 256 字节、摘要 32 字节(示例值):
| 实现方式 | 验签耗时量级 | 说明 |
|---|---|---|
| 软件 ECDSA/RSA | 数百 ms ~ 数 s | 低主频 MCU 明显卡顿 |
| 硬件加速(crypto 协处理器) | 数十 ms 量级 | 首选 |
| 只校验摘要 + CRC 兜底 | 数 ms | 不能替代签名,仅作完整性辅助 |
验签应放在启动阶段一次性完成,不要在运行期反复验签;若启动时间有约束(如设备需快速上电进入控制),可采用"先验签后使能外设"的顺序,避免未验签代码驱动执行机构。
四、可远程核实的度量
安全启动要能被云端看见,否则"是否被篡改"无法运维。做法是启动时把度量值(固件哈希、版本、单调计数、构建 ID)签名后上报,云端比对期望值:
| 上报项 | 用途 |
|---|---|
| fw_hash | 与发布库比对,检出未知固件 |
| fw_ver / mono | 检出降级与灰度偏差 |
| boot_status | 区分正常启动 / 恢复模式 / 校验失败次数 |
校验失败要累计计数并上报,连续失败说明存在攻击或硬件故障。
五、验证方法
一是篡改测试:修改固件 1 字节,确认启动被拒并进入恢复模式;二是降级测试:刷回旧版本,确认被单调计数拒绝;三是耗时实测:打点测验签耗时,确认满足启动时间约束;四是度量核对:云端确认能检出被篡改设备的 fw_hash 异常。
六、小结
安全启动的三段信任链要求公钥固化在不可写区、私钥永不入设备;防回滚用不可逆单调计数而非单纯版本号,并覆盖恢复通道;验签放在启动期一次完成并预算耗时;上报签名度量让云端可核实。用篡改、降级、耗时、度量四类测试闭环。