Category Archives: UEFI

Posts related to UEFI

Linux Foundation Secure Boot System Released

As promised, here is the Linux Foundation UEFI secure boot system.  This was actually released to us by Microsoft on Wednesday 6 February, but with travel, conferences and meetings I didn’t really get time to validate it all until today.  The files are here

I’ve also put together a mini-USB image that is bootable (just dd it on to any USB key; the image is gpt partitioned, so use the whole disk device).  It has an EFI shell where the kernel should be and uses gummiboot to load.  You can find it here (md5sum 7971231d133e41dd667a184c255b599f).

To use the mini-USB image, you have to enroll the hashes for loader.efi (in the \EFI\BOOT directory; actually gummiboot) as well as shell.efi (in the top level directory).  It also includes a copy of KeyTool.efi which you have to enrol the hash of to run as well.

What Happened to KeyTool.efi?

Originally this was going to be part of our signed release kit.  However, during testing Microsoft discovered that because of a bug in one of the UEFI platforms, it could be used to remove the platform key programmatically, which would rather subvert the UEFI security system.  Until we can resolve this (we’ve now got the particular vendor in the loop), they declined to sign KeyTool.efi although you can, of course, authorize it by hash in the MOK variables if you want to run it.

Let me know how this goes because I’m very interested to gather feedback about what works and what doesn’t work.  In particular, there’s a worry that the security protocol override might not work on some platforms, so I particularly want to know if it doesn’t work for you.

LCA2013 and Rearchitecting Secure Boot

I’ve been quiet for a while, so it’s time to give an update about what’s happening with the Linux Foundation secure boot loader (Especially as this has recently been presented at LCA2013 [slides]).

The gist of the problem is that GregKH discovered in early December that the proposed Pre-BootLoader wouldn’t work in its current form with Gummiboot.  This was a bit disheartening because it meant that it didn’t fulfill the Linux Foundation mission of enabling all bootloaders.  On investigation, the reason was simple: Gummiboot was created to demonstrate you could make a small and simple bootloader that takes advantage of all the services available in the UEFI platform instead of being the massive link loader that things like grub are.  Unfortunately this means that it boots kernels using BootServices->LoadImage(), which means that the kernel to be booted is run through the UEFI platform secure boot checks.  Originally Pre-BootLoader, like shim, was written to use PE/Coff link loading to defeat the secure boot checks.  Unfortunately, this means that something run by the Pre-BootLoader must also use link loading to defeat the secure boot checks on anything it wants to load and thus, Gummiboot, which is deliberately not a link loader, won’t work under this scheme.

So time for a re-architecture and a re-write:  The problem has now gone from being how do we create a Microsoft signed link loader that obeys their policies to how do we enable all children of the bootloader to use BootServices->LoadImage() in a way that obeys their policies.  Fortunately, there is a way to intercept the UEFI platform signing infrastructure by installing your own security architecture protocol (See the Platform Initialization spec Volume 2 section 12.9).  Unfortunately, the PI Spec isn’t actually part of the UEFI specification, but fortunately it is implemented by every Windows 8 system that I can find.  The new architecture now Intercepts this protocol and adds its own security check.  However, there’s a second problem: While we’re in the security architecture protocol callback, we don’t necessarily own the screen of the UEFI system, making it completely impossible to do a present user test for authorising the running of the bnary.  Fortunately, there does exist a non interactive way of doing this and that’s the SUSE MOK mechanism.  Thus, the Linux Foundation Pre-BootLoader has now evolved to use the standard MOK variables to store hashes of authorized binaries.

The upshot of all of this is you can now use Pre-BootLoader with Gummiboot (as demoed at LCA2013).  To boot, you have to add two hashes: one for Gummiboot itself and one for the kernel you’re booting, but actually this is a good thing because now you have a single security policy controlling all of your boot sequence.  Gummiboot itself has also been patched to recognise a failure due to secure boot and pop up a helpful message telling you which hash to enrol.

I’ll be doing a separate post explaining how the new architecture works (or you can read the slides), but I thought I’d better explain what’s been going on for the last month.

The ARM Windows 8 Lockdown

A lot of people have been asking why the Linux Foundation is concentrating on making sure there’s a Linux Boot solution for Windows 8 PCs that’s compatible with the GPLv3 requirements and not really doing anything about ARM (for which the current Windows 8 hardware requirements mandate no ability either to turn off secure boot or to replace the keys).

