4. 核心能力二
设备配置这个能力,说白了就是解决两个问题:设备跑的是不是我写的代码,以及代码坏了能不能安全地修。安全启动负责前者,安全固件更新负责后者。这两件事绑在一起,构成了物联网设备的第一道防线。
我见过太多设备,固件随便刷、启动随便跑,结果被植入后门还浑然不觉。嗯,咱们今天就把这两个机制拆开揉碎了讲清楚。
4.1 安全启动:从第一行代码开始信任
安全启动的核心逻辑其实很简单——链式信任。从芯片上电那一刻起,每一级代码都要验证下一级的签名或哈希,直到整个操作系统启动完成。任何一环校验失败,设备就拒绝启动。
关键原则:信任的根必须在硬件里,不可篡改。通常是一个一次性烧录的密钥或哈希值,存放在芯片的 OTP(一次性可编程)区域。
4.1.1 典型的启动链
我个人习惯把启动链分成四个阶段,你对照着看自己的设备架构:
| 阶段 | 内容 | 验证方式 |
|---|---|---|
| 阶段 0 (BootROM) | 芯片出厂固化的只读代码 | 硬件不可改,信任根 |
| 阶段 1 (SPL/FSBL) | 一级引导加载程序 | BootROM 验证其签名 |
| 阶段 2 (UBoot/ATF) | 二级引导加载程序 | SPL 验证其哈希或签名 |
| 阶段 3 (Kernel/OS) | 操作系统内核 | UBoot 验证其签名 |
我在项目中遇到过最典型的翻车案例:某厂商把公钥存在 SPI Flash 里,结果攻击者直接替换 Flash 芯片,用自己的公钥签了个恶意固件,设备就“合法”地跑起了后门程序。所以记住:信任根必须焊死在芯片里,不能放在外部存储上。
4.1.2 安全启动的落地检查清单
- 硬件信任根是否存在? 芯片有没有 OTP 或 eFuse?
- 密钥是否唯一? 每台设备用同一把密钥,一台被破全部沦陷。
- 是否支持回滚防护? 防止攻击者刷回有漏洞的旧版本固件。
- 启动失败后的行为? 是死循环、报警,还是降级启动?
避坑指南:我曾经帮一家客户做安全审计,发现他们的安全启动只验证了 Kernel,却没验证文件系统。攻击者把恶意脚本塞进根文件系统,设备照样“安全启动”了。记住:链式信任必须覆盖整个启动路径,不能留缺口。
4.2 安全固件更新:给设备打补丁的正确姿势
固件更新这件事,看起来就是“下载-校验-刷写”三步。但实际落地时,坑比想象的多得多。你想想看,如果更新过程本身不安全,那攻击者完全可以伪造一个更新包,让设备自己把自己“毒死”。
4.2.1 安全更新的核心要素
我总结了一个五要素模型,你可以拿它来对照自己的方案:
- 来源认证:固件包必须有数字签名,设备必须验签。
- 完整性校验:传输过程中有没有被篡改?用哈希或签名保证。
- 机密性保护:固件内容是否敏感?需要加密传输。
- 版本管理:防止回滚攻击,只允许升级,不允许降级。
- 原子性操作:刷写失败怎么办?必须有回滚机制或双备份。
个人经验:我建议在固件包头里加一个字段叫 minimum_security_version。设备启动时检查当前版本是否低于这个值,如果是,强制更新。这比单纯比较版本号更安全,因为版本号可以被伪造,但签名后的字段伪造不了。
4.2.2 双备份更新机制
我最推荐的方式是 A/B 分区更新。说白了就是设备里有两份固件分区,一份运行,一份待更新。更新时写入备用分区,校验通过后切换启动分区。如果新固件启动失败,自动回滚到旧分区。
这样做的好处很明显:
- 更新失败不影响设备运行
- 可以在后台静默更新,用户无感知
- 天然支持回滚
4.2.3 固件更新的典型流程
下面这张图展示了从云端到设备的完整更新链路:
4.3 安全启动与固件更新的联动
这两者不是孤立的。安全启动保证了设备每次启动时固件的完整性,而安全固件更新保证了设备能持续修复漏洞。但有一个容易被忽略的点:更新后的固件必须通过安全启动的验证。
我曾经见过一个方案:固件更新流程做得花里胡哨,签名、加密、双备份全都有。但更新完成后,设备直接跳过了安全启动,从新分区启动。结果攻击者只要伪造一个更新包,就能绕过安全启动。这相当于给大门装了十把锁,但后门直接敞开着。
正确的做法:更新完成后,设备必须重启并走完整的安全启动链。新固件的签名必须与硬件信任根匹配,才能正常启动。这才是闭环。
4.4 落地时的常见坑与对策
| 常见问题 | 后果 | 对策 |
|---|---|---|
| 信任根放在外部存储 | 可被物理替换 | 使用芯片 OTP 或 eFuse |
| 固件签名私钥泄露 | 可伪造任意固件 | 使用 HSM 管理私钥,定期轮换 |
| 未做版本回滚防护 | 攻击者可刷回有漏洞的旧版本 | 在签名中包含版本号,设备强制校验 |
| 更新过程无原子性 | 断电导致设备变砖 | 采用 A/B 分区或双备份机制 |
| 调试接口未关闭 | 攻击者通过 JTAG/SWD 绕过安全启动 | 量产时熔断调试接口 |
血的教训:我曾经审计过一个智能门锁项目。他们的安全启动和固件更新都做得不错,但调试接口(SWD)没熔断。攻击者直接通过调试接口读取了 OTP 里的公钥哈希,然后伪造了一个固件包。所以记住:安全启动的强度,取决于最薄弱的那个环节。调试接口、串口、甚至未使用的 GPIO,都可能成为突破口。
4.5 小结
设备配置这个核心能力,说白了就是建立一条从硬件到软件的信任链。安全启动保证设备只跑你授权的代码,安全固件更新保证这条信任链能持续维护。两者缺一不可,而且必须联动。
我个人建议,在项目初期就把这两个机制纳入架构设计,而不是等产品快量产了才补。因为一旦硬件定型,很多安全特性就加不进去了——比如 OTP 区域的大小、双分区的布局、调试接口的熔断方案。这些事,越早想清楚,后面越省心。