Skip to main content

·540 words·3 mins
Vimal A R
Author
Vimal A R
Still figuring it out!

Secure boot with QEMU and UEFI
#

https://www.labbott.name/blog/2016/09/15/secure-ish-boot-with-qemu/

(Edit 9/21: I've gotten some feedback and clarifications about a few steps and also updated the wiki. Thanks to the OVMF developers!)

Despite having too many machines in my possession, none of the x86 machines I have are currently set up to boot with UEFI. This put a real damper on my plans to poke at secure boot. Fortunately, there is virtualization technology to solve this problem. I really like being able to boot kernels directly without a full VM image. There are some instructions for getting started but they are a bit incomplete for what I wanted to do. This is what I used to get secure boot working (or at least detected) in QEMU. I make no guarantees about it actually being secure or signed correctly but it's a starting point for experiments.

The secure boot firmware is available as part of the standard Fedora package.

1$ sudo dnf install edk2-ovmf

You need to tell QEMU to pick up the firmware and emulate a file for storing EFI variables. The firmware used here is going to be OVMF_CODE.secboot.fd.

1$ cp /usr/share/edk2/ovmf/OVMF_VARS.fd my_vars.fd

This creates a copy of the base variables file for modification and use. The options you need to append to QEMU are (with some comments in #)

 1# required machine type
 2-machine q35,smm=on,accel=kvm
 3# Due to the way some of the models work in edk2, we need to disable
 4# s3 resume. Without this option, qemu will appear to silently hang
 5# althouh it emits an error message on the ovmf_log
 6-global ICH9-LPC.disable_s3=1
 7# Secure!
 8-global driver=cfi.pflash01,property=secure,value=on
 9# Point to the firmware
10-drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd,readonly=on
11# Point to your copy of the variables
12- drive if=pflash,format=raw,file=/home/labbott/my\_vars.fd

I added these to the existing command I had for QEMU. I bumped the memory on the KVM command line to 500 as well (-m 500). If all goes well, you should be able to boot a kernel and have it detect EFI (dmesg | grep EFI) with this setup.

To actually enable secure boot, we need to run an EFI program to load a set of certificates. The default Fedora build provides a nice .iso with the UEFI shell and EFI application built in, /usr/share/edk2/ovmf/UefiShell.iso. Add -hda /usr/share/edk2/ovmf/UefiShell.iso to your QEMU command and remove the -kernel and -initrd options. If all goes well, you should be dropped into the UEFI shell. You can now run the command to add keys

1Shell> FS0:
2FS0:\> EnrollDefaultKeys.efi

Your vars file should now be all set up for secure boot. If you boot with a -kernel and -initrd option, you should be able to boot a kernel and have it detect secure boot (dmesg | grep Secure).

Booting your own kernels isn't too difficult. If you take a tree that has secure boot patches in it, make sure the following set of options is enabled

 1CONFIG_SYSTEM_DATA_VERIFICATION=y
 2CONFIG_SYSTEM_BLACKLIST_KEYRING=y
 3CONFIG_MODULE_SIG=y
 4CONFIG_MODULE_SIG_ALL=y
 5CONFIG_MODULE_SIG_UEFI=y
 6CONFIG_MODULE_SIG_SHA256=y
 7CONFIG_MODULE_SIG_HASH="sha256"
 8CONFIG_ASN1=y
 9CONFIG_EFI_STUB=y
10CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE=y
11CONFIG_ASYMMETRIC_KEY_TYPE=y
12CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
13CONFIG_X509_CERTIFICATE_PARSER=y
14CONFIG_PKCS7_MESSAGE_PARSER=y
15CONFIG_SIGNED_PE_FILE_VERIFICATION=y
16CONFIG_EFI_SIGNATURE_LIST_PARSER=y
17CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
18CONFIG_SYSTEM_TRUSTED_KEYRING=y
19CONFIG_SYSTEM_TRUSTED_KEYS=""

This will be enough for the kernel to detect that secure boot is enabled and let you experiment with things. You can even issue your own pesign command

1$ pesign -c 'Red Hat Test Certificate' --certdir /etc/pki/pesign-rh-test -i arch/x86/boot/bzImage -o vmlinuz.signed -s