Secure Boot
Secure Boot is a UEFI security feature found in the UEFI standard, designed to add a layer of protection toprotect the pre-boot process:environment byfrom maintainingmalware like bootkits and rootkits, or to strictly enforce which operating systems are permitted to load. By validating bootloaders, kernels, and drivers against a cryptographicallyuser-controlled signed listdatabase of binaries authorized orcryptographic forbidden to run at boot,signatures, it helpsblocks inboth improvingunauthorized thecode confidenceand thatunapproved theoperating machinesystems corefrom boot components (boot manager, kernel, initramfs) have not been tampered with.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
TheThis outputprints looksinformation somethingabout likethe this:current boot environment:
System:
Firmware: UEFI 2.70 (AmericanEDK MegatrendsII 5.17)1.00)
Firmware Arch: x64
Secure Boot: enableddisabled (user) <-- SEE THIS LINE
TPM2 Support: yes
Measured UKI: yesno
Measured OS: no
Boot into FW: supported
Platform Lang: n/a
...
In order to proceed you need to set your firmware's Secure Boot mode into "setup" mode. This can usually be achieved by wiping the key store of the firmware. Refer to your mainboard's user manual on how to do this.
Installation
WARNING:
ForPurging the most straight-forwarddefault Secure Boot toolchainkeys installto 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 everything the system needs into a single file.
mkinitcpio recommends using sbctlukify: for UKI generation but it's an optional dependency that needs to be installed:
pacman -S sbctl--asdeps systemd-ukify
ItIf tremendouslymkinitcpio simplifiesdetects generatingukify Secureon Bootthe keys,system loadingit keysuses intoit firmwareautomatically.
Refer signingto kernelthe images.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) | KEK database. |
| Key Exchange Key (KEK) | db and dbx. |
| Signature Database (db) | |
| Forbidden Signatures Database (dbx) | db. |
Tosystemd-ukify has built-in support for generating Secure Boot keys. It can then use systemd-sbsign to sign the UKIs it generates.
The simplest way of generating keys is supplying ukify with a config file that lists all the keys intended for signing. 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 newthe keys listed in the config file:
ukify genkey --config=/etc/kernel/uki.conf
If mkinitcpio is set up to generate UKIs with ukify it will automatically sign the UKIs it builds during system upgrades from this config.
Signing systemd-boot
The bootloader of a Secure Boot system needs to be signed as well, or the firmware will not authorize its execution when the system boots.
A simple pacman hook takes care of signing the bootloader during installation and storeupgrades, them undere.g. /:var/lib/sbctl/keysetc/pacman.d/hooks/90-systemd-boot-sign.hook
sbctl[Trigger]
create-keysOperation = 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 hook:
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 knows two modes of operation:
integrity: kernel features that allow userland to modify the running kernel are disabled (kexec, bpf)confidentiality: kernel features that allow userland to extract confidential information from the kernel are also disabled
The recommended mode is integrity, as confidentiality can break certain applications (e.g. Docker).
To enable Lockdown Mode, set the lockdown=MODE kernel command line parameter with your preferred mode.
EnrollEnrolling keys in firmware
WARNING: Replacing the platform keys withIf your ownsystem canloads end up bricking your machine, making it impossible to get into the UEFI/BIOS settings to rectify the situation. This is due to the fact that some device firmwareOpROMs (OpROMs, e.g. GPU firmware), thatyou getsneed executedto duringmake boot,sure mayto beeither signed usinginclude Microsoft's keys. Run sbctl enroll-keys --microsoft if you're unsure if this applies to you (enrolling Microsoft's Secure Boot keys alongside your own custom ones) or includethe OpROM's digest value from the TPM Event Log into your firmware signature database. Check for OpROMs with . sbctlfind enroll-keys/sys/devices/ --tpm-eventlogname rom(ifIf there is output, your machinesystem has a TPMOpROMs and you don't need or want Microsoft's keys) to preventtake brickingextra steps to not soft-brick your machine.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.
TIP: If you plan to dual-boot Windows, run sbctl enroll-keys --microsoft to enroll Microsoft'sEnrolling Secure Boot keys alongcan withbe youraccomplished own custom keys.
To enroll your keys, simply:
sbctl enroll-keys
Automated signing of UKIs
sbctl comes with a hook for mkinitcpio which runs after it has rebuilt an image. Manually specifying images to sign is therefore entirely optional.
Signing the Bootloader
NOTE: This is the manual method. If you also want to automate the bootloader update process, skip to the section below.
If you plan on using a boot loader, you will also need to add its *.efi executable(s) to the sbctl database, e.g. systemd-boot:
sbctl sign --save /efi/EFI/BOOT/BOOTX64.EFI
sbctl sign --save /efi/EFI/systemd/systemd-bootx64.efi
Upon system upgrades, pacman will call sbctl to sign the files listed in the sbctl database.
Automateby systemd-boot updates and signing
systemd comes with a systemd-boot-update.service unit file to automate updating the bootloader whenever systemd is updated. However, it only updates the bootloader after a reboot, by which time sbctl has already run the signing process. This would necessitate manual intervention.
Recent versions of bootctl look for a .efi.signed file before a regular .efi file when copying bootloader files during install and update operations. So to integrate better with the auto-updatefollowing functionality of systemd-boot-update.service, the bootloader needs to be signed ahead of time.parameters:
sbctlbootctl sign --saveinstall \
-o-secure-boot-auto-enroll /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signedyes \
--certificate /usr/lib/systemd/boot/efi/systemd-bootx64.efietc/kernel/secure-boot-certificate.pem \
--private-key /etc/kernel/secure-boot-private-key.pem
This willcreates add$ESP/loader/keys/auto/{db,KEK,PK}.auth the sourcefiles and targetinstructs file pathssystemd-boot to sbctl'sattempt database.auto-enrollment Theon pacmannext hook included with sbctl will trigger whenever a file in usr/lib/**/efi/*.efi* changes, which will be the case when systemd is updated and a new version of the unsigned bootloader is written to disk at /usr/lib/systemd/boot/efi/systemd-bootx64.efi.boot.
Finally, enable the systemd-boot-update.service unit:
systemctl enable systemd-boot-update
Now when systemd is updated the signed version of the systemd-bootx64.efi booloader will be copied to the ESP after a reboot, completely automating the bootloader update and signing process!