Home Wiki > openSUSE:UEFI
Sign up | Login

openSUSE:UEFI

tagline: From openSUSE

About UEFI

Introduction to the standard

UEFI (Unified Extensible Firmware Interface) is a new industry standard that specifies the different interfaces that a system must provide in a pre-boot environment. UEFI will control the system after it is powered on and the operating system is fully loaded. Also, UEFI is responsible for providing an interface between the resources that the system provides and the operating system.

In other words, UEFI is to replace and extend the old BIOS firmware.

UEFI is not a new thing. Intel has been working in EFI/UEFI since mid 1990s, and there are vendors like HP or Apple that provided EFI machines since a long time ago. But it is when Microsoft announced Windows 8 that UEFI became the required way to boot the new certified machines.

The UEFI specification (http://www.uefi.org/specs/) is a big document that contains all the interfaces, variables and structures that the firmware manufacture must provide, and which are accessible to the operating system. The good news is that Linux has been able to use EFI at boot time since 2000 using GRUB or elilo. In fact, openSUSE 12.2 had support for UEFI, and the recent openSUSE 12.3 has experimental support for the Secure Boot extension.

Secure boot is an extension of UEFI. One of the key points of UEFI is that it can be extended. UEFI has an internal virtual machine that is independent of the architecture that it is using. The standard accepts special binary files compiled for this virtual machine (EFI binaries) that can be executed inside the environment. These binaries can be device drivers, applications or extensions to the UEFI standard. UEFI, in some sense, is like a small operative system that runs when the machine is powered on and whose main task is to find and load another operating system.

How you can determine whether you have a UEFI machine? Normally, check the firmware configuration pressing F1 (or ESC, depending on the machine) during the power on process. Browsing through the menus, it can be discover that the machine can run in legacy mode (the old BIOS mode), EFI mode and in a hybrid mode, where the actual model will be selected based on the operating system that will be loaded.

If your machine does not have UEFI support and you want to test this new technology with openSUSE, you can use QEMU and the Intel's reference implementation of UEFI: UEFI and Secure Boot with QEMU

GPT

UEFI changes more things than the firmware, the syscalls and the interfaces. It also proposes a new style of partitioning the hard disk. GUID Partitioning Table (GPT) is to replace the old Master Boot Record (MBR) solution.

MBR had some important limits, like the number of primary and logical partitions, and the size of these partitions. GPT resolves these issues and one can now have an arbitrary number of partitions (in sets of 128) and an addressable disk space of 2^64 bytes (i.e. in the order of exabytes). So, if you have have large disks, this is the kind of partition table that you would want. Another key difference is that GPT references every partition using an unique UUID number, avoiding collisions between partition identification.

If YaST detects that the machine is in EFI mode, it will try to create a GPT partition in a fresh install. Once GPT partitions are in place, the old fdisk cannot be used anymore to create, remove or edit partitions. The new tool to do that is gdisk and is in the gptfdisk package. The interface is the same one that we had in the fdisk tool.

From time to time, if we are planning to make some test and experiment with the different modes, we will want to remove the GPT format from our hard disk. We can do that using YaST2. To do that go to the Expert Partitioner option , select the correct hard disk and in the "Expert..." button select the "Create New Partition Table"

This will replace the partition table according to the system that we have running.

EFI System Partition

The EFI System Partition (ESP) is a partition where UEFI expect to find the EFI programs that can be used to boot all the operating systems installed on the device. Also, EFI will find here some device drivers used at boot time, and other tools needed to be run before the operating system is booted.

This partition use a FAT file system and can be created via YaST2 during a fresh installation, or reused in a dual boot machine. That means that if we have a previous Windows version installed on the system, YaST2 will detect the EFI partition, will put the new EFI bootloader used to load openSUSE, and will mount the partition in the /boot/efi mount point.

By default, the firmware will search /EFI/BOOT/bootx64.efi as the extension that will load and execute in order to load the operative system. In Windows machines, the correct extension is in /EFI/Microsoft/Boot/BCD.efi, and for openSUSE is /EFI/opensuse/grubx64.efi (or shim.efi if we have secure boot enabled)

The Boot Manager

In order to select the correct extension that will load the operating system, EFI provides to the user an internal boot manager. The operating system is responsible for creating a new entry for itself. We can launch the boot manager, and list all the boot entries, during the power on process, usually pressing F9 or F12. But we can use the efibootmgr tool to query and edit the entries. For example, to list the current entries we can run efibootmgr -v.

In the previous screenshot we can see that openSUSE created two different entries to boot. One is used when we are in secure mode, and the other when we are not.

If for some reason we lost one of the entries, we can recreate it using efibootmgr. For example, to recreate the entry 'opensuse' we can do:

# efibootmgr -c -L "openSUSE-alt" -l '\EFI\opensuse\grubx64.efi'

EFI Variables

The UEFI standard specify a set of variables that are stored in a non-volatile part in the firmware. Those variables are used to store information and to control the behavior of the UEFI system. When we create a new entry in the boot manager, or when we enable or disable the secure boot option, for example, we are accessing and changing the value of one of those variables.

We can query and access to these variables directly from openSUSE via Sysfs. Sysfs is a virtual file system that the kernel provide to export some internal information to user space. We can find the variables in '/sys/firmware/efi/vars/'. So, for example, the last boot loader entry can be queried with

$ hexdump -C /sys/firmware/efi/vars/Boot0007-*/data

Secure Boot

Background

UEFI Secure Boot is a method to restrict which binaries can be executed to boot the system. The firmware only executes boot loaders that carry the cryptographic signature of well known entities. In the context of Secure boot X.509 certificates are used to identify entities.

Today most consumer PC hardware that has secure boot enabled by default is shipped with Microsoft Windows 8. Therefore the firmware only knows about Microsoft as well known entity for signing boot loaders. To be able to boot openSUSE without having to reconfigure the list of known signature issuers and without having to turn off Secure Boot, the bootloader of openSUSE has to have a signature by Microsoft.

Implementation in openSUSE 12.3

The default boot loader used by openSUSE 12.3 on UEFI systems is grub2. When in secure boot mode, an additional boot loader called 'shim' is used too. Instead of directly calling grub2 in that mode the firmware first loads 'shim'. 'shim' carries a signature by Microsoft in order to be recognized by the firmware. 'shim' in turn knows about the openSUSE certificate that was used to sign grub2. grub2 then is able to load linux kernels that are also signed by the openSUSE certificates. After loading the Linux kernel the scope of secure boot ends. The linux kernel used in openSUSE does not impose additional restrictions.

In order to allow having custom boot loaders as well as custom kernels shim offers a way to import custom signatures. The program 'MokManager' is used for that purpose. When 'shim' is instructed to load a binary that is not signed by a well known entity it calls into MokManager which allows to import certificates into the database of well known signature issuers.

How to enable or disable Secure Boot support

Secure Boot support in openSUSE 12.3 is still considered experimental. The installation program YaST can not automatically detect whether secure boot is enabled. During the installation it offers an option to manually enable Secure Boot support. Turning that option on is required for shim to be installed. To enable or disable support for Secure Boot in an installed system the YaST bootloader module can be used.

How to determine whether a system has secure boot turned on

To determine whether a machine has secure boot enabled in the firmware enter the following command as root in a Linux shell:

# od -An -t u1 /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data

Secure Boot is enabled if the command outputs '1'. Some firmware versions are known to be broken and display '0' there even if secure boot is enabled though.

Booting a custom kernel

Secure boot does not prevent you from using your own self compiled kernel. You just have to sign it with your own certificate and make that certificate known to the firmware or MOK.

  1. create a custom X.509 key and certificate used for signing:
    openssl req -new -x509 -newkey rsa:2048 -sha256 -keyout key.asc -out cert.pem -nodes -days 666 -subj "/CN=$USER/"
  2. package key and cert as PKCS#12 structure:
    openssl pkcs12 -export -inkey key.asc -in cert.pem -name kernel_cert -out cert.p12
  3. generate NSS database for use by pesign:
    certutil -d . -N
  4. import key and certificate contained in PKCS#12 into NSS database:
    pk12util -d . -i cert.p12
  5. bless the kernel with the new signature:
    pesign -n . -c kernel_cert -i arch/x86/boot/bzImage -o vmlinuz.signed -s
  6. list the signatures on the kernel image:
    pesign -n . -S -i vmlinuz.signed

At that point you may install the kernel in /boot as usual. Since the kernel now has a custom signature the certificate used for signing needs to be imported into the firmware or MOK.

  1. convert certificate to DER format for import into UEFI firmware or MOK:
    openssl x509 -in cert.pem -outform der -out cert.der
  2. copy the certificate to the ESP for easier access:
    sudo cp cert.der /boot/efi/

Unfortunately mokutil is still broken on openSUSE 12.3 so there is no convenient way to launch MOK automatically. The following procedure describes how to launch MOK manually.

  • reboot
  • in the grub menu press the 'c' key
  • type (assuming the ESP is 'gpt1' on 'hd0'):
    chainloader (hd0,gpt1)/EFI/opensuse/MokManager.efi
    boot
  • select "Enroll key from disk"
  • navigate to the cert.der file and press enter
  • follow the instructions to enroll the key. Normally this should be pressing '0' and then 'y' to confirm

Alternatively the firmware menu may provide ways to add new key to 'db'.

Booting a Tumbleweed kernel

The kernels from the Tumbleweed repository are not signed with the standard openSUSE certificate, but with that of the Tumbleweed project. In order to boot them you either have to strip the signature from the binary using pesign -n . -r -u 0 -i vmlinuz -o vmlinuz.unsigned and resign them by following the instructions above. You have to repeat this procedure each time a new kernel is installed.

Alternatively, you can import the Tumbleweed project key as MOK and use the kernel packages directly. However, in order to get the signing certificate you need to have an account with the openSUSE Build Service (or any other SUSE account). The SSL certificate can be retrieved in PEM format via https://api.opensuse.org/source/openSUSE:Tumbleweed/_project/_sslcert?meta=1 . Enter your SUSE username and password when asked. You can now convert the certificate to DER format and enroll it as MOK by following the instructions in the previous section.

The current (as of June 23, 2014) Tumbleweed certificate is

-----BEGIN CERTIFICATE-----
MIIDujCCAqKgAwIBAgIJAMk7ZhLBbXDnMA0GCSqGSIb3DQEBCwUAMGExKDAmBgNV
BAMMH29wZW5TVVNFOlR1bWJsZXdlZWQgT0JTIFByb2plY3QxNTAzBgkqhkiG9w0B
CQEWJm9wZW5TVVNFOlR1bWJsZXdlZWRAYnVpbGQub3BlbnN1c2Uub3JnMB4XDTEz
MDIxODE3MTAzN1oXDTE1MDQzMDE3MTAzN1owYTEoMCYGA1UEAwwfb3BlblNVU0U6
VHVtYmxld2VlZCBPQlMgUHJvamVjdDE1MDMGCSqGSIb3DQEJARYmb3BlblNVU0U6
VHVtYmxld2VlZEBidWlsZC5vcGVuc3VzZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDdyvze0Q5FQ6tARNmm5LJOT8q6OvpuXAj/b2xZjpy/7yzp
Kb09b43xPs+c3c9ItKfWF62RyLZnT3freN3nq2G8tj1SzybBc4fcIQ4ngN5/vAC2
2u1czjo8vUb5mzde8HnuRLog4JeXmOrZvOlRWmt7jd4NYCkpZOlsDbrSDd2cUmS2
ROixthA588432UjaCP5v77yKDCijvJUg+1dwz84qvhkgd84CMzGHQgMZGVMA6Eo7
MOuFrBjv26lD4CSIacARamqDyoZRkBDaV48bj8/xONBIjLRhPziVNPJJi+YSOUsL
oRzX53myjguTDTwsVS2bZdwLnP1wr1vdf5qAi6ZjAgMBAAGjdTBzMAwGA1UdEwEB
/wQCMAAwHQYDVR0OBBYEFGszE3ufhxeDqUdv1sfxNQhB91AUMB8GA1UdIwQYMBaA
FGszE3ufhxeDqUdv1sfxNQhB91AUMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK
BggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAhSn8TDl8Rm2P6PomDFCQ6gP+
BvXz4HtrRqlFNWlcm+4hw1jHE1/K6uUN6pSf0sRKCVAjNj3G0IzGeovDCG2KaUfK
RYAkqfT6kG6suIKsIbgDjwXeaRDOtP1Vgs/CMVoUQo3LoDASMXba8gSQ4/7j6CNe
/Wf8jEfjYi7BQARJiKdnokAG36F352HnozigrEXqHvv05BcaUI0WiaoCGVvGGzy/
q9lezSXNZMt0EF4UoYiwVSFdyss8SPeUW3IjZAOA74Akbygh0aGKxf1X33aNtqZp
MIdgoMhEkJmOJj4IZ47U8S0HjMwthFc6JY2RilNNfXjMxcHAtVPm9LwrWIwx5A==
-----END CERTIFICATE-----

Booting the Machine without vendor provided Keys

If the firmware menu offers options to reset the keys used for secure boot you may install new PK, KEK and db without Microsoft keys. Import /usr/lib64/efi/shim-opensuse.der into db to make openSUSE kernels boot in that case. The default shim is signed by both Microsoft and openSUSE. Some firmware versions don't support double signing though. In that case install /usr/lib64/efi/shim-opensuse.efi which only has the openSUSE signature as /boot/efi/EFI/opensuse/shim.efi

Booting the Machine that supports only one signature with vendor provided Keys

Some firmwares could not parse more than one signature in the EFI images, and the default shim would fail in this case. If the firmware menu doesn't provide options to install new keys, you have to strip the openSUSE signature manually to work around the issue.

  1. install mozilla-nss-tools and pesign
    zypper install mozilla-nss-tools pesign
  2. create a temporary nss database
    mkdir certdb
    certutil -N -d certdb
    (press "Enter" to ignore the password request)
  3. strip the openSUSE signature
    pesign -n certdb/ -r -i /usr/lib64/efi/shim.efi -o shim.efi -u 1
  4. replace the default shim.efi with the newly-generated shim.efi
    mv shim.efi /boot/efi/EFI/opensuse/shim.efi
  5. remove the temporary nss database
    rm -rf certdb

Those steps have to be done every time after shim is updated. This kind of firmwares should be less and less since the multi-signature support is already included in the edk2 upstream for more than a year, but it could still happen in the old machines.

Glossary

PK
The "Platform Key" typically refers to a certificate installed by the hardware vendor on the machine. To be able to modify the KEK a valid signature of the PK is required.
KEK
A valid signature of the "Key Exchange Key" is required to update the signature database.
db
The Signature Database contains well known certificates, signatures or hashes of binaries. Only binaries that can be verified using that database are executed by the firmware. A valid signature of the KEK is required to update the Signature Database.
dbx
The Forbidden Signatures Database is the opposite of 'db', basically blacklist of certificates, signatures and hashes. If a binary matches any of the entries there it cannot be executed. A valid signature of the KEK is required to update the Forbidden Signature Database.
MOK
Machine Owner Keys. An extra database of certificates or hashes used by MokManager. MokManager can be used interactively by the user during boot to update MOKs.