This guide details how to build a Unified Kernel Image (UKI) on Qubes, which has the benefit of opening the ability to cryptographically verify the state of all EFI code, as well as kernel boot parameters. This acknowledges the classic form of the "Evil Maid" Attack.
Currently, Qubes OS does not offer strong guarantees for boot security on most devices. The existing options for protecting the unencrypted bootloader include:
During the creation of the UKI, you can permanently leave your existing EFI entry to boot to (with secure boot disabled) as a backup if anything fails.
Through GitHub threads shared with me by user ryona, there is a script called uki-generate that can be used to create a UKI on Qubes using existing files within /boot and an additional xen.cfg. You can find the script here: https://github.com/QubesOS/qubes-core-admin-linux/blob/main/uki-generate
Note: This script will be used to generate an EFI binary, which is a very sensitive type of file. After you copy the script code, it is recommended to look over it yourself, or even better, verify the git GPG signature of the last commit modifying the script.
I used the vault qube for the entire process, but you can also create a dedicated AppVM for this purpose. If you use an alternative build qube, replace vault with the name of your qube in all of the commands within this guide.
In your build qube:
nano ~/uki-generate
chmod +x ~/uki-generate
In dom0:
# Replace these file names with your actual matching files
# if you are on a newer version of Qubes.
sudo qvm-copy-to-vm vault \
/boot/efi/EFI/qubes/xen-4.19.3.efi \
/boot/vmlinuz-6.12.7-1.qubes.fc41.x86_64 \
/boot/initramfs-6.12.7-1.qubes.fc41.x86_64.img \
mv ~/QubesIncoming/dom0/* ~/
xen.cfgIn dom0:
cat /proc/cmdline
root=/dev/mapper ...), then Copy dom0 clipboard via the clipboard manager applet, and then pass it to your build qube with Ctrl+Shift+V.
In the build qube:
nano ~/xen.cfg
xen.cfg file to look like this in the end:
[global]
default=qubes
[qubes]
options=console=none loglvl=all
kernel=placeholder YOUR KERNEL PARAMTERS
ramdisk=placeholder
kernel=placeholder, paste the string you copied from dom0 (root=/dev/mapper...) in place of YOUR KERNEL PARAMETERS.
Finally you can run the script to build your EFI binary. Replace the filenames if they are different for your version of Qubes.
~/uki-generate \
~/xen-4.19.3.efi \
~/xen.cfg \
~/vmlinuz-6.12.59-1.qubes.fc41.x86_64 \
~/initramfs-6.12.59-1.qubes.fc41.x86_64.img \
~/xen-unified.efi
Copying to dom0 is very sensitive, more so booting from a copied EFI entry; ensure you have built it securely before doing this step.
qvm-run --pass-io vault 'cat /home/user/xen-unified.efi' > ~/xen-unified.efi
sudo mv ~/xen-unified.efi /boot/efi/efi/qubes/xen-unified.efi
# Replace /dev/nvme0n1 with the path to your
# drive, such as /dev/sda
sudo efibootmgr --create --disk /dev/nvme0n1 \
--part 1 --label "Qubes OS UKI" \
--loader "\EFI\qubes\xen-unified.efi"
efibootmgr | grep "Qubes OS UKI" to see that your boot option has registered.
Once this is finished, you can now test your UKI boot entry. Reboot and spam whichever key lets you choose boot options (F12 in my instance), or access it from your standard UEFI setup if available. You should find an option called Qubes OS UKI. Boot from this.
The boot process should look normal, except that instead of the GRUB, you see a brief black screen with white text showing certain configuration details. If you can decrypt your disk and log in normally, you've now verified that the UKI works.
A UKI alone does not improve your boot security inherently; it simply opens opportunities for proper cryptographic verification. You must use another method to verify the boot process.
To enable Secure Boot, you will want to enroll your own key in the authorized signatures database and self-sign the EFI binary. (It is also possible on some systems to simply enroll the EFI binary itself in the authorized signatures database, though this has to be done every time the UKI is updated). It may also be beneficial to replace the existing Platform Key and Key Exchange Keys with your own keys. I will not go into detail about this, but the latter step (along with revoking existing authorized signatures, but this can be dangerous especially if you have a discrete GPU) can help to reduce trust in the case of a vendor key compromise.
However, Secure Boot is not a strong protection by itself. If your UEFI can be reset by shorting the CMOS (most hardware), then someone can disable Secure Boot and boot to any OS they want, so this should not be treated as a protection against someone else booting to a malicious OS. More importantly, unless you check your secure boot policy every boot, then you likely won't notice if your bootloader has been modified if an attacker also has reset the UEFI---defeating the purpose of verifying the bootloader.
TPM-based attestation is still necessary to reliably ensure boot integrity. The easiest way to do that is through LUKS TPM 2.0 unsealing via systemd-cryptenroll in dom0 with a TPM PIN (bound to PCR 4, or if you have Secure Boot PCR 7). This has its security concerns, as attacks have historically been able to find vulnerabilities in trusted platform modules key storage (FaulTPM, for instance). If you do decide to go this route, ensure that your specific CPU model is not known to be vulnerable, and enable "Pluton TPM" in your UEFI security settings if available.
Many threat models do not permit the potential vulnerabilities with storing encryption keys in the TPM. It may be possible to authenticate the system to the user using a non-static integrity verification code in initramfs, using tpm2-totp for instance, before the user types in their LUKS passphrase. If this is implemented, the user would compare the code on their screen to their own authenticator app such as Aegis. If the codes match, then that means the assigned PCRs (such as PCR 4, and you can include others as well to detect modified firmware, for instance) match the expected values, so the bootloader is safe and the LUKS passphrase can be entered. If you know this is possible, then please let me know and I will add that to this post.
Finally, this only covers the classic example of an Evil Maid Attack---a maliciously modified bootloader. There are other ways for the Evil Maid to physically compromise a computer, such as writing firmware. Running fwupdmgr security in a live Linux USB can help to quickly gauge what types of hardware vulnerabilities are open, but it is not a comprehensive test and cannot assess the quality of the implementation of the features it tests for.