信任根(Root of Trust):硬件信任锚点与不可信组件隔离

说实话,做硬件安全这些年,我最大的体会就是:你得有一个可信的起点。你想想看,如果连芯片启动的第一行代码都不确定是不是安全的,那后面所有的安全措施,说白了都是空中楼阁。

这个起点,就是我们要讲的信任根(Root of Trust, RoT)。它是整个硬件安全体系的基石。我个人习惯把RoT比喻成“安全种子”——这颗种子必须是纯净的、不可篡改的,然后才能从这个种子里长出整棵安全大树。

信任根(RoT)核心逻辑结构图 信任根芯片(RoT) 安全执行环境的源头 硬件信任锚点 • Boot ROM(不可写死区) • eFuse / OTP(唯一密钥) • PUF(物理不可克隆函数) 信任链(Chain of Trust) 1. Boot ROM 验签 → 2. SPL / BL1 验签 → 3. 主Bootloader + OS内核 不可信组件隔离 • MPU / SSU / 总线防火墙 • DMA 访问隔离 • 外设地址空间保护 运行时安全服务 • 安全启动(Secure Boot) • 安全固件更新(FOTA) • 可信执行环境(TEE) 每一级验上一级签名

硬件信任锚点:可信的起点

为什么要硬件信任锚点?你想想看,纯软件方案能不能实现“可信”?不能。软件可以被打补丁、被篡改、被绕过去。真正的信任根,必须固化在芯片的硬件层面,不能被改写。

我在项目中遇到过很多次这样的事情:客户说“我们用软件加密启动就够了”,结果产品上市不到一个月就被攻破了。从那以后,我深知硬件锚点的重要性。

常见的硬件信任锚点有这么几种:

锚点类型 技术实现 防篡改能力 典型用途
Boot ROM 芯片出厂掩膜写入,物理上无法改写 ★★★★★ 启动第一级代码验证
eFuse / OTP 一次性可编程存储单元,烧断即永久 ★★★★☆ 存储根密钥、设备身份
PUF 利用制造差异提取物理指纹 ★★★★★ 密钥生成,防物理探测
TRNG 基于物理噪声的真随机数发生器 ★★★☆☆ 为密码操作提供随机种子
我的建议:如果项目成本允许,尽量选择包含 PUF 的 SoC。我记得有次做车规级 T-Box,客户要求密钥不能被任何方式读出,哪怕是探针攻击也不行。用 PUF 直接在芯片内部生成密钥,开机即用,关机即散,物理上就杜绝了密钥提取的可能性。

信任链:一级验一级,层层递进

有了硬件锚点之后,如何从“可信”扩展到整个系统?答案就是信任链(Chain of Trust)。

说白了,就是一级验证一级。每一级只信任上一级签名过的代码。一个典型的信任链流程如下:

  1. Boot ROM 运行:ROM 里固化的代码最先执行,它验证下一级 Bootloader 的数字签名。
  2. 签名验证通过:则跳到 Bootloader,Bootloader 再去验证下一级(比如主 Bootloader 或 OS 内核)。
  3. 验签失败:直接停止启动,或者进入一个受限的恢复模式。

我曾经在一个物联网网关项目里吃过亏——当时只验了前两级,第三级固件没验签,结果攻击者直接替换了内核镜像,整个安全链形同虚设。所以记住:信任链必须覆盖到最终运行态,少一环都不行。

// 伪代码:信任链验签逻辑示意
int chain_of_trust(boot_img_t *img, rsa_pub_key *root_key) {
    // 第一级:Boot ROM 验签 SPL
    if (rsa_verify(img->spl, img->spl_len, root_key) != SUCCESS) {
        panic("Boot ROM: SPL signature invalid");
        return -1;
    }
    exec(img->spl);

    // 第二级:SPL 验签主 Bootloader
    if (rsa_verify(img->bootloader, img->bootloader_len, root_key) != SUCCESS) {
        panic("SPL: Bootloader signature invalid");
        return -1;
    }
    exec(img->bootloader);

    // 第三级:Bootloader 验签 OS 内核
    if (rsa_verify(img->kernel, img->kernel_len, root_key) != SUCCESS) {
        panic("Bootloader: Kernel signature invalid");
        return -1;
    }
    exec(img->kernel);

    return 0;
}
关键点:每一级的验签操作必须在上一级的受保护环境中执行。比如 ROM 代码不能轻易跳过,SPL 必须锁在安全内存区域。我见过一些团队把验签代码放在普通 RAM 里,结果被内存攻击篡改了验签函数...嗯,教训惨痛。

不可信组件隔离:信任也分边界

信任根建好之后,是不是所有组件都能信任了?当然不是。现实系统里,总有一些组件是“不可信的”。比如 Wi-Fi 芯片、蓝牙栈、第三方 Sensor Hub,这些组件可能来自不同的供应商,代码质量参差不齐,说不定就藏着漏洞。

所以,我们要做隔离——把可信区域和不可信区域物理或逻辑地隔离开。隔离的手段通常包括:

  • 内存保护单元(MPU / SSU):限制不可信 Master(如 DMA、USB 控制器)只能访问特定地址空间,防止越界读取安全内存。
  • 总线防火墙:在 AHB/AXI 总线上设置防火墙规则,只允许授权的总线事务通过。
  • 外设专用隔离:比如把关键 GPIO、定时器、加密引擎分配给安全世界,非安全世界无法访问。
隔离策略 保护范围 性能影响 典型场景
MPU / SSU 内存访问权限 极小(硬件检查) TrustZone 非安全世界隔离
DMA 隔离 DMA 传输目标 无 防止外设 DMA 窃取密钥
IOMMU / SMMU 设备 DMA 地址映射 中等(页表查找) 虚拟化、多租户场景
物理内存加密 DRAM 数据机密性 中等(加解密延迟) 高安全等级、金融设备
注意:隔离不是万能的。你不禁要问:如果防火墙配置本身被篡改怎么办?所以防火墙的配置寄存器必须保护在安全世界中,并且只有 Boot ROM 或 TEE 才能修改。我曾经见过一个产品,防火墙寄存器是 MMIO 可写的,攻击者直接写寄存器就关了隔离——这种“信任根”跟没有差不多。

实践建议:如何落地

讲了这么多,到底怎么落地呢?我给你几个具体的建议:

  1. 芯片选型时:确认芯片是否提供硬件 RoT 模块(如 ARM TrustZone + 专用安全核、NXP i.MX HABv4/ v5、Intel Boot Guard)。我个人推荐优先选支持硬件密钥注入的型号,这样量产时安全。
  2. 信任链要闭合:从 Boot ROM 到 OS 内核,每一级都必须验签。不要偷懒,不要跳过中间环节。
  3. 隔离策略要细化:不仅仅是分“安全/非安全”,还要具体到哪个 Master 能访问哪个 Slave,地址范围是多少。用表格写清楚,团队评审。
  4. 测试要覆盖攻击场景:比如试试能不能用 DMA 从安全内存偷数据,或者修改 Bootloader 镜像看芯片是否拒绝启动。
小窍门:如果是做高安全产品(比如支付终端、车规域控),建议在主 SoC 之外再加一个独立的安全芯片(如 Microchip ATECC608A、Infineon SLM9670)。你的信任根就完全独立于主处理器了。我有个项目就是这么做的,虽然 BOM 成本多了几块钱,但安全等级直接拉满,客户很认可。

嗯,信任根这件事,说白了就是从源头建立信任,然后层层保护、明确隔离。选好硬件锚点、搭好信任链、做好隔离,你的系统就有了一个坚实的底座。后面再去做安全启动、固件更新、运行时保护,才有真正的根基。