1、可信计算基础:可信计算概念、TPM/TCM规范、信任根与信任链、度量启动原理
各位好,我是老周。今天咱们开始聊启动度量这个主题。说实话,我在安全领域摸爬滚打了十几年,真正让我觉得“这事靠谱”的,还是可信计算这套体系。它不是什么玄学,而是一套能落地的硬件安全方案。
咱们先搞清楚一个根本问题:什么是可信计算?
1.1 可信计算的核心概念
可信计算(Trusted Computing,TC)不是让计算机“信任你”,而是让计算机能被你信任。说白了,就是通过硬件机制保证系统行为可预期、可度量、可验证。
我习惯用一个比喻来解释:
你出差前在家里装了摄像头。回家后查看录像,发现没人进来过——这叫“可信”。
可信计算就是给计算机装了个“不可篡改的摄像头”,从开机第一行代码开始录像。
可信 ≠ 安全。可信是说“系统会按照预期的方式运行”,安全是说“系统不会被攻破”。可信是安全的基础,但可信的系统也可能有漏洞。
可信计算的三个核心目标:
- 身份可信:证明你是你(平台身份认证)
- 行为可信:代码没有被篡改(完整性度量)
- 数据可信:敏感数据只被可信程序访问(密封存储)
嗯,这里要注意:这三个目标不是并列的,而是层层递进的。没有身份可信,行为可信就无从谈起。
1.2 TPM/TCM 规范:硬件信任的基石
聊可信计算,绕不开两个硬件规范:TPM 和 TCM。
| 对比项 | TPM(Trusted Platform Module) | TCM(Trusted Cryptography Module) |
|---|---|---|
| 制定组织 | TCG(Trusted Computing Group) | 中国国家密码管理局 |
| 密码算法 | RSA、SHA-1/SHA-256、ECC | SM2、SM3、SM4(国密算法) |
| 核心功能 | 度量存储、密钥管理、远程证明 | 与TPM类似,但算法全部国密化 |
| 物理形态 | 独立芯片或固件TPM(fTPM) | 独立芯片或SoC集成 |
| 应用场景 | 国际主流(Windows、Linux) | 国内信创、政务、金融 |
我在项目中遇到过不少坑。有一次客户要求用TCM做启动度量,结果发现BIOS里根本没有TCM驱动支持——硬件焊上去了,但上层软件不认识。所以我的建议是:选型阶段就要确认固件和OS的兼容性,别等板子打回来再哭。
个人经验:TPM 2.0 和 TCM 在功能上高度相似,但算法生态不同。如果你的产品要出海,选TPM;如果做信创,选TCM。两头都想占?那就做双模设计,但成本翻倍。
1.3 信任根与信任链
信任不能凭空产生,必须有一个绝对可信的起点。这个起点就是信任根(Root of Trust)。
TCG定义了三个信任根:
- 度量信任根(RTM):通常是CPU执行的第一段代码(如BIOS的Boot Block)
- 存储信任根(RTS):TPM/TCM中的一组PCR寄存器,用于存储度量值
- 报告信任根(RTR):TPM/TCM的签名能力,用于证明度量值的真实性
这三个信任根配合起来,就形成了信任链(Chain of Trust)。
我画了一张图,帮你理解信任链的传递过程:
信任链的核心思想是:信任不能传递,但度量可以。每一级只信任上一级,但每一级都要度量下一级。你想想看,如果Boot Block被篡改了,那后面所有的度量都是白费——因为度量者本身已经不可信了。
我曾经踩过的坑:某次做安全启动方案,发现Boot Block竟然可以被SPI Flash的写保护绕过。原因是硬件工程师把写保护引脚悬空了。从那以后,我要求所有项目必须检查写保护引脚的硬件连接,不能只依赖软件配置。
1.4 度量启动原理
度量启动(Measured Boot)是信任链的具体实现。它的工作流程可以概括为四个字:度量-扩展-存储-验证。
具体来说:
- 度量:当前代码段对下一级代码进行哈希计算(如SHA-256)
- 扩展:将哈希值“扩展”到TPM的PCR寄存器中(PCR_new = SHA256(PCR_old || hash))
- 存储:PCR值被安全保存在TPM内部,外部无法篡改
- 验证:远程验证方或本地策略引擎比对PCR值与预期值
这里有个关键点:为什么用“扩展”而不是“覆盖”?
我解释一下:如果直接覆盖PCR,那么攻击者可以在度量之后、启动之前篡改代码,然后重新度量一次——PCR值还是对的。但扩展操作是不可逆的,你无法通过第二次度量“抹掉”第一次的结果。这就保证了度量历史的完整性。
核心公式:PCR_new = SHA256(PCR_old || 度量值)
这个公式保证了:
1. 度量顺序不可篡改(历史被记录)
2. 无法通过碰撞构造出相同的PCR值(除非找到SHA256碰撞)
3. 任何一次度量值的变化都会导致最终PCR完全不同
咱们看一个简化的代码示例,理解度量扩展的过程:
// 伪代码:度量启动的核心逻辑
void measure_and_extend(void *code, size_t len, uint32_t pcr_index) {
uint8_t hash[32];
// 1. 度量:计算代码的哈希值
sha256(code, len, hash);
// 2. 扩展:读取当前PCR值,与新哈希拼接后再次哈希
uint8_t pcr_current[32];
tpm_pcr_read(pcr_index, pcr_current);
uint8_t extend_input[64];
memcpy(extend_input, pcr_current, 32);
memcpy(extend_input + 32, hash, 32);
uint8_t pcr_new[32];
sha256(extend_input, 64, pcr_new);
// 3. 写入新PCR值
tpm_pcr_write(pcr_index, pcr_new);
// 4. 记录度量日志(用于远程证明)
log_measurement(pcr_index, code, len, hash);
}
这段代码虽然简单,但包含了度量启动的全部精髓。我在实际项目中,曾经因为PCR索引搞错导致整个信任链断裂——BIOS把BootLoader的度量写到了PCR[0],但OS验证时却去读PCR[1]。这种低级错误,排查起来真要命。
避坑指南:PCR索引的分配是有规范的。TCG规定:
PCR[0]:BIOS代码
PCR[1]:BIOS配置
PCR[2]:Option ROM代码
PCR[3]:Option ROM配置
PCR[4]:MBR/GPT
PCR[5]:MBR/GPT配置
PCR[6]:状态变更
PCR[7]:厂商自定义
千万别自己乱分配,否则兼容性会出问题。
1.5 为什么需要度量启动?
你可能会问:我装个杀毒软件不就行了?为什么搞这么复杂?
原因很简单:杀毒软件是在OS启动之后才运行的,而恶意软件可以在OS启动之前就加载。比如Bootkit、Rootkit,它们修改的是MBR或UEFI固件,杀毒软件根本看不到。
度量启动解决的是“谁在最早阶段控制了系统”的问题。它把信任的起点锁定在硬件层面,而不是软件层面。说白了,就是让TPM/TCM充当一个“不撒谎的见证人”,从开机第一刻就开始记录系统的状态。
我记得有一次帮客户排查服务器被入侵的案例。OS层面查了个底朝天,什么木马都没找到。最后一看TPM的PCR值,发现PCR[4](MBR)和预期值对不上——原来是Bootkit修改了主引导记录。如果没有度量启动,这种攻击根本发现不了。
总结一下度量启动的价值:
- 检测:发现启动链中任何环节的篡改
- 证明:向远程方证明系统启动状态的可信性
- 隔离:将度量逻辑与OS隔离,避免OS级别的攻击影响度量结果
好了,这一章的内容就到这里。可信计算的基础概念、TPM/TCM规范、信任根与信任链、度量启动原理,这些是后续所有章节的基石。你把这些搞清楚了,后面讲远程证明、密封存储、平台固件保护的时候,就会轻松很多。