systemd-cryptenroll
- systemd-cryptenroll 是一个用于将硬件安全令牌和设备注册到 LUKS2 加密卷中的工具,之后便可在启动过程中使用它们解锁该卷。
systemd-cryptenroll 允许将smartcards、通用第二因素 令牌、可信平台模块安全芯片以及普通密码注册到 LUKS 设备中。之后,systemd-cryptsetup@.service(8) 可以使用已注册的令牌解锁这些设备。
安装
systemd-cryptenroll 是 systemd包 的组成部分,并随该软件包提供。不过,要将硬件设备用作密钥,还需要安装额外的软件包:
- 要使用 PKCS#11 令牌,请安装 libp11-kit包,可能还需要 opensc包。
- 要使用 FIDO2 令牌,请安装 libfido2包。
- 要使用 TPM2 设备,请安装 tpm2-tss包。
列出密钥槽
systemd-cryptenroll 可以列出 LUKS 设备中的密钥槽,功能类似于 cryptsetup 的 luksDump,但输出格式更加易于阅读。
# systemd-cryptenroll /dev/disk
SLOT TYPE 0 password 1 recovery 2 tpm2
擦除密钥槽
# systemd-cryptenroll /dev/disk --wipe-slot=SLOT
其中,SLOT 可以是:
- 单个密钥槽的索引,如#列出密钥槽所示。
- 密钥槽类型,这将擦除该类型的所有密钥槽。有效类型包括
empty、password、recovery、pkcs11、fido2和tpm2。 - 以上各项的组合,以逗号分隔。
- 字符串
all,用于擦除设备上的所有密钥槽。此选项只能在同时注册另一个设备或密码时使用。
--wipe-slot 操作可以与所有注册选项组合使用,便于更新已有的设备注册信息:
# systemd-cryptenroll /dev/disk --wipe-slot=fido2 --fido2-device=auto
注册密码
普通密码
此操作等同于 cryptsetup luksAddKey。
# systemd-cryptenroll /dev/disk --password
恢复密钥
- 恢复密钥与密码基本相同,但它由计算机生成,而不是由用户自行选择,因此能够保证较高的熵。恢复密钥使用易于输入的字符集,也可以通过扫描屏幕上的二维码获取。
恢复密钥用于在硬件令牌不可用时作为备用解锁方式,并且可以在任何需要普通密码的场合代替普通密码使用。
# systemd-cryptenroll /dev/disk --recovery-key
注册硬件设备
--type-device 选项必须指向对应设备类型的有效设备路径。可以向该选项传入 list 参数,获取可用设备列表。或者,如果只连接了一台所需类型的设备,可以使用 auto 选项自动选择。
PKCS#11 令牌或智能卡
令牌或智能卡必须包含一对 RSA 密钥,用于加密所生成的卷解锁密钥。
# systemd-cryptenroll /dev/disk --pkcs11-token-uri=device
FIDO2 令牌
任何支持“hmac-secret”扩展的 FIDO2 令牌都可以与 systemd-cryptenroll 配合使用。以下示例将一个 FIDO2 令牌注册到加密的 LUKS2 块设备中,仅要求通过用户在场验证进行身份认证:
# systemd-cryptenroll /dev/disk --fido2-device=device --fido2-with-client-pin=no
此外,systemd-cryptenroll 还支持使用令牌内置的用户验证方式:
-
--fido2-with-user-presence指定解锁前是否验证用户在场(例如触摸令牌),默认为 yes。 -
--fido2-with-user-verification指定解锁前是否要求用户验证,默认为 no。
- 如果令牌不支持这些功能,上述选项将不起作用。
- 有关两者区别的更多信息,请参阅 用户在场与用户验证。
默认情况下,生成 FIDO2 凭据时使用的加密算法为 es256,即采用 NIST P-256 曲线和 SHA-256 的椭圆曲线数字签名算法(ECDSA)。如果需要,并且 FIDO2 令牌支持,也可以在注册时指定其他加密算法。
假设此前已经注册过一个 FIDO2 令牌,而用户希望再注册一个令牌,则可以使用以下命令生成采用 Curve25519 和 SHA-512 的 EdDSA 凭据(eddsa),并使用此前注册的令牌而非密码来认证设备:
# systemd-cryptenroll /dev/disk --fido2-device=device --fido2-credential-algorithm=eddsa --unlock-fido2-device=auto
可信平台模块
systemd-cryptenroll 原生支持将 LUKS 密钥注册到 TPM。使用此功能需要满足以下条件:
- 必须安装 tpm2-tss包。
- 使用 LUKS2 设备(目前也是 cryptsetup 默认使用的类型)。
- 如果打算在根分区上使用此方法,需要对 initramfs 进行一些调整(高级配置参阅 Dm-crypt/系统配置#使用systemd-cryptsetup-generator):
-
mkinitcpio 用户:启用
systemd和sd-encryptMkinitcpio#钩子(HOOKS)。注意:钩子的排列顺序非常重要。非标准顺序可能导致系统无法启动(此时需要在 arch-chroot 环境中重新生成 initramfs 才能恢复)。正确顺序的示例参阅 Dm-crypt/系统配置#示例。 -
dracut 用户:启用
tpm2-tssDracut#dracut 模块。
-
mkinitcpio 用户:启用
首先,运行以下命令列出已安装的 TPM 及其使用的驱动程序:
$ systemd-cryptenroll --tpm2-device=list
- 如果计算机安装了多个 TPM,请在后续步骤中使用
--tpm2-device=/path/to/tpm2_device指定要使用的设备。 - 考虑使用 Trusted Platform Module#PCR policies,而不是直接将机密绑定到原始 PCR 值。
只需一条命令,就可以同时将密钥注册到 TPM 和 LUKS 卷。以下示例会生成一个新的随机密钥,将其添加到卷中,使其能够与现有密钥一样用于解锁,并将这个新密钥绑定到 PCR 7(安全启动状态):
# systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/sdX
其中,/dev/sdX 是加密 LUKS 卷的完整路径。如果 LUKS 卷使用密钥文件而非密码解锁,请使用 --unlock-key-file=/path/to/keyfile。
有关 Linux 中常见的 PCR 测量内容,请参阅 systemd-cryptenroll(1) 和 可信平台模块#访问_PCR_寄存器。根据需要调整 --tpm2-pcrs=7(多个参数之间使用 + 符号分隔)。
- 绑定到 PCR 7 时,请确保 安全启动已启用且处于用户模式,否则未经授权的启动设备可能解锁加密卷。
- 如果固件证书发生变化,PCR 7 的状态也可能改变,从而导致用户无法解锁设备。这种变化可能由 fwupd[1] 间接引起,也可能由轮换安全启动密钥直接引起。
- 仅绑定到启动前测量的 PCR(PCR 0–7)会带来恶意操作系统攻击的风险。攻击者可以创建一个恶意分区,并复制真实根文件系统的元数据(例如分区 UUID),使其伪装成原始分区。随后,initramfs 会尝试将恶意分区挂载为根文件系统(解密失败时将回退到密码输入),而启动前 PCR 的值保持不变。由攻击者控制文件内容的恶意根文件系统仍然可能获取真实根分区的解密密钥。详情参阅 Brave New Trusted Boot World 和 BitLocker 文档。
- 对于根卷,一种解决方案是使用
--tpm2-pcrs=other_pcrs+15:sha256=0000000000000000000000000000000000000000000000000000000000000000绑定到初始为空的 PCR 15。如果设置了任何rd.luks内核参数,或者在/etc/crypttab中使用了x-initrd.attach选项,还需要在rd.luks.options=或/etc/crypttab的第四个字段中添加tpm2-measure-pcr=yes选项;如果依赖 GPT 分区自动挂载,则无需这样做。在早期用户空间解锁根卷后,PCR 15 将发生变化,已注册的密钥也将无法再被取回。 - 另一种更简洁的解决方案参阅 Dm-crypt/系统配置#固定 LUKS 卷。
绑定哪些 PCR,需要根据具体情况在易用性和安全限制之间取得平衡。例如,你可能希望更新 UEFI 固件时无需手动干预 安全启动状态,或者希望使用不同的启动设备。另一个例子是,微软的 BitLocker 倾向于使用 PCR 7+11,但也可能采用其他 PCR 组合。
- 除了要求 TPM 状态正确外,还可以要求输入 PIN。只需在上述命令中添加
--tpm2-with-pin=yes选项,并在提示时输入 PIN。 - systemd-cryptenroll 不会在请求输入 PIN 之前检查 TPM 测量值,因此应考虑使用专用 PIN,因为当前环境可能并不可信。
要检查新密钥是否已成功注册,可以转储 LUKS 配置,并查找 systemd-tpm2 令牌条目,以及 Keyslots 部分中新增的密钥槽条目:
# cryptsetup luksDump /dev/sdX
要测试密钥是否有效,请在 LUKS 卷处于关闭状态时运行以下命令:
# systemd-cryptsetup attach mapping_name /dev/sdX none tpm2-device=auto
其中,mapping_name 是为卷解锁后所创建的映射指定的名称。
有关如何在启动时解锁卷,请参阅 Dm-crypt/系统配置#crypttab 和 Dm-crypt/系统配置#可信平台模块与FIDO2密钥。
/etc/crypttab 中使用 LUKS 卷的 UUID 代替设备路径,但 systemd-cryptenroll 命令本身目前只支持路径名。更多信息和示例请参阅 systemd-cryptenroll(1) 和 crypttab(5)。