Date Tags linux / lkm


success

For Windows PCs, it's very likely that they are already configured to use secure boot. The main benefit of secure boot for desktop users is they are protected from malicious code that hijacks the boot process of Windows OS, known as "bootkit".

If you want protection from physical threat (that can access your PC physically), you will also need to set a BIOS password otherwise attackers can turn off secure boot easily.

Distros like Fedora sign their EFIs using Microsoft keys so it works out of box. But we can always opt to use our own keys, which is very easy, I will show you the steps:

Secure Boot using your own keys

  1. Enter BIOS secure boot settings, switch to "setup mode" then reboot to Linux
  2. Use sbctl:
# Enable setup mode in BIOS, then you should see this
$ sbctl status
Installed:  ✘ Sbctl is not installed
Setup Mode: ✘ Enabled
Secure Boot:    ✘ Disabled

# create PK/KEK keys, find them in `/usr/share/secureboot`
$ sbctl create-keys
Created Owner UUID a9fbbdb7-a05f-48d5-b63a-08c5df45ee70
Creating secure boot keys...✔
Secure boot keys created!

# enroll keys
$ sbctl enroll-keys
Enrolling keys to EFI variables...✔
Enrolled keys to the EFI variables!

# find EFIs that can be signed
$ sbctl verify
Verifying file database and EFI images in /efi...
✘ /boot/vmlinuz-linux is not signed
✘ /efi/EFI/BOOT/BOOTX64.EFI is not signed
✘ /efi/EFI/BOOT/KeyTool-signed.efi is not signed
✘ /efi/EFI/Linux/linux-linux.efi is not signed
✘ /efi/EFI/arch/fwupdx64.efi is not signed
✘ /efi/EFI/systemd/systemd-bootx64.efi is not signed

# sign the EFIs
# files will be different on your own machine, just sign them all
$ sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI
✔ Signed /efi/EFI/BOOT/BOOTX64.EFI...

$ sbctl sign -s /efi/EFI/arch/fwupdx64.efi
✔ Signed /efi/EFI/arch/fwupdx64.efi...

$ sbctl sign -s /efi/EFI/systemd/systemd-bootx64.efi
✔ Signed /efi/EFI/systemd/systemd-bootx64.efi...

$ sbctl sign -s /usr/lib/fwupd/efi/fwupdx64.efi -o /usr/lib/fwupd/efi/fwupdx64.efi.signed
✔ Signed /usr/lib/fwupd/efi/fwupdx64.efi...

# make sure all EFIs are signed
$ sbctl verify
Verifying file database and EFI images in /efi...
✔ /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
✔ /efi/EFI/BOOT/BOOTX64.EFI is signed
✔ /efi/EFI/arch/fwupdx64.efi is signed
✔ /efi/EFI/systemd/systemd-bootx64.efi is signed
✘ /boot/vmlinuz-linux is not signed
✘ /efi/EFI/BOOT/KeyTool-signed.efi is not signed
✘ /efi/EFI/Linux/linux-linux.efi is not signed

# now reboot, enter BIOS then enable secure boot
# you should be able to boot into Linux using your own signed EFIs

Run sbctl sign-all if anything needs to be signed again.

How to sign kernel modules

Now you have enabled secure boot, and your machine can boot the OS with your own signed EFI binaries. But wait, off-tree kernel modules are not loaded!

Yeah, why? Because considering how secure boot is implemented in Linux world, your modules need to be signed as well, otherwise it won't be picked up by SHIM. You can take a look at the picture at the begining of this post.

Multiple Linux distributions have implemented UEFI Secure Boot, but this creates problems deploying 3rd party modules and custom-built kernels alongside components signed by the UEFI Certificate Authority (CA). The Machine Owner Key (MOK) concept can be used with a signed shim loader to enable key management at the user/sysadmin level.

Specifically, Fedora provides some tools to add your own key as MOK, so you can sign your modules easily.

# if your key is in PEM format, convert it to DER first
$ openssl x509 -in my_signing_key_pub.pem -out my_signing_key_pub.der -outform DER

# import as MOK
$ mokutil --import my_signing_key_pub.der

# You will be asked to enter and confirm a password for this MOK enrollment request.
# Reboot the machine.

Once a key is on the MOK list, it will be automatically propagated to the system key ring on this and subsequent boots when UEFI Secure Boot is enabled.

Sign your modules and EFIs using this script:

# sign modules
signer="/usr/src/kernels/$(uname -r)/scripts/sign-file"
mod_dir="/lib/modules/$(uname -r)/extra/nvidia"
key="/usr/share/secureboot/keys/KEK/KEK.key"
cert="/usr/share/secureboot/keys/KEK/KEK.pem"

for mod in "$mod_dir/"*; do
    modinfo "$mod" | grep signer || {
        xz -d "$mod"
        mod_decompressed="${mod%.*}"
        "$signer" sha256 "$key" "$cert" "$mod_decompressed"
    }
done

# sign EFIs
/usr/local/sbin/sbctl sign-all

Comments

comments powered by Disqus