Translate

Image of XSLT 2.0 and XPath 2.0 Programmer's Reference (Programmer to Programmer)
Image of Operating System Concepts
Image of Linux Kernel Development (3rd Edition)
Image of Android Wireless Application Development

List UEFI Secure Boot Certificate Contents

Now that consumer versions of Windows 8 have been released and UEFI Secure Boot-enabled systems are becoming more common, how can a user (or a developer) see what keys have been installed on their system to control what applications they can boot on their system? This post explains how to list out the contents of such keys from the UEFI Shell command line.

Why UEFI Secure Boot? The answer is simple – because there are an increasing number of real-world exploits where fraudulently modified early boot code has introduced vulnerabilities into an operating system. It has lead to calls for means to secure platforms from such exploits.

According to the UEFI specification, securing a platform means establishing a chain of trust starting with the platform manufacturer and extending to the operating system vendors (OSV) like Microsoft and even to ISVs. This chain of trust is instantiated via public key cryptography. The platform vendor puts a so-called Platform Key (PK) into NVRAM (Non Volatile RAM). This PK represents the root of trust, i.e. the basis for the trust environment on a UEFI platform. The trust relationship with an OSV is documented by signing their key with the PK. Platform security is established by requiring that no code will be executed by the firmware unless it has been signed by one of these trusted keys.

UEFI Secure Boot is supported for UEFI Class 2 and Class 3 platforms (see UEFI documentation for more details about Classes). For UEFI Class 2 platforms, the Compatibility Support Module (CSM) must be disabled so that the platform can only boot UEFI-enabled operating systems. UEFI Secure Boot requires a platform that meets the UEFI 2.3.1 specification.

The UEFI specification could mandate an absolute chain of trust by requiring that everything that ever gets run on a platform be signed, i.e. the boot loader, the operating system, the modules it loads, the binaries and shared libraries it loads, all the scripts executed by any interpreter, and all the commands typed into at the command line. However such a chain of trust would be difficult to achieve in practice. As far as the current version (2.3.1) of the UEFI Specification is concerned, the chain of trust terminates when the platform firmware hands control over to an operating system. Essentially, this means that if you want to use UEFI Secure Boot, your OS loader must be signed by a key trusted by the platform firmware, and the OS kernel must be trusted by the OS loader before it is loaded.

Technically, UEFI is built upon another firmware standard called the Platform Initialization (PI) Standard. PI provides a standard flow and architecture for early machine initialization. The security (SEC) phase of the PI platform is the root of trust for the platform and provides the anchor point from which to build an authenticated boot process. The PK is anchored here. The holder of the PK is able to modify any of the other trust anchor lists that exist on a platform. Typically, the PK is held by a device manufacturer, but it there is no reason that it could not be held by an enterprise that wishes to have full control of Secure Boot in their particular organization. Naturally there can be only one PK on a platform.

In addition to the PK, the UEFI specification mandates two trust anchor databases:

  • The Key Enrollment Key (KEK) database. Also known as Key Exchange Key.
  • The Allowed Signature (db) database

The KEK database contains those trust anchors that are allowed to modify the Allowed Signature (db) database. A KEK can do everything permitted to a PK except change the PK. The Allowed Signature (or White List) database in turn contains those trust anchors that are used when verifying the signature on UEFI images. This database lists the signers or image hashes of UEFI applications, OS loaders, UEFI drivers, etc. that can be loaded on the the platform. There is also another database, the Forbidden (dbx) database. This database is also known as the Revoked Signature or Black List database. This database identifies keys that have been revoked and hashes of images that are no longer trusted and may not be loaded. PK and KEKs can be used to modify db and dbx.

UEFI Secure Boot supports using digital certificates and/or hashes to determine whether a signed UEFI firmware component or UEFI image is trustworthy or not. If the hash of a given image is present in the db database but not in the dbx database, then the fact that only the PK or a trust anchor in the KEK database can modify the contents of these two databases suffices to determine the validity of an image.

With this design, hashes of individual images can be added to the db database, i.e. white-listed, or added to the dbx database, i.e. black-listed. There is no need to revoke a vendor KEK. Consider the case where a specific driver from a vendor has been found to contain a vulnerability. The vendor KEK should not be revoked as this would impact all images signed by the vendor. Instead the driver hash should be added to dbx. Consider the alternative case where a new unsigned driver is detected by the platform. After appropriate investigation the driver is approved for use by adding a hash of the driver image to db.

