This guide is written for Arch Linux.
systemd
version 248 or newer- Use
mkinitcpio
for initramfs generation
You need to find out what kernel module/driver is needed for your TPM.
# Note the DRIVER (`tpm_*`, e.g. `tpm_tis`) for your TPM
systemd-cryptenroll --tpm2-device=list
You need to edit /etc/mkinitcpio.conf
. Basically, you'll switch to systemd
hooks and add tpm_X
(replace with your actual TPM driver name) to MODULES
.
For more information on configuring mkinitcpio
, check out the mkinitcpio
page on ArchWiki.
Look for a line that starts with MODULES=
in /etc/mkinitcpio.conf
, and add tpm_X
(replace with your actual TPM driver name) inside the parentheses.
For example, if you have this line in /etc/mkinitcpio.conf
MODULES=(i915)
Change it to this
MODULES=(i915 tpm_tis)
Replace the following HOOKS
:
Original | Replace with |
---|---|
udev, usr, resume | systemd |
keymap, consolefont | sd-vconsole |
encrypt | sd-encrypt |
Place the replacement HOOKS in the original place of the original HOOKS.
For example, if you have this line in /etc/mkinitcpio.conf
HOOKS=(base udev autodetect modconf block keyboard encrypt filesystems fsck)
Change it to this
HOOKS=(base systemd autodetect modconf block keyboard sd-encrypt filesystems fsck)
At the minimum, you should have these hooks:
HOOKS=(base systemd modconf block keyboard sd-encrypt filesystems fsck)
sudo mkinitcpio -P
At the minimum, you should have
rd.luks.uuid=your-uuid rd.luks.options=tpm2-device=auto
Notes:
- You may use
rd.luks.name=your-uuid=name
instead ofrd.luks.uuid=your-uuid
to mount the LUKS volume with a specific name - You may include other options after
tpm2-device=auto
. Options should be comma-separated.
See man systemd-cryptenroll
for a full list of available options.
# Auto-detect the available TPM and use PCR 0,2,4,7 for verification
# Replace /dev/block-device with your LUKS volume
sudo systemd-cryptenroll /dev/block-device --tpm2-device=auto --tpm2-pcrs=0,2,4,7
With PCR 0,2,4,7, these are validated at boot time:
- System firmware executable (0)
- Kernel (2)
- Bootloader (4)
- Secure boot state (7)
If you're using PCR 2 and multiple kernels, you need to enroll a key within each kernel.
Your LUKS volume should automatically decrypt.
- PCR 0,2,4,7 validates the firmware, kernel, and bootloader before releasing the decryption key.
- If you upgraded firmware, kernel, or bootloader, TPM will not release the key. As a result, auto decryption will fail, and you'll be prompted for a passphrase.
- You need to wipe the old key and enroll a new key.
# wipe all TPM2 keys and enroll a new key with PCR 0,2,4
systemd-cryptenroll /dev/block-device --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=0,2,4,7
This will ask for your volume's passphrase. If you'd like to automate this, you may set the PASSWORD
environment variable to your passphrase.
⚠️ SECURITY WARNING: Storing secrets (such as your LUKS volume's passphrase) is not a good idea. See this article for why you shouldn't do this.
Wanted to add a note for posterity. I was able to solve the issue I mentioned above, but not by precomputing the PCRs. The answer is simpler.
Most major Linux distros have adopted the shim bootloader in order to support a UEFI Secure Boot chain of trust. Here's a list of PCRs set by this bootloader.
Are you running the shim bootloader?
If UEFI secure boot is enabled on your system, the answer is probably yes.
You can check UEFI SecureBoot state by running
mokutil --sb-state
,or run
sudo tpm2_pcrread
to see if PCR 14 has a non-zero value (it is set by the shim bootloader).To avoid re-enrolling your LUKS encryption TPM key on every kernel upgrade, you can seal the key to TPM values 7 and 14.
If you trust your distro's signed kernel and bootloader images, PCRs 7 and 14 will give you the same level of protection as you would with 0, 2 and 4, without the need for re-enrollment.
There's a much longer discussion of this in this blog post and in this PR.