====== UEFI Secure Boot ======
===== Why =====
* Currently the only protection against EvilMaid attacks.
* LUKS isnt that useful if someone modifies your initrd from an USB-stick and saves your password for cryptsetup somewhere in /boot
===== How =====
There are multiple ways to get to a SecureBoot Linux. Starting from selfsigned EFI-Stub kernels, booting directly from UEFI to a chain of UEFI -> SHIM -> GRUB2 -> Linux
==== Current plan ====
Using only EFI-Stub kernels isnt that elegant, because we would need to change the EFI-Boot-Config everytime. So we want a bit more flexibility, without having to chainload from SHIM to GRUB.
- UEFI
- Signed [[https://www.freedesktop.org/wiki/Software/systemd/systemd-boot/|systemd-boot]]
- Signed BLOB of Kernel + Initrd + Commandline
==== Getting there ====
=== first steps: new bootloader and EFI-stub-kernel ===
First we will change the bootloader and ensure that we can load an unsigned EFI-Stub-kernel, then we will create a signable BLOB
== installing systemd-boot ==
The EFI System Partition (ESP) needs to be mounted, and the efivars need to be readable
bootctl --path=/boot/efi/ install
== New EFI-bootable kernel image ==
cd /usr/src/linux
make menuconfig
# set CONFIG_EFI_STUB=y
make -j6 && make modules_install
cp ./arch/x86/boot/bzImage /boot/efi/kernel.efi
#also, new initrd
dracut /boot/efi/initramfs.img --force --xz -H 4.14.0-rc7 --omit "i18n" --add-drivers i915
== Add the new kernel to the systemd-boot list ==
timeout 3
default gentoo
title Gentoo
linux /kernel.efi
initrd /initramfs.img
options root=/dev/mapper/cryptroot ro rootflags=subvol=rootfs init=/lib/systemd/systemd rd.luks.allow-discards log_buf_len=4M
== test the new bootloader and EFI-kernel ==
Try to boot the new kernel with systemd-boot. If something goes wrong, you can just use the previous bootloader (in most cases GRUB2) by selecting it in the UEFI boot menu.
=== preparing for secure boot: creating keys ===
I got most of the commands for the keygeneration and the key-entry from the wonderful [[https://wiki.gentoo.org/wiki/Sakaki%27s_EFI_Install_Guide/Configuring_Secure_Boot|Sakaki's EFI Install Guide]] - which is really good and explains what is going on in great depth. Look at his page if you want to know the details.
== key and signature list generation ==
We generate the PK (Plattform Key), KEK (Key Exchange Key) and a DB (Signature Database) certs and keys. The DB will be used to sign our kernel, however, the PK needs to sign the KEK and the KEK will sign the DB key. Also, we get the current keys from EFI and create merged signature lists - so that we can keep the Microsoft Keys if we want to.
mkdir /etc/efikeys; chmod 400 /etc/efikeys; cd /etc/efikeys
#create new keys - save the passwords somewhere save, and create a backup of the keys.
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=brot PK/" -keyout PK.key -out PK.crt -days 3650 -sha256
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=brot KEK/" -keyout KEK.key -out KEK.crt -days 3650 -sha256
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=brot DB/" -keyout db.key -out db.crt -days 3650 -sha256
#get current state of the key-databases
efi-readvar -v PK -o old_PK.esl
efi-readvar -v KEK -o old_KEK.esl
efi-readvar -v db -o old_db.esl
#for insertion into the UEFI we need siglists
cert-to-efi-sig-list -g "$(uuidgen)" PK.crt PK.esl
sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth
cert-to-efi-sig-list -g "$(uuidgen)" KEK.crt KEK.esl
sign-efi-sig-list -a -k PK.key -c PK.crt KEK KEK.esl KEK.auth
cert-to-efi-sig-list -g "$(uuidgen)" db.crt db.esl
sign-efi-sig-list -a -k KEK.key -c KEK.crt db db.esl db.auth
#create compound-signature-lists - so that we preserve the Microsoft and OEM Keys.
cat old_KEK.esl KEK.esl > compound_KEK.esl
cat old_db.esl db.esl > compound_db.esl
sign-efi-sig-list -k PK.key -c PK.crt KEK compound_KEK.esl compound_KEK.auth
sign-efi-sig-list -k KEK.key -c KEK.crt db compound_db.esl compound_db.auth
== changing to setup mode/clearing the keys and inserting keys ==
Go in the UEFI-Setup, navigate to the Secure Boot settings. There should be a option to either enter "Setup Mode" or "Clear all Keys" - or both. Clearing all keys will automatically enter setup mode. Then, reboot to insert the keys.
# Variant: Keep OEM and Microsoft keys
efi-updatevar -e -f compound_db.esl db
efi-updatevar -e -f compound_KEK.esl KEK
efi-updatevar -f PK.auth PK
# Variant: Only own keys
efi-updatevar -e -f db.esl db
efi-updatevar -e -f KEK.esl KEK
efi-updatevar -f PK.auth PK
After the PK has been set, the system should switch to "User Mode"
== building a new kernel and signing it ==
Thanks to [[https://bentley.link/secureboot/|Matthew Bentley's blog]], i have found the objtool method of combining the kernel, initramfs and options into one large blob which can be signed.
cd /usr/src/linux
dracut ./initramfs.img --force --no-compress -H 4.14.0-rc8 --omit "i18n" --add-drivers i915
cat /proc/cmdline > cmdline.txt
objcopy --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 --add-section .cmdline="cmdline.txt" --change-section-vma .cmdline=0x30000 --add-section .linux="./arch/x86/boot/bzImage" --change-section-vma .linux=0x40000 --add-section .initrd="./initramfs.img" --change-section-vma .initrd=0x3000000 /usr/lib/systemd/boot/efi/linuxx64.efi.stub kernel.efi
sbsign --key db.key --cert db.crt --output /boot/efi/kernel-signed.efi kernel.efi
We need to add this new kernel as a new boot-entry in systemd-boot
title Kernel signed
linux /kernel-signed.efi
Also, we need to sign the systemd-boot bootloader
#sign the bootloader
cp /boot/efi/EFI/systemd/systemd-bootx64.efi /boot/efi/EFI/systemd/systemd-bootx64.efi.org
sbsign --key db.key --cert db.crt --output /boot/efi/EFI/systemd/systemd-bootx64.efi /boot/efi/EFI/systemd/systemd-bootx64.efi.org
Everything should be prepared for the first Secure boot :)
=== First secure boot ===
Even after the "User Mode" has been enabled, Secure Boot itself should still be disabled. We should change that in the UEFI setup, and try to boot the signed bootloader and the signed kernel-initramfs-blob. If everything works now, good job, you can now secure boot.
:!: **If you have no password for the UEFI setup, Secure Boot can just be disabled. So, for Secure Boot to be effective, set a reasonable safe password for the UEFI Setup.** :!:
=== Creating new kernel ===
Now, with Secure Boot working, we want a faster method of creating new kernels and signing those. I use the following command line to generate new kernels.
export KVER=`make kernelversion` && make -j6 && make modules_install && dracut ./initramfs.img --force --no-compress -H $KVER --omit "i18n" --add-drivers i915 && \
cp /proc/cmdline ./cmdline.txt && objcopy --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 --add-section .cmdline="./cmdline.txt" \
--change-section-vma .cmdline=0x30000 --add-section .linux="./arch/x86/boot/bzImage" --change-section-vma .linux=0x40000 --add-section .initrd="./initramfs.img" \
--change-section-vma .initrd=0x3000000 /usr/lib/systemd/boot/efi/linuxx64.efi.stub kernel-$KVER.efi && \
sbsign --key /root/efi-keys-try1/db.key --cert /root/efi-keys-try1/db.crt --output ./kernel-$KVER-signed.efi ./kernel-$KVER.efi && mount /boot/efi && \
cp ./kernel-$KVER-signed.efi /boot/efi/ && echo -e "title Gentoo Linux signed\nversion $KVER\nlinux /kernel-$KVER-signed.efi" > /boot/efi/loader/entries/gentoo-$KVER.conf
The new kernel will then be the next default startup if systemd-boot has the following config
timeout 3
default gentoo-*
==== Helpful Information ====
This stuff is copied from other blogs/Websites, and has been of use.
=== Signing EFI Binaries ===
sbsign --key db.priv --cert db.pub --output signed_binary.efi binary.efi
Taken from: https://docs.slackware.com/howtos:security:enabling_secure_boot
sbsign --key test-key.rsa --cert test-cert.pem --output grubx64.efi /boot/efi/efi/ubuntu/grubx64.efi
cp /boot/efi/efi/ubuntu/grubx64.efi{,.bak}
cp grubx64.efi /boot/efi/efi/ubuntu/
Taken from https://wiki.ubuntu.com/UEFI/SecureBoot
=== Generating own Keys ===
openssl genrsa -out test-key.rsa 2048
openssl req -new -x509 -sha256 subj '/CN=test-key' -key test-key.rsa -out test-cert.pem
openssl x509 -in test-cert.pem -inform PEM -out test-cert.der -outform DER
Taken from https://wiki.ubuntu.com/UEFI/SecureBoot
The easiest way is to use the x509 CA creation command
openssl req -new -x509 -newkey rsa:2048 -keyout PK.key -out PK.crt -days -subj “/CN=/”
Will create two files, PK.crt (which is the public certificate we’ll use as the UEFI key) and PK.key which is the private signing key (note: the UEFI spec mandates that all X509 keys be 2048 bit rsa keys). Fill in with how long you want the certificate to be valid for and with whatever information you want the common name to be (UEFI doesn’t use this, but it’s customary for every X509 certificate to have at least a common name). We’re still not quite done, because the keys must be in DER form. Conversion is done like this
openssl x509 -in PK.crt -out PK.cer -outform DER
Note that the .cer extension is what tells UEFI that the file contains an x509 key, so you must use it.
Taken from https://blog.hansenpartnership.com/uefi-secure-boot/
=== dependencies (on gentoo) ===
emerge -av pesign efitools
Also, systemd needs the "gnuefi" USE-Flag
=== More links ===
https://www.rodsbooks.com/efi-bootloaders/controlling-sb.html#creatingkeys
https://wiki.gentoo.org/wiki/Sakaki%27s_EFI_Install_Guide/Configuring_Secure_Boot#Testing_Secure_Boot_with_a_Signed_Kernel
http://kroah.com/log/blog/2013/09/02/booting-a-self-signed-linux-kernel/
https://bentley.link/secureboot/
https://wiki.ubuntu.com/SecurityTeam/SecureBoot/
https://github.com/haraldh/mkrescue-uefi/blob/master/mkrescue-uefi.sh
http://www.lightofdawn.org/blog/?viewDetailed=00163