NEBULA.CAT // MFD-2600 BARCELONA · ES
BLOG/THE ENCRYPTION WAR

// NOTES FROM THE TERMINAL

POST

The Encryption War

2026-06-29 ~11 min read securitylinuxtpmluks

The goal was simple to state and miserable to deliver: TPM-backed full-disk encryption on a fleet of Ubuntu 26.04 workstations, so disks unlock automatically on trusted hardware and stay sealed on a stolen one — no passphrase prompt, no shared key on a wiki.

Five separate things stood in the way: a GPU, a BIOS, SSSD, adsys, and — improbably — a Rust rewrite of sudo. Here is the order they fell in.

The plan

LUKS2 on the root volume, with the TPM2 acting as the keyholder. The TPM releases the key only when the boot-measurement PCRs match a known-good state, so any tampering with firmware or boot chain breaks the unlock.

SHELLenroll tpm2 into luks
# bind the LUKS slot to PCRs 0,2,4,7
systemd-cryptenroll --tpm2-device=auto \
  --tpm2-pcrs=0+2+4+7 /dev/nvme0n1p3

Obstacle 1 — the GPU

The discrete GPU's option ROM wrote into PCR 0 on some cold boots but not others, depending on display state at POST. A PCR that changes between boots is useless as a seal — the TPM would refuse to release the key roughly one boot in four.

LESSON

Don't seal against firmware PCRs you don't control. Measure what you sign — the kernel and initrd — and leave volatile hardware ROMs out of the policy.

Obstacle 2 — the BIOS

Secure Boot was on, but the vendor BIOS shipped with a setup-mode quirk that reset PCR 7 after a firmware update — silently re-locking every machine in the building the morning after a routine patch window.

Obstacles 3 & 4 — SSSD and adsys

With the disks finally unlocking, login itself broke. The interaction between SSSD's credential cache and adsys group-policy application raced the TPM-unlocked home mounts, so the first login after boot landed in a half-provisioned session.

  • SSSD cached an offline credential before the network came up
  • adsys applied policy against a home directory that wasn't mounted yet
  • the fix was an ordering dependency, not a code change — After= is a load-bearing line

Obstacle 5 — the Rust sudo

Ubuntu 26.04 ships sudo-rs, the Rust rewrite, as default. It is stricter about a malformed /etc/sudoers.d drop-in than classic sudo — a trailing-comment quirk my provisioning template had carried for years was now a hard parse error, locking out privilege escalation on freshly imaged machines.

OUTCOME

All five fell. Disks now unlock sealed-to-TPM with no passphrase on trusted hardware, and the whole policy is reproducible from Ansible. The war was won line by line, in the boot log.

// daniel.nebula.cat/blog/the-encryption-war
— END OF DISPLAY · MFD-2600 —