Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第十章 · 进阶地图:接下来学什么

本章目标

到这里,你已经把 TPM 入门的主线走完了:

  • 第三章:亲手 extend PCR,看清哈希链是怎么滚动的;
  • 第四章:把秘密 Seal 到 PCR 状态上,篡改后解封失败;
  • 第五章:重放固件度量日志,和芯片里的真实 PCR 逐一比对;
  • 第六章:把 LUKS 全盘加密绑到 TPM,开机自动解锁;
  • 第七章:摸清口令、PCR Policy、PolicyAuthorize 这套授权体系。

原理和实践的骨架都有了。这一章不再是实验,而是一张地图:告诉你接下来有哪些方向值得深入,每个方向解决什么问题、用什么工具、先读什么资料。顺序按我推荐的优先级排列,越靠前越实用。

书后还有三个附录:附录 A 是全书的踩坑实录,附录 B 是命令速查表,附录 C 收录了两个重放脚本的完整代码和逐段讲解。正文里来不及展开的细节,不少都在那里。

PCR 11 + systemd-pcrlock:可预测策略的终极形态

第六章我们把 LUKS 绑到了 --tpm2-pcrs=7。第七章讲了 PolicyAuthorize 的思路:与其绑定“具体的 PCR 值“,不如绑定“一把密钥的签名“。PCR 7 的问题是第八章讲的——它度量的是 Secure Boot 状态而非系统内容,固件度量链里混着太多不可预测的变量。

systemd 给出的现代答案是 PCR 11。在 UKI 架构下,内核、initrd、命令行这些组件在被打包成 UKI 时就被度量(度量进 PCR 11 的预期值可以提前算出来),systemd 还会把 UKI 内嵌的 .pcrsig 签名段交给 systemd-pcrlock 工具:它解析这些签名,生成一个“升级后可以预测“的 pcrlock 策略文件。最终形态是:

systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+11 /dev/vda2

PCR 7 管 Secure Boot 没被关掉,PCR 11 管启动组件没被换掉,而系统升级(换内核、换 UKI)时新 UKI 自带的新签名会被 pcrlock 吸收,不用像裸 PCR 绑定那样每次升级都重新 enroll。

注意 这套方案目前主要在 Fedora、Arch 等走 systemd 全栈的发行版上成熟,而且要求你的启动链是 UKI 形态。第六章的实验环境恰好就是 UKI + Limine,已经具备条件,可以直接动手试。思路上它和第七章的 PolicyAuthorize 一脉相承:都是“用签名授权代替对易变值的硬绑定“。

动手前先看清楚现状再改:

# 当前 enroll 状态:绑了哪些 PCR、用的什么策略
cryptsetup luksDump /dev/vda2 | grep -A5 tpm2
# pcrlock 分析出的组件树和预测策略
systemd-pcrlock

systemd-pcrlock 不带参数时会打印它识别到的 UKI 组件和预测出的策略摘要,先把输出读懂再决定切不切换。另外老规矩不变:任何改动 enroll 的操作之前,确认还留着一个传统口令 keyslot 当退路——第六章立下的这条,在这里照样救命。

TPM 当日用密钥库:我最推荐你立刻用起来的方向

如果说前面所有实验都是在学原理,那这个是学完马上能落地、每天都能受益的用法:把 SSH 私钥存进 TPM。

传统做法是私钥躺在 ~/.ssh/id_ed25519 里,靠 passphrase 和文件权限保护。机器一旦被人拿到 shell(哪怕只是一次短暂的未锁屏),私钥文件被拷走就是永久沦陷。用 tpm2-pkcs11 把密钥生成在 TPM 内部之后,私钥从物理上不可导出——任何签名操作都必须让 TPM 芯片代劳。攻击者就算偷走整个 ~/.ssh 目录,里面也只有指向 TPM 对象的句柄,没有密钥本体。

接入方式和普通 PKCS#11 模块一样:

# 初始化 token 并生成 RSA 密钥(密钥本体在 TPM 里)
pkcs11-tool --module /usr/lib/pkcs11/libtpm2_pkcs11.so --login --keypairgen \
  --key-type rsa:2048 --label myssh
# 让 ssh 走 PKCS#11
ssh -I /usr/lib/pkcs11/libtpm2_pkcs11.so user@host

代价是每次签名要过一次 TPM,比纯软件慢一点,以及换机器意味着重新生成密钥、更新各服务的 authorized_keys。对日常使用来说,这个代价完全值得。

