2. 密码学基础回顾

各位同学,咱们今天聊点硬核的。做TEE安全启动,密码学是绕不开的基石。我见过不少工程师,上来就撸代码,结果签名验签搞反了,哈希算法选错了,最后启动流程跑不通。嗯,咱们先把基础夯实。

一、哈希函数:数据的“指纹”

哈希函数,说白了就是把任意长度的数据,压缩成一个固定长度的摘要。这个摘要就像人的指纹,理论上很难找到两个不同的输入产生相同的输出。

SHA-256 是目前最常用的哈希算法之一。它输出256位(32字节)的摘要。我在项目中遇到过,有人为了省空间,只取了前16字节做校验,结果被攻击者碰撞了。记住,安全启动里,哈希值必须完整使用。

核心特性:

  • 单向性:从摘要反推原始数据,计算上不可行。
  • 抗碰撞性:找到两个不同输入,产生相同摘要,极其困难。
  • 雪崩效应:输入改一个比特,输出会有一半以上的比特发生变化。

为什么TEE启动要用哈希?你想想看,固件镜像可能几兆甚至几十兆,直接签名效率太低。我们通常先对镜像做哈希,然后只对哈希值签名。这样既安全又高效。

// 伪代码示例:计算固件哈希
uint8_t firmware_hash[32];
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx, firmware_image, firmware_size);
sha256_final(&ctx, firmware_hash);
// 此时 firmware_hash 就是固件的“指纹”

我的经验: 选择哈希算法时,别只看输出长度。SHA-256在大多数嵌入式芯片上都有硬件加速,性能远好于SHA-512。我曾经在一个Cortex-M4项目里,用软件实现SHA-512,结果启动时间多了3秒,后来切回SHA-256,问题解决。

二、非对称加密:RSA与ECC

非对称加密,核心思想是“公钥加密,私钥解密”或者“私钥签名,公钥验签”。这和对称加密完全不同,对称加密两边用同一个密钥,分发密钥本身就是个大麻烦。

RSA 基于大整数分解难题。密钥越长越安全,但计算也越慢。我建议在TEE场景下,RSA密钥至少2048位,1024位已经被证明不安全了。

ECC(椭圆曲线密码学) 基于椭圆曲线离散对数难题。它的优势在于,同等安全强度下,密钥长度更短。比如,256位的ECC密钥,安全性和3072位的RSA相当。这对嵌入式设备来说,简直是福音——存储空间和计算资源都有限。

安全等级 RSA密钥长度 ECC密钥长度
80位 1024位 160位
112位 2048位 224位
128位 3072位 256位
256位 15360位 512位

避坑指南: 我曾经在一个项目中,看到有人把ECC私钥直接硬编码在固件里。这等于把家门钥匙挂在门外。私钥必须存储在安全硬件中,比如TEE的信任根或安全元件(SE)。

三、数字签名原理

数字签名,说白了就是用私钥给数据“盖章”,别人用公钥来验证这个章是真的。它保证了数据的完整性和来源的真实性。

流程是这样的:

  1. 发送方对数据做哈希,得到摘要。
  2. 发送方用私钥对摘要加密,生成签名。
  3. 接收方收到数据和签名后,用同样的哈希算法计算摘要。
  4. 接收方用公钥解密签名,得到原始摘要。
  5. 比较两个摘要,一致则签名有效。

在TEE安全启动里,这个流程被用在每个启动阶段。BootROM验证下一级Bootloader的签名,Bootloader再验证OS内核的签名,环环相扣。

// 签名验证伪代码
uint8_t hash[32];
sha256(firmware, firmware_size, hash);

// 使用公钥验证签名
int result = rsa_verify(public_key, hash, signature);
if (result == 0) {
    // 签名有效,启动继续
} else {
    // 签名无效,拒绝启动
    panic();
}

我的习惯: 验证签名时,一定要做“恒定时间比较”,防止时序攻击。不要用memcmp,它一旦发现不匹配就立即返回,攻击者可以通过响应时间推断出正确字节。用专门的恒定时间比较函数。

四、证书链与PKI体系

公钥怎么分发?你总不能把公钥写在固件里吧?万一被篡改了呢?这就引出了PKI(公钥基础设施)和证书链。

证书,本质上是一个把公钥和身份信息绑定在一起的数据结构,由证书颁发机构(CA)签名。证书链,就是从根CA证书,到中间CA证书,再到最终实体证书的一条信任路径。

在TEE安全启动中,通常会在芯片出厂时,把根CA的公钥烧录到一次性可编程存储器(OTP)里。这就是信任根。后续所有证书的验证,都追溯到这根公钥。

验证流程:

  • 用根CA公钥验证中间CA证书的签名。
  • 用中间CA公钥验证设备证书的签名。
  • 用设备证书中的公钥验证固件的签名。

只要任何一环验证失败,启动过程立即终止。

为什么需要中间CA?直接让根CA给每个设备签名不行吗?行,但风险太大。根CA私钥一旦泄露,整个体系就完了。中间CA相当于一个缓冲,即使某个中间CA的私钥泄露,只需要吊销它的证书,根CA还是安全的。

TEE安全启动证书链验证流程 根CA证书 (烧录在OTP中) 验证 中间CA证书 (由根CA签名) 验证 设备证书 (由中间CA签名) 验证 固件镜像

我曾经踩过的坑: 证书有效期没检查。有一批设备出厂两年后,证书过期了,导致无法进行安全更新。后来我们强制在验证逻辑里加入时间检查,并且使用有效期更长的证书。记住,证书不是永久的。

好了,密码学基础就聊到这儿。这些概念在后续的TEE启动流程里会反复出现。你理解得越深,后面写代码就越顺手。