The answer to this comes in several parts: firstly in the PC space, Microsoft has an effective headlock on the OEM and ODMs: no desktop PC ships without a Windows compatibility sticker (the situation is different in the server market, but this is specifically about desktop PCs).  Therefore in order to continue simply booting Linux on laptops and desktops, it is a huge priority to find a solution to this problem.  Secondly: in the overall mobile marketplace, which encompasses tablets and smartphones, Microsoft has a very tiny presence: somewhere between 2-5%.  Linux (Android) has the majority presence: by some counts, Android is >50% in this market space with Apple a close second.  Therefore, a Microsoft mandate in an industry where they have no dominance is simply not really threatening (unlike the PC space where they have complete dominance).

The third problem is more philosophical: all Apple phones and tablets are locked down via cryptographic or other means (it’s not exactly the same as the UEFI secure boot lockdown, but it is similar) so it seems unreasonable to attack Microsoft but not Apple for doing this.  Additionally, a lot of Android devices also come locked down out of the box, so we haven’t even got our own house in order yet.  HTC and Samsung have bought into the argument that a flourishing mod rom ecosystem aids sales of mobile devices, so a growing number of Android phones ship with the oem unlock functionality (which turns off the boot lock in exchange for voiding the warranty) and thus we’ve been making considerable headway opening up the Android mobile ecosystem to the mod roms.  In this instance, I’d like to proceed with the economic argument and use persuasion to make at least the Android ecosystem more open.  Since Apple wants to retain a tight leash on what they regard as their hardware, I can’t ever see them doing anything other than battle with their mod rom ecosystems, and Microsoft is pretty much of the same mind set.  In the long run it cuts them off from external sources of innovation and limits their horizons to what their in-house engineers can think of, so I really believe that having Microsoft and Apple employ lockdowns will actually contribute, at least in part, to the rise of Linux on mobile devices.

The final argument is pragmatic: every apple phone and tablet has been rooted within a few weeks of release, so in practical terms, using cryptographic methods to lock determined users out of their own hardware is ineffective.  It’s actually rarely the cryptographic protection that’s broken; most often the rootkits exploit bugs and problems in the actual boot sequence itself.  So if the Surface (or Windows phone) hardware is really enticing, I’ve no doubt we’ll see a Linux variant running on it in the near future regardless of UEFI secure boot.

Adventures in Microsoft UEFI Signing

As I explained in my previous post, we have the code for the Linux Foundation pre-bootloader in place.  However, there was a delay while we got access to the Microsoft signing system.

The first thing you have to do is pay your $99 to Verisign (now Symantec) and get a verified by Verisign key.  We did this for the Linux Foundation, and all they want to do is call head office to verify. The key comes back in a URL that installs it in your browser, but the standard Linux SSL tools can be used to extract this and create a usual PEM certificate and key.  This is nothing to do with UEFI signing, but it’s used to validate to the Microsoft sysdev system that you are who you say you are.  Before you can even create a sysdev account, you have to prove this by signing an executable they give you and upload it.  They make strict requirements that you sign it on a specific Windows platform, but sbsign worked just as well and bingo our account is created.

Once the account is created, you still can’t upload UEFI binaries for signature without first signing a paper contract.  The agreements are pretty onerous, include a ton of excluded licences (including all GPL ones for drivers, but not bootloaders).  The most onerous part is that the agreements seem to reach beyond the actual UEFI objects you sign.  The Linux Foundation lawyers concluded it is mostly harmless to the LF because we don’t ship any products, but it could be nasty for other companies.  According to Matthew Garrett, Microsoft is willing to negotiate special agreements with distributions to mitigate some of these problems.

Once the agreements are signed then the real technical fun begins.  You don’t just upload a UEFI binary and have it signed.  First of all you have to wrap the binary in a Microsoft Cabinet file.  Fortunately, there is one open source project that can create cabinet files called lcab. Next you have to sign the cabinet file with your Verisign key.  Again, there is one open source project that can do this: osslsigncode. For anyone else needing these tools, they’re now available in my openSUSE Build Service UEFI repository. The final problem is that the file upload requires silverlight.  Unfortunately, moonlight doesn’t seem to cut it and even with the version 4 preview, the upload box shows up blank, so time to fire up windows 7 under kvm. When you get to this stage, you also have to certify that the binary “to be signed must not be licensed under GPLv3 or similar open source licenses”.  I assume the fear here is key disclosure but it’s not at all clear (or indeed what “similar open source licences” actually are).

Once the upload is done, the cabinet file goes through seven stages.  Unfortunately, the first test upload got stuck in stage 6 (signing the files).  After about 6 days, I sent a support email in to Microsoft asking what was going on.  The response: “The error code thrown by our signing process  is that your file is not a valid Win32 application? Is it valid Win32 application?”.  Reply: obviously not, it’s a valid UEFI 64 bit binary.  No further response …