日常用起来还有两个实用技巧:

  • ~/.ssh/config 里给特定主机写 PKCS11Provider /usr/lib/pkcs11/libtpm2_pkcs11.so,就不用每次敲 -I 参数;
  • 想验证明私钥确实不在磁盘上,可以拔掉 TPM 会话后试试签名——它会失败,而这正是你要的效果。

同样的思路还能延伸:GPG 子密钥、VPN 客户端证书、代码签名密钥,凡是以文件形式躺在磁盘上的长期私钥,都值得考虑搬进来。

思考 这个方向其实贯穿了全书的一个核心思想:密钥的安全边界从“文件系统权限“收缩到“硬件芯片内部“。理解了 seal 的原理,再看 tpm2-pkcs11 就会发现它只是把同一套原语包装成了标准接口。

远程证明:从单机到集群的收官一步

第五章你重放日志、和本机 PCR 比对——这本质上是一次“自我证明“:你自己既是度量者又是验证者。远程证明(Remote Attestation)要解决的是:怎么让一台不信任你的机器,验证你的启动状态。

机制的关键多了一层签名。流程大致是:

  1. 验证方发来一个随机数(nonce,防重放);
  2. 被验证方让 TPM 用证明密钥(Attestation Identity Key, AIK)对“当前 PCR 值 + nonce“做一次 quote(引用),产出一份签名证据;
  3. 验证方拿着 AIK 公钥验签,再像第五章那样重放度量日志,确认日志内容确实能滚出 quote 里的 PCR 值;
  4. 验证方对照自己的“已知良好值“数据库,判断这台机器的启动环境是否可信。

AIK 的存在是为了隐私:如果每台机器直接拿背书密钥(Endorsement Key, EK)签名,所有 quote 都能被关联到同一颗芯片,等于给每台机器发了个全球唯一追踪 ID。AIK 是一把可以随时重新生成的二级密钥,它的可信性由隐私 CA(Privacy CA)背书——隐私 CA 验证你的 EK 证书是真实 TPM 厂商签发的之后,才给你的 AIK 发证。这样验证方知道“这是一颗真 TPM 签的“,但不知道是哪一颗。

动手练推荐 Keylime,CNCF 旗下的开源远程证明项目。它把整套流程封装成了 verifier(验证方)+ agent(被验证方)两个组件,跑起来不需要你自己实现 nonce 交换和日志比对。你的实验环境天然适合:再克隆一台虚拟机当 verifier,原虚拟机装 agent,就能在一个 KVM 宿主机上跑通完整的双向证明流程。

如果想先用原始命令感受一下 quote 长什么样,tpm2-tools 就有:

# 生成 AIK 后对当前 PCR 做 quote,nonce 由验证方提供
tpm2_quote -c aik.ctx -l sha256:0,1,2,3,7 -q <nonce> -m quote.msg -s quote.sig

第五章的 replay_pcrs.py 在这里直接复用:验证方重放被验证方发来的日志,算出的值和 quote 里签名的 PCR 值对得上,证据链就闭合了。

思考 走到这一步,可信启动的视角就从单机扩展到了集群和云:数据中心里成千上万台机器,每一台开机后都向 verifier 报到,证明“我跑的是没被篡改的固件和系统“,不通过的拒绝接入。这就是零信任架构里“工作负载可信度“那一层的实现方式。

TPM 流量嗅探:你以为芯片内部安全,总线上呢

这是很多人忽略的攻击面。离散 TPM(discrete TPM, dTPM)是一颗独立芯片,通过 SPI 或 LPC 总线连在主板上。芯片内部的运算确实安全,但 CPU 和 TPM 之间传输的数据是明文走总线的——攻击者只要在总线上焊一个几美元的嗅探器,就能截获所有通信。

这不是理论。已有公开研究演示过用 SPI 嗅探器截获 BitLocker 的 VMK(卷主密钥):Windows 开机时 TPM 把解封后的密钥明文送回内存,嗅探器原样抄走,全盘加密形同虚设。整个过程不需要动芯片一根毫毛。

防御手段 TPM 2.0 规范里就有:加密会话。tpm2_startauthsession--enable-encrypt 之类的参数建立加密会话后,敏感参数在总线上是密文,嗅探器抄走的只是一堆乱码。tpm2-tools 里不少命令支持会话加密,只是默认不开——这也是“安全默认值“很重要的一个例子。

