2、密码学基础:哈希算法、非对称加密、数字签名、证书链等核心概念,以及它们在安全启动中的应用
安全启动(Secure Boot)的本质,是建立一个从硬件根信任到操作系统加载的完整信任链。这条信任链的每一环,都依赖于密码学中的几项核心原语:哈希算法保证数据完整性,非对称加密保证密钥分发的安全性,数字签名同时提供完整性与身份认证,而证书链则解决“公钥本身是否可信”的终极问题。理解这些概念在安全启动中的具体角色,是掌握嵌入式系统安全设计的基石。本章将逐一拆解这些密码学原语,并深入分析它们如何在启动流程中协同工作。
上图展示了安全启动的信任链模型与密码学原语之间的映射关系。从硬件根信任(eFuse中烧录的根公钥哈希)出发,BootROM使用该哈希验证BL1的签名,BL1再验证BL2,BL2最终验证操作系统内核。每一级验证都依赖哈希算法计算镜像摘要,依赖非对称加密算法验证签名,而整个信任链的起点则依赖于证书链或直接烧录的公钥哈希。下面我们逐一深入这些核心概念。
2.1 哈希算法:数据完整性的守门员
核心原理
哈希算法(如SHA-256、SHA-512)是一种单向函数,它将任意长度的输入数据映射为固定长度的输出(摘要)。对于安全启动而言,哈希算法最重要的特性包括:抗碰撞性(难以找到两个不同输入产生相同哈希值)、单向性(从哈希值无法反推原始数据)以及雪崩效应(输入微变,输出剧变)。在嵌入式系统中,SHA-256是最常见的选择,因为它计算速度快、硬件加速器支持广泛,且安全性在当前算力下足够。
在安全启动流程中,哈希算法主要用于两个场景:一是计算固件镜像的摘要值,用于签名验证;二是将公钥的哈希值烧录到eFuse中,作为信任根。例如,某款车规级MCU在出厂时,会将根公钥的SHA-256哈希值写入一次性可编程(OTP)存储器。BootROM启动时,先从OTP读取该哈希值,再对Flash中存储的BL1公钥计算哈希,两者比对一致后,才信任该公钥。
| 哈希算法 | 输出长度 | 安全性 | 嵌入式适用性 |
|---|---|---|---|
| MD5 | 128 bit | 已破解,不推荐 | 仅用于非安全校验 |
| SHA-1 | 160 bit | 存在碰撞攻击 | 禁止用于安全启动 |
| SHA-256 | 256 bit | 当前安全 | 主流选择,硬件加速支持 |
| SHA-512 | 512 bit | 更安全 | 计算开销大,较少用于启动 |
判断方法与操作流程
在实际部署中,工程师需要确认哈希算法是否被正确使用。关键检查点包括:
- 哈希值存储位置:根公钥哈希必须存储在不可篡改的介质中(eFuse/OTP),而非Flash。
- 哈希计算覆盖范围:签名验证时,哈希必须覆盖整个固件镜像(包括头部、正文、尾部),不能遗漏任何字节。
- 防回滚机制:哈希值本身无法防止版本回滚,需要配合版本号或单调计数器。
// 典型的安全启动哈希验证伪代码
uint8_t stored_hash[32]; // 从eFuse读取
uint8_t computed_hash[32];
sha256_compute(bl1_image, bl1_size, computed_hash);
if (memcmp(stored_hash, computed_hash, 32) != 0) {
// 哈希不匹配,拒绝启动
panic();
}
案例拆解:一次固件损坏的启动失败
某工业控制器的BootROM在启动时发现BL1镜像的SHA-256哈希与eFuse中存储的值不匹配,系统进入恢复模式。工程师通过调试串口获取了以下信息:
- eFuse中存储的哈希值:
0x3A7B...F1E2 - 实际计算BL1镜像的哈希值:
0x9C4D...A8B3
分析过程:首先确认Flash中BL1数据是否被意外修改(如静电干扰、编程错误)。使用JTAG读取BL1原始数据,与编译产物比对,发现偏移0x2A3处有4字节差异。进一步排查发现,该位置是BL1的配置参数区,在产线测试时被错误写入。修复方案:重新烧录正确BL1镜像,并在产线测试流程中增加哈希校验步骤。复盘经验:哈希校验只能发现数据被篡改,但无法定位篡改原因,需要结合日志和硬件调试手段。
2.2 非对称加密:公钥与私钥的分工协作
核心原理
非对称加密使用一对密钥:公钥(Public Key)和私钥(Private Key)。公钥可以公开分发,私钥必须严格保密。RSA和ECC(椭圆曲线密码学)是嵌入式领域最常用的两种算法。RSA基于大整数分解难题,密钥长度通常为2048或3072位;ECC基于椭圆曲线离散对数难题,在相同安全强度下密钥更短(256位ECC约等于3072位RSA),计算开销更小,非常适合资源受限的嵌入式设备。
在安全启动中,非对称加密的核心应用是数字签名。签名过程使用私钥,验证过程使用公钥。这种设计确保了:即使攻击者获取了所有公开信息(固件、公钥、签名),也无法伪造新的有效签名,因为私钥不在设备上。
判断方法与操作流程
选择非对称加密算法时,需要综合考虑以下因素:
- 安全强度:RSA-2048和ECC-256在当前被认为是安全的,但需关注量子计算威胁。
- 计算性能:ECC在签名验证速度上优于RSA,但签名生成较慢(通常由服务器完成)。
- 硬件加速:检查SoC是否内置RSA/ECC加速器,可显著提升启动速度。
- 密钥存储:私钥存储在安全服务器或HSM中,公钥存储在设备端。
| 特性 | RSA-2048 | ECC-256 (secp256r1) |
|---|---|---|
| 密钥长度 | 2048 bit | 256 bit |
| 签名验证速度 | 较慢(指数运算) | 较快(标量乘法) |
| 签名大小 | 256 字节 | 64 字节 |
| 硬件资源占用 | 较高 | 较低 |
| 典型应用 | 传统BootROM | 现代车规/物联网芯片 |
实战场景:密钥生成与分发流程
在量产环境中,密钥管理是安全启动的关键环节。一个典型的流程如下:
- 在离线安全环境中生成密钥对(如使用HSM)。
- 私钥保存在HSM中,用于签名固件镜像。
- 公钥经过哈希处理后,烧录到每颗芯片的eFuse中。
- 固件发布时,使用私钥对固件哈希进行签名,生成签名文件。
- 设备启动时,使用eFuse中的公钥验证签名。
2.3 数字签名:完整性与身份认证的双重保障
核心原理
数字签名是哈希算法与非对称加密的结合。签名过程:发送方使用私钥对消息的哈希值进行加密运算,生成签名。验证过程:接收方使用公钥解密签名,得到原始哈希值,再对消息重新计算哈希,两者比对。如果一致,则证明消息未被篡改且确实来自私钥持有者。
在安全启动中,签名验证的典型流程为:
1. 读取固件镜像(如BL1)
2. 计算镜像的SHA-256哈希值 H
3. 使用公钥解密签名,得到 H'
4. 比较 H 与 H',一致则通过验证
这里有一个关键细节:签名覆盖的范围。签名必须覆盖固件的所有关键部分,包括头部信息(版本号、加载地址、大小)和正文数据。如果签名只覆盖部分数据,攻击者可能修改未覆盖区域(如版本号)进行降级攻击。
案例拆解:签名验证失败的排障过程
某物联网设备在升级固件后无法启动,串口日志显示“Signature verification failed”。工程师的排查步骤:
- 第一步:确认公钥正确性。读取eFuse中的公钥哈希,与编译时使用的公钥比对,发现一致。
- 第二步:检查签名文件。使用openssl命令验证签名文件是否与固件匹配:
openssl dgst -sha256 -verify public.pem -signature sig.bin firmware.bin,结果显示验证失败。 - 第三步:分析固件差异。对比升级前后的固件二进制,发现升级工具在固件头部添加了4字节的填充数据,导致哈希计算偏移。
- 解决方案:修改升级工具,确保签名时使用的固件数据与烧录到Flash的数据完全一致。
复盘经验:签名验证失败往往不是密码学算法问题,而是数据格式不一致。建议在签名和验证时使用统一的固件打包格式(如FIT Image),并增加格式校验。
2.4 证书链:构建可管理的信任体系
核心原理
直接烧录公钥哈希到eFuse虽然简单,但存在密钥管理问题:一旦私钥泄露,无法在不更换芯片的情况下更新公钥。证书链(Certificate Chain)通过引入证书颁发机构(CA)解决了这个问题。信任链结构为:根证书 → 中间证书 → 实体证书。根证书的公钥(或哈希)烧录在eFuse中,中间证书和实体证书存储在Flash中。
验证过程:设备使用根公钥验证中间证书的签名,再使用中间证书的公钥验证实体证书的签名,最后使用实体证书的公钥验证固件签名。这种设计允许在不修改eFuse的情况下,通过更换中间证书和实体证书实现密钥轮换。
判断方法与操作流程
在嵌入式系统中部署证书链时,需要注意:
- 证书格式:通常使用X.509格式,但嵌入式系统可能使用精简的DER编码以节省空间。
- 证书有效期:设备可能长期离线运行,需要确保证书验证不依赖在线时间戳。
- 证书撤销:嵌入式系统难以维护CRL(证书撤销列表),通常采用短有效期证书或黑名单机制。
| 信任模型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 直接烧录公钥哈希 | 实现简单,信任根固定 | 密钥轮换困难 | 低成本MCU |
| 单级证书链 | 支持密钥轮换 | 根密钥泄露风险 | 主流应用处理器 |
| 多级证书链 | 灵活的分层管理 | 验证复杂度高 | 车规/高安全场景 |
实战场景:车规级安全启动的证书链设计
某车规级SoC采用三级证书链:根CA(离线存储)、中间CA(用于不同车型)、实体证书(用于单个ECU)。设计要点:
- 根CA私钥存储在HSM中,仅在年度密钥更新时使用。
- 中间CA私钥存储在产线安全服务器中,用于签发实体证书。
- 实体证书包含ECU唯一ID和固件版本信息,支持细粒度撤销。
- BootROM验证根证书 → 中间证书 → 实体证书 → 固件签名,共4次验签操作。
该设计的优势在于:如果某车型的中间CA私钥泄露,只需在eFuse中更新根证书哈希(如果支持),或通过OTA更新中间证书,而无需更换硬件。
2.5 密码学原语在安全启动中的协同工作
核心原理
安全启动的完整流程是多种密码学原语的协同工作。以ARM TrustZone和U-Boot的典型启动流程为例:
- BootROM阶段:从eFuse读取根公钥哈希,验证BL1的签名(哈希+非对称解密)。
- BL1阶段:初始化DDR,验证BL2的签名。
- BL2阶段:验证BL33(如U-Boot)或直接验证内核镜像。
- 内核阶段:内核验证设备树和initramfs的签名。
每一级验证都遵循相同的模式:计算哈希 → 使用公钥验签 → 比对结果。这种链式验证确保了从硬件根到操作系统的每一层都是可信的。
判断方法与操作流程
在部署安全启动时,工程师需要验证以下关键点:
- 信任根是否安全:eFuse/OTP是否启用了读保护?是否支持一次性编程锁定?
- 签名算法是否匹配:签名时使用的哈希算法和填充方案(如RSA-PSS vs PKCS#1 v1.5)必须与验证端一致。
- 启动路径是否完整:从BootROM到内核的每一级都必须有验证,不能存在未验证的跳转。
// 安全启动验证链的简化代码逻辑
int verify_image(struct image *img, uint8_t *pubkey) {
uint8_t hash[32];
sha256(img->data, img->size, hash);
if (rsa_verify(pubkey, hash, img->signature) != 0) {
return -1;
}
return 0;
}
案例拆解:一次完整的启动链验证测试
某网络交换机产品在量产前进行安全启动合规测试。测试用例包括:
- 正常启动:所有镜像签名正确,启动时间2.3秒(其中验签耗时0.4秒)。
- 篡改BL1:修改BL1中一个字节,BootROM拒绝启动,串口输出错误码0x01。
- 篡改BL2:BL1验证失败,错误码0x02。
- 回滚攻击:将BL2替换为旧版本,版本号检查失败,错误码0x03。
- 公钥替换:尝试修改eFuse中的公钥哈希,由于OTP锁定,写入失败。
测试结果全部符合预期。复盘经验:安全启动测试需要覆盖正常路径和所有异常路径,建议使用自动化测试脚本模拟各种攻击场景。