3、芯片安全启动链:Boot ROM不可篡改性、代码签名与验证、安全加载固件

芯片安全启动链,说白了就是给芯片装上一套「出生证明 + 指纹锁 + 防拆封条」。你想想看,如果芯片上电后执行的第一个代码就被篡改了,那后面所有安全措施都是白搭。我在做物联网芯片安全审计时,见过太多「裸奔」的启动流程——攻击者直接替换固件头,就能让设备加载恶意代码。嗯,这章我们就来拆解这条链上的三个关键环节。

3.1 Boot ROM:芯片的「基因锁」

Boot ROM 是芯片出厂时固化在硅片上的只读代码。它不可篡改,因为物理上就没有写入接口。我习惯把它比作芯片的「基因」——你没法改变自己的 DNA,对吧?

核心特性:

  • 物理只读:掩膜 ROM 或 OTP(一次性可编程)实现,流片后无法修改
  • 最先执行:上电复位后,CPU 直接从 Boot ROM 地址取指
  • 最小可信基:整个安全启动链的信任锚点

我记得有一次,客户问能不能通过固件升级修复 Boot ROM 的漏洞。我直接告诉他:「除非你把芯片拆了重新流片,否则没戏。」这就是为什么 Boot ROM 的代码必须经过极其严格的验证——它没有后悔药。

注意:有些低成本芯片会用 Flash 模拟 Boot ROM,这种方案存在被物理篡改的风险。我在消费电子项目中遇到过,攻击者用探针直接改写 Flash 内容,绕过了整个安全启动链。如果你选型时看到「Flash Boot」字样,一定要问清楚是否有写保护机制。

3.2 代码签名与验证:给固件贴上「防伪标签」

Boot ROM 执行完后,需要加载下一级固件(比如 Bootloader)。但怎么保证这个固件是厂商发布的、没被中间人动过手脚?答案就是代码签名。

流程其实不复杂:

  1. 厂商用私钥对固件哈希签名,生成签名值
  2. 固件包 = 固件 + 签名值 + 证书链
  3. 芯片用预置的公钥验证签名

这里有个关键点——公钥存在哪?我建议放在 Boot ROM 或 OTP 中。如果公钥存在外部 Flash,攻击者可以替换公钥,那签名就形同虚设了。

实战经验:我曾经帮一家车规芯片厂商设计签名方案。他们最初用 RSA-2048,但验签时间太长(约 200ms),影响启动速度。后来换成 ECDSA P-256,验签时间降到 30ms 以内。如果你对启动时间敏感,建议优先考虑 ECC 系列算法。

代码示例(伪代码,展示核心逻辑):

// Boot ROM 中的验签流程
void verify_firmware(uint8_t* firmware, uint32_t len, 
                     uint8_t* signature, uint8_t* pubkey) {
    // 1. 计算固件哈希
    uint8_t hash[32];
    sha256(firmware, len, hash);
    
    // 2. 用预置公钥验签
    if (ecdsa_verify(hash, signature, pubkey) != SUCCESS) {
        // 验签失败,进入错误处理
        halt_boot();
        return;
    }
    
    // 3. 验签通过,跳转到固件入口
    jump_to(firmware);
}

避坑指南:我曾经见过一个方案,验签通过后直接跳转,没检查固件头部的版本号。结果攻击者把旧版本固件(含已知漏洞)重新签名后加载进去,实现了降级攻击。记住:签名验证只是第一步,版本号、设备 ID、防回滚标记都要一起校验。

3.3 安全加载固件:逐级信任,层层把关

现代芯片的启动链通常不止两级。以手机 SoC 为例:

启动阶段 加载者 验证者 存储介质
Boot ROM 硬件固化 物理不可篡改 掩膜 ROM
Primary Bootloader (PBL) Boot ROM Boot ROM 验签 内部 SRAM
Secondary Bootloader (SBL) PBL PBL 验签 DDR
OS Kernel SBL SBL 验签 Flash

每一级只信任上一级,上一级验证下一级的签名后才加载执行。这就是「信任链」的概念。我习惯把它画成下面这张图:

芯片安全启动信任链 Boot ROM 物理不可篡改 PBL Boot ROM 验签加载 SBL PBL 验签加载 OS Kernel SBL 验签加载 应用/服务 内核验签加载 🔑 信任链核心原则 • 每一级只信任上一级,形成单向信任传递 • 任何一级验签失败,立即终止启动(安全熔断) • 公钥必须存储在不可篡改的介质中(Boot ROM / OTP)

你可能会问:为什么不用一级启动,直接加载 OS?原因很简单——Boot ROM 空间有限(通常只有几十 KB),放不下复杂的验签逻辑和驱动。分级的另一个好处是:如果 SBL 发现固件损坏,可以回退到 PBL 的恢复模式,不至于变砖。

安全加载的四个检查点:

  • 签名验证:确保固件来源可信、未被篡改
  • 版本检查:防止降级攻击(结合防回滚计数器)
  • 完整性校验:加载过程中 CRC 或哈希校验,防止传输错误
  • 地址范围检查:防止固件越界覆盖敏感区域

嗯,说到地址范围检查,我踩过一个坑。某次项目中,Boot ROM 加载 PBL 时没检查目标地址,攻击者构造了一个超长固件头,让 PBL 代码覆盖了安全配置寄存器。结果验签虽然通过了,但安全区域被禁用。从那以后,我每次设计启动链都会加一条硬规则:加载前必须校验目标地址是否在合法范围内。

个人习惯:我建议在 Boot ROM 中实现一个「最小验签引擎」,只支持一种签名算法(比如 ECDSA P-256)和一种哈希算法(SHA-256)。算法越少,攻击面越小。别想着在 Boot ROM 里搞算法可配置——那等于给攻击者留后门。

最后说一句:安全启动链不是万能的。它只能保证加载的固件是厂商签名的,但管不了固件本身有没有漏洞。不过,没有这条链,芯片连「可信」的资格都没有。它是所有上层安全的基础,也是供应链身份安全的第一道防线。