I’m sort of a security junkie, so I wanted to see how locked down I could get the Framework laptop. It supports UEFI, and has a TPM 2.0, so the theory was that it could get pretty far. Following in the footsteps of Matthew Garret and Trammel Hudson’s Safeboot project, I wanted to see how easy it would be to do the following:
- Full disk encryption (FDE) with the decryption key stored in the TPM
- Arbitrary secure boot key enrollment
- Secure boot using a signed unified kernel
- Additional goodies, like tpm2-totp
- Systemd-boot for boot management
I have rolled out FDE+Secure Boot on a pretty wide variety of systems in the past using a wide variety of tools. Typically the trick with FDE is getting the disk to unlock on boot, assuming everything checks out in the firmware (akin to Microsoft BitLocker). Until recently, it had been theoretically possible but I’d never had much luck. Recently, however, systemd has implemented support for early-stage TPM interaction, including storing a LUKS2 key in the TPM and pulling it out at boot if certain PCR values check out. The new features are systemd-cryptenroll, which I happily discovered when setting up LUKS this most recent time.
So, following the standard disk formatting and encrypting guides for LVM and LUKS, setting a password, and enrolling the initcpio hook, I could enter a password at boot time to unlock the disk. Running systemd-cryptenroll, I can cache the key in the TPM, and unlock it if PCRs 0 and 7 match expected values automatically on boot, no password needed! (PCRs are hash chained, so once you have the PCR you want, in this case PCR 7, which stores Secure Boot info, you know what you need to know. Keeping 0 just makes sure that we’re on the machine we think we are). It works like a dream!
The next step was to actually set up Secure Boot, which along with systemd-boot allows us to verify the system state up to the launch of the kernel. Following the arch wiki, I generated keys using Rod Smith’s script and put them on my efi system partition (
/boot by default). Then I opened the Framework firmware interface,set a firmware password, turned on Secure Boot, and enrolled the keys under the Secure Boot option on the Security page. This was by far the easiest time I’ve ever had enrolling keys. Now my system decrypts the disk and boots only if the firmware checks out. By using
sbupdate to generate and sign a unified bootloader+kernel image, it’s now much harder carry out Evil Maid attacks and the like on my Framework laptop (though as recent findings have shown, not impossible if you can sniff keys of the TPM bus).
Ideally I’d like to get TPM2-TOTP implemented, where the system shows me a one-time password on each boot that I can verify with a MFA app on my phone. So far, I can’t seem to get the value to display in Plymouth, though I’m not sure what I’m doing wrong. It’s all very new tech, so it could just be that.
I’d also like to use dm-verity to set my root partition as read-only, which in theory extends Secure Boot guarantees up into the OS (something akin to Safeboot’s SIP clone). That’s what I’m going to work on next.
Despite some initial uncertainty, the TPM and Secure Boot infrastructure on the laptop works exactly as expected, and the firmware has been a dream to work with compared to other vendors (ahem HP). It’s even easier than Lenovo IMO. Hopefully this helps someone else make their Framework more secure! Most of the tools aren’t specific to Arch, if you’re using Debian/Ubuntu you can just use Safeboot to get a lot of what I’ve done above. I’m sure Fedora has similar packages too.
If there’s any interest, I’d be happy to do a step-by-step write-up.