Canonical Voices

Posts tagged with 'secure-boot'

The Ubuntu Developer Summit was held in Copenhagen last week, to discuss plans for the next six-month cycle of Ubuntu. This was the most productive UDS that I've been to — maybe it was the shorter four-day schedule, or the overlap with Linaro Connect, but it sure felt like a whirlwind of activity.

I thought I'd share some details about some of the sessions that cover areas I'm working on at the moment. In no particular order:

Improving cross-compilation

Blueprint: foundations-r-improve-cross-compilation

This plan is a part of a mutli-cycle effort to improve cross-compilation support in Ubuntu. Progress is generally going well — the consensus from the session was that the components are fairly close to complete, but we still need some work to pull those parts together into something usable.

So, this cycle we'll be working on getting that done. While we have a few bugfixes and infrastructure updates to do, one significant part of this cycle’s work will be to document the “best-practices” for cross builds in Ubuntu, on wiki.ubuntu.com. This process will be heavily based on existing pages on the Linaro wiki. Because most of the support for cross-building is already done, the actual process for cross-building should be fairly straightforward, but needs to be defined somewhere.

I'll post an update when we have a working draft on the Ubuntu wiki, stay tuned for details.

Rapid archive bringup for new hardware

Blueprint: foundations-r-rapid-archive-bringup

I'd really like for there to be a way to get an Ubuntu archive built “from scratch”, to enable custom toolchain/libc/other system components to be built and tested. This is typically useful when bringing up new hardware, or testing rebuilds with new compiler settings. Because we may be dealing with new hardware, doing this bootstrap through cross-compilation is something we'd like too.

Eventually, it would be great to have something as straightforward as the OpenEmbedded or OpenWRT build process to construct a repository with a core set of Ubuntu packages (say, minbase), for previously-unsupported hardware.

The archive bootstrap process isn't done often, and can require a large amount of manual intervention. At present, there's only a couple of folks who know how to get it working. The plan here is to document the bootstrap process in this cycle, so that others can replicate the process, and possibly improve the bits that are a little too janky for general consumption.

ARM64 / ARMv8 / aarch64 support

Blueprint: foundations-r-aarch64

This session is an update for progress on the support for ARMv8 processors in Ubuntu. While no general-purpose hardware exists at the moment, we want to have all the pieces ready for when we start seeing initial implementations. Because we don't have hardware yet, this work has to be done in a cross-build environment; another reason to keep on with the foundations-r-improve-cross-compilation plan!

So far, toolchain progress is going well, with initial cross toolchains available for quantal.

Although kernel support isn’t urgent at the moment, we’ll be building an initial kernel-headers package for aarch64. There's also a plan to get a page listing the aarch64-cross build status of core packages, so we'll know what is blocked for 64-bit ARM enablement.

We’ve also got a bunch of workitems for volunteers to fix cross-build issues as they arise. If you're interested, add a workitem in the blueprint, and keep an eye on it for updates.

Secure boot support in Ubuntu

Blueprint: foundations-r-secure-boot

This session covered progress of secure boot support as at the 12.10 Quantal Quetzal release, items that are planned for 13.04, and backports for 12.04.2.

As for 12.10, we’ve got the significant components of secure boot support into the release — the signed boot chain. The one part that hasn't hit 12.10 yet is the certificate management & update infrastructure, but that is planned to reach 12.10 by way of a not-too-distant-future update.

The foundations team also mentioned that they were starting the 12.04.2 backport right after UDS, which will bring secure boot support to our current “Long Term Support” (LTS) release. Since the LTS release is often preferred Ubuntu preinstall situations, this may be used as a base for hardware enablement on secure boot machines. Combined with the certificate management tools (described at sbkeysync & maintaining uefi key databases), and the requirement for “custom mode” in general-purpose hardware, this will allow for user-defined trust configuration in an LTS release.

As for 13.04, we're planning to update the shim package to a more recent version, which will have Matthew Garrett's work on the Machine Owner Key plan from SuSE.

