附录 B · 命令速查表
本书用到的命令按用途分四组。每条只给最典型的写法和一句用途,完整参数以各自 --help 或 man 手册为准——tpm2-tools 版本间参数有变动,别背,查。
TPM 基础操作
| 命令 | 用途 |
|---|---|
tpm2_getcap properties-fixed | 查看 TPM 芯片的固定属性(厂商、固件版本、支持的算法等) |
tpm2_pcrread | 读取所有 bank 的所有 PCR 当前值 |
tpm2_pcrread sha256:16 | 只读 sha256 bank 的 PCR 16 |
tpm2_pcrextend 16:sha256=<哈希值> | 把一个 32 字节哈希 extend 进 PCR 16(第三章实验 A 的核心动作) |
tpm2_pcrreset 16 | 重置 PCR 16(只有 16-23 等可本地重置的 PCR 允许此操作) |
tpm2_getrandom --hex 32 | 从 TPM 真随机数发生器取 32 字节随机数,十六进制输出 |
tpm2_eventlog <日志路径> | 解析二进制固件度量日志为可读 YAML(日志在 /sys/kernel/security/tpm0/binary_bios_measurements) |
实验 A 的一条完整练习链路:
tpm2_pcrreset 16 # 清空 PCR 16,回到全零
echo -n "hello tpm" | sha256sum # 先自己算出要 extend 的哈希
tpm2_pcrextend 16:sha256=<上一步的哈希> # extend
tpm2_pcrread sha256:16 # 读回来,和手工滚哈希的结果对比
预期观察点:extend 后 PCR 16 不再是全零,且等于 sha256(00...00 || 你的哈希)——第三章就是让读者手工验证这个等式。
对象与策略
| 命令 | 用途 |
|---|---|
tpm2_createprimary -C o -c primary.ctx | 在 owner 层次下创建主密钥(primary key),存为上下文文件 |
tpm2_createpolicy --policy-pcr -l sha256:16 -L pcr.policy | 创建一条 PCR 策略:要求 PCR 16 等于当前值 |
tpm2_create -C primary.ctx -L pcr.policy -u seal.pub -r seal.priv -i- | 在主密钥下创建密封对象,stdin 读入秘密,绑定策略 |
tpm2_load -C primary.ctx -u seal.pub -r seal.priv -c seal.ctx | 把密封对象的公/私部分载入 TPM,得到句柄 |
tpm2_unseal -c seal.ctx -p session:session.ctx | 解封:策略会话满足条件才吐出秘密 |
tpm2_startauthsession --policy-session -S session.ctx | 开启一个策略会话(区别于口令会话,可叠加多条策略命令) |
tpm2_policypcr -S session.ctx -l sha256:16 | 在会话上附加“PCR 16 须等于指定值“条件 |
tpm2_policyauthorize -S session.ctx -n key.name -i policy -t ticket | PolicyAuthorize:用授权密钥的签名把策略授权出去(第七章核心) |
tpm2_verifysignature -c key.ctx -g sha256 --scheme=rsassa -m msg -s sig -t ticket | 验签并生成 ticket,供 PolicyAuthorize 使用 |
tpm2_loadexternal -C o -G rsa -u key.pub -c key.ctx -n key.name | 把外部公钥(如 openssl 生成的)载入 TPM 供验签 |
tpm2_flushcontext session.ctx | 冲刷会话/对象上下文,释放 TPM 有限的会话槽位 |
实验 B 的 seal/unseal 完整链路(各命令按依赖顺序):
tpm2_createprimary -C o -c primary.ctx
tpm2_pcrread sha256:16 -o pcr16.bin
tpm2_createpolicy --policy-pcr -l sha256:16 -L pcr.policy
echo -n "my secret" | tpm2_create -C primary.ctx -L pcr.policy \
-u seal.pub -r seal.priv -i-
tpm2_load -C primary.ctx -u seal.pub -r seal.priv -c seal.ctx
tpm2_startauthsession --policy-session -S session.ctx
tpm2_policypcr -S session.ctx -l sha256:16
tpm2_unseal -c seal.ctx -p session:session.ctx # 输出: my secret
tpm2_flushcontext session.ctx
预期观察点:PCR 16 被 extend 过任意值之后,同一条链路走到 tpm2_unseal 会报策略校验失败——那就是“篡改检测“的体感。
磁盘加密
| 命令 | 用途 |
|---|---|
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 <设备> | 把 LUKS 卷绑定到 TPM,PCR 7(Secure Boot 状态)作为解封条件 |
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+11 <设备> | 进阶形态:叠加 PCR 11,配合 systemd-pcrlock(见第十章) |
cryptsetup luksDump <设备> | 查看 LUKS 头信息,确认 TPM2 token 和 keyslot 登记情况 |
enroll 后的自检链路:
cryptsetup luksDump /dev/vda2
# 预期看到:Keyslots 里新增一个类型为 tpm2 的槽位,
# Tokens 段有 systemd-tpm2 记录,pcrs 字段写着 7
lsblk # 确认根分区在 dm-crypt 设备上
重启验证时,如果 TPM 解锁成功,启动过程不会出现 LUKS 密码提示,直接进系统;用附录 A 第 7 条的方法确认解密确实发生了。
虚拟机管理
| 命令 | 用途 |
|---|---|
virsh list --all | 列出所有虚拟机(含关机的) |
virsh start <虚拟机名> | 开机 |
virsh shutdown <虚拟机名> | 正常关机(依赖客户机 ACPI 响应) |
virsh snapshot-create-as <虚拟机名> <快照名> --disk-only --atomic | 对做危险实验前创建仅磁盘快照 |
virsh snapshot-revert <虚拟机名> <快照名> | 回滚到快照——改 initramfs 翻车后的救命稻草 |
virsh snapshot-list <虚拟机名> | 查看快照列表 |
virt-viewer --connect qemu:///system --attach <虚拟机名> | 打开虚拟机显示窗口(注意必须带 --attach) |
实验前的快照习惯(第六章改 initramfs 之前必做):
virsh snapshot-create-as tpm-lab before-initramfs --disk-only --atomic
virsh snapshot-list tpm-lab
# 翻车后:
virsh snapshot-revert tpm-lab before-initramfs
坑
virsh shutdown只是“请求“关机,客户机里系统卡住时它不会有任何效果,等多久都没用。确认卡死后用virsh destroy <虚拟机名>强制断电——前提是已有快照兜底,否则先看看还能不能从别的途径进去救数据。
注意 凡是
tpm2_开头的命令,输入输出对象大多是上下文文件(.ctx)而非密钥本身——密钥本体永远留在 TPM 内部,文件里只是引用。看到一堆.ctx.pub.priv文件别慌,那正是 TPM 的工作方式。