Skip to content

Raspberry Pi TPM2 LUKS2 Auto-Unlock with systemd-cryptenroll

systemd-cryptenroll can enroll an external TPM 2.0 device as an unlock token for a LUKS2 volume. Test this on an empty removable data partition—not the running root filesystem—and keep an independently stored passphrase or recovery key. Auto-unlock improves unattended operation but makes recovery design more important.

The formatting commands in this guide erase the selected partition

Use an empty test device with a verified backup. Replace every <test-partition> placeholder manually only after checking lsblk. Never experiment on the current root, boot, or production data partition.

What this design protects

Scenario Expected result
Encrypted storage removed without TPM Data remains encrypted
Same Pi and TPM, accepted policy Volume unlocks automatically
TPM removed or cleared TPM unlock fails; recovery credential is required
PCR-bound boot state changes TPM unlock may fail; recovery/update procedure is required
Attacker controls an already-unlocked running Pi Data may be accessible through the running OS

The TPM is not the bulk encryption engine. LUKS/dm-crypt encrypts data; the TPM protects release of an enrolled randomized key.

Prerequisites

  • A TPM 2.0 module already exposed as /dev/tpmrm0
  • Raspberry Pi OS Trixie with current updates
  • An empty, disposable USB/SSD partition
  • Local console access
  • A tested backup and a place to store recovery material offline

Complete TPM module detection before continuing:

1
2
3
ls -l /dev/tpm* 2>/dev/null
tpm2_getcap properties-fixed
systemd-cryptenroll --tpm2-device=list

If the last command is unavailable or lacks TPM2 support, check the installed systemd version and package documentation before changing storage.

1. Identify an empty test partition

List stable identifiers, filesystems, mounts, and the current root source:

1
2
3
findmnt -no SOURCE /
lsblk -o NAME,PATH,MODEL,SERIAL,SIZE,FSTYPE,FSVER,MOUNTPOINTS
ls -l /dev/disk/by-id/

Confirm all of the following:

  • it is not the device containing /
  • it is not bootfs
  • it contains no required data
  • it is unmounted
  • its size and hardware identity match the intended test device

Prefer a stable /dev/disk/by-id/...-partN path. Do not rely on /dev/sda1, which can change when devices are reconnected.

2. Install and record the tool versions

1
2
3
4
5
6
sudo apt update
sudo apt install cryptsetup tpm2-tools

systemd --version
cryptsetup --version
tpm2_getcap properties-fixed

Save this information with the test results because token formats, options, and boot integration can change across systemd releases.

3. Create a LUKS2 test volume

After verifying the target again, create the LUKS2 header:

sudo cryptsetup luksFormat --type luks2 <test-partition>

Use a strong temporary test passphrase and store it outside the Raspberry Pi. Verify the header before creating a filesystem:

1
2
3
sudo cryptsetup luksDump <test-partition>
sudo cryptsetup open <test-partition> securedata
ls -l /dev/mapper/securedata

Creating the filesystem below erases any previous filesystem inside the mapping:

1
2
3
4
sudo mkfs.ext4 -L securedata /dev/mapper/securedata
sudo install -d -m 0750 /srv/securedata
sudo mount /dev/mapper/securedata /srv/securedata
findmnt /srv/securedata

Write a non-secret marker and confirm it survives a close/reopen cycle:

1
2
3
4
5
6
printf 'encrypted test volume\n' | sudo tee /srv/securedata/test.txt
sudo umount /srv/securedata
sudo cryptsetup close securedata
sudo cryptsetup open <test-partition> securedata
sudo mount /dev/mapper/securedata /srv/securedata
cat /srv/securedata/test.txt

4. Add and verify a recovery credential

The original LUKS passphrase is already a recovery path. You can also generate a systemd recovery key in another slot:

sudo systemd-cryptenroll --recovery-key <test-partition>

The command prints a recovery key. Store it in an offline password manager or controlled recovery record, not in shell history, a screenshot left on the Pi, or a file on the encrypted device.

Close the mapping and test the recovery key before enrolling the TPM:

1
2
3
4
sudo umount /srv/securedata
sudo cryptsetup close securedata
sudo cryptsetup open <test-partition> securedata
sudo cryptsetup close securedata

At the prompt, use the recovery key for one test. A credential that has not successfully unlocked the volume is not a recovery plan.

Back up the LUKS header to separately protected storage:

sudo cryptsetup luksHeaderBackup <test-partition> \
  --header-backup-file /path/on/separate-secure-storage/securedata-luks-header.img

The header backup and any valid credential can be security-sensitive. Protect and inventory it like other recovery material.

5. Enroll the TPM without PCR binding first

For the first controlled test, bind the token to the TPM device but explicitly select no PCRs:

1
2
3
4
sudo systemd-cryptenroll \
  --tpm2-device=auto \
  --tpm2-pcrs= \
  <test-partition>

This proves device discovery and token handling without confusing the test with boot measurements. It does not restrict unlock to a particular boot state.

Inspect the LUKS2 token metadata and remaining key slots:

sudo cryptsetup luksDump <test-partition>

Do not remove the passphrase or recovery-key slots.

The systemd TPM2 crypttab documentation describes how a randomized key is encrypted to a TPM-derived primary key and stored in the LUKS2 JSON token metadata.

6. Test manual TPM unlock

Close any active mapping:

sudo umount /srv/securedata 2>/dev/null || true
sudo cryptsetup close securedata 2>/dev/null || true

