These rough steps will setup a Debian 12 system to:
- Secure boot with a custom platform key (PK) with Microsoft's certificates in the trust db for OpROMs.
- Enroll the secure boot material automatically at boot.
- Boot a signed UKI.
- Have an encryped root partition that unlocks automatically with a TPM key released only if the secure boot parameters are known (PCR 7 hash) and the UKI is signed by a trusted key (PCR 11 sig).
- Install new kernels with
kernel-install
which will generate an initramfs with dracut and create a signed UKI with ukify which will be installed in the EFI system partition for systemd-boot.
- Put system in secure boot setup mode.
- This usually means enabling securte boot and erasing all keys from the UEFI menu.
- Create simple partition scheme with an EFI system partition and a root partition.
- The EFI system partition size should be generous, at least 1 GB.
- You may be forced to create a boot partition when enabling encryption for the root partition, since at that point the bootloader will not be able to read the kernel image from root. If/when the installer allows installing the kernel and initrd to the EFI system partition, or to install a UKI, then this boot partition won't be needed. It is not needed once the system uses a UKI.
- You can throw in a swap partition if your system needs it.
- Encrypt root partiton with LUKS2.
- Password should simple, it will be removed after setup.
- Reboot into the system (but see next step first).
If you can get a shell at the end of the install, you could this before rebooting to the new system.
- Change partition types to be discoverable.
- https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
- Include the boot and swap partitions if they were created.
fdisk
is a good tool to do this.
- Delete all the entries in
/etc/fstab
pertaining to any partitions that will be auto-mounted. - Reboot.
Some steps have a $BOOT
path placehoder. This matches the description in https://uapi-group.org/specifications/specs/boot_loader_specification/#the-boot-partition-placeholder. Some steps have a
$ESP
placeholder for the EFI system parition. Check your system's specific configuration and
mounts.
- Remove grub and initramfs tools.
apt purge --allow-remove-essential grub* grub2* os-prober shim* cryptsetup-initramfs initramfs*
- Install dracut, tpm tools, sbsign, and other dependencies.
apt install curl dracut keyutils libtss2-esys-3.0.2-0 libtss2-mu0 libtss2-rc0 policykit-1 python3-cryptography python3-pefile sbsigntool tpm2-tools
- Hold grub so it never gets reinstalled.
apt-mark hold grub* grub2*
- Install systemd-254 or later from backport.
apt install -t bookworm-backports systemd systemd-boot systemd-coredump systemd-networkd systemd-resolved systemd-timesyncd
- Generate secure boot keys.
./gen-secure-boot-keys.sh
- Install secure boot keys.
cp db.key /etc/kernel/secure-boot.key.pem
cp db.pem /etc/kernel/secure-boot.cert.pem
cp {db,KEK,PK}.auth $ESP/loader/keys/auto/
- NOTES: Keys have to be stored on the ESP!
- Sign systemd-boot's EFI binary.
sbsign --key db.key --cert db.pem --output /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi
- NOTE: There is nothing here to automatically sign new versions of systemd-boot, and
bootctl install
will prefer the signed file, which means systemd-boot updates will not be installed to the EFI. This is good as the unsigned version would be rejected by the system, but it does mean you may need to manually sign and update systemd-boot from time to time.
- Generate PCR keys.
- Must use ukify-255 or later, which at the time of writing is not in backports.
- Since it's a Python program, you can download it from upstream and run it directly to generate these keys. There is no need to overwrite the system's copy.
./ukify genkey --pcr-private-key=/etc/kernel/pcr-initrd.key.pem --pcr-public-key=/etc/kernel/pcr-initrd.pub.pem
./ukify genkey --pcr-private-key=/etc/kernel/pcr-system.key.pem --pcr-public-key=/etc/kernel/pcr-system.pub.pem
- Copy the PCR initrd public key for systemd-cryptenroll.
cp /etc/kernel/pcr-initrd.pub.pem /etc/systemd/tpm2-pcr-public-key.pem
- Install the material in
kernel
to/etc/kernel/
.install.d/55-dracut.install
is a custom kernel-install plugin to generate an initramfs that will be picked up by60-ukify.install
.
- Install
60-ukify.install
from systemd-255 or later to/etc/kernel/install.d
.- Must use systemd-255 or later, which at the time of writing is not in backports.
- systemd-254's version does not discover initrds in the UKI staging area.
- Install the material in
dracut.conf.d
to/etc/dracut.conf.d/
. - Install the material in
dkms
to/etc/dkms/
.- All modules have to be signed to be loaded by the kernel.
- Re-install the kernel with
kernel-install
to generate the signed UKI.kernel-install add $(uname -r) /boot/vmlinuz-$(uname -r)
- Install systemd-boot in the EFI system partition.
bootctl install
- Reboot.
At this point, secure boot is setup, but we need one more phase to enroll the TPM key to decrypt the root partition. When the system reboots next, systemd-boot will enroll the secure boot material, and you will need to enter the password to decrypt root.
Now that secure boot is enabled, with the system in a trusted state, we can enroll a decryption key for the root partition bound to the TPM. We also replace the easy install password with a recovery key.
WARNING: Do not lose the recovery key! You cannot modify the LUKS partition, including adding or removing other keys, with just a TPM entry.
- Find the device node for the root LUKS partition using
lsblk
or similar tool. - Enroll the new LUKS keys
systemd-cryptenroll /dev/$ROOTDEV --wipe-slot=tpm2 --tpm2-device=auto
systemd-cryptenroll /dev/$ROOTDEV --recovery-key
- Delete the easy installer password
systemd-cryptenroll /dev/$ROOTDEV --wipe-slot=password
- Reboot.