Tried again.  This time I got a download email for the signed file and the dashboard says the signing failed.  Downloaded and verified.  The binary works on the secure boot platform and is signed with the key

subject=/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/OU=MOPR/CN=Microsoft Windows UEFI Driver Publisher
issuer=/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011

Asked support why the process was indicating failed but I had a valid download and, after a flurry of emails, got back “Don’t use that file that is incorrectly signed. I will get back to you.”  I’m still not sure what the actual problem is, but if you look at the Subject of the signing key, there’s nothing in the signing key to indicate the Linux Foundation, therefore I suspect the problem is that the binary is signed with a generic Microsoft key instead of a specific (and revocable) key tied to the Linux Foundation.

However, that’s the status: We’re still waiting for Microsoft to give the Linux Foundation a validly signed pre-bootloader.  When that happens, it will get uploaded to the Linux Foundation website for all to use.

Linux Foundation UEFI Secure Boot System for Open Source

I’m pleased to announce that the Linux Foundation and its Technical Advisory Board have produced a plan to enable the Linux (and indeed all Open Source based distributions) to continue operating as Secure Boot enabled systems roll out.  In a nutshell, the Linux Foundation will obtain a Microsoft Key and sign a small pre-bootloader which will, in turn, chain load (without any form of signature check) a predesignated boot loader which will, in turn, boot Linux (or any other operating system).  The pre-bootloader will employ a “present user” test to ensure that it cannot be used as a vector for any type of UEFI malware to target secure systems.  This pre-bootloader can be used either to boot a CD/DVD installer or LiveCD distribution or even boot an installed operating system in secure mode for any distribution that chooses to use it.  The process of obtaining a Microsoft signature will take a while, but once it is complete, the pre-bootloader will be placed on the Linux Foundation website for anyone to download and make use of.

Philosophy Behind this Announcement

The Linux Foundation is committed to giving users freedom of choice on their platforms.  Conforming to this stance, we have already published a variety of tools to permit users to take control of their secure boot platforms by replacing the Platform Key and managing (or replacing) the installed Key Exchange Keys here.  However, as one of the enablers of the Linux ecosystem, the Foundation recognizes that not everyone is willing (or able) to do this so it was also necessary to find a solution that would enable people to continue to try out Linux and other Open Source Operating Systems in spite of the barriers UEFI Secure boot would place in their way and without requiring that they understand how to take control of their platforms.  Therefore, we also formulated a technical plan, which is implemented in this pre-bootloader, to allow distributions to continue functioning in a secure boot environment.

The current pre-bootloader is designed as an enabler only in that, by breaking the security verification chain at the actual bootloader, it provides no security enhancements over booting linux with UEFI secure boot turned off.  Its sole purpose is to allow Linux to continue to boot on platforms that come by default with secure boot enabled.  The Linux Foundation welcomes efforts by some of the major distributions (e.g. Fedora, SUSE and Ubuntu) to tackle the problem of taking full advantage of UEFI secure boot to enhance platform security and sees the pre-bootloader it is releasing as a stop-gap measure that will give all distributions time to come up with plans that take advantage of UEFI secure boot.

Technical Details

The source code for the pre-bootloader is available in

git://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git

As Loader.c

It is designed to be as small as possible, leaving all the work to the real bootloader.  The real bootloader must be installed on the same partition as the pre-bootloader with the known path loader.efi (although the binary may be any bootloader including Grub2).  The pre-bootloader will attempt to execute this binary and, if that succeeds, the system will boot normally.  If the loader.efi fails to load with a security error (because it is unsigned), the pre-bootloader will stop at a splash screen and ask the user to confirm, by selecting a menu option, that they wish to continue booting loader.efi.  If this confirmation (which is the “present user” test) is successful, the pre-bootloader will then execute loader.efi without security verification (if the user denies permission to boot, the pre-bootloader will signal failure and the UEFI boot sequence will continue on to the next boot path, if there is one).  To facilitate repeat booting (and to make the pre-bootloader useful for booting hard disks as well as USB keys or DVDs) the pre-bootloader will also check to see if the platform is booting in Setup Mode and if it is, will ask the user for permission to install the signature of loader.efi into the authorized signatures database.  If the user gives permission, the signature will be installed and loader.efi will then boot up without any present user tests on all subsequent occasions even after the platform is placed back into secure boot mode.  The present user test splash screen that appears in secure boot mode asking for permission to boot loader.efi will also direct the user to a Linux Foundation website where we will gather details of how to place platforms in setup mode and advise the user how to do this, either to install the signature of loader.efi or to take full control of the platform by replacing the Platform and Key Exchange Keys.

