TLDR:
If you do not secure boot with your keys and instead use someone else’s you can not guarantee you are booting securely.
XKCD's very valid opinion about security
For starters, if you boot into your computer with the default Microsoft EFI keys they have been leaked or they were leaked back in 2016. This means that anyone who has access to Microsoft’s keys can hypothetically get the first execution in front of your EFI firmware. The reason this is problematic is that without being the first EFI file to execute you do not necessarily know if there is some in-memory kernel level process that has to fill access to your system. This might not yet be a thing that script kiddies can do or even reasonably advance adversaries, but once it hits it will be hard to detect. This is because if a kernel-level process could hook into the kernel-level process then the kernel-level process could filter what you see so that you do not see the implant.
With understanding the rough challenge that this poses there needs to be a more secure and safer way of going about this. In concept, this is different based on different computers/motherboards. The rough idea is going to be to set up a unified kernel image, set up a key set to sign and verify the kernel in the boot process, set up an automated signing process, and enable bios verification of the kernel image.
- set up a way to create a single file for the boot process
- Create a pair of keys
- add the keys to UEFI
- create an automated way of signing these keys
- get UEFI pre-boot to validate the file it runs with your keys
Programs that will be used and there packages
cert-to-efi-sig-list
This converts openssl certifications to EFI signature lists (file format)
Arch: extra/efitools
efibootmgr
This converts openssl certifications to EFI signature lists (file format)
Arch: core/efibootmgr
openssl
OpenSSL is one of the more popular programs that can generate X.509 certificates (it does more, but irrelevant for this use case)
used arguments:
-days n This is how many days the certifications are available for
-newkey this is the new key’s type fallowed by a colon and how many bits the keys are
-keyout the file to put the newly created private key
-nodes tells the computer to not encrypt the private key
-sha256 changes the digest algorithm to sha256
-in input file to change the format of
-out the output file with the altered encoding
-outform the output file format [DER|PEM]
Arch: core/openssl
sbsign
This is an UEFI file signing tool that a
-key the private key file
-cert the certificate file
-output the newly signed file
Arch: extra/sbsigntools
sbverify
This is an UEFI secure boot verifivation program
--list list all signatures (but don’t verify)
Arch: extra/sbsigntools
sign-efi-sig-list
This generates
Arch: extra/efitools
uuidgen
this generated a UUID in this example the arguments that are used in for this program is --time which gives UUID version 1 or very close that uses the current time and mac address to generate the UUID. If a random UUID was desired it is possible to use the --random
Arch: core/util-linux
Create a Unified Kernel Image
This step should be very easy to do all that is needed is to update one file. To make the boot process look a bit nicer there are a few more steps. Part 1 the need portion
This is the most important part. In order to have EFI files automatically generated it is needed to edit /etc/mkinitcpio.d/linux.preset to have an option that generates the EFI file.
1--- /proc/self/fd/11 2022-06-22 20:29:48.186393990 -0400
2+++ /etc/mkinitcpio.d/linux.preset 2022-06-17 17:40:05.916223661 -0400
3@@ -7,8 +7,11 @@
4
5 #default_config="/etc/mkinitcpio.conf"
6 default_image="/boot/initramfs-linux.img"
7+default_efi_image="/efi/EFI/Linux/archlinux-linux.efi"
8+default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
9 #default_options=""
10
11 #fallback_config="/etc/mkinitcpio.conf"
12 fallback_image="/boot/initramfs-linux-fallback.img"
13-fallback_options="-S autodetect"
14+fallback_efi_image="/boot/archlinux-linux-fallback.efi"
15+fallback_options="-S autodetect --splash /usr/share/systemd/bootctl/splash-arch.bmp"
1efibootmgr --create --disk /dev/sdX --part partition_number --label "label" --loader 'EFI\Linux\file.efi' --verbose
Creating the keys
For generating the keys I based my lines off of the lines of code i seen in the First you have to create yout key pairs that latter gets used to sign unified kernel images.
1openssl req -new -x509 -newkey rsa:4096 -subj "/CN=$NAME PK/" -keyout PK.key \
2 -out PK.crt -days 3650 -nodes -sha256
3openssl req -new -x509 -newkey rsa:4096 -subj "/CN=$NAME KEK/" -keyout KEK.key \
4 -out KEK.crt -days 3650 -nodes -sha256
5
6openssl req -new -x509 -newkey rsa:4096 -subj "/CN=$NAME DB/" -keyout DB.key \
7 -out DB.crt -days 3650 -nodes -sha256
This converts the file to a DER file format since some sets of firmware require this
1openssl x509 -in PK.crt -out PK.cer -outform DER
2openssl x509 -in KEK.crt -out KEK.cer -outform DER
3openssl x509 -in DB.crt -out DB.cer -outform DER
Since most files on the EFI system needs a GUID this creates the GUID
1GUID=`uuidgen --time`
2echo $GUID > myGUID.txt
This converts the keys to the file format that is supported by the
1cert-to-efi-sig-list -g $GUID PK.crt PK.esl
2cert-to-efi-sig-list -g $GUID KEK.crt KEK.esl
3cert-to-efi-sig-list -g $GUID DB.crt DB.esl
This file is latter used to be capable of revoking the the PK certificate
1rm -f noPK.esl
2touch noPK.esl
This converts the files to auth files so that the UEFI firmware can unserstand the keys.
1sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
2 -k PK.key -c PK.crt PK PK.esl PK.auth
3sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
4 -k PK.key -c PK.crt PK noPK.esl noPK.auth
5sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
6 -k PK.key -c PK.crt KEK KEK.esl KEK.auth
7sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
8 -k KEK.key -c KEK.crt db DB.esl DB.auth
This prevents other users from reading the file.
1chmod 0600 *.key
add keys to the EFI system
Automatically sign the EFI file
Two things need to happen. First, thing needed to enable will be creating a pacman hook so that when kernel updates happen a script runs to sign the kernel images. The second thind that needs to happen is to build a script to sign the kernel images.
This first part looks for a new vmlinuz file or looks for a initcpio then it runs the signing script. Since this file starts with 91 it gets ran after the 90-mkinitcpio-install.hook which sets up the EFI files.
1cat << __EOF__ | sudo tee /etc/pacman.d/hooks/91-mkinitcpio-sbsign.hook
2[Trigger]
3Type = Path
4Operation = Install
5Operation = Upgrade
6Target = usr/lib/modules/*/vmlinuz
7Target = usr/lib/initcpio/*
8
9[Action]
10Description = Signing linux kernels...
11When = PostTransaction
12Exec = /usr/local/share/libalpm/scripts/mkinitcpio-sbsign
13NeedsTargets
14__EOF__
This is a simple script that checks that a kernel has changed then it goes to sign the kernel image and puts it in the the EFI directory.
1cat << __EOF__ | sudo tee /usr/local/share/libalpm/scripts/mkinitcpio-sbsign
2#!/bin/bash -e
3
4while read -r line; do
5 if [[ \$line != */vmlinuz ]]; then
6 # triggers when it's a change to usr/lib/initcpio/*
7 continue
8 fi
9
10 if ! read -r pkgbase > /dev/null 2>&1 < "\${line%/vmlinuz}/pkgbase"; then
11 # if the kernel has no pkgbase, we skip it
12 continue
13 fi
14
15 # always sign the kernel
16 if [[ -f /boot/archlinux-\${pkgbase}.efi ]]; then
17 sbsign --key /etc/efi-keys/DB.key --cert /etc/efi-keys/DB.crt --output "/efi/EFI/Linux/archlinux-\${pkgbase}-signed.efi" "/boot/archlinux-\${pkgbase}.efi"
18 fi
19done
20__EOF__
21sudo chmod +x /usr/local/share/libalpm/scripts/mkinitcpio-sbsign
enable secure boot
The best that I can say is that you need to go into your UEFI settings and enable secure boot.