Evil maid attacks, Secure Boot and TPM2-TOTP

Full disk encryption (FDE) is a good way to protect your personal data if your computer gets stolen (or seized by law enforcement, if you don't live in a country with key disclosure laws. It's always a good idea to use it on all your devices; you can for example sell your old smartphone or hard disk and be reasonably sure that the data on it can't be recovered. There are a few exceptions where FDE is not easy (old hardware where cryptographic primitives are a real performance bottleneck; machines that need to boot non-interactively…).

FDE doesn't protect against targeted attacks, for example evil maid attacks. For example, an evil mail (let's call her Eve) could, while you're not at home, make a block-level copy of your encrypted hard disk, then replaces its contents with a dummy bootloader/system that just accepts any passphrase you type and exfiltrates it over the network. Because, so far, all the boot process looked the same on your end, you don't know you your disk's contents has been swapped until it's too late. Eve can now decrypt her copy of your data with your passphrase.

Unfortunately, FDE always relies ultimately on a master key; you cannot do challenge-response based systems that are not vulnerable to replay attacks. Even if you use a fancy keyfile on a removable drive, or a yubikey, these all reduce to typing a fancy passphrase in the context of FDE.

What about Secure Boot?

Secure Boot doesn't, on its own, protect against any kind of evil maid attack. Secure Boot authenticates the early boot process (the bootloader, the kernel, the initramfs, the cmdline), but an attacker with physical access can easily install their own keys and boot their own compromised bootloaders/kernels. Secure Boot still has legitimate use cases; it protects against malware that attempts to tamper with the early boot process.

Disclaimer: the solutions below are not perfect. This is not security advice. You are still vulnerable to, for example, hardware keyloggers (even more-so if you run a keyboard with customisable firmware). This just makes it slightly harder to pull off an evil maid attack.

First solution: encrypted initramfs with TOTP secret

The idea is to show a token that authenticates a known secret, before you type the passphrase that unlocks your root partition. To protect against replay attacks (eg, Eve can know the secret by just looking at you boot your computer at home), TOTP can be used:

  1. Generate a random secret. Use this to derive a TOTP authentication. Save it on your phone (which is, hopefully, also protected by a different passphrase), and on your encrypted initramfs (/boot partition).

  2. Have the early boot (initramfs) show you the TOTP six-digit code before prompting for the passphrase that unlocks the root partition.

Now Eve can't access the TOTP secret without knowing the passphrase of the /boot partition; if you see the right code during early boot, you know you are booting your own (presumably uncompromised) kernel/initramfs. If you were using Secure Boot, you can also authenticate the bootloader. If you don't see the right code, you know NOT to type the passphrase of your root partition.

This method can be done on virtually any hardware, using GRUB_ENABLE_CRYPTODISK=y to make GRUB boot from an encrpyted /boot partition.

The main drawback of this, is that you need to type two passphrases during the boot process, and they both have to be strong and different.

Second solution: TPM2-TOTP

On EFI hardware with a TPM2 chip (most recent motherboards have this, as a discrete chip or in firmware), you can seal the TOTP secret in the TPM2 chip itself. And you can directly ask the TPM2 chip to generate the one-time code for you, during early boot.

The clever bit is that you can lock down accessing the one-time code based on values of PCRs; this allows authentication of your kernel, your initramfs, your cmdline, your bootloader without having to type a passphrase.

On Arch Linux, you can install tpm2-totp and use the sd-tpm2-totp (or the non-sd variant) initramfs hook:

(in /etc/mkinitcpio.conf)
HOOKS="base systemd ... sd-tpm2-totp sd-encrypt sd-vconsole ..."

Typical usage below. Enable PCRs based on personal needs.

# recreate initramfs with tpm2 stuff
mkinitcpio -p linux

# generate a strong passphrase $PASSPHRASE. save it somewhere safe.
pwgen -s 32

# flash the QR code on your phone.
tpm2-totp -P $PASSPHRASE -p 0,1,2,3,4,5,6,7 generate

# depending on which PCRs you enable, run this every time after upgrading the firmware/kernel and rebooting
tpm2-totp -P $PASSPHRASE -p 0,1,2,3,4,5,6,7 reseal