4. 安全启动与信任链实现
安全启动的本质不是“加一个校验函数”,而是把设备从上电到应用运行的全过程组织成一条可验证的信任链:每一级代码在执行前,先由上一级可信代码验证其完整性与来源,验证通过才移交控制权。医疗设备固件一旦被篡改,可能改变治疗参数、报警阈值或数据上报逻辑,因此信任链必须从不可修改的 ROM 引导开始,逐级延伸到应用固件,并在异常时给出可恢复、可审计的确定行为。
一、信任链的层级与移交条件
典型 MCU/MPU 医疗设备的信任链可划分为四级:芯片 ROM Boot(不可改)、一级引导 BL1(通常位于受保护扇区或 OTP 锁定区)、二级引导 BL2/安全固件、应用固件 App。ROM 内部固化的公钥哈希或根公钥(Root Public Key)是整条链的信任锚点,它不依赖外部存储,因此无法被固件升级改写。BL1 的签名由 ROM 用根公钥验证;BL1 验证通过后,再用其内置的下一级公钥验证 BL2;BL2 再验证 App。每一级只信任“上一级已验证过的公钥”,而不是信任存储介质本身。
移交控制权前必须同时满足三个条件:签名验证通过、版本/防回滚检查通过、目标镜像的加载地址与长度在允许范围内。任一条件不满足,都不能跳转到该级代码,而应进入预定义的失败处理路径。这样即使攻击者替换了 Flash 中的 App,也无法让设备执行未签名代码。
二、签名验证的实现要点
签名验证通常采用“哈希 + 非对称验签”的组合。以 ECDSA-P256 为例,构建镜像时先对镜像体(不含签名段)计算 SHA-256 摘要,再用私钥对摘要签名,把签名、公钥标识和版本号写入镜像头。设备端验证时,先按镜像头声明的长度截取镜像体,重新计算 SHA-256,再用对应公钥验签。这里有两个容易出错的细节:一是签名覆盖范围必须明确,不能把签名段自身纳入哈希;二是镜像头中的长度字段必须参与校验,否则攻击者可通过篡改长度让验证器只校验前一小段合法数据。
公钥的存放方式直接影响信任链强度。根公钥哈希应固化在 ROM 或一次性可编程(OTP)区域;中间级公钥可放在 BL1 的只读段中,但必须由上一级签名保护。不建议把公钥放在普通可写 Flash 中再由自身验证,这等于把锁和钥匙放在同一个抽屉里。
三、密钥存储与防回滚
私钥永远不应出现在设备端。设备端只保存公钥或公钥哈希。若设备需要支持多版本固件,可保存一组公钥并附带密钥标识,但密钥标识本身也要被签名覆盖。对于高安全等级设备,可将根公钥哈希写入 OTP 熔丝,一旦烧录不可更改;量产阶段通过安全产线注入,避免私钥泄露。
防回滚保护依赖单调递增的版本计数器。常见实现有两种:一是利用 MCU 内部的版本熔丝,每次升级烧录更高版本号,不可降低;二是使用受保护的单调计数器,由 BL2 维护,升级时先检查新固件版本号是否大于等于当前计数器,通过后再递增。若设备支持 A/B 双分区,两个槽的版本号都要参与判断,防止攻击者把设备切回旧版有漏洞的槽。
四、启动失败恢复策略
恢复策略的目标是:设备不能因为一次升级失败而变砖,也不能因为反复失败而无限重启。推荐采用“A/B 双分区 + 失败计数 + 安全恢复模式”的组合。正常运行时 App 位于 A 槽,升级包写入 B 槽并标记为“待验证”。重启后 BL2 优先尝试 B 槽,若验签或启动自检失败,则回退到 A 槽,并把 B 槽标记为无效。若 A 槽也失败,则进入安全恢复模式,只允许通过签名升级包恢复,不进入治疗逻辑。
失败计数应保存在掉电不丢失的区域,例如备份寄存器或带校验的 Flash 页。连续失败达到阈值(示例取 3 次)后,设备停止自动重试,进入锁定状态并提示现场维护。这样既避免无限重启,也保留可维护性。
五、实测验证方法
安全启动不能只靠代码审查,必须通过可复现的测试用例验证。以下给出一组示例测试用例,参数为教学假设,实际项目应按器件手册调整。
| 用例 | 操作 | 预期结果 | 观察点 |
|---|---|---|---|
| 正常启动 | 烧录已签名 App,版本 1.2.0 | 进入应用,启动日志显示各级验签通过 | 启动时间、日志级别 |
| 篡改镜像体 | 修改 App 中 1 字节后重启 | 验签失败,回退至上一可用槽 | 失败原因码、回退槽号 |
| 篡改签名 | 修改签名段 1 字节 | 验签失败,不执行 App | 是否进入恢复模式 |
| 回滚攻击 | 烧录版本 1.1.0(低于计数器) | 拒绝启动,记录回滚事件 | 版本计数器值 |
| 双槽均失败 | A/B 槽均写入无效镜像 | 进入安全恢复模式,等待签名升级包 | 恢复模式串口输出 |
| 掉电恢复 | 升级写入 B 槽过程中断电 | 重启后仍从 A 槽启动,B 槽标记无效 | 分区状态标志 |
测试时建议使用可编程电源模拟掉电,用逻辑分析仪或调试串口抓取启动阶段日志,重点确认三件事:失败时是否真的没有跳转到未验证代码;回退是否发生在正确的槽;失败计数和审计日志是否掉电保持。对于医疗设备,还应验证安全恢复模式下治疗输出被禁用,报警功能保持可用。