2. 硬件根密钥(HRK):芯片安全的第一块基石

各位同学,咱们今天聊聊硬件根密钥——HRK。这玩意儿,说白了就是整个安全启动体系的“祖宗”。你想想看,信任链再长,总得有个起点吧?HRK就是这个起点。没有它,后面所有的签名验证、镜像校验都是空中楼阁。

我在做嵌入式安全这行之前,总觉得“根密钥”就是个概念。直到有一次,我参与一个IoT设备的固件安全审计,发现厂商直接把根密钥硬编码在Flash里——嗯,结果可想而知,整个设备的安全体系形同虚设。从那以后,我对HRK的敬畏心就上来了。

2.1 HRK的概念与作用

HRK,全称Hardware Root Key,硬件根密钥。它是一段存储在芯片内部的、不可篡改的密钥数据。它的核心作用只有一个:作为信任链的锚点

具体来说,HRK负责以下几件事:

  • 验证BootROM的完整性:芯片上电后,BootROM是第一个执行的代码。HRK会验证BootROM的签名,确保它没有被篡改。
  • 派生次级密钥:HRK本身不直接用于大量数据的加解密。它更像一个“种子”,用来派生其他密钥,比如SSK(安全存储密钥)、MEK(媒体加密密钥)等。
  • 提供硬件隔离:HRK存储在芯片内部的OTP(一次性可编程)存储器或eFuse中,软件无法直接读取。这就保证了即使操作系统被攻破,攻击者也拿不到HRK。

核心要点:HRK是信任链的“第一块砖”。如果HRK被泄露,整个安全体系就崩塌了。所以,保护HRK是芯片安全设计的重中之重。

2.2 HRK的生成与存储

HRK的生成,可不是随便写个随机数就完事的。我见过一些厂商图省事,直接用软件生成HRK,然后烧录到芯片里。这种做法,说实话,风险很大。

正确的做法是:

  1. 硬件真随机数生成器(TRNG):在芯片制造过程中,利用芯片内部的TRNG生成一个高质量的随机数。这个随机数就是HRK的原始材料。
  2. 物理不可克隆函数(PUF):更高级的做法是利用PUF技术。PUF利用芯片制造过程中的工艺偏差,生成一个唯一的、不可克隆的“指纹”。这个指纹可以直接作为HRK,或者用来加密HRK。
  3. 安全烧录:生成的HRK通过安全通道写入芯片的OTP或eFuse中。这个过程通常在芯片的“安全制造”阶段完成,确保HRK不会被中间人截获。

存储方面,HRK的存放位置非常关键:

存储介质 特点 典型应用
OTP(一次性可编程存储器) 写入后不可更改,容量较小 存储HRK本身
eFuse 可多次编程,但每次编程都是永久性的 存储HRK的派生密钥或配置信息
安全RAM 仅在芯片上电后可用,掉电即失 临时存储HRK的派生密钥

个人经验:我在一个项目中,曾经遇到过HRK存储位置选错的问题。当时工程师把HRK放在了普通Flash里,结果一次固件升级后,HRK被意外擦除了。嗯,从那以后,我坚持HRK必须放在OTP或eFuse里,绝不妥协。

2.3 三星Exynos芯片中的HRK实现

咱们来看看三星Exynos芯片是怎么做的。Exynos系列芯片在移动端和IoT设备中应用广泛,它的HRK实现很有代表性。

Exynos的HRK机制大致是这样的:

  • BootROM中的HRK验证:芯片上电后,BootROM会从OTP中读取HRK,然后用它来验证下一级Bootloader(通常是BL1)的签名。如果签名验证失败,芯片直接进入“死循环”或“安全错误”状态。
  • 密钥派生:Exynos使用HRK作为根,通过硬件加密引擎(如AES、SHA)派生出一系列次级密钥。这些次级密钥分别用于验证不同阶段的镜像,比如BL2、U-Boot、Linux内核等。
  • 硬件隔离:Exynos芯片内部有一个“安全域”(Secure World),HRK的读取和操作都在这个安全域内完成。普通世界的软件(比如Android)根本无法触及HRK。

我举个例子,Exynos 9820芯片的HRK实现:

// 伪代码:Exynos BootROM中的HRK验证流程
void bootrom_main() {
    // 1. 从OTP读取HRK
    uint8_t hrk[32];
    read_otp(OTP_HRK_ADDR, hrk, 32);

    // 2. 读取BL1镜像及其签名
    uint8_t bl1_image[BL1_SIZE];
    uint8_t bl1_signature[64];
    read_flash(BL1_OFFSET, bl1_image, BL1_SIZE);
    read_flash(BL1_SIG_OFFSET, bl1_signature, 64);

    // 3. 使用HRK验证BL1签名
    if (!verify_signature(hrk, bl1_image, BL1_SIZE, bl1_signature)) {
        // 验证失败,进入安全错误状态
        enter_secure_error();
    }

    // 4. 验证通过,跳转到BL1
    jump_to(bl1_image);
}

这段代码看起来简单,但背后涉及复杂的硬件逻辑。比如,read_otp()函数实际上是通过硬件安全模块(HSM)来访问OTP的,软件无法直接读取。这就是硬件隔离的体现。

避坑指南:我曾经在调试Exynos芯片时,发现BL1签名验证总是失败。排查了半天,最后发现是OTP中的HRK被意外写入了错误的值。原因是生产线上烧录HRK时,没有做校验。所以,HRK烧录后一定要做回读校验,确保写入的数据是正确的。

2.4 HRK的保护机制

HRK的保护,不能只靠“藏起来”。攻击者有的是办法,比如物理攻击(探针、激光)、侧信道攻击(功耗分析、电磁辐射)、软件攻击(漏洞利用)等。所以,HRK的保护必须是多层次的。

常见的保护机制包括:

  • 物理防护:芯片内部有金属屏蔽层、传感器(如温度、电压、光线传感器),一旦检测到异常,立即擦除HRK或触发安全复位。
  • 逻辑隔离:HRK只能由硬件安全模块(HSM)或安全CPU访问。普通CPU和DMA控制器都无法直接读取HRK。
  • 密钥派生:HRK不直接用于加解密,而是通过密钥派生函数(KDF)生成会话密钥。这样,即使会话密钥泄露,HRK仍然是安全的。
  • 防回滚:通过eFuse记录已使用的密钥版本,防止攻击者将系统回滚到旧版本,从而利用旧密钥的漏洞。

我特别想强调一下“防回滚”机制。很多攻击者会尝试把固件降级到有漏洞的旧版本,然后利用旧版本的漏洞来获取HRK。所以,Exynos芯片在每次升级后,都会在eFuse中写入一个“版本号”。BootROM在启动时,会检查当前镜像的版本号是否大于等于eFuse中的版本号。如果不是,直接拒绝启动。

总结一下:HRK的保护,本质上是“硬件+软件”的组合拳。硬件提供物理隔离和防篡改能力,软件提供逻辑隔离和密钥管理能力。两者缺一不可。

好了,关于HRK的内容就讲到这里。下一章,咱们聊聊“安全启动流程”——从芯片上电到操作系统启动,信任链是如何一步步建立起来的。到时候我会结合Exynos芯片的实际案例,给大家拆解每一步的细节。

记住一句话:HRK是根,根不牢,地动山摇