Skip to main content

Secure Boot

Secure Boot

Secure Boot is a UEFI security feature designed to protect the pre-boot environment from malware like bootkits and rootkits, or to strictly enforce which operating systems are permitted to load. By validating bootloaders, kernels, and drivers against a user-controlled database of authorized cryptographic signatures, it blocks both unauthorized code and unapproved operating systems from executing.

ATTENTION: When using Secure Boot it's imperative to use it with disk encryption. If the storage device that stores the keys is not encrypted, anybody can read the keys and use them to sign bootable images, thereby defeating the purpose of using Secure Boot at all. Therefore, this guide will assume disk encryption is being used.

Preparations

Firmware

To determine the current state of Secure Boot, execute:

bootctl status

This prints information about the current boot environment:

System:
      Firmware: UEFI 2.70 (EDK II 1.00)
 Firmware Arch: x64
   Secure Boot: disabled (user) <-- SEE THIS LINE
  TPM2 Support: yes
  Measured UKI: no
   Measured OS: no
  Boot into FW: supported
 Platform Lang: n/a

...

To proceed, you must set your firmware's Secure Boot mode to Setup Mode (this is usually done by clearing/wiping the default factory keys inside your UEFI settings). Refer to your motherboard's manual for specific instructions.

WARNING: Purging default Secure Boot keys to enroll custom ones can soft-brick your machine! Hardware Option ROMs (OpROMs)—such as your GPU's VBIOS—are typically signed using the Microsoft 3rd Party UEFI CA certificate. If this specific certificate is missing from the signature database (db) when Secure Boot is active, the firmware will block the GPU's OpROM from executing. This results in a black screen during POST, completely disabling display output and locking you out of the UEFI settings needed to revert the change!

Unified Kernel Image

The most practical way to sign images is a Unified Kernel Image, which combines the kernel, initramfs, and kernel command line into a single EFI executable.

mkinitcpio recommends using ukify for UKI generation. Install it as an optional dependency:

pacman -S --asdeps systemd-ukify

If mkinitcpio detects ukify on the system, it will use it automatically. Refer to your local UKI configuration on how to set up UKIs with mkinitcpio.

Refer to the Unified Kernel Image section of initramfs on how to set up UKIs with mkinitcpio.

Generating keys

SEE ALSO: The Meaning of all the UEFI Keys

Secure Boot implementations use these keys:

Key Type Description
Platform Key (PK) Establishes platform ownership and toggles Setup Mode. The private key signs updates to the KEK database.
Key Exchange Key (KEK) Database of certificates authorized to sign updates to db and dbx.
Signature Database (db) Database containing certificates or SHA-256 hashes of allowed EFI binaries, kernels, and Option ROMs.
Forbidden Signatures Database (dbx) Database containing revoked certificates or hashes of banned binaries. Checked first; overrides matches in db.

systemd-ukify has built-in support for generating Secure Boot keys and will use systemd-sbsign to sign the generated UKIs.

To generate the keys, supply ukify with a configuration file. Create /etc/kernel/uki.conf with the following contents:

NOTE: The [PCRSignature] sections are optional. They allow a TPM to unlock a LUKS volume with signed PCR Policies during boot. If you don't intend to use TPM unlocking, you can leave them out.

[UKI]
SecureBootSigningTool=systemd-sbsign
SignKernel=true
SecureBootPrivateKey=/etc/kernel/secure-boot-private-key.pem
SecureBootCertificate=/etc/kernel/secure-boot-certificate.pem

[PCRSignature:all]
PCRPrivateKey=/etc/systemd/tpm2-pcr-private-key.pem
PCRPublicKey=/etc/systemd/tpm2-pcr-public-key.pem

[PCRSignature:initrd]
Phases=enter-initrd
PCRPrivateKey=/etc/systemd/tpm2-pcr-private-key-initrd.pem
PCRPublicKey=/etc/systemd/tpm2-pcr-public-key-initrd.pem

Instruct ukify to generate the keys listed in the config file:

ukify genkey --config=/etc/kernel/uki.conf

When mkinitcpio rebuilds the initramfs during system upgrades it calls ukify with /etc/kernel/uki.conf and will automatically sign the resulting UKIs with the keys listed in that config.

Signing systemd-boot

The bootloader itself must be signed, or the firmware will refuse to execute it.

Create a pacman hook at /etc/pacman.d/hooks/90-systemd-boot-sign.hook to automatically sign systemd-boot during installation and upgrades:

[Trigger]
Operation = Install
Operation = Upgrade
Type = Path
Target = usr/lib/systemd/boot/efi/systemd-boot*.efi

[Action]
Description = Signing systemd-boot EFI binary for Secure Boot
When = PostTransaction
Exec = /bin/sh -c 'while read -r f; do /usr/lib/systemd/systemd-sbsign sign --private-key /etc/kernel/secure-boot-private-key.pem --certificate /etc/kernel/secure-boot-certificate.pem --output "${f}.signed" "$f"; done;'
Depends = sh
NeedsTargets

This takes all .efi binaries in the target path and creates signed .efi.signed copies of them.

Reinstall systemd to invoke the bootloader signing hook and build a signed UKI:

pacman -S --asdeps systemd

To keep the bootloader up-to-date, enable systemd-boot-update.service:

systemctl enable systemd-boot-update

It invokes bootctl update on every boot, checking if a newer version is available for installation, and copies the updated, signed version of the bootloader to the ESP.

Kernel Lockdown Mode

To further strengthen security you might want to consider using the kernel's built-in Lockdown Mode. When engaging lockdown, access to certain features and facilities is blocked, even for the root user. This helps prevent Secure Boot from being bypassed through a compromised system, for example by editing EFI variables or replacing the kernel at runtime.

Lockdown Mode supports two levels:

  • integrity: Disables kernel features that allow userland to modify the running kernel (e.g., kexec, certain eBPF modifications, and raw port access).
  • confidentiality: Additionally blocks userland from extracting confidential information from the kernel space.

To enable Lockdown Mode, set the lockdown= kernel command line parameter with your preferred mode.

Enrolling keys in firmware

WARNING: If your system loads OpROMs (e.g. GPU firmware) you need to make sure to either include Microsoft's keys or the OpROM's digest value from the TPM Event Log into your firmware signature database. Check for OpROMs with find /sys/devices/ -name rom. If there is output, your system has OpROMs and you need to take extra steps to not soft-brick your machine!

ATTENTION: Make sure your firmware's Secure Boot mode is set to setup mode! You can do this by going into your firmware settings and wiping the factory default keys. Additionally, keep an eye out for any setting that auto-restores the default keys on system start.

systemd-boot is capable of enrolling Secure Boot keys. To instruct it to do so automatically on next boot:

bootctl install \
  --secure-boot-auto-enroll yes \
  --certificate /etc/kernel/secure-boot-certificate.pem \
  --private-key /etc/kernel/secure-boot-private-key.pem

This creates the necessary signature lists inside $ESP/loader/keys/auto/ and triggers native auto-enrollment on reboot.