I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
Note also that there’s one minor change this month. Here’s
the diff.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
Last week, it became public that there is an attack against Secure Boot, utilizing one of Microsoft’s utilities to install a set of security policies which effectively disables bootloader verification.
In the announcement, the authors liken the this vulnerability to a
“secure golden key”, referencing the Washington Post Editorial Board’s
suggestion of cryptographic back doors in their wildly
misguided apologia on cell phone decryption from 2014. On social
media, one author has gone so far as to declare Secure Boot dead. The
trade press has widely covered this as a leak of signing keys, and as
such treated this as a major vulnerability with long-term implications
for the ability to stop bootkits.
Rumours of My Death
The implication of a signing key leak is a strange analogy to make,
since no such key has been made public, as is the declaration that this
renders Secure Boot “dead”. Clear descriptions of what has actually
gone wrong have been published elsewhere, and while
these are vulnerabilities, they don’t defeat1 the Secure Boot
mechanism. The vulnerabilities are in the interaction of Microsoft’s
bootloaders and other tools. As such, Secure Boot can be used to
block those binaries, mitigating the issue and stopping exploitation.
In response, UEFI is distributing an
updated version of the
Secure Boot revocation list, aka dbx. dbx is used to remove
previously granted access from a UEFI driver or application, or from a
signing certificate, declaring that signature invalid or signatures with
the blacklisted certificate to be invalid. This update adds 64 new
individual signature entries into dbx, raising the total to 77. The
policy for issuing dbx updates has always been stated as requiring
well known public vulnerabilities or active exploitation in the wild, so
some entries may be for Microsoft bootloaders, while some are plausibly
batched updates for minor vulnerabilities in more obscure tools—vendor
drivers and tools which may have vulnerabilities but are not well known.
Obviously, a major malfunction has occurred
There has been some confusion about exactly what has been blacklisted,
as the original discoverers of the vulnerability note on their updated
website:
I checked the hash in the signature of several bootmgrs of several architectures against this list, and found no matches. So either this revokes many “obscure” bootmgrs and bootmgfws, or I’m checking the wrong hash.
As I’m sure they know, they did not check the wrong hash. It appears
Microsoft has only added dbx entries to blacklist bootloaders for
their ARM-based Windows RT platforms, on which you can normally not
disable Secure Boot. This seems to indicate that either Microsoft
does not believe x86 machines are vulnerable2, or that their threat
model has defined this as a major problem on one platform because you
can’t disable Secure Boot there, but not on the other, where you
normally can. It’s also likely that the threat model takes into
consideration whether they believe the exploit can be used manually or
is automatable, and on whether local presence is required at any point
of the exploit. Part of the impetus for such distinctions lies in the
economics of dbx entries.
When you update dbx, the system firmware performs a special append
operation which adds any entries in the new list which are not in the
existing list into the persistent storage, and the resulting value
represents the combined set of entries. On a typical system, that
storage is a different region of the same flash part as the system
firmware. That flash part is as small as the vendor can possibly make
it, due to market pressure to minimize the cost of goods sold for
system’s components, to keep the marginal revenue as high as possible.
In a market where pennies per machine can determine profitability, the
difference between shipping 10000 64Mb
W25Q64FV chips at $0.65132/per vs the 128Mb
W25Q128FV at $1.05315 is a decision that will receive significant
scrutiny. Even one-off machines for firmware developers often ship with
the smaller part3.
The result is that the governing principle for the minimum size of a
flash part you can ship winds up being the Windows logo requirements,
because the Windows logo certification includes participation with
Microsoft marketing programs, thus increasing revenue. Those
requirements mandate that in order to use the Windows logo, systems must
implement particular UEFI features, have certain defaults, et cetera. On
the subject of the flash part, they say: <blockquote><p>Reserved Memory for Windows Secure Boot UEFI Variables. A total of at least 64 KB of non-volatile NVRAM storage memory must be reserved for NV UEFI variables (authenticated and unauthenticated, BS and RT) used by UEFI Secure Boot and Windows, and the maximum supported variable size must be at least 32kB. There is no maximum NVRAM storage limit.</p></blockquote><figcaption class='quote-source'>System.Fundamentals.Firmware.UEFISecureBoot</figcaption>
Prior to this update, the shared dbx list was 13 entries, all
SHA-256 hashes of individual binaries, for a total of 680 bytes[^4].
This update adds 64 new entries, also all SHA-256 hashes of individual
binaries, which brings the size up 77[^5] entries taking 3780 bytes. This update is 9.5% of the guaranteed available space, and 11.5% is now
in use. The good news, though, is that each binary only needs to be
blacklisted once; any new exploit in the same binary is covered by the
same entry.
I say we take off and nuke the site from orbit. It's the only way to be sure.
Burning through a cool 10% of the space in one afternoon is obviously not a
sustainable plan, so you can see why one might conclude that this is a
death knell to Secure Boot. I don’t think that’s the case. There is
more we can do. In the worst case scenario, all signing keys are
re-generated, every vendor updates all their boot media, UEFI drivers,
and whatnot to have new signatures, and updates are issued to wipe dbx
completely4, add a dbx entry for the signing certificate, and add a
new signing certificate to db5. That’s clearly the nuclear
option, and there are some better options.
Currently the Microsoft bootloaders are signed by a certificate with
CN=Microsoft Windows, which is issued by CN=Microsoft Windows Production PCA
2011, and it in turn is issued by Microsoft’s CA, CN=Microsoft Root
Certificate Authority 2010, a self-signed CA certificate. The PCA certificate
in the middle of this chain is required by Windows logo requirements to be in a
system’s db.
For other UEFI binaries, such as drivers and bootloaders which aren’t from
Microsoft, the signing chain is different: they’re signed by CN=Microsoft
Windows UEFI Driver Publisher, which is issued by CN=Microsoft Corporation
UEFI CA 2011, and it is issued by CN=Microsoft Corporation Third Party
Marketplace Root, which is a self-signed CA certificate. As in the Windows
case, it’s the CA cert in the middle of the chain which is in the system’s
db.
This organization means it’s possible to have a slightly smaller nuclear option than just blacklisting everything—all of the Windows bootloaders can be blacklisted without blacklisting everything else. That’s obviously still not a palatable solution for Microsoft for this exploit, but it hints at changes in policy by the Signing Service and the CA that could help keep this situation from recurring.
As a first step, every organization getting anything signed should be under a signing cert unique to them, and those certificates should be periodically retired and replaced. Organizations that get a large number of binaries signed should be subdivided into different signing certificates and cycled more often, possibly with an intermediate CA certificate. That would enable blacklisting of either individual signing certificates or intermediate CAs[^8], removing relatively broad swathes of applications en masse, rather than having to blacklist individual binaries.
This is all more overhead, but the cost of generating more certificates, storing them appropriately on HSMs, and choosing which to use on a per-binary basis pales in comparison to the prospect of filling up the flash part with dbx entries. In this setup, the ARM Windows 8.1 RT signatures could have been issued by a series of signing certificates each issued by a single intermediate CA specific to that product. This could have been one entry in the blacklist. It would not have affected other versions of Windows or other products. It would have blacklisted the exact same list of binaries, taking up 76 bytes.
I’ve had vendors mail me the larger one and tell me to replace it before applying a test update. Good thing I’ve got that hot air rework station handy. ↩
I don’t think this will work at all with any OS’s current tooling, but that’s a surmountable problem. ↩
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
It’s probably worth mentioning where we are on firmware updates.
A bit of background
One common issue we’ve all had for the last couple of decades is
addressing bugs in system and peripheral firmware. For quite some time,
machines have had the ability to have their various firmwares updated.
Though these mechanisms have existed, they have generally been highly
proprietary, and the tools to perform updates have been difficult to use,
required manual, in-person operation, had a very different user interface
from each vendor, been difficult to mechanically apply to multiple
machines, and had various other usability issues. Vendors have solved
some of these problems in various ways, sometimes with the result of
exacerbating others.
The overall outcome has been that firmware updates are never applied to
the overwhelming majority of systems. You may have noticed this on
systems of your own. I myself recently discovered I had a laptop
firmware that was 54 releases behind current.
So, this has to be made better. And some things have happened that can
help make this better!
Things added to system firmware that can help this
UEFI 2.x has a feature called Update Capsule (or sometimes
Capsule updates), implemented with an EFI Runtime Services function
called UpdateCapsule(). This function is a relatively generic method
to let operating system code running before or after ExitBootServices()
pass a message, identified by a GUID, to the firmware. The message
itself is comprised of a header, which includes some flags and the
GUID, and a scatter-gather list of physical memory addresses (“the
capsule”).
In UEFI 2.5, a separate feature is added in section 22.3 called the
EFI System Resource Table, or ESRT. The ESRT is a UEFI configuration table
that provides a table of GUIDs to be used in capsule updates, each of which
specifies a hardware device which has upgradeable firmware, and associated
information such as the current firmware version and status of previous
attempts to upgrade that firmware.
Specifically, the ESRT formalizes the GUIDs for use in UpdateCapsule()
calls to initiate a firmware update, with the capsule (i.e. the
scatter-gather list) containing the new firmware. When UpdateCapsule() is
called with one of these GUIDs, the firmware performs some validation, and
if it is successful, then either an update will initiate immediately, or
it will initiate after a reboot. What this does not provide is
information to be used by the OS to match entries to specific hardware
devices, nor to firmware update files themselves - that all has to be
orchestrated externally. It’s just a list of which GUIDs are upgradeable
with UpdateCapsule() and the status of the firmware matching each GUID.
Higher level progress
Richard Hughes and I have
made a lot of headway on this. Currently we have a couple of projects
that can use this data and with which you can initiate firmware updates
on some test machines:
Linux 4.2 exposes the ESRT to userland via sysfs; see
gmane or the source or documentation in git for details.
fwupdate is a simple command line tool and a library which provides the bare functionality of scheduling an update. The command line utility doesn’t do a lot for you; you do something like fwupdate -a 6c1ce37d-3325-4654-98e2-318b4ca7e174 fwupdate.cap and it sets up BootNext for you to initiate the firmware update during the next reboot. The main purpose here is to provide libfwupdate.so for other tools to use. Right now this only works with local updates, i.e. you have to have an EFI System Partition, but support for other things like https are planned.
fwupd provides integration between libfwupdate.so and the desktop, and also provides support for keeping track of firmware update packages from your linux distro and matching them up with your hardware, providing useful descriptive text, etc. It provides command line tools that understand the metadata and know when there are new updates available from whomever you’re getting updates from, and extends this functionality into graphical tools and the GNOME Software update system.
Richard has also made a website with further information, including a (beta) website for uploading firmware to be distributed through distro’s mechanisms, instructions on how to get test accounts, etc. We’re looking for feedback on this and how we can make it as broadly usable as possible, for everyone involved.
So, what's next
Well, next is more system vendors participating, through supporting these
interfaces on their machines, providing test machine access so we can be
reasonably sure everything works on various platforms, and moving forward
on making sure the actual updated firmwares are as widely available as
possible by providing feedback on the various tools.
Most of the work on this so far has been done on x86 test machines,
because that’s what we have. I have written dummy drivers to test it
with OVMF and AAVMF on virtual machines, and verified that the code
does at least basically function on Aarch64, but we could really use
more support and testing from the ARM community.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
In this edition, there are a couple of changes! Don’t worry
though—they’re all just URLs being updated.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
When we talk about UEFI Secure Boot, a lot of times we talk about what we call the whitelist and the blacklist. These databases go by many names—formally EFI_IMAGE_SECURITY_DATABASE and EFI_IMAGE_SECURITY_DATABASE1, sometimes d719b2cb-3d3a-4596-a3bc-dad00e67656f:db and d719b2cb-3d3a-4596-a3bc-dad00e67656f:dbx, but most often just db and dbx. These two[^1] databases, stored in UEFI Authenticated Variables[^2], constitute lists of which binaries can and cannot be executed within a UEFI environment when Secure Boot is enabled.
When a UEFI binary is loaded, the system first checks to see if any
revocations in dbx are applicable to that binary. A dbx entry
may apply in three ways—it may contain the hash of a specific binary,
an X.509 certificate, or the hash of a certificate[^3]. If any of these
matches the binary in question, UEFI raises the error
EFI_SECURITY_VIOLATION, and your binary will not go to space today.
If a binary successfully passes that hurdle, then the same verification
method is processed with db, the whitelist, but with the opposite
policy: if any entry describes the binary in question, verification has
succeeded. If no entry does, EFI_SECURITY_VIOLATION is raised.
The need for updates
When a UEFI binary is discovered to have a serious security flaw which
would allow a malicious user to circumvent Secure Boot, it becomes
necessary to prevent it from running on machines. When this happens,
the UEFI CA issues a dbx update. The mechanism for the update is a file
that’s structured as a UEFI Authenticated Variable append. This file
gets distributed as part of an OS update, and when the update is
applied, the UEFI variable is updated.
One mechanism for doing this in Linux is via dbxtool. In Fedora, the
dbxtool package includes the current dbx updates in
/usr/share/dbxtool/DBXUpdate-2014-04-13-22-14-00.bin, as well as a
systemd service to apply them during boot[^4]. In the special case of
Fedora’s shim being added to a blacklist, we would include a
dependency on the fixed version of shim in the dbxtool package so
that systems would remain bootable.
The structure of a `dbx` update
The dbx variable is composed of an array of EFI_SIGNATURE_LIST
structures, each themselves containing an array of EFI_SIGNATURE_DATA
entries. A dbx update is that same structure, but wrapped in a
EFI_VARIABLE_AUTHENTICATION_2 structure to authenticate it. The
definitions look like this[^5]:
wincert.h
typedefstruct{
efi_guid_tSignatureOwner;// who owns this entry
uint8_tSignatureData[0];// the data we want to
// fish out of this thing
}EFI_SIGNATURE_DATA;
typedefstruct{
efi_guid_tSignatureType;// type of structure in
// EFI_SIGNATURE_DATA.SignatureData
uint32_tSignatureListSize;// Total size of the signature
// list, including this header.
uint32_tSignatureHeaderSize;// Size of type-specific header
uint32_tSignatureSize;// The size of each individual
// EFI_SIGNATURE_DATA.SignatureData
// in this list.
// uint8_t SignatureHeader[SignatureHeaderSize]
// this is a header defined by
// and for each specific
// signature type. Of course
// none of them actually define
// a header.
// EFI_SIGNATURE_DATA[...][SignatureSize] // actual signature data
}EFI_SIGNATURE_LIST;
typedefstruct{
efi_guid_tHashType;
uint8_tPublicKey[256];
uint8_tSignature[256];
}EFI_CERT_BLOCK_RSA_2048_SHA256;
typedefstruct{
uint32_tdwLength;// Length of this structure
uint16_twRevision;// Revision of this structure (2)
uint16_twCertificateType;// The kind of signature this is
//uint16_t bCertificate[0]; // The signature data itself. This
WIN_CERTIFICATEHdr;// Info about which structure this is
efi_guid_tCertType;// Type of certificate in CertData
uint8_tCertData[0];// A certificate of some kind
}WIN_CERTIFICATE_EFI_GUID;
typedefstruct{
EFI_TIMETimeStamp;// monotonically increasing
// timestamp to prevent replay
// attacks.
WIN_CERTIFICATE_EFI_GUIDAuthInfo;// Information about how to
// authenticate this variable
// against some KEK entry
}EFI_VARIABLE_AUTHENTICATION_2;
</pre></div></figure>
Conceptually, this means the structure we've got is:
[ dbx update file:
[ Authentication structure:
[ monotonic number | timestamp ]
[ WIN_CERTIFICATE Header ]
[ Cert Type ]
[ Certificate Data ] ]
[ EFI_SIGNATURE_LIST:
[ EFI_SIGNATURE_DATA ]
[ EFI_SIGNATURE_DATA ]
[ EFI_SIGNATURE_DATA ] ]
[ EFI_SIGNATURE_LIST:
[ EFI_SIGNATURE_DATA ]
...
[ EFI_SIGNATURE_DATA ] ]
... ]
So a full update looks something like this:
``` plain auth2.TimeStamp
00000000 da 07 03 06 13 11 15 00 00 00 00 00 00 00 00 00 |................|
```
2010-03-06 19:17:21 GMT+0000
``` plain auth2.AuthInfo.Hdr.DwLength
00000010 bd 0c 00 00 |.... |
```
It is 0x00000cbd bytes long[^6].
``` plain auth2.AuthInfo.Hdr.wRevision
00000010 00 02 | .. |
```
It's revision is 2. It is always revision 2.
``` plain auth2.AuthInfo.Hdr.wCertificateType
00000010 f1 0e | .. |
```
0x0ef1, which as we see above is `WIN_CERT_TYPE_EFI_GUID`. The interesting
bit here is that `.bCertificate` isn't quite a real thing. This is
actually describing that `auth2.AuthInfo` is a `WIN_CERTIFICATE_EFI_GUID`,
and `.bCertificate` is actually the fields other than `auth2.AuthInfo.Hdr`—`auth2.AuthInfo.CertType` and `auth2.AuthInfo.CertData`. Again, this
shouldn't confuse you at all.
As a result, next, in the place of `.bCertificate`, we have:
``` plain auth2.AuthInfo.CertType
00000010 9d d2 af 4a df 68 ee 49 | ...J.h.I|
00000020 8a a9 34 7d 37 56 65 a7 |..4}7Ve. |
```
`4aafd29d-68df-49ee-8aa9-347d375665a7`, aka `EFI_GUID_PKCS7_CERT`, which
means that `.CertData` is verified against `EFI_SIGNATURE_DATA` entries in
the Key Exchange Keys database (`KEK`), but only those entries which are
contained in `EFI_SIGNATURE_LIST` structures with `.SignatureType` of
`EFI_CERT_X509_GUID`. *Whew*.
``` plain auth2.AuthInfo.CertData
00000020 30 82 0c a1 02 01 01 31 | 0......1|
00000030 0f 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 |.0...`.H.e......|
[ what an X.509 certificate looks like is left as an exercise for the reader ]
00000cb0 b6 2b 89 02 73 c4 86 57 83 6f 28 57 e0 12 cb 05 |.+..s..W.o(W....|
00000cc0 6d d0 3e 60 8f 85 9f dd fc 46 ac 54 44 |m.>`.....F.TD |
```
Yep, that's an ASN.1 DER encoding of a PKCS-7 Certificate.
That's the end of the `EFI_VARIABLE_AUTHENTICATION_2` structure, and so on
to the actual *data*:
``` plain EFI_SIGNATURE_LIST.SignatureType
00000cc0 26 16 c4 | &..|
00000cd0 c1 4c 50 92 40 ac a9 41 f9 36 93 43 28 |.LP.@..A.6.C( |
```
That's c1c41626-504c-4092-aca9-41f936934328, aka `EFI_GUID_SHA256`
``` plain EFI_SIGNATURE_LIST.SignatureListSize
00000cd0 cc 01 00 | ...|
00000ce0 00 |. |
```
The list size is 0x00001cc bytes
``` plain EFI_SIGNATURE_LIST.SignatureHeaderSize:
00000ce0 00 00 00 00 | .... |
```
This is actually always 0.
``` plain EFI_SIGNATURE_LIST.SignatureSize
00000ce0 30 00 00 00 | 0... |
```
0x00000030 bytes. That's 16 bytes for the `efi_guid_t`, and since
`.SignatureType` was `EFI_GUID_SHA256`, 32 bytes of SHA-256 data.
``` plain EFI_SIGNATURE_DATA[0].SignatureOwner
00000ce0 bd 9a fa 77 59 03 32 |.....0......wY.2|
00000cf0 4d bd 60 28 f4 e7 8f 78 4b |M.`(...xK |
```
77fa9abd-0359-4d32-bd60-28f4e78f784b , which is the GUID Microsoft uses
to identify themselves[^7]
``` plain EFI_SIGNATURE_DATA[0].SignatureData
00000cf0 80 b4 d9 69 31 bf 0d | ...i1..|
00000d00 02 fd 91 a6 1e 19 d1 4f 1d a4 52 e6 6d b2 40 8c |.......O..R.m.@.|
00000d10 a8 60 4d 41 1f 92 65 9f 0a |.`MA..e.. |
```
This is the actual SHA-256 data. It goes on like this:
``` plain EFI_SIGNATURE_DATA[1..8]
00000d10 bd 9a fa 77 59 03 32 | ...wY.2|
00000d20 4d bd 60 28 f4 e7 8f 78 4b f5 2f 83 a3 fa 9c fb |M.`(...xK./.....|
00000d30 d6 92 0f 72 28 24 db e4 03 45 34 d2 5b 85 07 24 |...r($...E4.[..$|
00000d40 6b 3b 95 7d ac 6e 1b ce 7a bd 9a fa 77 59 03 32 |k;.}.n..z...wY.2|
00000d50 4d bd 60 28 f4 e7 8f 78 4b c5 d9 d8 a1 86 e2 c8 |M.`(...xK.......|
00000d60 2d 09 af aa 2a 6f 7f 2e 73 87 0d 3e 64 f7 2c 4e |-...*o..s..>d.,N|
00000d70 08 ef 67 79 6a 84 0f 0f bd |..gyj.... |
...
00000e60 bd 9a fa 77 59 03 32 | ...wY.2|
00000e70 4d bd 60 28 f4 e7 8f 78 4b 53 91 c3 a2 fb 11 21 |M.`(...xKS.....!|
00000e80 02 a6 aa 1e dc 25 ae 77 e1 9f 5d 6f 09 cd 09 ee |.....%.w..]o....|
00000e90 b2 50 99 22 bf cd 59 92 ea |.P."..Y..|
```
How the structure is used
When you apply a database update, you're basically doing a `SetVariable()`
call to UEFI with a couple of flags set:
``` c
rc = efi_set_variable(EFI_IMAGE_SECURITY_DATABASE_GUID, "dbx", data, len,
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS |
EFI_VARIABLE_APPEND_WRITE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_NON_VOLATILE);
```
These flags tell the firmware some crucial things - that this variable
is authenticated with the `EFI_VARIABLE_AUTHENTICATION_2` structure, that
this is an append, that both *Boot Services* (i.e. the firmware) and *Runtime
Services* (i.e. the OS) should have access to it, and that it should
persist across a reboot. As a special case in the spec, an append has a
special meaning for the UEFI security databases:
For variables with the GUID EFI_IMAGE_SECURITY_DATABASE_GUID (i.e. where the data buffer is formatted as EFI_SIGNATURE_LIST), the driver shallnot perform an append of EFI_SIGNATURE_DATA values that are already part of the existing variable value.
Note: This situation is not considered an error, and shall in itself not cause a status code other than EFI_SUCCESS to be returned or the timestamp associated with the variable not to be updated.
UEFI Specification section 7.2.1 revision 2.4
As a result, what happens here is that the first time you write to
`dbx`, any `EFI_SIGNATURE_LIST` structures and the `EFI_SIGNATURE_DATA`
entries they contain get added to the variable, but not the
`EFI_VARIABLE_AUTHENTICATION_2` structure. Then when later `dbx`
updates are issued, they contain a superset of the previous ones. When
you apply them, the firmware only appends the difference to the
variable.
Tools
Obviously a system this complex needs some tools. To manage these
databases on linux, I've written a tool called `dbxtool`, which may
be available in your linux distribution of choice. It can be used to
apply `dbx` changes[^8], to list the contents of the UEFI Security
Databases, and to list the contents of updates files:
As usual, there are a couple of places where vendors have not gotten
everything quite right, and sometimes things fail to work correctly—but
that's for another post.
[^1]: There is actually a third in this set, `dbt`, which can be used in revocation processing.
[^2]: Strictly speaking these are only an analog to *Authenticated Variables*, which can only be appended to, replaced, or deleted by updates signed with the key that created them. Key database updates are instead controlled by a list of keys stored in another variable called `KEK` - the Key Exchange Keys. Otherwise the mechanism is the same.
[^3]: That is, the digest of the certificate's `TBSCertificate` as defined in RFC 5280 section 4.1.1.1, using the digest specified in the database entry itself.
[^4]: This is currently disabled by default in Fedora. I'm looking at enabling this as an F22 feature. Getting these things right is important, and it takes time.
[^5]: I have left out the definitions of `EFI_TIME` and `efi_guid_t`; they are quite boring.
[^6]: Here `dwLength` includes the size of `Hdr` itself (that is, the size of `dwLength`, `wRevision`, and `wCertificateType`) as well as the data following it (`bCertificate`). Because we live in the best of all possible worlds, Authenticode signatures—the signatures on binaries themselves—use the same structure but only include the size of `Hdr.bCertificate`. This hasn't ever confused *anybody*.
[^7]: Big congratulations to Acer, who used 55555555-5555-5555-5555-555555555555 for this in one of their db entries. Not only did they win the random number generator lottery to get that, but also experienced a minimum of 3 single bit errors, since the closest valid GUID to that is 55555555-5555-4555-9555-555555555555.
[^8]: Also theoretically `db` updates, `dbt` updates, and `KEK` updates, but those are much more rare.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
This message fixes a small grammar error from the previous one and adds
a section about CentOS and Secure Boot.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
After the big kerfuffle with TrueCrypt, it seems clear to me that I need
to make some statements about Secure Boot and any interaction with
governments whose regimes I fall under.
I’m going to try to remember to post a message like this once per month
or so. If I miss one, keep an eye out, but maybe don’t get terribly
suspicious unless I miss several in a row.
Note that there are parts of this chain I’m not a part of, and obviously
linux distributions I’m not involved in that support Secure Boot. I
encourage other maintainers to offer similar statements for their
respective involvement.
A lot of the time, we talk about creating a partition to serve as the
EFI System Partition. This partition is mandated by the UEFI
specification for several tasks. Adam covered what’s going on at a
relatively high level on his recent blog post, and you should read the
whole thing:
An ‘EFI system partition’ is really just any partition formatted with one of the UEFI spec-defined variants of FAT and given a specific GPT partition type to help the firmware find it. And the purpose of this is just as described above: allow everyone to rely on the fact that the firmware layer will definitely be able to read data from a pretty ‘normal’ disk partition.
There’s nothing truly special about an ESP. It isn’t an ESP because of
the GPT GUID and label, nor because of the file system type. Those are
how the firmware identifies a partition, and the file system it contains,
as candidates to treat as the ESP, when it really needs to find one. The
only factor in determining if a partition is the ESP is this: is the firmware
attempting to use it as the ESP?
At the same time, the requirements for the ESP give us latitude; we know
that we can use UEFI’s APIs to find correctly constructed FAT file systems,
but there’s no need for those to be the ESP. In fact, even when we create
multiple partitions with the ESP’s GUID and label, there’s no requirement
that the firmware looks at more than one of them if it needs to find the
ESP, and there’s no guarantee as to which one it will pick, either.
Normal booting
Thankfully, most of the time we don’t care. Under normal circumstances,
the system isn’t actually looking for something to fill the role of the
ESP. When the system starts up, it consults the BootOrder, which is
just a list of 16-bit numbers, such as BootOrder: 0001,001A,0003.
When this is found, the firmware will iterate the list, as you might
expect. For each entry in the list, it looks for a corresponding
Boot#### variable — Boot0001 for 0001, Boot001A for 0x001a, and so
on, with the value from BootOrder rendered in capitalized
hexadecimal. If it doesn’t find the variable, it continues to the next
entry in BootOrder. If it does find the variable, it reads the contents
of the variable to try to decide what to do. Generally speaking, what’s in
there is a human friendly label, a Device Path like ACPI(a0341d0,0)PCI(1f,2)SATA(0,0,0)HD(1,800,64000,12029cda-8961-470d-82ba-aeb17dba91a5)File(\EFI\fedora\shim.efi), and optional data to be passed to whatever program is to be loaded.
This Device Path reflects the series of parts that need to be initialized
in order to find the ultimate media device HD(1,800,64000,12029cda-8961-470d-82ba-aeb17dba91a5)1, which specifies a partition number, the partition’s
offset and size, and the partition’s GUID.
This partition need not be an “EFI System Partition” properly; the
firmware doesn’t care if the GUID in the partition table is the ESP
GUID, only that it matches the GUID in the Device Path. Likewise, it
doesn’t care about the label. This file system may be the ESP,
but there’s no requirement. The only real requirement here is that we
have to use FAT, because it’s the only file system the firmware is
guaranteed to know about.
At this point, the system firmware is going to initialize each device that’s
part of that Device Path, in order, that hasn’t already been initialized.
Some things will always be initialized — it’s unlikely that ACPI tables
and the PCI root hub specified in this particular path2 weren’t already
needed to get this far — but other things, like the SATA controller or
its port 0, port multiplier 0, LUN 0 device, SATA(0,0,0)3, will probably
need to be initialized. Once that is done, the firmware will examine the
disk and see if it has a partition matching the HD() path above. If it
finds that, and it contains a FAT file system, it looks for File(\EFI\fedora\shim.efi).
If any of that goes wrong, it moves on to the next Boot#### entry,
and follow the exact same process, initializing one peripheral at a time
until it can load a file from the FAT it finds.
What if everything we know is wrong?
If all of that fails, and there is no working boot entry found by
traversing BootOrder, there are still things to do. At this point, the
firmware will start initializing all peripherals it can find, in whatever
order it happens to choose — for some peripherals this will be linear and
predictable, for some it will start things all at once and they’ll respond
in whatever order they become ready. For each media device it finds, it will
check if it’s a removable device, such as optical media, or a fixed device
like a hard drive. At this phase, the firmware only considers removable
devices. On each of those, it looks for an EFI System Partition4 with
a FAT file system using whatever method it knows for that type of media,
and if it finds one, it checks for\EFI\BOOT\BOOTX64.EFI5.
Typically, if it finds a removable device it can boot, that’s because
you have your OS install image connected in some way, which may well be
an indicator that you’re trying to start the OS installer. It’s also
possible you’ve installed to removable media, or you’re running off a
live image.
If it doesn’t find suitable removable media, or if a failure condition
is returned by the application it tries to start, it continues traversing
all removable media until it has exhausted the possibilities.
If it still hasn’t found any removable media it can boot, the firmware
will move on to fixed media. At this point, all media is probably
discovered — you may have hot-plugged a USB stick or something, but don’t
plan on that sort of action working reliably at this stage. Since there’s
no real device or media discovery left to do, the firmware is going to
iterate back over the devices once more, and will try to start each fixed
media device in the same manner it previously did with the removable
devices - it will look for an ESP, and try to start
\EFI\BOOT\BOOTX64.efi. This is known as the “Default Boot Behavior”.
The Default Boot Behavior
On Fedora systems, and likely any other OS using shim, we handle the Default
Boot Behavior through a utility shim provides named fallback.efi. Our
signed shim package provides several files, all of which reside on
whichever partition we’ve mounted as the ESP, which is mounted at
/boot/efi:
/boot/efi/EFI/BOOT/BOOTX64.EFI
/boot/efi/EFI/BOOT/fallback.efi
/boot/efi/EFI/fedora/BOOT.CSV
/boot/efi/EFI/fedora/MokManager.efi
/boot/efi/EFI/fedora/shim-fedora.efi
/boot/efi/EFI/fedora/shim.efi
When we’re operating under the Default Boot Behavior, the system
firmware launches the Device Path File(EFI\BOOT\BOOTX64.EFI), which
corresponds to /boot/efi/EFI/BOOT/BOOTX64.EFI on our file system.
This is actually just another copy of /boot/efi/EFI/fedora/shim.efi,
but it behaves slightly differently.
Upon startup, shim checks to see if it’s been launched from
\EFI\BOOT6. If it has, it checks to see if there’s another file in
this directory called fallback.efi, which our shim package
provides on an installed system, but which we purposefully omit from
removable media. If it finds fallback.efi, it executes it as a normal
UEFI application.
fallback.efi
It is expected that this default boot will load an operating system or a maintenance utility. If this is an operating system setup program it is then responsible for setting the requisite environment variables for subsequent boots.
UEFI Specification section 3.3 revision 2.4
As you may well have come to realize, the purpose of fallback.efi is
to rebuild boot options in the case that BootOrder or the Boot####
variables it references have been destroyed, or the case that you’ve
moved a fixed disk between machines with the intent on booting from it.
When fallback runs, it queries the firmware for the disk from which it
was loaded. It then iterates over every subdirectory of \EFI on that
disk that isn’t BOOT, looking for files named BOOT.CSV. On Fedora,
we provide such a file in \EFI\fedora\BOOT.CSV. This file is a UCS-2
file of comma separated values, and its contents look like this:
shim.efi,Fedora,,This is the boot entry for Fedora
For each valid entry in each BOOT.CSV file it finds, fallback creates a
new Boot#### variable and appends it to BootOrder. In this case
it creates a boot entry with the label ‘Fedora’, with a Device Path
that points to the disk fallback was run from, and the file path
corresponding to the directory in which shim found this particular BOOT.CSV,
with the first entry in the CSV appended: File(\EFI\fedora\shim.efi)
Once fallback has finished iterating all the CSV files in all the
directories other than BOOT, it boots the first option it has added. On
the next reboot, there will be a BootOrder variable, and its first
entries will be whichever Boot#### variables fallback created.
Astute readers will no doubt notice that often we have device paths with only the HD(1,800,64000,12029cda-8961-470d-82ba-aeb17dba91a5) and File(\EFI\fedora\shim.efi) components. The spec allows this explicitly, and in this case it initializes every peripheral in no particular order until it finds a partition matching that Hard Disk Media Device Path, and the appropriate file on it. ↩
In this case ACPI(a0341d0,0) represents the PCI Express Root Port on my CPU, and PCI(1f,2) is what lspci whould show as 00:1f.2 SATA controller: Intel Corporation 6 Series/C200 Series Chipset Family SATA AHCI Controller (rev 05). ↩
Yes, seriously, SATA(0,0,0) represents the disk and HD(1,800,64000,12029cda-8961-470d-82ba-aeb17dba91a5) represents the partition on it. I’m so sorry. ↩
Strictly speaking, the firmware is required to check one partition which has the correct GUID and label in GPT and is a FAT file system. It is allowed to check partitions without that GUID and label, but you can’t depend on it, and it is allowed to check other partitions that have file systems it understands, but you can’t depend on that either. ↩
Or whatever file name is appropriate on your architecture. ↩
I’m using backslashes for paths seen by code that’s running under UEFI, and forward slashes for code running under Linux, because that’s what those parts of the system typically use. ↩
James Bottomley recently posted an
item
regarding problems he’s seen involving UEFI binaries’ signature alignment,
and I’d like to fill in a bit more detail.
UEFI systems use Microsoft’s PE/COFF binary format, with a modification in the headers to reflect the status as
UEFI binaries rather than Windows Executables or DSOs. When the UEFI
Spec Working Group (USWG) began considering how to specify Secure Boot,
the obvious route was to use Microsoft’s binary signing system,
Authenticode.
Authenticode appears, at first glance, to be a straightforward signing
system. Specific parts of a binary are digested with a cryptographic hash —
in Secure Boot’s case, generally SHA-256 — and that hash is used in a PKCS#7
signature. The result is embedded in a special section of the binary,
the “Certificate Table”. Neither the pointer to the Certificate Table, nor
the table itself are included in the hashing, and so the same algorithm can
be used during verification. Hash the binary, find a signature in the
Certificate Table, and compare the stored hash from that signature to the
one you’ve computed. If they match, the signature is for this binary,
if they don’t, the binary has been modified. Once the hash has been
verified, it’s a simple matter of checking the authorization of the
signer against your system’s certificate databases, and you know whether
to allow execution.
Except it’s not that simple.
In a PE/COFF binary, the Certificate Table is found by looking at a
particular entry in an array known as the Data Directory. This entry
contains a file offset for the table, as well as the size that the table
takes up in the binary. Inside the table itself, there’s a header with a
size, a version code, and a GUID to show that the body is an PKCS#7
signature. Given that it’s described as a table and clearly set up so the
container can be larger than a given signature, the natural conclusion
is that this is an array, and multiple signatures are allowed.
When I implemented pesign, I erroneously assumed that this was a packed
array of signatures. When multiple signature support was added to
Tiano, the UEFI reference implementation,
the same assumption was made. Testing commenced, and the two worked
together just fine.
Some time later, somebody noticed that the Tiano code was not in
compliance with the specification. PE/COFF version 6.0 states:
Notice that certificates always start on an octaword boundary. If a certificate is not an even number of octawords long, it is zero padded to the next octaword boundary. However, the length of the certificate does not include this padding and so any certificate navigation software must be sure to round up to the next octaword to locate another certificate.
Aside from the constant use of the word “certificate” to refer to a
signature, or the use of “octaword”, which has never confused anybody, I’m
sure, what this says is that if you compute the address to put the
Certificate Table, and that address isn’t on an 8 byte boundary — that is,
the address modulo 8 is not zero — then you should round it up to the next
8 byte boundary. But it doesn’t really cover the array-like nature of
the table — in fact, this version of the specification doesn’t really
treat it as more than a single entry, though the data structure to allow
you to treat it as an array is present.
In version 8.0, which UEFI binaries were standardized against, the format
slightly changed, as did the language. The only mention of this
alignment requirement is now (in 8.0 and 8.3):
The attribute certificate table is composed of a set of contiguous, octaword-aligned attribute certificate entries.
and <blockquote><p>Notice that certificates always start on an octaword boundary. If a certificate is not an even number of octawords long, it is zero padded to the next octaword boundary. However, the length of the certificate does not include this padding and so any certificate navigation software must be sure to round up to the next octaword to locate another certificate.</p></blockquote>
Ignoring for the moment that “contiguous” and “octaword-aligned” stand in
opposition to each other, this spells out how to structure the list in
more detail than older versions of the specification.
This all brings us to Tiano revisision 14141:<blockquote><p>Update the DxeImageVerificationLib to support for Authenticode-signed UEFI images with multiple signatures.
Signed-off-by: Fu Siyuan siyuan.fu@intel.com
Reviewed-by: Ye Ting ting.ye@intel.com
Reviewed-by: Dong Guo guo.dong@intel.com</p></blockquote>
Among other changes is this:
- //
- // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
- //
- if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
This, for the first time in UEFI code, enforce alignment requirements on
the signatures embedded in the binary.
As a result, signers have needed to be fixed to properly reflect this
requirement. In pesign, that work was done in March of 2012. But this,
once again, isn’t as simple as it seems.
Typically the Certificate Table is the very last thing in the binary —
after all, it’s the last change you’re going to make, or else it’s going
to be full of invalid signatures. In UEFI, you can either enroll a
certificate into the security databases, or you can enroll the hash of a
specific binary. When you have an unsigned binary, there’s no guarantee
of what the size of the binary will be. If the last section happens to
be full of structured data, it will probably end on an alignment that
matches that of that data. If the last thing is a string table or
executable code for an 8086 CPU, it could end at any offset. So there’s
basically only a one in eight chance that it’s aligned correctly for
appending the Certificate table. If it isn’t, then you pad to the right
alignment before appending the table.
When the signature is calculated on a binary with a Certificate Table,
that padding is included in the data being digested. The inevitable
conclusion is that the Authenticode hash of a signed binary is not
guaranteed to be the same as the hash of the exact same binary if it has
never been signed.
So now in addition to “pesign –sign”, the command to sign a binary, and
“pesign –hash”, which outputs the hash of a binary so you can enroll it
specifically, pesign now also supports “pesign –hash –pad”, which you
can use to find out what the hash of an unsigned binary would be,
were it signed.
This all went in to pesign 0.104, released Wed Mar 27 09:41:52 2013 -0400 .
Edit:
Just in case anybody is interested, in Fedora, we tracked this issue
with bug
963361.
Today I received a flier for your campaign for City Council. This in
itself is not particularly surprising. The method by which it was
delivered, however, is wholly unacceptable.
When campaign workers stuff campaign fliers haphazardly into the edges
of urban mail boxes, it sends a clear signal: this campaign is about the
candidate, not the voters. There are several problems with stuffing
fliers into mail boxes this way: illegality and dangers you’re placing
on voters being the most obvious.
Make no mistake — this behavior is illegal. Under DMM 508, section
3.1.3, your campaign owes postage on fliers delivered this way.
Defrauding the government is a fairly bad sign for your dedication to
the rule of law. If you’re willing to violate such simple regulations
for a quick buck, why would a voter think you’re not willing to violate
other laws?
Additionally, leaving mail dangling from a mail box places the
recipient’s property in danger. Most urban mail boxes are closed and
locked for a reason. If you leave mail dangling outside an urban
mail box, you’re sending a message regarding that residence was last
checked in on. Especially in the late Summer, this is a clear way to
measure the vulnerability of a residence to theft.
Aside from the above, it’s sloppy and insulting to have your flier include
a signature and a hand written note which are clearly in different hand
writing, especially if the names in the note clearly include outdated
entries from voter roles which don’t match the names printed on the actual
mail box. I know your campaign workers are just going door to door and
stuffing them in mail boxes, and that these fliers have been prepared
ahead of time, but the careless failure of attention to detail just
seems patronizing.
A lot of work has recently been going on in terms of Secure Boot support
on Fedora. Recently we’ve set up builders with a special configuration
for signing appropriate packages, provisioned keys onto hardware
cryptographic devices to keep them safe in the event of an intrusion,
and started building packages with our production signing keys.
What's next
The next step will be to have shim signed by the UEFI signing
service. But there’s still much that can be done before we cross that
threshold, and we could use help from those that have appropriate
hardware to test with. Today, Fedora-signed packages for shim and
grub2 have been built, and they’ve got updates filed in Bodhi for
Fedora 18: here for shim and here for grub2. Sometime soon - most likely
tomorrow - we’ll build a kernel that will be signed by the production
keys as well. You can tell if it’s a signed kernel by viewing the build
log. Look for this:
If the “-t” argument to pesign-client says “OpenSC Card (Fedora
Signer)”, then it’s the correct build. I’ll post an update here with the
relevant kernel build as well.
Once that happens, those of you who already have Fedora 18 test composes
installed using UEFI on hardware that supports secure boot can help test.
The test procedure
First, ensure that your machine is in “setup” mode - that is, Secure Boot
is disabled, and no keys are enrolled. Once you’ve done that, install the
updated shim, grub2, and kernel packages, and then it’s time to install
some new keys. Download this utility into /boot/efi/EFI/fedora/ . Now you’ll need to run
this utility from your UEFI firmware. Unfortunately how to do that will
vary across many systems, so you’re on your own figuring that out. Once
you’ve run it, reboot the machine one more time so that the settings are
live.
Now the machine should be booting in Secure Boot mode signed with the
Fedora keys.
One thing we’ve heard several times during the discussions of the UEFI
“Secure Boot” mechanism is that there’s no genuine security benefits. In
fact there are several. The ability to guard against “bootkit” systems has
been covered elsewhere, so I’ll not cover it here. Instead, I’d like to
focus on a less publicized aspect of Secure Boot’s mechanism.
With secure boot, it’s possible to verify any UEFI application which has
been signed. There’s a reasonable standard of attestation that if a binary
has been signed by our key, it was consciously signed by us.
A simple example
One side effect of this is that with a few hoops, we can sign arbitrary
data, and wrap it in a UEFI envelope. Such code would look something like:
</pre></div></figure>
At this point you'd build it like any ```gnu-efi``` application, and then
have it signed as a UEFI application.
At this point you've got an envelope for data which is signed and explicitly
trusted by your hardware platform. At runtime, you can verify the signature
against ```DB```, the UEFI key database, and verify that this is a trusted
binary. At that point in time you can unwrap the UEFI binary to get at
the ELF DSO that fundamentally lies underneath, and examine the DSO. If
you do "eu-readelf --section-headers ${file}" on the DSO, you'll see that
there are 21 section headers. Here's a subset:
Section Headers:
[Nr] Name Type Addr Off Size ES Flags Lk Inf Al
[ 0] NULL 0000000000000000 00000000 00000000 0 0 0 0
[ 1] .hash HASH 0000000000000000 00200000 00000690 4 A 9 0 8
[ 2] .eh_frame PROGBITS 0000000000001000 00201000 000016b0 0 A 0 0 8
[ 3] .text PROGBITS 0000000000003000 00203000 000053bd 0 AX 0 0 16
[ 4] .reloc PROGBITS 0000000000009000 00209000 0000000a 0 A 0 0 1
[ 5] .data.hellothere PROGBITS 000000000000a000 0020a000 00000004 0 WA 0 0 4
[ 6] .data PROGBITS 000000000000a020 0020a020 00001770 8 WA 0 0 32
.data.hellothere starts at 0x20a000 and is 4 bytes long.
Something with more substance
What's this useful for, you ask? Well, let's assume we've got a slightly
different binary:
keys.c
One additional component here is packaging. If we package the file on a per-repo basis, with a well known name, there's a bit more.
So let's say, for example, that we can have ```${repo}-release``` provide a file, ```/etc/pki/sbkeys/${repo}-keys.efi```, which looks roughly like what's shown above.
At this point, we can add the extraction code to anaconda and kickstart, and we can automatically import trusted keys for any repository that includes a correctly signed keyfile. This is bug 253897, a bug that's been open for 5 years.
Wait for it
There's an even larger goal here - bug 253897 is the remaining blocker on bug 998, open since 1999.
With the above system, we can enable signature checking for all packages during installation.
One of the many things I work on is UEFI support. It’s an interesting thing to
work on, in part because there’s a lot of new development and it’s at a fairly
low level, which is just the sort of thing I like.
Often during UEFI development, we’ll see a bug and need to diagnose whether
it’s a problem with the hardware, the firmware, the bootloader, the OS kernel,
or even a userland program. One case of this is when console graphics don’t
work right.
A recent bug reported that console graphics weren’t working due to an invalid
pixel format being chosen. While diagnosing this problem, there are a couple
of things that could go wrong. The firmware driver could be reporting the
wrong modes, the bootloader could have a bug where it’s querying the modes
incorrectly or misinforming the kernel as to the mode chosen, or the kernel
could have a bug where it uses the mode incorrectly. It’s also possible that
the console works until a KMS driver - that is, a native driver for the card -
is loaded.
In UEFI, console graphics involves every part of the stack. The system firmware
provides an API known as Graphics Output Protocol, or GOP. The
algorithm used by the bootloader basically looks like this somewhat simplified
function:
</pre></div></figure>
This is a simplified version - for more details, check out efigraph.c for the excrutiating details.
```set_kernel_params()``` in turn fills out the data structure we give to the
kenrel, which then uses the efifb driver to configure a framebuffer console
with the correct resolution and pixel format.
Clearly, there is plenty that can go wrong here. With that in mind, I wrote
a tool called modelist.efi to debug some of these problems.
In the bug, I'm told:
With a 1280x1024 capable monitor connected to a censored or censored in
uEFI mode, the remote video redirection via BMC (censored) does not display
anything. The reason is that the efifb driver chooses the VGA mode
1280x1024x32bpp which the video redirection doesn’t support (the censored
chip doesn’t support video modes that need more than 4MB video RAM).
See also bug #XXXXXX for the same problem reported in the past for Xorg / mga
driver.
efifb: probing for efifb
efifb: framebuffer at 0x90000000, mapped to 0xffffc90011800000, using 8192k,
total 8192k
efifb: mode is 1280x1024x32, linelength=5120, pages=1
efifb: scrolling: redraw
efifb: Truecolor: size=8:8:8:8, shift=24:16:8:0
fbcon: EFI VGA (fb0) is primary device
Console: switching to colour frame buffer device 160x64
fb0: EFI VGA frame buffer device
With the knowledge of how the stack works in mind, I know that we need to find
out what the firmware is actually returning to the bootloader in order to tell
what layer the problem is at, so I ask:
Can you run /boot/efi/EFI/redhat/modelist.efi (from the gnu-efi package) and
show us the output?
So this tells me that the firmware is listing 4 video modes, each of which has
a 32-bit pixel of the form (blue,green,red,reserved). At this point we know
that the firmware is telling us about modes that the hardware cannot support,
and efifb cannot correctly support this device until the firmware is fixed.
It's important to have and use the right tools.
The Economist has run an article this week that’s left me quite disappointed. In A tangled web, they make an attempt to explain the question of Net Neutrality without taking sides. In doing so, some critical details of the history of the debate are omitted and biased terms are allowed to stand without serious discussion. This leaves the reader in a position where forming an unbiased understanding of the facts is impossible. The result is a rather more biased viewpoint than I’ve come to expect from The Economist. The article’s major failings are twofold. It forms a broad analogy which doesn’t hold up to scrutiny - that “fast-tracking” and “pay for priority” are the same thing - and fails to appropriately distinguish between backbone “transit” (bandwidth between ISPs) and end-user bandwidth.
Fast tracking, they explain, is the practice of being able to pay more money to an ISP to get a faster internet connection. “Pay for priority”, in contrast, is a term used by service providers to describe selling ad-hoc services to a consumer. The problem with the latter is in the details. To implement “pay for priority”, they must limit bandwidth on a per-service basis for other services - either at the transit level or at routers that service individual consumer connections. This necessarily means interfering with network connections, stifling connections that don’t originate at their services in order to provide services to their customers faster. There are several methods which can be utilized for this, ranging from simply providing insufficient transit bandwidth to actively tampering with user’s connections.
The transit method requires that the ISP is also fulfilling the role as content provider, which is the normal case in practice. This method is to simply have much more bandwidth between the ISP’s content servers and the customer than the amount of bandwidth customers demand to other content providers, or to artificially restrict bandwidth between the ISP customers and outside content. This is what they refer to as “reasonable network management”, but it’s anything but reasonable. Under this scenario, an ISP customer buys (for example) 20Mb/s of download bandwidth. But what the customer actually receives is 20Mb/s of download bandwidth from content their ISP hosts, and severely limited bandwidth to other content providers. This is essentially what Comcast wants to do with Netflix bandwidth - they want Netflix’s ISP, Level 3, to pay extra to send data to Comcast’s internet customers, or Comcast will limit their customers’ access to Netflix’s streaming video data.
What the cable companies want agency to do concerning their ISP customers, however, is not limited to merely extortive practices with other content providers’ data. Nor have they attempted to charge their ISP customers more in order to provide more bandwidth to outside content. When Comcast decided that bittorrent was in competition with their TV and movie content interests, for example, they didn’t simply block all bittorrent traffic and demand a fee from their ISP customers for access to the service. In this case there was no individual company from which to extract fees, since bittorrent is a so-called peer-to-peer service, where traffic originates at individual ISP customers both inside and outside of Comcast’s network. Instead, they intentionally modified their ISP customers’ bittorrent traffic by introducing fake packets which reset their customers’ connections, dramatically increasing the protocol overhead for any bittorrent users to the point where the service was not usable. The customer saw what was a technically functioning service, but with performance so degraded that nobody would want to use it. This is what “pay for priority” means in practice. In short, it’s institutionalized fraud: in theory the consumer is paying for bandwidth, a commodity, from an ISP, but in practice the ISP has control over what the customer can use that bandwidth for - thus relieving it of commodity status.
While the article’s conclusion - that lack of competition among service providers is a large problem which must be addressed - is correct, the authors fail to understand that allowing service providers to discriminate among services being carried through the connections leaves an Internet where price discrimination for access to bandwidth is irrelevant.