TPM 2.0 在 Linux 上的工具链:tpm2-tss 与 tpm2-tools 深度解析
在 Linux 上操作 TPM 芯片,你几乎一定会遇到这两个名字。它们同属一个由 Intel 主导贡献的开源生态,但分工截然不同:一个负责“让程序能对 TPM 说话”,另一个负责“让你能对 TPM 说话”。
一、全局视角:TSS 架构的五层结构
要真正理解这两个工具,必须先看清它们所处的整体架构。TPM 2.0 的软件栈(TSS,TPM Software Stack)由可信计算组织(TCG)定义规范,从上层到下层依次为:
应用层(tpm2-tools) → 高层 API 库(FAPI) → 增强 API 库(ESAPI) → 系统 API 库(SAPI) → 编解码库(MU) → 传输接口(TCTI) → 内核驱动 → TPM 芯片
当你安装 tpm2-tools 时,tpm2-tss 会作为依赖被自动安装。这意味着你获得的是一套完整的分层软件栈,而不是两个孤立的工具。
二、tpm2-tss:开发者与 TPM 之间的“翻译层”
tpm2-tss 的全称是 TPM Software Stack 2.0,它是 TCG 规范的官方开源实现。它的核心使命是:把应用层的意图,翻译成 TPM 能理解的精确二进制命令流。
2.1 三个 API 层次的设计逻辑
tpm2-tss 并非单一库,而是一组按抽象级别分层的库集合。每一层解决的问题不同,面向的使用者也不同:
SAPI(System API,系统 API)—— 裸金属级接口
libtss2-sys 提供的是与 TPM 2.0 Part 3 命令一一对应的最底层接口。它的设计目标非常明确:不做任何多余的事。
根据 TCG 的 SAPI 规范,这一层被严格要求:
- 不允许进行密码学运算(不处理 HMAC 或会话加密)
- 不允许进行堆内存分配(调用者负责分配所有缓冲区)
- 不允许文件 I/O
- 数据必须使用本地字节序,SAPI 负责转换为 TPM 要求的大端格式
这意味着 SAPI 适合固件、嵌入式系统或需要极致控制的专家应用。它没有任何“智能”,你告诉它发什么命令、带什么参数,它就原样发送。
ESAPI(Enhanced System API,增强系统 API)—— 通用应用的首选
libtss2-esys 是绝大多数 C 应用程序实际使用的层。它在 SAPI 之上增加了会话管理、HMAC 授权计算、参数加密解密、TPM 对象元数据跟踪等能力。
简单说:如果你要使用一个需要授权的 TPM 命令(比如创建一个密钥),SAPI 要求你手动计算授权 HMAC、手动建立加密会话;而 ESAPI 帮你自动完成这些繁琐的密码学操作。代价是它需要依赖密码学库并会进行动态内存分配。
FAPI(Feature API,特性 API)—— 最高层抽象
libtss2-fapi 的目标是让开发者几乎不需要了解 TPM 的细节。它提供了 JSON 数据格式和策略语言支持,试图把密钥管理、策略授权等操作简化为几条高层函数调用。FAPI 对应的规范是 TCG 的 Feature API Specification。
2.2 支撑层:MU 与 TCTI
在三个 API 层之下,还有两个关键的支撑组件:
MU(Marshaling/Unmarshaling,编解码):libtss2-mu 负责把 C 语言的数据结构“打包”成 TPM 能理解的紧凑二进制格式,以及把 TPM 返回的字节流“解包”回 C 结构。TPM 通信使用最小化传输,MU 确保数据在正确的位置以正确的格式出现。
TCTI(TPM Command Transmission Interface,命令传输接口):libtss2-tcti-* 负责实际的“搬运”工作。它抽象了不同 TPM 接入方式的差异:本地硬件 TPM 通过 libtss2-tcti-device 走内核驱动,软件模拟器通过 libtss2-tcti-mssim 走模拟协议。这种设计让上层 API 无需关心 TPM 是物理芯片、固件还是远程服务。
三、tpm2-tools:命令行工具箱
如果说 tpm2-tss 是发动机,tpm2-tools 就是仪表盘和方向盘。它是一套构建在 tpm2-tss 之上的命令行工具集,让用户无需编写代码就能操作 TPM。
3.1 BusyBox 式的设计
一个值得注意的实现细节:新版本的 tpm2-tools 中,所有命令实际上都是同一个可执行文件 tpm2 的软链接。官方文档将其描述为“一个类似于 BusyBox 的单一小型可执行文件”。
这意味着 tpm2_getcap 和 tpm2 getcap 是等价的——程序根据调用时使用的名字来决定执行哪种功能。这种设计方便管理,也节省空间。
3.2 命令覆盖范围
tpm2-tools 的命令列表非常长,覆盖了 TPM 操作的几乎所有方面。按功能分类:
信息查询:tpm2_getcap(查看 TPM 能力)、tpm2_pcrread(读取 PCR 值)、tpm2_getrandom(从 TPM 获取随机数)。
密钥管理:tpm2_createprimary(创建主密钥)、tpm2_create(创建子密钥)、tpm2_load(加载密钥)、tpm2_readpublic(读取公钥)。
密码学操作:tpm2_sign(签名)、tpm2_verifysignature(验签)、tpm2_rsadecrypt(RSA 解密)、tpm2_hash(哈希)。
NV 存储:tpm2_nvdefine、tpm2_nvwrite、tpm2_nvread 用于操作 TPM 的非易失性存储空间。
策略与会话:大量 policy* 前缀的命令用于构建复杂的授权策略。
四、两者的实际关系:依赖与配合
tpm2-tools 与 tpm2-tss 的关系是明确的依赖关系:tpm2-tools 中的每一个命令,最终都通过调用 tpm2-tss 的库函数(通常是 ESAPI 或 FAPI)来完成实际的 TPM 通信。
这种分层带来的实际好处是调试变得有据可依。假设你配置 ssh-tpm-agent 时遇到问题,可以先用 tpm2-tools 做基本测试:
tpm2_getcap properties-fixed # TPM 是否在线?
tpm2_createprimary -C o -c primary.ctx # 最基础的密钥创建流程是否畅通?
如果这些命令成功,说明 tpm2-tss 到 TPM 芯片的整条链路正常,问题出在上层应用的配置。如果失败,则问题在 TPM 本身或底层驱动。
五、回到你的 Ubuntu 环境
你之前已经通过 tpm2_getcap 确认了 Intel Lunar Lake 固件 TPM 正常工作,/dev/tpmrm0 设备节点也已就位。这意味着从 tpm2-tss 的库层到 tpm2-tools 的命令层,整条链路都是通的。
当你后续使用 ssh-tpm-agent 或 tpm2-pkcs11 来保护 SSH 私钥时,这些上层工具最终都会调用 tpm2-tss 的库与你的 TPM 芯片通信。而 tpm2-tools 是你手边随时可用的检查工具——它既是学习 TPM 工作原理的教具,也是排查问题的实用诊断器。