另外两个相关的知识点:

  • fTPM(firmware TPM)直接做在 CPU 内部(Intel 叫 PTT,AMD 叫 fTPM),CPU 和“TPM“之间根本没有暴露在外的总线,物理嗅探这条路天然断了。代价是它依赖 CPU 厂商的固件实现,历史上出过漏洞。
  • EK 证书里烧录的是芯片厂商的私钥签名,配合 TPM 内部“密钥不可导出、芯片不可克隆“的设计,让伪造一颗“身份相同的 TPM“在物理上很难做到。嗅探解决的是传输安全,EK 解决的是芯片身份,两者是不同层面的防线。

坑 虚拟机里的 swtpm 没有真实的总线攻击面——它和 QEMU 之间走的是本机 Unix socket,物理嗅探无从谈起。所以这一节的内容没法在第二章的环境里复现,属于“知道有这回事、真机上记得开加密会话“就足够的知识。真想看总线流量,可以在宿主机上抓 swtpm 的控制通道包聊作替代。

更前沿的方向(纯阅读即可)

下面这些超出本书范围,但值得知道它们存在,读文献遇到时不陌生:

  • DRTM(Dynamic Root of Trust for Measurement,动态信任根):前面所有内容都基于 SRTM——信任链从开机那一刻的固件开始滚。DRTM 的思路是系统跑着跑着,随时可以“重启信任根“,从一个硬件强制的小型度量点开始重新建链。开源实现看 TrenchBoot 项目。
  • 机密计算(Confidential Computing)里的 vTPM:Intel TDX、AMD SEV 这类技术把整台虚拟机的内存加密隔离,连 hypervisor 都看不到里面。虚拟机里的 TPM 自然也得是虚拟的——swtpm(你第二章用的那个软件 TPM)在云场景下就是这个角色,QEMU 通过它给虚拟机提供 TPM 2.0 设备。
  • Pluton:微软主推的方案,把安全处理器直接集成进 CPU 封装,目标是取代独立 TPM 芯片,同时承担 Secure Boot、密钥管理等职责。Xbox 和新款 Windows 设备上已经落地。

书单与资料

按性价比排序:

  • 《A Practical Guide to TPM 2.0》(Will Arthur, David Challener):IBM 出的,代码示例丰富,网上能找到免费版本。本书很多概念讲法参考了它,想深入对象层次、会话、授权细节就读这本。
  • TCG 官方规范(Trusted Computing Group 网站):枯燥但权威。分四部分——架构、结构体、命令、支持例程。遇到“这个命令到底支持哪些参数“的问题时直接查规范第三部分,比博客靠谱。
  • Arch Linux Wiki 的 “Trusted Platform Module” 词条:实践向资料的标杆,配置细节和发行版差异都写得很清楚。本书第六章的很多做法和它互相印证。
  • systemd 的 PCR 注册表文档(systemd.io 上的 “TPM2 PCR Measurements”):讲清楚每个 PCR 在 systemd 启动链里度量了什么,读懂 PCR 7/11 的分工绕不开它。

如果只能选一个方向

地图给全了,最后说说我自己的选择逻辑,供参考:

  • 想要立刻见效的安全收益:选 tpm2-pkcs11。半天配置完,从此 SSH 私钥不怕偷,这是性价比最高的一步。
  • 把本书的 LUKS 实验做到生产级:选 PCR 11 + pcrlock。它和第六章无缝衔接,是“实验走向实用“的最后一公里。
  • 往职业发展或研究上走:选远程证明。它把本书所有零散知识点串成一个完整系统,也是云厂商和零信任架构正在真金白银投入的方向。
  • 嗅探与参数加密属于防御意识,不用专门练,但真机上配置任何 TPM 功能时记得问自己一句:这段通信加密了吗?

结语

回头看这本书走过的路:从“TPM 是什么“开始,到你亲手 extend 出一条哈希链,到一个秘密因为一个字节的改动而拒绝解封,到逐条重放固件度量日志并全部对上,再到把整块硬盘的钥匙交给启动环境的度量值,最后理解了授权策略如何在这之上分层。

如果要用一句话收束可信计算的核心思想,我会这样写:

不信任任何软件关于自身的声明,只信任从硬件信任根出发、可以被独立验证的度量证据链。

PCR 不可重置、哈希链不可逆、密钥不可导出、日志可重放——这些看似零散的机制,拼在一起就为了服务这一句原则。你在虚拟机上验证过的每一条命令,都是这条证据链上的一环。

剩下的路,地图上已经标出来了。去走就是了。