Chris Xiao

Aspiring Software Engineer

Chris Xiao

Aspiring Software Engineer

Auto-Decrypt Root Volumes with TPM2

With systemd-cryptenroll (part of systemd 248), auto-decrypting LUKS2 volumes is easier than ever.

linux 
Last updated on April 18, 2021

Requirements

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

Notes

  • This guide is intended for advanced users.
  • This guide is written for, and tested on, Arch Linux.
  • Theoretically, it should work on any Linux distro with systemd version 248 or newer. You'll need to adapt the instructions below for your distro.

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.

Switch to systemd hooks

Replace the following HOOKS:

<table> <thead><tr> <th>Original</th> <th>Replace with</th> </tr> </thead> <tbody> <tr> <td>udev, usr, resume</td> <td>systemd</td> </tr> <tr> <td>keymap, consolefont</td> <td>sd-vconsole</td> </tr> <tr> <td>encrypt</td> <td>sd-encrypt</td> </tr> </tbody> </table>

At the minimum, you should have

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

This article is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.