To modify any of the databases described above, a party must be able to do so only with proper authorization. The UEFI Secure Boot authorization model follows a consistent design in that it leverages digital signatures itself. UEFI variables that requires authentication of the caller in order to be updated are known as Authenticated Variables (AKA Secure Variables.)

The current UEFI specification defines two types of Authenticated Variables (AV):

  • Counter based.
  • Time based.

In order to prevent replay attacks, a counter-based Authenticated Variable includes a monotonic count within the variable EFI_VARIABLE_AUTHENTICATION section, while a time-based Authenticated Variable includes a timestamp within the EFI_VARIABLE_AUTHENTICATION_2 section. When an Authenticated 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 (the authentication descriptor) and which have the same update type (time based or monotonic count) that it was created with and have a later time or higher monotonic count. The authentication descriptor proves that the party updating the Authenticated Variable possesses the private part of the key used to create the variable.

An Authenticated Variable may be cleared by writing an empty update (a valid authentication descriptor is still required). Authenticated Variables can be updated from within the Boot Services environment or from the OS.

According to the UEFI Specification, time-based Authenticated Variables are preferred. If the update is accepted, the time or count is also updated. The UEFI specifications also only specifies two types of signing keys: X.509 and RSA2048. See section 7.2 of the UEFI specification for more details.

With UEFI Secure Boot, images that are not explicitly white-listed must be digitally signed in such a way that the UEFI loader can verify the image signature. UEFI images use the PE/COFF binary format and the Microsoft Authenticode specification for image signatures.

To summarize, a UEFI boot loader will load a UEFI image which meets one of the following criteria:

  • is unsigned but has a SHA256 hash of the image in db and not in dbx, or
  • is signed and has a signature in db but not in dbx, or
  • is signed by a key in KEK or in db and neither the key nor a SHA356 hash of the image is in dbx.

Now that we have an understanding of UEFI Authenticated Variables, let us turn our attention to the concept of a UEFI signature database. A UEFI signature database consists of zero or more signature lists.

Each signature list is a list of signatures of one type only, identified by SignatureType. The signature list contains a header and then an array of zero or more signatures in the format specified by the header. The size of each signature in the signature list is specified by SignatureSize. Each signature has an owner SignatureOwner, which is a GUID identifying the agent which inserted the signature in the database. Agents can be the operating system or an OEM-supplied driver or application.

Signature databases are implemented as UEFI Authenticated Variables with a GUID of EFI_IMAGE_SECURITY_DATABASE_GUID.

#define EFI_IMAGE_SECURITY_DATABASE_GUID \
     { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }}

#define EFI_PLATFORM_KEY_NAME   L"PK"
#define EFI_KEY_EXCHANGE_KEY_NAME   L"KEK"
#define EFI_IMAGE_SECURITY_DATABASE   L"db"
#define EFI_IMAGE_SECURITY_DATABASE1   L"dbx"

To obtain the information we want about each of the Secure Boot keys, we need to be able to decode X.509 (often written as X509) certificates.

X.509 is an ITU-T standard for PKI (Public Key Infrastructure) and PM (Privilege Management Infrastructure). X.509 specifies, amongst other things, standard formats for public key certificates, certificate revocation lists, attribute certificates, and a certification path validation algorithm.

X.509 certificates are encoded using ASN.1 (Abstract Syntax Notation One) which is a commonly used standard that describes data structures for representing, encoding, transmitting, and decoding data. ASN.1 structures are either complex structures or simple types. Complex structures define objects made of other objects. Simple types are used when fields can be represented by native types: INTEGER, UTCTIME, BIT STRING, etc.

ASN1 is a high-level language that is human readable. However, when we want to use the information described in the ASN1 notation, for instance inside a network packet, we need to encode our message as a string of bits using an ASN1 compiler. ASN1 specifies type and structure but does not specify encoding (representation) rules. This is where BER (Basic Encoding Rules) and DER (Distinguished Encoding Rules) come into play. The difference between BER and DER is that with BER a single piece of information can be encoded in multiple ways while DER is a subset of the BER rules to ensure that there is only one possible encoding for a given information. In order to create a valid X.509 certificate we only need to DER-encode the different fields of the ASN1 description using the TAG, LENGTH, CONTENTS format. PEM is the Base64 encoded version of a DER encoded certificate.

Here is the ASN.1 source that I used to decode the X509 certificates:


– X509 certificate

Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING
}

TBSCertificate ::= SEQUENCE {
version [ 0 ] Version DEFAULT,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier ({ do_signature }),
issuer Name ({ do_issuer }),
validity Validity,
subject Name ({ do_subject }),
subjectPublicKeyInfo SubjectPublicKeyInfo ({ do_subject_public_key_info }),
issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
extensions [ 3 ] Extensions OPTIONAL ({ do_extensions })
}

Version ::= INTEGER ({ do_version })

CertificateSerialNumber ::= INTEGER ({ do_serialnumber })

AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER ({ do_algorithm }),
parameters ANY OPTIONAL
}

Name ::= SEQUENCE OF RelativeDistinguishedName

RelativeDistinguishedName ::= SET OF AttributeValueAssertion

AttributeValueAssertion ::= SEQUENCE {
attributeType OBJECT IDENTIFIER ({ do_attribute_type }),
attributeValue ANY ({ do_attribute_value })
}

Validity ::= SEQUENCE {
notBefore Time ({ do_validity_not_before }),
notAfter Time ({ do_validity_not_after })
}

Time ::= CHOICE {
utcTime UTCTime,
generalTime GeneralizedTime
}

SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING
}

UniqueIdentifier ::= BIT STRING

Extensions ::= SEQUENCE OF Extension

Extension ::= SEQUENCE {
extId OBJECT IDENTIFIER ({ do_extension_id }),
critical BOOLEAN DEFAULT,
extValue OCTET STRING
}

The final concept that you need to understand as far as this post is concerned is the concept of an OID (Object Identifier). OIDs are used extensively in X.509 certificates where they are used to name almost every object type in an X.509 certificate. An OID consists of a node in a hierarchically-assigned namespace. IANA issues PENs (Private Enterprise Number) under the 1.3.6.1.4.1 (iso.org.dod.internet.private.enterprise) arc. For example, the Microsoft assigned PEN is 1.3.6.1.4.1.311

For example, here is a list of the Microsoft cryptography OIDs. Some of these OIDs appear in UEFI Secure Boot key certificates.

I wrote a simple UEFI utility using the above ASN1 file to decode and output the UEFI Secure Boot X.509 certificates. You can obtain the full source code for this utility (listcerts) at GitHub under the UEFI-Utilities repository. Here is what was output when I complied and ran this utility on my Lenovo T430 (with firmware v2.5):

VARIABLE: PK  (size: 983)

Type: X509  (GUID: 3CC24E96-22C7-41D8-8863-8E39DCDCC2CF)
  Version: 3 (0x02)
  Serial Number: 00:EB:B5:13:D4:6B:B1:DC:6E
  Signature Algorithm: sha256WithRSAEncryption
  Issuer: CN=JP ST=Kanagawa L=Yokohama O=Lenovo Ltd. CN=Lenovo Ltd. PK CA 2012
  Validity - Not Before: 2012-06-29 10:34:36 UTC   Not After: 2032-06-24 10:34:36 UTC
  Subject: CN=JP ST=Kanagawa L=Yokohama O=Lenovo Ltd. CN=Lenovo Ltd. PK CA 2012
  Subject Public Key Algorithm: rsaEncryption
  Extensions: SubjectKeyIdentifier AuthorityKeyIdentifier BasicConstraints

VARIABLE: KEK  (size: 2545)

Type: X509  (GUID: 7FACC7B6-127F-4E9C-9C5D-080F98994345)
  Version: 3 (0x02)
  Serial Number: 00:95:52:43:82:8A:5A:65:2E
  Signature Algorithm: sha256WithRSAEncryption
  Issuer: CN=JP ST=Kanagawa L=Yokohama O=Lenovo Ltd. CN=Lenovo Ltd. KEK CA 2012
  Validity - Not Before: 2012-06-29 10:35:34 UTC   Not After: 2032-06-24 10:35:34 UTC
  Subject: CN=JP ST=Kanagawa L=Yokohama O=Lenovo Ltd. CN=Lenovo Ltd. KEK CA 2012
  Subject Public Key Algorithm: rsaEncryption
  Extensions: SubjectKeyIdentifier AuthorityKeyIdentifier BasicConstraints