Easier Way to take control of UEFI secure boot platform

All the tools are in the git repository

http://git.kernel.org/?p=linux/kernel/git/jejb/efitools.git;a=summary

But for ease of consumption, this is now packaged and build by the opensuse build server as installable rpm files. If you install the efitools-0.1.rpm package, it will automatically provision you with Platform Key, Key Exchange Key and db key.  The README file in /usr/share/efitools/ explains what’s going on, but you can also do a quick lockdown of your UEFI plaform (or simply boot out the old keys) if you copy all the efi files in /usr/share/efitools/efi/ and the *.auth files from /usr/share/efitools/keys/ into a partition accessible to the efi boot loader.  Then in Setup Mode (must be Setup Mode to alter the keys) do

UpdateVars db db.auth

UpdateVars KEK KEK.auth

UpdateVars PK PK.auth

After the PK update, the platform should once again be in user mode.  Verify by trying to run the HelloWorld efi binary (should fail) and it’s signed counterpart HelloWorld-signed (should print Hello World!).

 

 

The Microsoft Keys

Thanks to Matthew Garrett, we have copies of the keys from the Insyde reference platform.  As expected, the platform key is a self signed X509 certificate with /CN=Insyde/.  You can get it here (signature list, der).

The Key Exchange Key is a Microsoft X509 certificate with /CN=Microsoft Corporation KEK CA 2011/ It’s not self signed, it’s signed by /CN=Microsoft Corporation Third Party Marketplace Root/ you can get it here (signature list, der).

The Signature database contains three microsoft X509 certificates; you can get the signature list here.

  1. /CN=Microsoft Windows PCA 2010/ signed by /CN=Microsoft Root Certificate Authority 2010/ (db.0.cer).
  2. /CN=Microsoft Corporation UEFI CA 2011/ signed by /CN=Microsoft Corporation Third Party Marketplace Root/ (db.1.cer)
  3. /CN=Microsoft Windows Production PCA 2011/ signed by /CN=Microsoft Root Certificate Authority 2010/ (db.2.cer)

The interesting thing to note is that while Insyde owns the PK (as the windows hardware certification requires them to), they have no other certificates in the system, so in secure mode any bios update they do must be signed by a Microsoft key.

Updating PK, KEK, db and dbx in user mode

As of commit a2185c6 sign-efi-sig-list: functional version for time based updates

http://git.kernel.org/?p=linux/kernel/git/jejb/efitools.git;a=summary

has the capability to construct runtime updates to the secure variables.  So far I’ve managed to add extra keys to db; replace KEK and take the platform into setup mode.

The Basics

The repository now contains an efi program Update.efi which can be run in User Mode (must be signed with a key in db or KEK) and supply authenticated updates to the keys.  So far, I’ve only implemented time based updates for X509 keys.

In order to construct and update, you must first convert from a PEM format X509 certificate to an EFI Signature List.  To do that execute

cert-to-efi-sig-list mycert.crt mycert.esl

The result will be a binary signature list in mycert.esl.  Now you take this binary signature list and append the authentication header that authorises the platform to accept the key into the signature database variable db

sign-efi-sig-list -a db KEK.crt KEK.key mycert.esl db.update

And this will create a KEK signed append based update to the db variable.  To apply the update, in the UEFI environment run

UpdateVars -a db db.update

And the signature will be appended.

Note that there is a trick to this.  Since the current qemu platform is locked down at boot time, the timestamp associated with the variables is the time the system was booted.  In order to prevent replay problems, the timestamp generated by sign-efi-sig-list is the current time plus one year.  This would be unacceptable for production, but it solves the huge annoyance where you have to boot the platform, then create the update and then convey it into the platform to keep the timestamps correct.

If you wished to replace the contents of db instead of  merely appending to it, remove the -a flag from both commands.

Taking the Platform into Setup Mode again

This is achieved by clearing the platform key.  To do this, create an empty signature list

> null.esl

And use this as the basis for a non append based update of PK:

sign-efi-sig-list PK PK.crt PK.key null.esl PK.update

Note: updates to PK must be signed with the current platform key.  Now apply this update to the running system

UpdateVars PK PK.update

And voila, the Platform Key will be cleared and the system reset into setup mode again.

The Meaning of all the UEFI Keys

Introduction

The UEFI specification (2.3.1c) defines several key stores and their formats:  The Platform Key (PK), The Key Exchange Key (KEK) The key database (db) and the forbidden signatures database (dbx).  This post describes the relationships between them all and how they’re implemented in the Tianocore reference implementation.  This means that not everything possible is implemented because Tianocore follows the Windows 8 hardware certification requirements closely.

