Secure(ish) boot with QEMU

| categories: fedora

(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.

$ 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.

$ 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 #)

# required machine type
-machine q35,smm=on,accel=kvm
# Due to the way some of the models work in edk2, we need to disable
# s3 resume. Without this option, qemu will appear to silently hang
# althouh it emits an error message on the ovmf_log
-global ICH9-LPC.disable_s3=1
# Secure!
-global driver=cfi.pflash01,property=secure,value=on
# Point to the firmware
-drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd,readonly=on
# Point to your copy of the variables
- 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

Shell> FS0:
FS0:\> 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


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

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