Type: X509  (GUID: 77FA9ABD-0359-4D32-BD60-28F4E78F784B)
  Version: 3 (0x02)
  Serial Number: 61:0A:D1:88:00:00:00:00:00:03
  Signature Algorithm: sha256WithRSAEncryption
  Issuer: CN=US ST=Washington L=Redmond O=Microsoft Corporation CN=Microsoft Corporation Third Party Marketplace Root
  Validity - Not Before: 2011-06-24 20:41:29 UTC   Not After: 2026-06-24 20:51:29 UTC
  Subject: CN=US ST=Washington L=Redmond O=Microsoft Corporation CN=Microsoft Corporation KEK CA 2011
  Subject Public Key Algorithm: rsaEncryption
  Extensions: msCertsrvCAVersion SubjectKeyIdentifier msEnrollCertTypeExtension KeyUsage BasicConstraints
              AuthorityKeyIdentifier CrlDistributionPoints CertAuthInfoAccess

VARIABLE: db  (size: 4209)

Type: X509  (GUID: 77FA9ABD-0359-4D32-BD60-28F4E78F784B)
  Version: 3 (0x02)
  Serial Number: 61:07:76:56:00:00:00:00:00:08
  Signature Algorithm: sha256WithRSAEncryption
  Issuer: CN=US ST=Washington L=Redmond O=Microsoft Corporation CN=Microsoft Root Certificate Authority 2010
  Validity - Not Before: 2011-10-19 18:41:42 UTC   Not After: 2026-10-19 18:51:42 UTC
  Subject: CN=US ST=Washington L=Redmond O=Microsoft Corporation CN=Microsoft Windows Production PCA 2011
  Subject Public Key Algorithm: rsaEncryption
  Extensions: msCertsrvCAVersion SubjectKeyIdentifier msEnrollCertTypeExtension KeyUsage BasicConstraints
              AuthorityKeyIdentifier CrlDistributionPoints CertAuthInfoAccess

Type: X509  (GUID: 77FA9ABD-0359-4D32-BD60-28F4E78F784B)
  Version: 3 (0x02)
  Serial Number: 61:08:D3:C4:00:00:00:00:00:04
  Signature Algorithm: sha256WithRSAEncryption
  Issuer: CN=US ST=Washington L=Redmond O=Microsoft Corporation CN=Microsoft Corporation Third Party Marketplace Root
  Validity - Not Before: 2011-06-27 21:22:45 UTC   Not After: 2026-06-27 21:32:45 UTC
  Subject: CN=US ST=Washington L=Redmond O=Microsoft Corporation CN=Microsoft Corporation UEFI CA 2011
  Subject Public Key Algorithm: rsaEncryption
  Extensions: msCertsrvCAVersion msCertsrvPreviousCertHash SubjectKeyIdentifier msEnrollCertTypeExtension
              KeyUsage BasicConstraints AuthorityKeyIdentifier CrlDistributionPoints CertAuthInfoAccess

Type: X509  (GUID: 7FACC7B6-127F-4E9C-9C5D-080F98994345)
  Version: 3 (0x02)
  Serial Number: 09:45:63:7A:D8:C2:20:DF:61:EA:52:44
  Signature Algorithm: sha256WithRSAEncryption
  Issuer: CN=JP ST=Kanagawa L=Yokohama O=Lenovo Ltd. CN=Lenovo Ltd. Root CA 2012
  Validity - Not Before: 2012-06-29 10:47:31 UTC   Not After: 2032-06-24 10:47:31 UTC
  Subject: CN=JP ST=Kanagawa L=Yokohama O=Lenovo Ltd. CN=ThinkPad Product CA 2012
  Subject Public Key Algorithm: rsaEncryption
  Extensions: SubjectKeyIdentifier AuthorityKeyIdentifier BasicConstraints

VARIABLE: dbx  (size: 76)


There is a lot more useful information that you could extract from the UEFI Secure Boot keys. However, for the purpose of this post I kept the extracted information to a useful subset of what is possible. In a follow-on post, I will show you how to obtain this information and more from the Linux command line prompt.

1 comment to List UEFI Secure Boot Certificate Contents

  • Isidoro

    Gracias y enhorabuena por este articulo tan interesante sobre seguridad con sistemas EFI.

    Me gustaría formular una pregunta:

    Desde la BIOS ccidentalmente borré la (db) de firmas admitidas en mi portátil ASUS K55A con boot EFI,la pregunta es:

    Podría recuperar las “Keys” firmas admitidas de MicroSoft para, asi, poder arrancar de forma segura?.

    Un saludo y gracias de nuevo.