Ubuntu 12.10 supports UEFI secure boot. I did some research in order to understand the actual implementation on Ubuntu and would like to share my findings. Since Windows 8 requires secure boot, most new Computer contain Microsoft’s Platform Key. Microsoft allows to sign own binaries with this Platform Key. As outlined in the Canonical blog post Ubuntu 12.10 uses a signed version of the EFI application Shim (to maintain the chain of trust) and Grub2 as its default boot manager.
Canonicals version of the Shim EFI application
Ubuntu’s 12.10 Shim EFI application is a early version of Shim which don’t has any support for MOKs (Machine Owner Keys). Shim was made by Matthew Garrett. He wrote two blog posts how Shim works, but because Ubuntu uses an older version not all of his description apply to Ubuntu’s Shim. Matthew Garrett also published its own Microsoft-signed version of Shim. Ubuntu however doesn’t use this signed version.
Canonical let its version of Shim sign by Microsoft directly. The package shim provides a compiled but unsigned version of shim. The signed shim is inside the package shim-signed (since the binary is signed there is no direct source package of it).
Shim comes with just one public key from Canonical. You can find that public key inside a certificate in the Ubuntu specific changes made to the source package of Shim (see shim_0~20120906.bcd0a4e8-0ubuntu4.debian.tar.gz, canonical-uefi-ca.der).
The Grub2 binary signed by this public key is available from the package grub-efi-amd64-signed.
First Boot step: The signed version of Shim is verified using Microsoft’s platform key and loaded by the secure boot enabled UEFI firmware upon booting. Shim then verifies the Grub2 boot manager using the mentioned Canonical public key.
Grub2 with Shim & Secure Boot support
Ubuntu’s Grub2 boot loader is a modified version which does not support loading any modules when using secure boot. Since the Grub2 modules are not signed, it would be too easy to hide a malware in a Grub2 module. Ubuntu’s Grub2 also includes a new module “linuxefi” which verify, load and call the kernel and its own EFI stub boot loader. The module provides two new Grub2 commands to do so “linuxefi” and “initrdefi”. This module requires Shim in order to verify the signature of the kernel, without Shim, Ubuntu’s linuxefi implementation will refuse to use kernels EFI stub boot loader. Because the Linux kernel image acts as boot loader itself, it need to be signed too!
The EFI stub boot loader is available since Linux 3.3 and was added by Intel developer Matt Flaming (see also Rod Smiths information about Kernels EFI stub loader). The image is not only a bzImage, it is also a EFI application which can be executed. This makes the kernel to a boot loader for itself. The kernel can access the full EFI boot services and does that e.g. loading initrd or initialize graphic modes. The kernel itself ends the boot process by calling “ExitBootServices”.
The kernels are signed by Canonicals public key and are available as linux-signed-generic package from Ubuntu’s package repository. They land alongside their unsigned variants in /boot with the file suffix “.elf.signed”. When the signed kernel variant is available on a UEFI enabled system, the Grub scripts add the signed variants to its boot script (see /etc/grub.d/10_linux which generates grub.cfg).
Second Boot step: Grub2 loads the signed versions of the kernel image, asks Shim to verify it and try to find the Kernel EFI stub boot loader. If successful, the initrd is loaded and the kernels EFI stub boot loader is called. The kernel then boots and end the EFI boot process by calling ExitBootServices.
Caveats on Ubuntu’s secure boot implementation
The above boot process is the standard boot procedure on a secure boot enabled system. The Grub2 “linux” command implementation calls the “linuxefi” command, which boots the signed version only if it’s valid. If that fails, the default boot process for Linux continues. This means using the Grub2 Linux boot loader, calling ExitBootServices and hand over to the Linux kernel (without verifying any signature). In other words, Ubuntu 12.10 on a secure boot enabled machine loads signed kernels as well as unsigned kernels.
According to Steve Langasek’s first implementation plans for secure boot, secure booting ends with the EFI system call “ExitBootServices”. In this regard, the Ubuntu developer did not changed their plan. Jamie Strandboge says, this should be enough to fulfill the Windows 8 logo requirements for Secure Boot. It’s also obvious, that under this circumstances its not needed to verify the initrd-Image or any kernel modules (and Ubuntu 12.10 also doesn’t do it).
Matthew Garrett who outlined plans for Fedora don’t stop there. His approach also uses signed kernel images and describes mechanism to verify modules loaded by the kernel. So the whole OS should be secured against any untrusted code execution in kernel/supervisor mode. SuSE was the initiator of the MOK key concept, which would allow user signed code as well as Distribution signed code being executed.
One has to know, Ubuntu was the first Distribution who released an Secure Boot enabled Version! IMHO, I think its a weak implementation of what secure boot could do, but its very comfortable from the users perspective.
Some other, related interesting findings while I did my research:
- There is a new command in Grub (fwsetup) to return to UEFI firmware
- Installing Grub for UEFI is only possible if you have booted your system using EFI. The scripts check the currently running platform several times in order to choose the Grub2 image to install and kernel version to use.
Update 17. December 2012:
Although code clearly states that kernels without a signature should boot fine, on my test system it did not work. Instead Grub2 stopped working with the massage “loader/i386/efi/linux.c:60: Locating shim protocol”. I’m not sure what leads to this freeze, but grub should definitely print another message, either if kernel signature verification failed or passed… It looks like shim crashes at verify…
Update 25. November 2014:
Avoid the term UEFI BIOS, as BIOS mainly refers to the old 16-bit firmware “standard”