← Back to context

Comment by keeperofdakeys

3 months ago

You can mitigate this by including PCRs that sign the kernel and initrd, however it means whenever you update you need to unlock manually. On Redhat-based distros this can be done with PCRs 8 and 9, though IIRC this may change on other distros.

Also AFAIK there is no standard way to guess the new PCRs on reboot so you can't pre-update them before rebooting. So you either need to unlock manually or use a network decryption like dracut-sshd.

> You can mitigate this by including PCRs that sign the kernel and initrd.

No, that's not an effective mitigation. The signed kernel+initrd would still boot into the impersonated root.

> however it means whenever you update you need to unlock manually. On Redhat-based distros this can be done with PCRs 8 and 9, though IIRC this may change on other distros. > Also AFAIK there is no standard way to guess the new PCRs on reboot so you can't pre-update them before rebooting. So you either need to unlock manually or use a network decryption like dracut-sshd.

With some logic to update the values on kernel updates and re-seal the secret this can be handled transparently. That's the design with sdbootutil in openSUSE (https://en.opensuse.org/Systemd-fde, https://github.com/openSUSE/sdbootutil).

> You can mitigate this by including PCRs that sign the kernel and initrd

nope! the trick the article is describing works even if the kernel and initrd is measured. it uses the same kernel, initrd, and command line.

the reason this trick works is that initrds usually fall back to password unlock if the key from the tpm doesn't work. so the hack replaces the encrypted volume, not the kernel, with a compromised one. that is:

1. (temporarily) replace encrypted volume with our own, encrypted with a known password.

2. boot the device.

3. the automated tpm unlock fails, prompting for a password.

4. type in our password. now we're in, using the original kernel and initrd, but it's our special filesystem, not the one we're trying to decrypt.

5. ask the tpm again for the key. since we're still using the original kernel, initrd, and command line, we should now get the key to unlock the original encrypted volume.

the way to fix this is to somehow also measure encrypted volume itself. the article points to suggestions of deriving a value from the encryption key.

  • > 3. the automated tpm unlock fails, prompting for a password.

    > 4. type in our password.

    In a serious security conscious setup this should be a big red flag to investigate. Any unexpected boot password prompt.

It's ridiculous that there's no software implementation to do this, it's a huge problem.

Auto update should be able to include the kernel, initrd and grub cmdline from the running system I have no idea what's holding this back since evidently code already exists somewhere to do exactly that.

  • That's the design with sdbootutil in openSUSE (https://en.opensuse.org/Systemd-fde, https://github.com/openSUSE/sdbootutil).

    • I don't see anything explicit on those pages about solving this problem though?

      Like with my current clevis luks setup, which I somewhat random have to regen, I'm bound to PCR 0, 1, 2, 3, 4, 7, 8 and 9.

      From https://uapi-group.org/specifications/specs/linux_tpm_pcr_re... that gives me:

      0 - Core system firmware executable code

      1 - Core system firmware data/host platform configuration; typically contains serial and model numbers

      2 - Extended or pluggable executable code; includes option ROMs on pluggable hardware

      3 - Extended or pluggable firmware data; includes information about pluggable hardware

      4 - Boot loader and additional drivers; binaries and extensions loaded by the boot loader

      7 - SecureBoot state

      8 - Commands and kernel command line

      9 - All files read (including kernel image)

      Now the problem is, 8 and 9 I would argue are the most important (since technically 7 probably covers everything else in that list?), whereas my kernel and initrd are not encrypted and my command line can just be edited (but normally wouldn't need to be). But I can't find anyway to get grub, from a booted system, to simulate the output of those values so I can pre-seal the LUKS volume with the new values.

      So in practice, I just always need to remember my password (bad) which means there's no way to make a reasonable assessment of system integrity on boot if I get prompted (I'd argue also the UI experience here isn't good: if I'm being prompted for a password, that clevis boot script should output what changed at what level - i.e. if secure boot got turned off, or my UEFI firmware changed on me when I'm staying in a hotel, maybe I shouldn't unlock that disk).

At least for PCR 7, it's well specified and documented how the digest is generated. You can dump the component digests of a PCR using `tpm2_eventlog`, and I've written a tool that can be used to populate the requisite data structures for hashing.

https://github.com/balena-os/tcgtool