Monthly Archives: July 2012

Easier Way to take control of UEFI secure boot platform

All the tools are in the git repository;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;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


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.