banner
amtoaer

晓风残月

竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生。
github
x
telegram
steam
nintendo switch
email

Configuring Secure Boot for Arch Linux

Recently, I configured secure boot for my Arch Linux and I'm documenting the process and issues I encountered here.

Implementing Secure Boot

The implementation methods for secure boot are described in detail in the Arch Wiki. However, the wiki format can make the process description complex. This section aims to provide a simplified method for implementing secure boot, skipping the more detailed conceptual content.

Note: This article only describes setting up secure boot for Arch Linux. For further implementation and coexistence with Windows secure boot, please refer to the corresponding entry in the Arch Wiki here.

Generating Keys

The implementation of secure boot involves four types of keys:

  • Platform Key (PK)
  • Key Exchange Key (KEK)
  • Signature Database (db)
  • Forbidden Signatures Database (dbx)

To use secure boot properly, we need at least the first three keys. To simplify the process, we can use a script to generate them:

# The sbupdate tool, which automatically handles kernel updates, etc., uses the keys located in /etc/efi-keys by default.

# To make it easier, we'll create this directory and generate the keys in it.

mkdir /etc/efi-keys
cd !$
curl -L -O https://www.rodsbooks.com/efi-bootloaders/mkkeys.sh
chmod +x mkkeys.sh
./mkkeys.sh
<Enter any name to embed in the key, for example "Secure Boot">

Automatic Signing

To automatically sign during kernel and bootloader updates, we can use the sbupdate tool.

Installation

Install it using the following command:

yay -S sbupdate-git

Configuration

After installation, we need to configure sbupdate by specifying the content that needs to be automatically signed.

Open /etc/sbupdate.conf and modify the configuration file. Here's an example of my settings and their explanations:

# Directory where the keys are located
KEY_DIR="/etc/efi-keys"
# Location of the EFI boot partition
ESP_DIR="/boot"
# Location to generate separate EFI boot files
OUT_DIR="EFI/Linux"
# Default kernel parameters carried by the generated separate EFI boot files
CMDLINE_DEFAULT="loglevel=3 quiet nomce rw"
# Additional files that need to be signed, usually including your own bootloader files
# The kernel is theoretically signed automatically, but for some reason my vmlinuz-linux-zen doesn't work, so I also put the kernel file here
EXTRA_SIGN=('/boot/EFI/BOOT/BOOTX64.EFI' '/boot/EFI/systemd/systemd-bootx64.efi' '/boot/vmlinuz-linux-zen')

# Individual kernel configurations
INITRD["linux-zen"]="/boot/initramfs-linux-zen.img"
# If no kernel parameters are configured, the CMDLINE_DEFAULT above will be used by default
CMDLINE["linux-zen"]="root=PARTUUID=db9157b1-bed4-fa44-a715-5c1bfc8bdfb4 quiet nomce loglevel=3 rw"

Here's a special note about individual kernel configurations:

sbupdate generates a separate boot file for each kernel (${ESP_DIR}/${OUT_DIR}/${kernel_name}-signed.efi), which includes kernel parameters and temporary file system configurations (corresponding to CMDLINE[${kernel_name}] and INITRD[${kernel_name}] in the configuration file).

There are three ways to boot using this file:

  1. Use the existing configuration of a boot loader (such as grub/systemd-boot, etc.)
  2. Boot directly using this file
  3. Use a boot loader to indirectly boot using this file

Most users typically use the first method. If this method works fine, there is no need to use the separate boot file. In other words:

You can ignore the OUT_DIR, CMDLINE_DEFAULT, and individual kernel configuration mentioned above.

Signing

After the initial configuration, you need to manually execute the signing command:

sudo sbupdate

In the future, this tool will automatically sign during kernel updates.

Special handling for automatic signing with systemd-boot

For other boot methods, the above configuration method may be sufficient. However, if you use systemd-boot as the boot loader, further configuration may be required.

Handling of hook execution order

Regarding this situation:

In general, we only need to use pacman hooks to update the signature when updating the kernel or systemd. However, when using systemd-boot, we also need to update the bootloader when updating systemd (i.e., sudo bootctl update, which replaces /boot/EFI/BOOT/BOOTX64.EFI and /boot/EFI/systemd/systemd-bootx64.efi with the latest versions). Therefore, the execution order of hooks becomes a big issue - we need to ensure that the bootloader update occurs before the signing process.

Users who use systemd-boot are probably familiar with the automatic update method using pacman hooks (see systemd boot - Automatic Updates). The document provides two methods:

  1. Install systemd-boot-pacman-hook (which essentially downloads systemd-boot.hook)
  2. Manually write the given content to /etc/pacman.d/hooks/100-systemd-boot.hook.

As per the alpm-hooks documentation:

Hooks are run in alphabetical order of their file name, where the ordering ignores the suffix.

According to this rule, neither the systemd-boot.hook obtained from method 1 nor the 100-systemd-boot.hook written in method 2 can meet the requirement of executing before the signing hook. My solution is to use method 2 but rename the file to 90-systemd-boot.hook to satisfy the order requirement.

Handling of additional signing for the boot loader

We have solved the first obstacle, but don't worry, there's another issue here.

We have listed the boot loader files that need to be additionally signed in sbupdate's EXTRA_SIGN. However, if you look at the 66-72 lines and 195-205 lines of the sbupdate source code, you'll see that the -k parameter indicates that sbupdate is called by a hook. For security reasons, when sbupdate is called by a hook, it skips the content in EXTRA_SIGN, which is obviously not what we expect.

The solution is simple. Open /usr/share/libalpm/hooks/95-sbupdate.hook and remove the -k parameter.

Writing Keys to the BIOS

After completing the above steps, we are almost there. The last step is to write the keys to the BIOS.

Deleting existing keys

By default, the BIOS comes with Microsoft keys. To write our own keys, we need to delete the existing keys.

In this step, you need to enter the BIOS, find the certificate management option for secure boot, and choose to delete the keys.

Writing new keys

Use sbsigntools to simplify the process of writing keys.

First, we need a directory like this:

/etc/secureboot/keys
├── db
├── dbx
├── KEK
└── PK

Create it using the following command:

mkdir -p /etc/secureboot/keys/{db,dbx,KEK,PK}

Then copy the *.auth files from /etc/efi-keys to the corresponding directories (it's normal if dbx doesn't exist).

Finally, execute the following commands:

sbkeysync --verbose
sbkeysync --verbose --pk

If you're lucky and there are no errors, congratulations! You have completed the configuration of secure boot for Arch Linux. Now you just need to enable the secure boot option in the BIOS and start it!

Conclusion

In this article, I have listed all the steps I took to configure secure boot for my machine. However, I cannot guarantee that readers will be able to reproduce my successful steps.

If you encounter any errors while performing the steps in this article, I recommend referring to the original Arch Wiki. The original article includes multiple implementation methods for the same step and provides detailed error handling, making it more representative than this article.

References

  1. security boot - Arch Wiki
  2. systemd boot - Arch Wiki
  3. sbupdate Readme.md - GitHub
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.