4. 安全启动与信任链实现

安全启动的本质不是“加一个校验函数”,而是把设备从上电到应用运行的全过程组织成一条可验证的信任链:每一级代码在执行前,先由上一级可信代码验证其完整性与来源,验证通过才移交控制权。医疗设备固件一旦被篡改,可能改变治疗参数、报警阈值或数据上报逻辑,因此信任链必须从不可修改的 ROM 引导开始,逐级延伸到应用固件,并在异常时给出可恢复、可审计的确定行为。

一、信任链的层级与移交条件

典型 MCU/MPU 医疗设备的信任链可划分为四级:芯片 ROM Boot(不可改)、一级引导 BL1(通常位于受保护扇区或 OTP 锁定区)、二级引导 BL2/安全固件、应用固件 App。ROM 内部固化的公钥哈希或根公钥(Root Public Key)是整条链的信任锚点,它不依赖外部存储,因此无法被固件升级改写。BL1 的签名由 ROM 用根公钥验证;BL1 验证通过后,再用其内置的下一级公钥验证 BL2;BL2 再验证 App。每一级只信任“上一级已验证过的公钥”,而不是信任存储介质本身。

移交控制权前必须同时满足三个条件:签名验证通过、版本/防回滚检查通过、目标镜像的加载地址与长度在允许范围内。任一条件不满足,都不能跳转到该级代码,而应进入预定义的失败处理路径。这样即使攻击者替换了 Flash 中的 App,也无法让设备执行未签名代码。

医疗设备安全启动信任链与失败恢复路径 ROM Boot 不可修改信任锚 内置根公钥哈希 BL1 一级引导 受保护扇区 / OTP 锁定 含下一级公钥 BL2 二级引导 安全固件 / 升级代理 校验 App 镜像 App 应用固件 治疗 / 报警 / 通信 版本号 + 签名 验签 验签 验签 每级移交前必须同时通过的检查 ① 签名验证 ECDSA-P256 / RSA-3072 ② 防回滚检查 版本 ≥ 熔丝/计数器 ③ 地址与长度 加载范围合法 ④ 完整性摘要 SHA-256 比对 验证失败 → 启动失败恢复策略 A/B 双分区回退 App 校验失败 切至上一可用槽 记录失败计数 安全恢复模式 仅接受签名升级包 串口/USB 受限通道 不进入治疗逻辑 安全状态锁定 连续失败 ≥ 3 次 停止自动重试 提示现场维护 审计日志 记录失败级别 原因码 / 版本号 掉电保持 信任链逐级验签;任一级失败即进入恢复路径,不执行未验证代码

二、签名验证的实现要点

签名验证通常采用“哈希 + 非对称验签”的组合。以 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 槽标记无效分区状态标志

测试时建议使用可编程电源模拟掉电,用逻辑分析仪或调试串口抓取启动阶段日志,重点确认三件事:失败时是否真的没有跳转到未验证代码;回退是否发生在正确的槽;失败计数和审计日志是否掉电保持。对于医疗设备,还应验证安全恢复模式下治疗输出被禁用,报警功能保持可用。

签名验证的覆盖范围、版本计数器的存储位置、失败计数的阈值,是安全启动方案评审中最容易产生分歧的三个点,建议在需求阶段就明确并写入接口文档。
不要把“能启动”当作“安全启动通过”。必须用篡改、回滚、掉电三类负向用例证明设备在异常输入下仍能进入确定的安全状态。