Chris Xiao

DevOps & Systems Engineer

Chris Xiao

DevOps & Systems Engineer

Auto-Decrypt Root Volumes with TPM2

With systemd-cryptenroll, auto-decrypting LUKS2 volumes is easier than ever.

Last updated on Jun 17, 2021

Requirements

  • systemd version 248 or newer
  • Use mkinitcpio for initramfs generation

Preparation

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

Configure mkinitcpio

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.

Add TPM module

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)

Switch to systemd hooks

Replace the following HOOKS:

OriginalReplace with
udev, usr, resumesystemd
keymap, consolefontsd-vconsole
encryptsd-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)

Rebuild initramfs

sudo mkinitcpio -P

Edit kernel cmdline

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 of rd.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.

Enroll a TPM-based key to the LUKS volume

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.

Reboot and test

Your LUKS volume should automatically decrypt.


Upgraded firmware, kernel, or bootloader?

  • 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.

Update TPM-based key

# wipe all TPM2 keys and enroll a new key with PCR 0,2,4,7
systemd-cryptenroll /dev/block-device --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=0,2,4,7

Have a question or suggestion? Please post it on GitHub Gist.

CC BY-SA 4.0 Written By Human Not By AI