UEFI Secure Variables

All of the keys are stored in UEFI secure variables (see section 7.2 of the UEFI specification).  A secure variable cannot be updated unless the person attempting the update can prove (with a digital signature on a specified payload, called the authentication descriptor) that they possess the private part of the key used to create the variable.  The UEFI specifications only allow two types of signing keys: X509 and RSA2048.  A secure variable may be cleared by writing an empty update (which must still contain a valid authentication descriptor).

Authentication Descriptor

The specifications allow two types of authentication descriptors: time based and monotonic count based.  Once a variable is created, it stores both the key that created it and the initial value for the time or monotonic count and will only accept subsequent updates signed with that key and which have the same update type (time based or monotonic count) that it was created with.  The reason for this is to prevent replay of previous updates, so a newer update must have either a later time or a higher monotonic count.  Once the update is accepted, the time or count is updated as well to the value in the authentication descriptor.

Setup and User Modes

When a platform is in Setup Mode, the secure variables may be altered without the usual authentication checks (although the secure variable writes must still contain an authentication descriptor for the initial key and update type but the actual authentication information isn’t checked).  In this mode, secure boot is turned off.

In user mode, the platform will check that any attempt to write to a secure variable has a validly signed authentication descriptor.  In user mode, the platform will also expose a secure boot flag (which is on by default).  If secure boot is set, it will only execute efi binaries which

  1. are unsigned but have a sha-256 hash that is in db and not in dbx or
  2. are signed and have a signature in db but not in dbx or
  3. are signed by either a key in KEK or a key in db and neither the key nor the signature appears in dbx.

Platform Key (PK)

The Platform Key is the key to the platform and is stored in the PK variable.  Its job is to control access to the PK variable and the KEK variable.  In most implementations, only one key at once may be stored in PK and the PK may only be an X509 key.

If the PK variable is cleared (either by an authenticated variable write or by a special user present firmware action), the platform must immediately enter setup mode.

The PK variable may only be updated by an authentication descriptor signed with the platform key.

Note: The platform key may not be used to sign binaries for execution.

Key Exchange Key (KEK)

The Key Exchange Key is used to update the signature database and is stored in the KEK variable.  It may be used either to update the current signature databases or to sign binaries for valid execution.  In most current implementations, the KEK variable may contain multiple keys which may be of type X509 or RSA2048 any of which may perform the function of the key exchange key.

The KEK variable may only be updated by an authentication descriptor signed with the platform key.

The Forbidden Signatures Database (dbx)

The forbidden signatures database is used to invalidate efi binaries and loadable roms when the platform is operating in secure mode.  It is stored in the dbx variable.  The dbx variable may contain either keys, signatures or hashes. In secure boot mode, the signature stored in the efi binary (or computed using SHA-256 if the binary is unsigned) is compared against the entries in the database.  Execution is refused if either

  1. The binary is unsigned and the SHA-256 hash of the binary is in dbx or
  2. The image is signed and the signature matches an entry in dbx or
  3. The image is signed and the key used to create the signature matches an entry in dbx.

Note: since unsigned binaries are automatically refused execution, the addition of a hash to dbx serves only to prevent that image being authorised by having an entry for its hash in the signature database (see below).

The dbx variable may only be updated by an authentication descriptor signed with the key exchange key.

The Signature Database (db)

The signature database is used to validate signed efi binaries and loadable roms when the platform is operating in secure mode. It is stored in the db variable.  The db variable may contain a mixed set of keys, signatures or hashes.  In secure boot mode, the signature stored in the efi binary (or the SHA-256 hash if there is no signature) is compared against the entries in the database.  The image will be executed if either

  1. the image is unsigned and a SHA-256 hash of the image is in the database or
  2. the image is signed and the signature itself is in the database or
  3. the image is signed and the signing key is in the database (and the signature is valid).

The db variable may only be updated by an authentication descriptor signed with the key exchange key.

How Key Verification Works

Although key verification with either X509 or RSA2048 keys looks to be SSL standard, it isn’t quite: the key chain is only verified back to the key in the databases and no further.  This means that none of the keys has to be self signed, and that the usual ssl approach to verify all the way to the root CA isn’t followed.

Some consequences of all of this

As you can see from the above, the holder of the platform key is essentially the owner of the platform.  However, simply knowing the platform key (the private part) isn’t enough because in order to change the platform you have to be able to execute binaries and the platform will only execute binaries signed by a key either in KEK or db.  If you take control of your platform by installing a platform key, you need to ensure that this key (or another you control) is also added to either KEK or db so you can sign binaries with it and have them execute.