We're also planning to figure out support for signed kernel modules, for users who wish to verify all kernel-level code. Of course, this will mean some changes to things like DKMS, which run custom module builds outside of the normal Ubuntu packages.

Netboot with secure boot is still in progress, and will require some fixes to GRUB2.

And finally, the sbsigntools codebase could do with some new testcases, particularly for the PE/COFF parsing code. If you're interested in contributing, please contact me at jeremy.kerr@canonical.com.

Read more

Over the last couple of weeks I've been working on a set of secure-boot tools. Originally, this project was intended as a quick implementation of an EFI-image-signing utility, but it has since grown a little. I've now added code to help maintain the UEFI signature databases from within a running OS.

A new utility, sbkeysync, reads the current EFI signature databases from firmware, and reads a set of keys from a standard location in the filesystem - for example, /etc/secureboot/keys. It then updates the firmware key databases with any keys that are not already present.

A filesystem keystore will look something like this:

  • /etc/secureboot/keys/PK/<pk-file>
  • /etc/secureboot/keys/KEK/<kek-file-1>
  • /etc/secureboot/keys/KEK/<kek-file-2>
  • /etc/secureboot/keys/KEK/…
  • /etc/secureboot/keys/db/<db-file-1>
  • /etc/secureboot/keys/db/<db-file-2>
  • /etc/secureboot/keys/db/…
  • /etc/secureboot/keys/dbx/<dbx-file-1>
  • /etc/secureboot/keys/dbx/<dbx-file-2>
  • /etc/secureboot/keys/dbx/…

These files need to be in a certain format: signed EFI_SIGNATURE_LIST data. There's two other utilities in the sbtools tree to help to create the key files: sbsiglist and sbvarsign. The following example shows how you'd use these tools to do a basic secure boot key configuration.

An example key setup

If you're interested in trying sbkeysync, the following guide should get you set up. To start, you'll need:

  • A build of the secure boot tools (git repository information below);
  • A kernel with the efivars filesystem. Either build your own kernel with efivars-1f087c6.patch (from Matthew Garrett, with some minor changes), or use linux-image-3.5.0-13-generic_3.5.0-13.14~efivars1_amd64.deb, which should work on Ubuntu 12.04 or 12.10; and
  • A machine with firmware that implements UEFI secure boot, configured to be in setup mode (ie, no PK installed).

Be warned that you're playing with three different layers of development code here: the secure boot tools are new, the efivars implementation hasn't had a lot of review yet, and firmware secure boot implementations are still fairly recent too. I'd recommend against doing this testing on a production machine.

generating keys

We'll generate a test key, and a self-signed certificate:

[jk@pecola ~]$ openssl genrsa -out test-key.rsa 2048
[jk@pecola ~]$ openssl req -new -x509 -sha256 \
        -subj '/CN=test-key' -key test-key.rsa -out test-cert.pem
[jk@pecola ~]$ openssl x509 -in test-cert.pem -inform PEM \
        -out test-cert.der -outform DER

We'll also need a GUID to represent the "key owner". Just generate one with uuidgen.

[jk@pecola ~]$ guid=$(uuidgen)
[jk@pecola ~]$ echo $guid

generating key updates

In order to install this key into the firmware signature databases, we need to create an EFI_SIGNATURE_LIST container for the key, and provide an EFI_VARIABLE_AUTHENTICATION_2 descriptor. The update data will be self-signed, to keep things simple.

First, we create the EFI_SIGNATURE_LIST containing the certificate:

[jk@pecola ~]$ sbsiglist --owner $guid --type x509 --output test-cert.der.siglist test-cert.der

Next, we create a signed update for the EFI signature databases. The signed update consists of the certificate, prefixed with an EFI_VARIABLE_AUTHENTICATION_2 descriptor. The authentication descriptor signs the key data, plus the variable name and attributes. Becuase the variable name is included, we need to generate a separate signed update for each variable (PK, KEK and db):

[jk@pecola ~]$ for n in PK KEK db
> do
>   sbvarsign --key test-key.rsa --cert test-cert.pem \
>     --output test-cert.der.siglist.$n.signed \
>     $n test-cert.der.siglist
> done