Test through the systemd cryptsetup helper installed on the system. Its path can be found with:

systemctl cat systemd-cryptsetup@.service | grep ExecStart

On many current installations, a direct test looks like:

sudo /usr/lib/systemd/systemd-cryptsetup \
  attach securedata <test-partition> - tpm2-device=auto

Verify and detach:

1
2
3
4
sudo mount /dev/mapper/securedata /srv/securedata
cat /srv/securedata/test.txt
sudo umount /srv/securedata
sudo /usr/lib/systemd/systemd-cryptsetup detach securedata

Use the actual helper path shown by the unit on your OS. If TPM unlock fails, stop and inspect logs; do not remove recovery slots.

7. Configure a non-critical data mount

Get the LUKS UUID:

sudo cryptsetup luksUUID <test-partition>

Add a line to /etc/crypttab, replacing <luks-uuid>:

securedata UUID=<luks-uuid> - tpm2-device=auto,nofail

Add the decrypted filesystem to /etc/fstab by its filesystem UUID:

sudo blkid /dev/mapper/securedata

Example:

UUID=<filesystem-uuid>  /srv/securedata  ext4  defaults,nofail,x-systemd.device-timeout=30s  0  2

Validate the filesystem table and test generated mounts before rebooting:

1
2
3
4
5
6
sudo findmnt --verify --verbose
sudo systemctl daemon-reload
sudo systemctl start systemd-cryptsetup@securedata.service
sudo mount /srv/securedata
systemctl status systemd-cryptsetup@securedata.service --no-pager
findmnt /srv/securedata

Keep local console access for the first reboot. nofail prevents this non-critical data volume from making an ordinary boot dependency mandatory; choose different semantics only when the application explicitly requires the volume.

8. Decide whether PCR binding is justified

PCR binding should be added only after identifying what measures the Raspberry Pi boot components and how legitimate updates change those measurements.

Record several normal cold boots and one software update in a test environment:

1
2
3
4
tpm2_getcap pcrs
tpm2_pcrread sha256
find /sys/kernel/security -maxdepth 3 -type f \
  \( -iname '*measurement*' -o -iname '*event*' \) -print

Questions to answer:

  • Which component extends each candidate PCR?
  • Is a matching event log available and complete?
  • Does an EEPROM, kernel, initramfs, or config.txt update change it?
  • How will the new expected state be authorized?
  • Can the recovery key unlock the volume after rejection?

Do not assume PCR 7 has PC/UEFI Secure Boot meaning on a Raspberry Pi boot stack. Empty PCR binding is device-bound only; arbitrary PCR binding can create denial of service without adding the intended trust.

When a tested PCR policy is ready, enroll a new TPM token or replace the test token using the exact systemd version's manual. Keep the previous recovery credential throughout rollout.

9. Failure drills

Perform these on the disposable volume:

Drill Expected outcome
Reboot with normal TPM Automatic data-volume unlock works
Disable/remove TPM connection with power off TPM unlock fails; recovery credential works
Change a measured boot component in a PCR-bound test TPM policy rejects; recovery works
Revert the boot change Approved state returns or documented re-enrollment works
Corrupt a copy of the LUKS header Header backup restores only the test copy
Replace module Old TPM token cannot unlock; new module can be enrolled after recovery

Never clear the only TPM protecting production data as a test. Test replacement with disposable keys or a cloned lab design.

Remove the TPM token safely

First confirm that a passphrase or recovery key unlocks the volume. Then list tokens and slots:

sudo cryptsetup luksDump <test-partition>

Remove TPM2 enrollment with the installed systemd tool:

sudo systemd-cryptenroll --wipe-slot=tpm2 <test-partition>

Verify the TPM token is gone and the recovery credential still works. Removing a LUKS token does not clear the entire TPM.

Root encryption is a separate project

Encrypting the Raspberry Pi OS root filesystem requires early-boot TPM availability, an initramfs containing the correct drivers and cryptsetup integration, correct kernel command-line/root mapping, and a remote/local recovery path. Raspberry Pi boot differs from a typical PC UEFI design.

Do not extend this data-volume walkthrough to / by changing device names. Build and test a reproducible image on separate media, then perform repeated cold boots and recovery drills before deployment.

Common mistakes

  • Formatting the wrong partition
  • Testing first on the current root filesystem
  • Enrolling TPM before verifying a recovery key
  • Removing every passphrase slot
  • Binding to PCRs copied from a PC guide
  • Storing recovery key and header backup beside the Raspberry Pi
  • Assuming TPM auto-unlock protects an already-running compromised OS
  • Clearing the TPM during troubleshooting
  • Rebooting a remote-only device without console recovery

FAQ

Does TPM auto-unlock weaken encryption?

It changes the access policy. Storage removed from the TPM remains encrypted, but the approved device can unlock unattended. Security depends on the boot policy, physical threat, and controls on the running OS.

Must I bind LUKS2 to PCRs?

No. Device-only enrollment is useful for integration testing and some threat models. PCR binding adds boot-state conditions only when those measurements are meaningful and maintainable.

Why keep a passphrase after TPM unlock works?

TPMs, wiring, policies, and boot measurements can fail or change. A separately stored recovery credential prevents an availability failure from becoming permanent data loss.

Can I use this for NVMe?

Yes, for a separate data partition when the NVMe device, TPM driver, and systemd integration are available. Identify it with a stable /dev/disk/by-id path and never format the boot/root partition by accident.