2024-07-05_Fedora-40-Signed-UKIs

Akaza Akari, smiling, heart near left eye, greets visitor

2024-07-05 | Fedora 40 and signed UKIs

Warning: This post is intended for advanced Linux users.

About Secure Boot

Secure Boot is an UEFI feature which allows only signed EFI executables to be loaded. By default most computers have pre-loaded Microsoft's keys. Of course, Windows boot facilities are signed by these.

Some Linux distributions ship with a preloader called shim for licensing reasons.

But the shim solution only allows to load these distributions without messing with secure boot. But what if you encrypt your data. They may be safe from being accessed, but it's still possible to mess with your kernel or initramfs, usually stored on unencrypted partition.

To solve this, we can pack kernel, initramfs and kernel cmdline parameters into a single EFI executable called Unified Kernel Image (UKI) and sign it with our keys. If we replace the Microsoft keys in firmware with our owns, we can be sure (ofc. unless some bug or backdoor occures) that only executables signed by our keys can be loaded.

I tried this on Arch Linuxbtw which is fairly trivial.

But I also wanted to try this on Fedora, a distribution which isn't that DIY friendly as Arch Linuxbtw is. So here it is.

For this, we are going to use

For existing installations

If you already do have a Fedora installation, you can just skip the installation, do firmware setup and then skip to Setting up secure boot

You may need to perform some adjustments. For example partitioning, in case your EFI partition is too small (tip: /boot partition is unnecessary in this setup).

Getting Fedora

This article uses Fedora 40 Workstation. These procedures may be outdated in next releases.

First of all, download and write the Fedora Workstation image. You can obtain it and read how to verify and write it here.

Installation

Here, I will be showing how to install Fedora using typical methods and then modifying the installed system, so most of the typical installation applies.

Firmware setup

First of all, we need to configure secure boot to be ready for custom keys. Entering firmare setup is usually done by pressing specific key, often shown on POST screen.

On systemd Linux system you can try systemctl reboot --firmware-setup

Then, you need to switch secure boot to Setup Mode. Sadly, this process varies across firmware setups and often isn't even marked as such. I recommend consulting a documentation or searching online.

Partitioning

  1. Select Full disk summary and bootloader… in bottom left corner
  2. Select your target disk
  3. Press Do not install bootloader to remove the Boot check

Now create an EFI partition. There the signed bootloader and UKIs are going to be stored.

  1. Select Blivet GUI and click Done
  2. Create a new partition
    • Filesystem: EFI System Partition
    • Mountpoint: /boot/efi
    • Size: 1 GiB

For root partition, I recommend using LUKS2 to encrypt the partition as secure boot would otherwise be pointless. Fedora by default uses BtrFS. The default layout looks like:

Setting up secure boot

Open a console and enter /mnt/sysroot

$ sudo chroot /mnt/sysroot

Then install sbctl, tools for signing the UKIs with Dracut, and setup the keys.

# dnf copr enable chenxiaolong/sbctl # dnf install sbctl sbsigntools # ln -s /dev/null /etc/kernel/install.d/91-sbctl.install # sbctl create-keys Created Owner UUID cd977b6b-34f6-4a2a-aba2-50500da4efce Creating secure boot keys...✓ Secure boot keys created!

Bootloader and UKIs

First, let's uninstall GRUB as we are going to use systemd-boot. And remove kernel and initramfs (and related stuff) as we are going to build our own UKIs.

# dnf --setopt=protected_packages= rm grub\* # kernel-install remove $(ls /usr/lib/modules) # rm -rf /boot/{efi/EFI,grub2,loader,vmlinuz*,initramfs*,symvers*,config*,System*,.vmlinuz*}

Now let's install and sign systemd-boot

# dnf in systemd-boot # sbctl sign -s /usr/lib/systemd/boot/efi/systemd-bootx64.efi -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed # bootctl install

Setting up UKI building

Now configure ``kernel-install` not to install kernel or care about that and leave it for Dracut. Then we update and configure Dracut to build UKIs.

# dnf up dracut # echo "layout=other" >> /etc/kernel/install.conf # cat << EOF > /etc/dracut.conf.d/20-uki.conf uefi=yes uefi_secureboot_cert=/usr/share/secureboot/keys/db/db.pem uefi_secureboot_key=/usr/share/secureboot/keys/db/db.ke dracut_rescue_image=no EOF

Kernel cmdline

Now it's time to set kernel cmdline parameters. These are by default stored in /etc/kernel/cmdline

  1. Read /etc/kernel/cmdline. If it contains newlines, replace them with spaces.
  2. Edit /etc/dracut.conf.d/10-cmdline.conf
  3. Paste the parameters inside kernel_cmdline+=" HERE " (including the spaces)

Fwupd and reinstalling kernel

Now let's configure fwupd, utility for updating firmware. It updates UEFI firmware by running an EFI executable which performs the update. There is already a signed one, not sure with which keys, but anyways, we are going to sign it with our owns.

We are also going to configure fwupd so it works with out custom keys + systemd-boot configuration.

  1. Edit /etc/fwupd/fwupd.conf.
  2. If not exists, create section [uefi_capsule]
  3. These, set EnableGrubChainLoad=false
  4. Also set DisableShimForSecureBoot=false

# sbctl sign -s /usr/libexec/fwupd/efi/fwupdx64.efi.signed # dnf rei kernel-core

Optionally, you can also edit /boot/efi/loader/loader.conf to eg. add bootmenu timeout.

Now you can exit the chroot and reboot your computer.

Enrolling keys

In order to firmware to check the executables, we need to enroll the keys to the firmware. Open a console in installed system after setting it up and run following command:

$ sudo sbctl enroll-keys

In the key enrollment process, sbctl can present you an error message that with custom keys only, OptionROMs may not load. You can use one of these arguments to deal with it:

On my desktop computer, when trying this with Arch Linuxbtw I went with the TPM eventlog option and everything worked fine. On my laptop as no OptionROMs are used, it didn't ask me at all.

And we are done!

Fedora GNOME desktop, fresh install. Two console windows. Left has bootctl output, proves secure boot and systemd-boot. Right has sbctl status output. Proves secure boot is enabled, not in setup mode, no vendor keys

Author's notes

This is my first post here! Yaay, finally after long time I wrote something. In big part at the instigation of songandsilence3 on Fedora Discord. Tried to make the thing structured for easy reading. And also, I kinda suck at writing, so I hope it wasn't that terrible :D

For the thing itself. Ooof. I tried many things. It was quite difficult to figure out how to make it work. And to make it clean, without writing or installing custom scripts.

I initially wanted to use systemd-ukify as I did on Arch, but then it didn't know how to generate initramfs so I ended up with UKI with only kernel and cmdline. I tried to make to use Dracut as UKI generator but Fedora's kernel-install script for Dracut doesn't support it. So eventually I went with generating UKIs plainly with Dracut like here.

Also taking some stuff from the mentioned article, I also researched on Arch Wiki (that thing's great even for non-Arch uses!) or in what was already implemented for UKIs in Fedora.

Written right next to my Warthunder playing girlfriend. I should play something too, I am pretty exhausted. Or go to bed (with my laptop ofc).

Update: I messed up some stuff a bit. Article updated on 2024-07-10

Written by Erin, 2024-07-05, took her few hours.