creating a keystore

Next up, we'll put our keys into standard locations for sbkeysync to find:

[jk@pecola ~]$ sudo mkdir -p /etc/secureboot/keys/{PK,KEK,db,dbx}
[jk@pecola ~]$ sudo cp *.PK.signed /etc/secureboot/keys/PK/
[jk@pecola ~]$ sudo cp *.KEK.signed /etc/secureboot/keys/KEK/
[jk@pecola ~]$ sudo cp *.db.signed /etc/secureboot/keys/db/

If you'd rather use a different location for the keystore, just use the --keystore and/or --no-default-keystores arguments to the sbkeysync commands that follow.

using sbkeysync

We can now use sbkeysync to synchronise the firmware key databases with the keystore we just created. Do a dry-run first to make sure all is OK:

[jk@pecola ~]$ sbkeysync --verbose --pk --dry-run
Filesystem keystore:
  /etc/secureboot/keys/db/test-cert.der.siglist.db.signed [2116 bytes]
  /etc/secureboot/keys/KEK/test-cert.der.siglist.KEK.signed [2116 bytes]
  /etc/secureboot/keys/PK/test-cert.der.siglist.PK.signed [2116 bytes]
firmware keys:
  PK:
  KEK:
  db:
  dbx:
filesystem keys:
  PK:
    /CN=test-key
     from /etc/secureboot/keys/PK/test-cert.der.siglist.PK.signed
  KEK:
    /CN=test-key
     from /etc/secureboot/keys/KEK/test-cert.der.siglist.KEK.signed
  db:
    /CN=test-key
     from /etc/secureboot/keys/db/test-cert.der.siglist.db.signed
  dbx:
New keys in filesystem:
 /etc/secureboot/keys/db/test-cert.der.siglist.db.signed
 /etc/secureboot/keys/KEK/test-cert.der.siglist.KEK.signed
 /etc/secureboot/keys/PK/test-cert.der.siglist.PK.signed

The output will list the keys were found in the EFI key databases, keys found in the filesystem keystore, and which keys should be inserted to the EFI key databases to bring them in sync with the keystore.

If all looks good, we can remove the --dry-run argument to actually update the firmware key databases. However, be careful here - once a PK is enrolled, the machine is no longer in setup mode, and secure boot is enforced. At the very least, ensure that your firmware setup screens have a facility for returning your machine to setup mode, and/or removing the PK.

Note that some firmware implementations may require a reboot for the changes to take effect in the EFI variables. Before you do this though, you'll probably want to sign your bootloader, so that you can actually boot something!

signing a bootloader

Now that secure boot is enabled, it'd be nice if we actually had something to boot. Although it isn't recommended for production systems, we'll just sign the GRUB2 binary that's already there:

[jk@pecola ~]$ sbsign --key test-key.rsa --cert test-cert.pem \
        --output grubx64.efi /boot/efi/efi/ubuntu/grubx64.efi
[jk@pecola ~]$ sudo cp /boot/efi/efi/ubuntu/grubx64.efi{,.bak}
[jk@pecola ~]$ sudo cp grubx64.efi /boot/efi/efi/ubuntu/

reverting to setup mode

Theoretically, since we have the private-key component of PK, we can revert the machine from user-mode to setup mode. This requires writing an empty signed update to the PK variable:

[jk@pecola ~]$ : > empty
[jk@pecola ~]$ sbvarsign --key test-key.rsa --cert test-cert.pem \
        --attrs NON_VOLATILE,BOOTSERVICE_ACCESS,RUNTIME_ACCESS \
        --include-attrs --output empty.PK.signed PK empty
[jk@pecola ~]$ sudo dd bs=4k if=empty.PK.signed \
        of=/sys/firmware/efi/vars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c

However, I have not been able to reset the PK on all firmware implementations so far; there may be bugs in the signing tools (or firmware) that prevent the update from being properly verified. Because of this, I strongly suggest checking for the facility to clear the PK through your firmware setup screens before attempting to set the PK.

secure boot tools resources

If you'd like to check out the code, the following links may be useful:

Read more