1、可信根的定义与核心概念:什么是可信根(RoT),为什么它是安全启动的基石

各位好,咱们今天开始聊可信根。说实话,这个名词听起来挺唬人的——"可信根"、"信任锚点",感觉像是某种玄学概念。但说白了,它就是整个安全体系里那个"绝对可信"的起点。

我刚开始接触嵌入式安全时,也困惑过:凭什么说某个东西是"可信"的?后来在做一个车规级项目时,甲方要求我们证明启动链的每个环节都没被篡改。嗯,那时候我才真正理解——你得先有一个不可伪造的信任起点,否则后面所有的校验都是空中楼阁。

1.1 可信根的本质定义

可信根(Root of Trust,RoT)是一个硬件或固件层面的不可变实体。它必须满足三个条件:

  • 不可伪造性:攻击者无法通过软件手段修改或替换它
  • 不可绕过性:系统启动时必须经过它,没有"后门"可以跳过
  • 行为可预测:它的行为是确定的,不会因为外部条件变化而改变

你想想看,如果连这个起点都不安全,那后面校验再多也是白搭。我在一个IoT网关项目里就踩过这个坑——当时用的MCU没有硬件RoT,全靠软件做校验。结果呢?攻击者直接通过JTAG把校验代码给改了,整个安全体系瞬间崩塌。

核心观点:可信根不是"最安全的组件",而是"最先被信任的组件"。它的安全级别决定了整个系统的安全上限。

1.2 可信根在安全启动中的位置

安全启动(Secure Boot)本质上是一条信任链。我习惯把它画成这样的结构:

安全启动信任链结构 硬件可信根 BootROM / eFuse Bootloader 由RoT验证签名 OS Kernel 由Bootloader验证 应用程序 信任链传递逻辑 1. 芯片上电,CPU从BootROM开始执行 2. BootROM读取eFuse中的根公钥哈希 3. 用根公钥验证Bootloader的数字签名 4. 验证通过后,控制权交给Bootloader 5. Bootloader用自身公钥验证OS Kernel 6. Kernel验证关键驱动和系统服务 7. 最后验证应用程序的签名 关键点: • 每一级只信任上一级 • 任何一级验证失败,立即停机 • 根公钥在芯片出厂时烧录,不可更改

这张图我每次培训都会拿出来讲。你看,信任是从最底层的硬件开始,一层一层往上传递。每一级都负责验证下一级的完整性和真实性。这就是所谓的链式信任(Chain of Trust)。

1.3 可信根的物理载体

在实际产品中,可信根通常由以下硬件组件承载:

载体类型 典型实现 不可篡改性来源 我见过的坑
BootROM 芯片内部Mask ROM 光刻掩膜,物理不可改 某厂商BootROM有bug,只能召回芯片
eFuse 一次性可编程存储 熔断后不可恢复 曾经烧录时电压不稳,导致eFuse部分熔断
OTP 一次性可编程存储器 写入后不可擦除 OTP空间有限,密钥存不下
TPM/HSM 独立安全芯片 物理隔离+防篡改封装 成本高,小产品用不起

重要警告:千万不要把根密钥放在Flash或外部EEPROM里。我见过一个团队把根公钥放在SPI Flash中,结果攻击者直接替换Flash芯片就绕过了所有安全校验。这相当于把保险柜钥匙挂在保险柜门上。

1.4 为什么说可信根是安全启动的基石?

这个问题我换个角度回答。你想想,如果没有可信根,安全启动会变成什么样:

  1. 谁来验证第一个执行代码? CPU上电后第一条指令从哪里来?如果这段代码可以被篡改,那后面所有校验都是假的。
  2. 根密钥存在哪里? 如果密钥存在可写的存储介质里,攻击者就能替换成自己的密钥,然后用自己的签名固件启动。
  3. 如何防止回滚攻击? 没有硬件RoT,攻击者可以把固件版本号改小,加载一个有漏洞的老版本。

我在一个医疗设备项目里就遇到过类似问题。当时客户说"我们用软件做校验就够了",结果渗透测试时,我们直接通过U-Boot命令行把整个文件系统给换了。嗯,从那以后,那个客户再也不敢省硬件RoT的钱了。

个人经验:判断一个系统是否有真正的可信根,就一个问题——"如果攻击者能物理接触设备,他能让设备执行未经签名的代码吗?" 如果答案是"能",那这个系统就没有真正的可信根。

1.5 可信根的分类

根据实现方式,我习惯把可信根分成三类:

  • 纯硬件RoT:比如独立TPM芯片、HSM模块。安全性最高,但成本也最高。适合服务器、金融终端等场景。
  • 硬件辅助RoT:在SoC内部集成安全子系统,比如ARM TrustZone、RISC-V的物理内存保护(PMP)。性价比不错,我最近几个项目都在用。
  • 软件RoT:纯靠软件实现的信任锚点。说实话,我不推荐任何对安全有要求的项目用这种方式。它只能防"君子",防不了"小人"。

我个人习惯在项目初期就确定RoT方案。因为一旦芯片选型定了,RoT的能力也就定了。后期想加硬件安全模块?那基本等于重新设计硬件。

1.6 一个典型的可信根工作流程

咱们用一个实际例子来说明。假设你用的是某款主流ARM Cortex-M系列MCU:

// 伪代码:可信根验证流程
void boot_sequence() {
    // 1. 芯片复位,从BootROM开始执行
    //    BootROM是Mask ROM,不可修改
    
    // 2. 读取eFuse中的根公钥哈希
    uint8_t root_key_hash[32];
    efuse_read(EFUSE_ROOT_KEY_HASH, root_key_hash);
    
    // 3. 从Flash读取Bootloader及其签名
    uint8_t bootloader[BL_SIZE];
    uint8_t signature[64];
    flash_read(FLASH_BOOTLOADER_ADDR, bootloader);
    flash_read(FLASH_SIGNATURE_ADDR, signature);
    
    // 4. 用根公钥验证签名
    if (ecdsa_verify(root_public_key, bootloader, signature) != SUCCESS) {
        // 验证失败,进入死循环
        while(1);  // 这就是所谓的"安全停机"
    }
    
    // 5. 验证通过,跳转到Bootloader
    jump_to(bootloader);
}

这段代码看起来简单,但实际实现时有很多细节。比如:

  • 根公钥本身不直接存在eFuse里,而是存它的哈希值。这样可以节省宝贵的OTP空间。
  • 签名算法通常用ECDSA P-256或Ed25519。RSA-2048也行,但计算时间会长一些。
  • 验证失败后的行为必须是"硬停机",不能有任何回退路径。我见过一个产品验证失败后居然还能用"恢复模式"启动——那这个安全启动就形同虚设了。

一句话总结:可信根就是那个"你不得不信任它,而且它永远不会背叛你"的硬件实体。没有它,安全启动就像没有地基的房子——看着挺高,一推就倒。

好了,这一章的内容就到这里。记住:选芯片时先看它有没有硬件RoT,再看它的RoT实现是否满足你的安全等级要求。这个顺序不能反,我吃过这个亏。