简介:面向准备华中科技大学可信计算线上测试及网络安全课程复习的学习者,这份资料以题目与答案对照的形式梳理可信计算核心考点,适合考前自测、课堂知识点复盘和查漏补缺。压缩包内仅含1个docx文件,大小约558KB,围绕可信计算理论担忧、TPM与TSS、Hash算法、对称与非对称加密、PKI、PCR及平台状态报告等模块组织问答,便于按主题快速检索和集中记忆。相关内容已有333人学习,说明其在华科可信计算备考场景中具有一定参考价值。读者可从中获得较完整的题目清单与答案解析,结合可信测量、信任链、TPM可迁移与不可迁移密钥、远程/本地报告等具体问题理解概念边界,也能对照MD4、MD5、SHA-1、DES、AES、RSA、ElGamal、ECC等算法特点与应用场景建立复习框架,提升对网安基础概念的辨析能力。
1. 可信计算最反直觉的一点:它不问代码有没有漏洞,只问代码是谁签的
可信计算和 TPM 常被当成“给电脑加一颗安全芯片、让系统变得安全”来讲,但真实的能力边界比这个描述窄得多,也直接得多。先把这条边界划清:可信计算没法检查一段可信代码有没有漏洞,只能确认这段代码是某个被认可的发布方出的;它也没法判断一段代码是不是恶意代码,因为压根没有这个功能。
这个结论看着像自曝其短,其实是整套信任链设计的起点。可信计算真正提供的,是“平台运行状态可被远程验证、且验证痕迹难以抹平”这件事。PCR 为什么只能扩展不能写、度量日志为什么不防篡改、虚拟机回滚为什么和它天然打架,答案都藏在这条边界里。下面从一颗封装成 TSSOP28 的芯片开始,一路拆到 PCR 扩展公式和密钥加载链。
2. TPM 的物理落点与 PCR:信任链在硬件上究竟存在哪里
2.1 一颗 TSSOP28 封装的芯片,凭什么代表整个平台
TPM 在 CPU 侧通常是一颗封装为 TSSOP28 的 IC。它既可以是一颗独立芯片,也可以嵌入到主板上其他的芯片里——安全芯片把指纹扫描、智能读卡器这类功能一并做进去的情况并不少见。物理上它就是挂在主板上的一个器件,和 CPU 一起被集成进 PC 硬件,本身并不“看”得见 CPU 在跑什么。
它跟外部世界打交道的路径是:固件和操作系统软件以访问内存映射寄存器的方式交互,CPU 芯片组把这层交互翻译成总线命令。上层软件看到的是寄存器读写,底下走的是总线事务。这层抽象很关键,它意味着 TPM 对外暴露的是一套命令—响应协议,而不是一组可以随手赋值的变量。
TPM 命令本身相当复杂,参数多、结构嵌套。为了不让每个应用都去手工拼字节,TCG 定义了软件栈 TSS,用来帮程序员更容易地利用这些接口。需要使用 TSS 服务的应用链接到提供简化编程接口的库;库把这些高层调用转换成等价的 TPM 命令,发给设备驱动,驱动再把命令送到芯片。整条路径可以压成四层:应用、简化编程接口库、TSS 命令编解码、设备驱动,最后落到芯片。
/* 以某开源 TSS 实现为例:一次 PCR 扩展调用要穿过的那几层 */ TSS_HCONTEXT ctx; TSS_HTPM tpm; TSS_HPCRS pcrs; Tspi_Context_Create(&ctx); /* 建立 TSS 上下文 */ Tspi_Context_Connect(ctx, NULL); /* 连到本机 TPM 设备 */ Tspi_Context_GetTpmObject(ctx, &tpm); /* 取 TPM 对象句柄 */ Tspi_Context_GetPcrRegister(ctx, &pcrs); /* 绑定一组 PCR */ /* 应用层只表达一件事:把这段摘要扩展进 17 号 PCR */ Tspi_PcrComposite_SelectPcrIndex(pcrs, 17); Tspi_TPM_PcrExtend(tpm, 20, digest, pcrs);digest是待扩展的度量值摘要,长度参数 20 对应 SHA-1 的 160 位输出;SelectPcrIndex选定目标 PCR。这层调用最终被 TSS 编成 TPM 的 PCR_Extend 命令,经驱动下发。注意这里没有“写入任意值”的接口——应用层能表达的只有“扩展”这一个动作,后面所有结论都建立在这个事实之上。
2.2 PCR 的两个写入口:Reset 和 Extend
PCR 里存储的是平台状态信息的 SHA-1 散列值,所以 PCR 的值能够代表机器的运行状态。TCG 1.1 规范要求至少有 16 个 PCR,1.2 规范又额外引入了 8 个,专门用于实现动态可信度量。
往 PCR 里改变取值只有两条路,而这两条路的权限模型完全相反。Reset 把 PCR 清零,触发时机被严格限制在机器重新启动或断电的时候;Extend 则不同,任何具有管理员权限的人在系统运行过程中都能执行。把这两句并排读,是整套机制最要紧的地方——攻击者拿得到 Extend 权限,拿不到 Reset 权限。
扩展的公式是PCR[i] = SHA-1(PCR[i] || newMeasurement),||表示拼接。新值不是覆盖旧值,而是把旧值和新的度量值串起来重新求摘要,历史因此被压进了当前这一个 20 字节里。
import hashlib PCR_LEN = 20 # SHA-1 输出 160 bit def pcr_reset(pcr): """只允许在重启/断电路径触发,结果全零""" pcr[:] = b"\x00" * PCR_LEN def pcr_extend(pcr, measurement): """PCR[i] = SHA-1(PCR[i] || newMeasurement)""" new = hashlib.sha1(bytes(pcr) + measurement).digest() pcr[:] = new # 原地改写,历史不可回退 return newpcr是长度 20 字节的可变缓冲区;measurement是本阶段被度量代码的摘要,通常也是 20 字节,拼接后 40 字节落入 SHA-1 的输入。函数有副作用,原地改写pcr,返回值同时给出,是为方便校验。这里有个容易被忽略的细节:拼接顺序固定为“旧值在前、新度量在后”,顺序反了算出的值完全不同,重放度量日志时顺序搞错就永远对不上期望值。
2.3 信任链的产生:先度量,再执行
信任传递的机制是:在信任当前某一环节的前提下,由该环节去评估下一个环节的安全性,确定下一环节可信之后再把控制权转交给它,然后依次向后推进。
整个启动序列遵循一个铁律——先度量,再执行。当前阶段的代码负责度量下一阶段即将执行的代码,把度量值扩展到 PCR 寄存器,再把控制权交出去,循环往复就构成了信任链。以上电过程为例,链条大致是这样推进的:CRTM 自己不被度量,它去度量 BIOS 的其余部分并扩展 PCR;BIOS 度量 bootloader 并扩展;bootloader 度量 OS loader 并扩展;OS loader 度量内核并扩展。
链条的起点是 CRTM,也就是核心可信度量根,它是引导时在平台上执行的第一部分代码——现有平台上就是 BIOS 或 BIOS 引导块,下一代平台上可能是 CPU 里的程序。CRTM 本身没有被度量,因为它是源头。这里存在一个明面上的假设:这个源头是安全可信的。
这个假设就是静态信任链最脆弱的地方。大多数 PC 系统使用的是可刷写的 BIOS 固件,攻击者改掉 BIOS,就能构造自己的信任链,往 PCR 里写任意值,远程证明也照样做得漂亮。所以符合 TCG 规范的系统必须拥有不可更改的 BIOS 代码——可以是一段短小的固化代码,由它去度量其余那一大块 BIOS,但最初执行的那段必须是固化的、不可修改的。这就是 CRTM 的门槛,跨不过去,后面所有的度量都是在流沙上盖楼。
2.4 扩展操作为什么能抗攻击,度量日志又为什么不防篡改
扩展操作让每一次系统状态的异常或改变都能体现在其后的度量序列里。攻击者的攻击痕迹难以消除,攻击也就失去了隐匿性。再加上 hash 的单向性,攻击者无法从当前 PCR 值反推出最初的状态,也就堵死了“得知初始状态再不断后推伪造状态”这条路。这两条合起来,让攻击无所隐藏。
但 PCR 有个硬限制:TPM 的存储空间有限,不可能存放与运行状态相关的完整信息,只能存其摘要。所以平台状态信息以日志的形式放在 TPM 外部的度量日志文件中,PCR 通过扩展来记录这些日志信息的摘要,供以后验证。
这就引出一个常见的误解:度量日志要不要防篡改?答案是没必要。即使攻击者篡改了度量日志,PCR 中记录的度量值也伪造不出来——用户对篡改后的日志重新求摘要,就会发现与度量值不匹配。日志是“正文”,PCR 是“摘要”,正文可以改,摘要对不上立刻露馅。
远程证明里挑战者计算期望值的过程,本质就是拿日志重放一遍:
def replay_expected(entries, init_value): """entries: 严格按扩展顺序排列的度量值列表(bytes) init_value: 该 PCR 的实际初值(静态 PCR 全 0,动态 PCR 全 1)""" acc = init_value for m in entries: acc = hashlib.sha1(acc + m).digest() return acc # 与挑战者拿到的 PCR 值逐字节比对entries必须按平台真实的扩展顺序排列,任何一项调换位置都会得到不同的最终值;init_value必须与平台重启后的实际初值一致,这一点在讲动态可信度量根时会变成一条关键防线。日志不需要签名也不需要加密,因为它的唯一作用是让验证方能自己把摘要算出来,真伪由 PCR 兜底。
3. 密钥体系的三段参数与加载链:SRK 下面为什么必须一层层解
3.1 三段参数对应三个问题
TPM 密钥共有 3 种参数。通用信息包括密钥类型、密钥算法和授权秘密;特殊信息包括密钥长度和密钥数据;密钥属性包括迁移属性和 PCR 值。三者合起来一共对应 7 种密钥类型。
拆开看,这三段其实在回答三个不同的问题:这把密钥能干什么(类型、算法)、它长什么样(长度、数据)、它受什么约束(能不能迁移、绑定了哪些 PCR)。授权秘密被放进通用信息而不是调用参数,意味着“使用这把密钥要不要口令”本身就是密钥定义的一部分,调用方没法临时绕开。
把这条设计想透,会发现它把“权限”从“调用现场”搬进了“对象定义”。审计一把密钥时,只要读出它的属性段,就知道它能被谁在什么状态下使用,不需要去翻调用日志。
3.2 自密钥加载链:一次串行的逐层解封
使用一个自密钥,是从顶端密钥(通常是 SRK)开始,依次加载各层密钥——包括迁移和不可迁移密钥、签名和绑定密钥等,直到所有密钥加载完成。
有个具体任务能把这条链说清楚:把签名密钥加载到 TPM 中用于签名操作,需要先建立到 SRK 的整条密钥链。做法分三步:用私有的 SRK 解密存储密钥 #1 的私钥;用存储密钥 #1 解密存储密钥 #2 的私钥;用存储密钥 #2 解密签名密钥的私钥。
之所以是“解密链”而不是“查表”,原因在于 TPM 内部只常驻 SRK 这一把根,下级密钥的私钥以被父密钥加密的形态保存在 TPM 外面。加载时必须逐层解封,缺一环就断。
def load_key_chain(chain, srk_handle): """ chain: 从父到子的密钥密文列表,每项含 {blob: bytes, auth: bytes} srk_handle: SRK 的句柄,其私钥从不出芯片 返回叶子密钥的可用句柄 """ parent = srk_handle for node in chain: # 每一次解密都发生在 TPM 内部,明文私钥不经过内存总线 parent = tpm_load(node.blob, parent_handle=parent, auth=node.auth) return parentchain的顺序必须父在前、子在后,顺序颠倒第一次 Load 就会失败;blob是被父密钥加密的私钥结构体;tpm_load对应 TPM 的 Load 命令,解密在芯片内部完成,上层只能拿到句柄。使用子密钥还需要父密钥的授权,使用前必须先加载,加载时可以绑定 PCR 或绑定口令——这三条经常被混着背,其实分别落在授权、生命周期、约束条件三个不同层面。
3.3 EK、SRK、AIK 的职责边界
| 密钥 | 是否可迁移 | 生成时机 | 主要用途 |
|---|---|---|---|
| EK 背书密钥 | 不可迁移 | 平台生产过程中 | 代表平台唯一真实身份;解密所有者授权数据、解密生成 AIK 相关数据 |
| SRK 存储根密钥 | 不可迁移 | 用户创建时生成 | 保护其余所有密钥,不以明文或密文离开 TPM |
| AIK 身份证明密钥 | 不可迁移 | 每个用户可持有多个,生成需可信第三方支持 | 对 TPM 产生的数据(PCR 值等)签名,证明平台身份与环境配置 |
| Sealing Key 密封密钥 | 不可迁移 | 首次创建时记录配置快照 | 把数据访问权限绑定到特定硬件/软件状态 |
| Binding Key 绑定密钥 | 可迁移 | 由目标平台公钥派生 | 在一个平台加密小规模数据(如对称密钥),到另一个 TPM 平台解密 |
EK 是一个 2048 bit 的 RSA 密钥对,生成于平台生产过程中,每个平台唯一一个,它从不用作数据加密和签名。它的主要功能是生成 AIK 和建立 TPM 平台的所有者,由所有者来生成 SRK,再用 SRK 加密、存储其他密钥。
AIK 专用于对 TPM 产生的数据签名,凡是经过 AIK 签名的实体,都表明已经过 TPM 处理。SRK 是存储密钥的特例,整个系统只有一把,创建时生成,管理该用户的全部数据,也就是存储可信根。
这里有一条很漂亮的推理链:EK 签名而不加密,所以没有密钥能用于加密 SRK;SRK 又需要保护,所以 SRK 必须存在 TPM 内部,且不会以明文或密文形式离开 TPM,于是它必然是不可迁移密钥。约束不是拍脑袋定的,是被 EK 的用途一步步倒推出来的。
3.4 可迁移与不可迁移:只能单向降级
可迁移与不可迁移都是密钥的属性。可迁移密钥不局限于某个特定平台,可以由平台用户控制,在平台之间迁移;不可迁移密钥则永久与某个指定平台关联。
不可迁移密钥的安全性更高:它全部由 TPM 内部产生,从产生到销毁的整个周期里,私钥部分都不会离开 TPM(除非被转化为可迁移密钥)。此外不可迁移密钥可以被 TPM 签名,这使它能够向用户证明自己的不可迁移属性,从另一个角度也证明了它的安全性。
两者不能相互转换,准确说是单向的:由于安全性等级上不可迁移密钥高于可迁移密钥,只能由不可迁移密钥单向转化为可迁移密钥。不可迁移密钥能够用来加密保护可迁移密钥,反之则不行。这个方向的含义是“降级”——把一把根密钥的约束放松,让它能出平台;反过来想升回去没有意义,因为你没法证明一把已经在外面流通过的密钥从没离开过 TPM。
密封加密是这条属性最典型的用法。设 M 是一份信息,K 是一个对称密钥,VPCR-x 是某 TPM 一组 PCR 的值,KPUB-S 和 KPRI-S 是该 TPM 的一对公私钥:先用 K 对 M 加密得到 K{M};再用 KPUB-S 对 VPCR-x 和 K 加密得到 KPUB-S{VPCR-x, K}。想取回 M 必须先拿到 K,而拿到 K 需要 TPM 用 KPRI-S 解密,此时 TPM 检查当前 PCR 组的值是否与 VPCR-x 相等,相等才提供 K,否则拒绝。
def seal(M: bytes, pcr_snapshot: bytes, pub_s: bytes) -> bytes: K = os.urandom(32) # 一次性对称密钥 body = sym_encrypt(K, M) # K{M} header = asym_encrypt(pub_s, pcr_snapshot + K) # KPUB-S{VPCR-x, K} return header + bodypcr_snapshot是密封那一刻的 PCR 值,解封时 TPM 在芯片内部比对当前值与快照值,任何一个字节不同都不会释放 K。这就是把数据的可访问性与机器状态绑定:正常启动后应销毁秘密信息、扩展 PCR 改变机器状态,确保后来者无法 unseal。反过来,本地报告也正是靠这一点——一条被 Seal 过的机密信息能被释放,说明相应的 PCR 值符合期望,进而说明启动过程是安全的。
4. 从静态根到 DRTM:把 BIOS 踢出信任链要付出什么代价
4.1 静态可信度量根的四个问题
静态根的毛病可以归成四条:易用性、可扩展性、度量时机、包容性。
易用性问题最直观:挑战者发起挑战时,需要重启才能证明安全,因为静态根只在启动路径上度量,想重新证明就得把机器重启一遍。包容性问题在于,要使一个静态可信根对第三方有说服力,必须度量 TCB 的所有组件,但在许多系统里 TCB 定义得有问题,导致系统中几乎所有可执行部件都要被度量,信任链变得极其庞大。可扩展性问题随之而来:庞大的信任链不易扩展,接收者要判定系统可信,需要知道链中每一个可执行部件的可信性,机器一修 BIOS 或者给操作系统打补丁,整条链就被破坏了。
度量时机的问题最要命:系统安全启动并被判定为可信之后,还可以发生很多事情,比如攻击者在一个可信系统中利用缓冲区溢出替换可执行文件。静态可信根只能提供装载时的保证,不能提供运行时的保证。
这四条指向同一个根因:静态根把信任锚点钉死在“启动那一刻”,而攻击面在运行期是持续敞开的。
4.2 三个经典缺陷与 DRTM 的消解思路
早期 TPM 规范被指出过三类缺陷。缺陷一是引导装载程序中存在 bug:有的可信引导程序装载不完整;有的实现把加载内核镜像和度量并扩展 PCR 分成两步做,两步之间存在时间窗;还有的在硬盘损坏或光盘启动时不扩展 PCR。缺陷二是无法抵御 BIOS 攻击:BIOS 可刷写,机器启动时又不对 BIOS 进行度量。缺陷三是对 TPM 的重启攻击:在平台没有重启的情况下,通过总线把 TPM 单独重启。
动态可信度量根的做法很干脆——直接把信任链里 BIOS 及其配置、可选 ROM 及其配置,以及那些带 bug 的 bootloader 全部移除,因此不会受到缺陷一和缺陷二的威胁。思路是把信任锚点从“固化的 BIOS 代码”上移到“CPU 的一条指令”,起点越靠近硅片,可被篡改的中间层就越少。
4.3 Locality 与新增 PCR 的全 1 初值
TPM 1.2 有 5 个 Locality,作用是鉴别一个 TPM 请求的发起者身份,每一级代表一类发起者。
| Locality | 代表身份 |
|---|---|
| 4 | 可信硬件,也表示动态可信度量根 |
| 3 | 辅助组件,使用与否取决于具体实现 |
| 2 | 可信操作系统运行时 |
| 1 | 可信操作系统为应用程序提供的执行环境 |
| 0 | 用于对 TPM 1.1 向下兼容 |
缺陷三的消解靠的是动态可信度量新增的那 8 个 PCR。它们初值是全 1,而通过总线发起的攻击只能让它们保持全 1,无法模拟 CPU 的指令;只有从 CPU 发出的指令(比如 SKINIT)才能使它们变为 0。初值不同,攻击者很难 hash 出一样的结果。
这里的精妙之处在于,它不是靠“禁止写”来防,而是靠“起点不同”来防。攻击者可以发起 Extend,甚至可以重复扩展,但只要初值不是 CPU 指令路径留下的那个值,算出来的结果就和正常路径对不上,挑战者一比就露。用初值加唯一清零路径,造出了一个物理层级的隔离。
4.4 SKINIT 与 SENTER:两条动态启动路径
SKINIT 路径的骨架是:指令对处理器重新初始化,建立一个安全的执行环境来运行 secure loader。虚拟机管理器或可信操作系统的 secure loader 被封装到一个安全引导块里,在 CPU 跳转到 secure loader 之前,这个安全引导块要先被度量,度量值放进 PCR17,PCR17 的值就形成了 DRTM。之后逐层度量—扩展,把信任链继续往下搭。
SENTER 路径靠的是签名验证。AC module 是经过签名的并包含一个公钥,CPU 里固化有这个公钥的 hash 值,所以第一步是 CPU 认证这个公钥,再用这个公钥去认证 AC module。整个执行过程分四段:经过度量的启动、MLE 初始化、MLE 运转、MLE 销毁。具体步骤包括确保执行环境没有受到不可信应用的监视、把 AC module 和 MLE 加载到内存、调用 GETSEC[SENTER] 指令、处理器验证 AC module 签名后执行它、由 AC module 度量 MLE 并把结果送进 TPM、启动 MLE。此外还可以通过 LCP 验证这一启动过程。
两条路径的差别在信任锚的形态:一条把信任建立在“安全引导块先被度量”,一条把信任建立在“链式签名验证”,共同骨架都是“最小初始代码 → 度量下一段 → 扩展 PCR”。
DRTM_PCRS = range(17, 25) # 动态度量的 8 个 PCR def drtm_pcr_init(pcrs): """上电/重启路径:DRTM PCR 初值为全 1,区别于静态 PCR 的全 0""" for i in DRTM_PCRS: pcrs[i][:] = b"\xff" * PCR_LEN def drtm_measure(pcrs, slb_digest): """SKINIT 先度量安全引导块,结果落进 PCR17,形成 DRTM""" pcr_extend(pcrs[17], slb_digest) for i in DRTM_PCRS: if i != 17: pcrs[i][:] = b"\x00" * PCR_LEN # 只有 CPU 指令路径能清零drtm_pcr_init与静态 PCR 的初始化是两套逻辑,混用会直接导致证明失败;slb_digest是安全引导块的摘要,扩展进 17 号 PCR 之后就构成了这条动态链的根。常见的实现思路是,把“清零”动作绑死在 CPU 指令的执行路径上,总线上根本发不出等价请求。
5. 常见问题与排查:五个把机制方向搞反的理解
这一章把题目内容中反复出现的错误理解整理成五条,每条按现象、原因、解决来写。这些坑大多不是知识点没背下来,而是把机制的作用方向搞反了——方向一反,结论就全错。
5.1 坑一:以为改掉度量日志就能骗过远程证明
现象:有人觉得只要把度量日志里那条“可疑程序”的记录删掉,挑战者就查不出来,平台照样能证明自己是干净的。
原因:PCR 是摘要,日志是正文。挑战者读度量日志,按扩展顺序对每条度量值重新执行扩展操作,算出期望的 PCR 值,再与客户端返回的 PCR 值比对。删掉一条记录,重算出来的摘要立刻不同。
解决:要让日志和 PCR 同时自洽,攻击者得能改写 PCR,而运行期 PCR 只有 Extend 一个入口,且扩展是单向的,改动中间任何一环都会改变其后所有值。真正该防的不是日志被改,而是“度量环节本身漏掉了某个可执行文件”——那才是信任链的真实缺口。
5.2 坑二:以为给 TPM 增加对称加密支持能提升 PC 安全性
现象:直觉上“芯片支持更多算法等于更安全”,于是认为给 TPM 加上对称加密支持是一步安全升级。
原因:系统安全的情况下,可以靠软件做对称加密,此时加入对称加密并不会改善安全性。系统不安全的情况下,黑客感兴趣的不是密钥,而是明文——他直接读明文就行,根本不需要去破密钥。所以这个加法在两个方向上都不产生安全增益。
解决:安全的边界不在于算法多不多,而在于密钥和明文在什么环境下被使用。TPM 的价值在“私钥不出芯片”和“状态可被远程验证”,不在“多支持一种算法”。判断一个 TPM 特性值不值得加,先问它改变的是密钥的驻留位置,还是只是多了一个可调用的实现。
5.3 坑三:以为虚拟机回滚时把 TPM 一起回滚就完事
现象:做快照回滚时,把 vTPM 的状态一并恢复到快照点,看上去一致性保住了,问题解决了。
原因:单纯回滚 TPM 数据会造成新产生数据的丢失——快照之后新建的密钥、新封装的秘密全部没了。更麻烦的是重放攻击:攻击者每次做远程证明时都回滚到可信状态,就能利用重放把入侵痕迹抹干净,挑战者看到的永远是一个“干净”的历史版本。
解决:部分回滚。PCR 回滚以保证与虚拟机状态一致,密钥不回滚以保证新产生的密钥不丢失;再增加两组不参与回滚的 PCR,用来记录回滚记录(快照时间、快照时的 TPM 状态、执行回滚的用户信息等),让回滚轨迹本身可被验证。
5.4 坑四:以为 BIOS 是信任根
现象:描述信任链时张口就是“从 BIOS 开始度量”,把 BIOS 当成链条起点。
原因:大多数 PC 用的是可刷写 BIOS 固件,攻击者改掉 BIOS 就能构造自己的信任链,往 PCR 里写入任意值,远程证明也能做得有模有样。把可刷写的东西当根,等于把根交给了攻击者。
解决:信任根是 CRTM——那段固化的、不可修改的启动代码。它可以很短,作用只是度量后面那一大块 BIOS。判断一段代码能不能当根,标准只有一条:它能不能被写。
5.5 坑五:以为 PCR 值等于“当前正在运行的软件列表”
现象:把 PCR 当成进程表或者已加载模块清单的快照,认为读一下 PCR 就知道机器上跑着什么。
原因:PCR 是扩展累加的结果,是一个关于历史序列的单向函数,20 个字节里塞不下任何列表信息。它只回答“这条历史序列的摘要是不是这个值”,不回答“历史里有什么”。
解决:要还原软件列表,必须读 TPM 外部的度量日志,按扩展顺序重放,得到期望值再与 PCR 比对。排查远程证明失败时的顺序也该照这个来:先看 PCR 索引是否选对,再看日志顺序是否与平台实际扩展顺序一致,再看初值(静态 PCR 全 0、动态 PCR 全 1)有没有搞混,然后看 Locality 是否匹配,最后才查 AIK 证书和密钥授权。
6. 回滚这笔账:vTPM 为什么只能“部分回滚”
6.1 一个物理 TPM 撑不住一群虚拟机
TPM 1.2 不适用于云计算的场景,这是
本文还有配套的精品资源,点击获取