The Funtoo Linux project has transitioned to "Hobby Mode" and this wiki is now read-only.
Difference between revisions of "Secure Boot"
(Category:HOWTO) |
(→See Also: add NSA pdf) |
||
Line 287: | Line 287: | ||
[https://ruderich.org/simon/notes/secure-boot-with-grub-and-signed-linux-and-initrd Secure Boot with GRUB 2 and signed Linux images and initrds] | [https://ruderich.org/simon/notes/secure-boot-with-grub-and-signed-linux-and-initrd Secure Boot with GRUB 2 and signed Linux images and initrds] | ||
[https://media.defense.gov/2020/Sep/15/2002497594/-1/-1/0/CTR-UEFI-Secure-Boot-Customization-UOO168873-20.PDF NSA pdf detailing the secureboot process] | |||
[[Category:HOWTO]] | [[Category:HOWTO]] |
Revision as of 06:22, January 8, 2023
Introduction
This page describes how to set up secure boot on Funtoo Linux with and without GRUB 2, using genkernel and boot-update. The resulting secure boot chain is:
- The firmware setup is password protected.
- The firmware has UEFI secure boot certificates installed, and you hold the corresponding private keys.
- GRUB is signed by your key registered in the UEFI secure boot signature database.
- GRUB config file, kernels and initramfs images are signed with the PGP key embedded in the GRUB image.
- GRUB requires a password to do anything besides booting, e.g., to edit boot parameters or to use the command line.
Many Linux secure boot guides on the Net recommend using Fedora's "shim" boot loader. I would not recommend it, for the following reasons:
- Shim only checks signatures of the boot loader and kernel, but not the GRUB config file or initramfs, which opens your machine to attacks.
- At the time of writing (early 2019), GRUB's shim support (needed to check kernels) has been committed to the GRUB repository but is not yet in any released version.
- I don't understand the point of MOKs and am not certain about their security model.
That said, shim may be useful if your machine's firmware doesn't allow you to install your own secure boot certificates.
Prerequisites
This guide assumes that:
- You have a bootable rescue medium in case something goes wrong.
- Your machine's firmware allows you to install your own secure boot certificates.
- You have a working Funtoo installation with full disk encryption.
- You are using the GRUB 2 bootloader installed on the EFI boot partition.
- The boot partition is mounted on
/boot
. - The EFI boot partition is separate and is mounted on
/boot/efi
.
Having full disk encryption is critical; without it, the attacker can take out your hard disk and change anything but kernel, initramfs and bootloader.
Generating and Installing Secure Boot Certificates
Enter the firmware setup utility and put secure boot in setup mode.
Install efitools
and sbsigntools
:
root # emerge -av app-crypt/efitools app-crypt/sbsigntools
Decide where you want to keep your keys. You may keep them on the hard disk (not recommended), on another machine or on an external drive.
If you keep the keys on an external drive, be aware that gpg creates a socket for gpg-agent in its config directory, so it should reside on a filesystem that supports sockets (i.e., not FAT) and be mounted read-write for signing.
Create the directory in which you will keep the keys:
root # mkdir -p 700 /path/to/keys root # cd /path/to/keys
Save old secure boot certificates:
root # efi-readvar -v PK -o old_PK.esl root # efi-readvar -v KEK -o old_KEK.esl root # efi-readvar -v db -o old_db.esl root # efi-readvar -v dbx -o old_dbx.esl
Generate new certificates valid for 27 years:
root # openssl req -new -x509 -newkey rsa:2048 -subj "/CN=PK/" -keyout PK.key -out PK.crt -days 10000 -nodes -sha256 root # openssl req -new -x509 -newkey rsa:2048 -subj "/CN=KEK/" -keyout KEK.key -out KEK.crt -days 10000 -nodes -sha256 root # openssl req -new -x509 -newkey rsa:2048 -subj "/CN=db/" -keyout db.key -out db.crt -days 10000 -nodes -sha256
Prepare certificate lists:
root # cert-to-efi-sig-list PK.crt PK.esl root # cert-to-efi-sig-list KEK.crt KEK.esl root # cert-to-efi-sig-list db.crt db.esl
If you want to dual boot preinstalled OSes, add old KEK and db certificates to the new lists:
root # cat old_KEK.esl >>KEK.esl root # cat old_db.esl >>db.esl
Sign the certificate lists:
root # sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth root # sign-efi-sig-list -k PK.key -c PK.crt KEK KEK.esl KEK.auth root # sign-efi-sig-list -k KEK.key -c KEK.crt db db.esl db.auth root # sign-efi-sig-list -k KEK.key -c KEK.crt dbx old_dbx.esl old_dbx.auth
Remount the efivars
partition read-write:
root # mount -o remount,rw /sys/firmware/efi/efivars
Install the certificates into EFI:
root # efi-updatevar -f old_dbx.auth dbx root # efi-updatevar -f db.auth db root # efi-updatevar -f KEK.auth KEK root # efi-updatevar -f PK.auth PK
Create a Rescue Kernel (Optional)
Before you start playing with GRUB, it's a good idea to prepare a kernel that is bootable directly from EFI.
Enable the following kernel configuration variables:
CONFIG_EFI_STUB=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="..."
CONFIG_CMDLINE_OVERRIDE=y
CONFIG_FB_SIMPLE=y
Under Processor type and features:
[*] EFI runtime service support [*] EFI stub support [*] Built-in kernel command line (...) Built-in kernel command string [*] Built-in command line overrides boot loader arguments
Set the value of Built-in kernel command string
to the current kernel command line (from /proc/cmdline
), but delete the rand_id
parameter. (After you run boot-update
, the random id for the new kernel will appear in /etc/boot.d/config/kernel/random.map
.)
Under Device Drivers-->Graphics support-->Frame buffer Devices-->Support for frame buffer devices:
[*] Simple framebuffer support
If you have early microcode, extract it to a temporary location:
root # mount /boot root # mkdir /tmp/early root # cd /tmp/early root # cpio -i </boot/early_ucode.cpio
Compile and install the kernel with integrated initramfs. This command will further modify the kernel config file.
root # genkernel --no-clean --no-save-config --integrated-initramfs --initramfs-overlay=/tmp/early --fullname=rescue all
Sign the kernel with the secure boot key and copy it to the EFI partition:
root # sbsign --key /path/to/db.key --cert /path/to/db.crt -o /boot/kernel-rescue /boot/kernel-rescue root # mount /boot/efi root # cp /boot/kernel-rescue /boot/efi/EFI/Funtoo\ Linux\ \[GRUB\]/rescue.efi
Add the kernel to the EFI boot order. Replace EFIBOOTDEVICE
below with the device mounted on /boot/efi
.
root # efibootmgr -c -l '\EFI\Funtoo Linux [GRUB]\rescue.efi' -L 'Funtoo Linux [Rescue Kernel]' -d /dev/EFIBOOTDEVICE
Shutdown, enter the firmware setup, enable secure boot and boot using the rescue kernel to make sure that it works.
In fact, you can use the scheme above to install new kernels and forego GRUB entirely. The downside is that you won't be able to use the command line, e.g., to enter the single user mode, in case anything goes wrong.
Installing GRUB
Generate a PGP key pair and export the public key:
root # mkdir -m 700 /path/to/gpg root # gpg --homedir=/path/to/gpg --quick-generate-key grub2 default default never root # gpg --homedir=/path/to/gpg --export grub2 >/path/to/grub.pub
Create the initial GRUB config file which will be embedded into the GRUB image:
grub-initial.cfg
- Initial GRUB configset superusers="root"
export superusers
password_pbkdf2 root grub.pbkdf2.sha512.10000.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
set root=ROOTDISK
search --no-floppy --fs-uuid --set FSUUID
configfile /grub/grub.cfg
echo grub.cfg did not boot the system but returned to initial.cfg.
echo Exiting in 10 seconds.
sleep 10
exit
You will have to edit the config file in three places:
- Use
grub-mkpasswd-pbkdf2
to generate a password hash to replace the zeroes. - Replace
ROOTDISK
with the value of theroot
variable from/boot/grub/grub.cfg
. - Replace
FSUUID
with the filesystem UUID from asearch
line in/boot/grub/grub.cfg
.
Mount /boot
and /boot/efi
:
root # mount /boot root # mount /boot/efi
Make a standalone GRUB image. Replace ROOTDISK
below with the same value as above.
root # grub-mkimage -O x86_64-efi -p "ROOTDISK/grub" -c /path/to/grub-initial.cfg -k /path/to/grub.pub -o "/boot/efi/EFI/Funtoo Linux [GRUB]/grubx64.efi" configfile loadenv part_gpt ext2 linux gcry_rsa gcry_sha256 password_pbkdf2 all_video gfxterm videoinfo search minicmd test echo reboot sleep root # sbsign --key /path/to/db.key --cert /path/to/db.crt -o "/boot/efi/EFI/Funtoo Linux [GRUB]/grubx64.efi" "/boot/efi/EFI/Funtoo Linux [GRUB]/grubx64.efi"
Sign some kernel and initramfs images:
root # gpg --homedir=/path/to/gpg -b /boot/kernel-rescue root # gpg --homedir=/path/to/gpg -b /boot/early_ucode.cpio root # gpg --homedir=/path/to/gpg -b /boot/kernel-genkernel-x86_64-4.20.0-gentoo root # gpg --homedir=/path/to/gpg -b /boot/initramfs-genkernel-x86_64-4.20.0-gentoo
You may leave some the kernels or initrd images unsigned for testing.
Edit /etc/boot.conf
:
- Add the rescue kernel (optionally).
- Only
kernel-genkernel-*
in the "Funtoo Linux genkernel" group. - Skip kernels ending with
.sig
. - Allow booting configured kernels without authentication.
/etc/boot.conf
- Boot config fragments"Funtoo Linux rescue" {
menuflags --unrestricted
kernel kernel-rescue
}
"Funtoo Linux genkernel" {
menuflags --unrestricted
kernel kernel-genkernel[-v] -*.sig
initrd initramfs-genkernel[-v]
# params += ...
# ... the rest of the section remains unchanged
}
Generate and sign grub.cfg
, and sign the font used by GRUB:
root # boot-update root # gpg --homedir=/path/to/gpg -b /boot/grub/grub.cfg root # gpg --homedir=/path/to/gpg -b /boot/grub/fonts/unicode.pf2
You should already have the Funtoo Linux [GRUB]
EFI boot entry. If you're not certain, check it with:
root # efibootmgr
If no such entry is found, add it. Replace EFIBOOTDEVICE
below with the device mounted on /boot/efi
.
root # efibootmgr -c -l '\EFI\Funtoo Linux [GRUB]\grubx64.efi' -L 'Funtoo Linux [GRUB]' -d /dev/EFIBOOTDEVICE
Look for the number of the entry and where it appears in the boot order. If it's not the first, you may want to change the boot order. Copy the BootOrder
line from the efibootmgr
output and rearrange the numbers to your liking:
root # efibootmgr -o 0001,0002,0000,0018,0019,001A,001B,001C,001D,001E,001F,0024
Shutdown, enter the firmware setup, enable secure boot and make sure that everything works. Particularly:
- You can boot the system without entering a password.
- You can not boot unsigned EFI images.
- You can not boot unsigned kernels or load unsigned initramfs images.
- If you try to edit kernel parameters or drop to the GRUB command line, you get a password prompt.
Set Up the Firmware Password
Shutdown, enter the firmware setup and enable the password. While you're there, look at the security-related options.
See Also
Secure Boot with GRUB 2 and signed Linux images and initrds NSA pdf detailing the secureboot process