本节摘要:可信计算把"信任"彻底变成了可操作的物件——信任出自证据,证据锁在硬件保障的防篡改存储里,验证串成首尾相扣的因果链。本节讲 PCR 的累积哈希记账算法、度量启动四阶段的 PCR 分工、TPM 密封与远程证明如何把度量变成决策,以及度量作为运行时信任基础设施的延伸与三重现实张力。
读完后你应当能:复述"主观信任到客观度量"的范式三句话;写出 PCR 扩展算法并解释单向、累积、顺序敏感三个性质;报出度量启动四阶段各写哪些 PCR;分清 TPM 的密封、远程证明、密钥派生三种本领;点出可信计算落地的三重结构性张力。
日常说的"可信"带着主观味:信某个人因为他历来靠谱,信某个软件因为它出自名门。但在计算安全语境里,这种信任相当危险——验不了、审不了、自动化不了。当攻击者不再满足于劫持用户态进程,而是直扑固件层埋后门、改启动策略、伪造验签结果时,"信任"就不再是哲学闲谈,而是一场必须在毫秒级内完成的数学核验与物理隔离的合奏。
可信计算的革命性,正在于把信任彻底操作化、可证化、可审计化。范式转移压成三句:
信任出自证据,不出自声明。 一个模块可不可信,不由签名或发布者一家说了算,而看它实际装载的二进制哈希是否与预期吻合。
证据不放在易失的内存里,而放在硬件保障的防篡改存储里。 哈希必须进受保护的专用芯片(TPM),不能搁普通内存或磁盘——内存能改写,磁盘能换掉。
验证不各管各,而串成首尾相扣的因果链。 上一环的度量结果直接参与下一环的验证策略——启动 ROM 度量不过关,固件拒载;驱动度量异常,加载器拒交控制权。
这就是信任链的实质:不是一条静态的传送带,而是一套"度量—存储—验证—决策"的动态闭环。每个环节既是上一环的裁判,又是下一环的考生。而链条的起点必须是被公认、物理隔离、难以篡改的信任根。x86 平台上它由两个实体搭档出演:度量信任根 CRTM——固化在 CPU 内部或 ROM 最前端的只读代码,硬件强制执行,是全部度量的绝对起点;TPM——独立的安全协处理器,备有加密引擎、密钥生成、随机数发生器,以及最要紧的平台配置寄存器 PCR。
设想一间老式银行金库,每笔进出都记在一本带钢印封条的账簿上:账簿不可擦写,新条目只能追加,而且每回落笔前必须核对上一页末尾的校验码——谁想偷偷撕一页重写,校验码当场作废。PCR 就是这么一本硬件级的信任账簿。
TPM 2.0 规范定义了至少二十四个 PCR,每个 256 位摘要长度。它们不存原始数据,只存度量值的累积哈希。更新走一个确定性算法:新值等于旧值与本次度量数据拼接后再哈希一次。注意是字节串拼接而不是数学相加——这个设计妙到毫巅,送给 PCR 三件法宝:
所以 PCR 不是快照,是轨迹:它不告诉你系统此刻"是什么",而是精确记录"它是怎样一步步走到现在的"。
那谁记账、谁报账、谁查账?度量信任根是第一位记账员,UEFI 固件是后续记账员兼初审员,操作系统与远程验证服务是终审与审计。
| PCR 编号 | 度量对象 | 语义 |
|---|---|---|
| PCR0 | CRTM 与固件主体 | 固件完整性指纹 |
| PCR2 | Option ROM 与 SMM 代码 | 影子固件状态 |
| PCR4 | 启动策略与选项 | 谁被允许启动 |
| PCR5 | 操作系统加载器代码 | 启动的是谁 |
| PCR7 | 安全启动策略状态 | 开关与密钥状态 |
| PCR8-10 | 内核、初始内存盘、早期模块 | 操作系统层 |
PCR 若是账簿,度量启动就是整套记账规程的正式施行。它从规范早期版本起就纳入核心框架(尽管各家实现深浅不一),矛头直指一个古老顽固的威胁:固件级持久化恶意软件。传统启动像不设安检的登机——每一步都盲信上一步交来的代码;度量启动则要求每装一段可执行代码,先算哈希、再扩展进指定 PCR。流程严格分四段。
第一段:度量根初始化。 复位之后,硬件强制跳到度量信任根(位于 Flash 最高地址区,带写保护)。它先核对自身完整性(与硬编码哈希比对),随后把自身代码哈希扩展进 PCR0。这是信任链的"零时刻",全系统可信性唯一无需条件的起点。
第二段:固件主体度量。 控制权交给主固件后,核心逐个装载驱动与应用,一边验签名、一边对每个模块的可执行镜像做哈希并扩展进 PCR0。PCR0 在这段持续累积,终值就是固件完整性的唯一指纹——任何一个驱动被替换、哪怕多装一个模块,指纹立刻变样。
第三段:启动管理层度量。 启动管理器按启动顺序挑加载器。装载前把加载器路径、签名状态、版本等元数据扩展进 PCR4(记下"谁被允许启动"),把加载器二进制哈希扩展进 PCR5(记下"启动的是谁")。两笔账合起来是启动决策的双因子凭证。
第四段:操作系统层度量。 加载器拿到控制权,调用固件给的 TCG2 协议接口继续量内核映像、初始内存盘与早期驱动模块,分别扩展进 PCR8 至 PCR10。这些值随后交给内核,用来搭建运行时可信环境。
至此,一条从硬件复位通到用户空间的完整度量链成形。但度量本身不产生安全价值——价值在对度量结果的消费里。
⚠️ 常见坑:度量启动与安全启动是搭档不是替补:度量的设计哲学是"全都记下、一律不拦",攻击者改了固件系统照样能开,只是 PCR 值变了。企业若只部署度量、不部署"读 PCR 再做决策"的策略(拒解密、拦入网),度量日志就只是躺在芯片里的档案,安全价值归零。
TPM 绝不是"哈希保险箱"。它的真正力量在于把静态度量数据变成动态、可验证的密码学证明,靠三大本领协同。
PCR 密封。 把敏感数据(磁盘加密密钥之类)与一组 PCR 值绑在一起:只有这些 PCR 值回到封存时的状态,数据才解得开。也就是说,攻击者若改了固件驱动,PCR0 一变,密钥永远作废——设备自动失能,而不是被敌人接管。这是"宁死不降"的设计哲学。
远程证明。 TPM 能出具一份由背书密钥签名、含当前全部 PCR 值的结构化报告,发给远端验证服务器;服务器拿 PCR 值对黄金基准,毫秒之间判定平台可不可信。主流云平台的保密虚拟机与证明服务都以此为底——租户能在数据落地之前确认宿主机固件没被动过。
密钥绑定与派生。 TPM 能生成并安全保管密钥对,私钥永不出芯片;再进一步,它支持按 PCR 值派生密钥,让密钥的一生与平台状态焊死——平台状态漂了,密钥自动作废。
TPM 集成的成败系于三个深层耦合点。一是通信通道安全:固件须经特定总线与 TPM 说话,通道一旦被中间人劫持(比如恶意 SMM 驱动),整条链塌方——所以现代平台要求 TPM 访问走 SMM 代理,而 SMM 代码自身受 SMRAM 保护并被度量进 PCR2。二是 PCR 分配的语义一致性:规范只划编号段不强制语义,不同厂商可能把同类模块记进不同 PCR,跨平台证明因此犯难;可信计算组织的 PC 客户端规范正在统一语义。三是所有权治理:TPM 出厂默认无主,企业部署要批量取得所有权并注入证书,这要求固件提供标准管理接口、且能被系统部署工具无缝调用。
💡 关键直觉:理解密封可以拿保险柜打比方——把磁盘密钥锁进一台"只有房间恢复原样才肯开"的保险柜。就算小偷把整台柜子搬走(TPM 芯片被物理移植),房间布局(PCR 状态)对不上,柜子照旧不开。这就是全盘加密配上 TPM 密封之后,拔盘挂到别的机器也读不出数据的原因。
度量启动常被误读成一次性的开机检查,其实它是整个平台可信生命周期的初始快照与持续参照系。拿内核的完整性度量架构来说:初始化时读入启动阶段的 PCR 值当基线;随后对所有后来装载的内核模块、可执行文件、共享库实时度量并扩展;应用要碰敏感资源时,策略引擎查当前 PCR 值是否与已知安全基线吻合,不吻合就拒。这完成了从"启动可信"到"运行时可信"的顺滑过渡——而固件层的度量正是这个过渡的锚:没有它,运行时度量的基线就断了源头。
更前沿的实验已经在跑:机密计算把度量概念推上虚拟化层——虚拟机监控器不光量自己,还给每台虚拟机开独立度量报告,装着那台虚拟机的固件、内核乃至客户应用的哈希链。固件的度量启动不再是终点,而是嵌套信任链最外的一层壳。
落地还得直面三重结构性张力。性能与安全的拔河:每次度量要给数兆字节的镜像算哈希(几十毫秒),与 TPM 通信也有毫秒级延迟,放在追求秒级启动的云实例场景里是一笔可观开销;演化中的对策包括哈希计算硬件化的度量卸载、只量核心驱动的选择性度量、与装载脱钩的异步度量。供应链信任的塔西佗陷阱:我们信 TPM,因为它出自某几家芯片厂;信固件,因为它出自某几家固件商——可一旦 TPM 固件有洞(历史上某厂商 RSA 密钥生成缺陷就是真事)、或固件供应商被迫埋后门,整条链就盖在流沙上;行业正推动固件可验证更新与源码透明度倡议,把信任从厂商声誉搬到可审计的代码与签名上。度量盲区的哲学难题:度量启动量得出"装了什么",量不出"跑了什么"——SMM 代码、GPU 固件、网卡 Option ROM、接口控制器固件,这些跑在独立处理器上的影子固件还没被主流规范强制覆盖;研究者披露的接口固件攻击正是钻这个盲区实现 DMA 攻击。信任链的长度,永远卡在我们对"平台"边界的定义上。
安全三角(拦截—守护—记录)至此合拢。下一章换上工程师的视角:如何用 EDK II 亲手搭环境、写驱动、做兼容。
度量启动的产物是 TPM 里的 PCR 寄存器,Linux 用户态工具可以直接读。对照前文的事件流,看 PCR[0-7] 的摘要:
$ tpm2_pcrread sha256:0,1,2,3,4,5,7 sha256: 0 : 0x3B2C4D8F...A1B2 (firmware + OEM cert measured by CRTM) 1 : 0xE4F50D19...77AC (option ROMs) 2 : 0x9A3F1B0C...D5E8 (option ROM config) 3 : 0x3A9B8C7D...01FE (platform config, e.g. boot order) 4 : 0xC7D8E9F0...3A2B (shim / bootloader) 5 : 0x1F2E3D4C...8890 (shim config, MOK list) 7 : 0xABCDEF01...6789 (kernel + initrd + cmdline) $ tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements | head -12 pcrIndex 0, digestType sha256: - EventNum: 0 Digest: "3d5f9c1e..." (SHA1(SpecId Event)) Event: { StringType: ASCII, EventData: "Spec ID Event03" } pcrIndex 0, digestExtend #2: - EventNum: 2, PCRIndex: 0 Event: "EFI_PLATFORM_FIRMWARE_BLOB" BlobBase=0xFF000000, BlobLength=0x100000 (测量的是 flash 里固件主卷的 SHA256)
事件日志解释了每条 PCR 是怎么"伸长"的:新摘要拼在旧值后面再哈希一次(extend),所以 PCR 是全部历史的累积指纹——这就是为什么度量只增不减、无法事后抹除。
重放验证是度量闭环的最后一步:把磁盘上的事件日志按同样顺序重算,结果若与 TPM 实寄存器一致,说明日志没被篡改。用 tpmevlogctl 或 IBM TSS 可以复现整个计算:
# 用 IBM tss 工具重放 PCR[4](启动加载器链) # tss 的 eventlog.sh 会把每条事件的 digest 依次 extend 到影子 PCR $ tss="eventlog /sys/kernel/security/tpm0/binary_bios_measurements" $ ( cd tss; ./$tss 2>/dev/null | grep -A1 "PCR index: 04" | tail -1 ) shadow PCR 04 final: 0xC7D8E9F0...3A2B $ tpm2_pcrread sha256:4 | grep -o '[0-9A-F]\{16,\}' | head -1 0xC7D8E9F0...3A2B # 两者一致 → 事件日志可信,远程证明方可基于日志展开
影子值与实寄存器逐位相等,是第 4 章信任链"可验证"三字的落点:不仅固件声称量了什么,而且第三方能独立复算出来。