https://mjg59.dreamwidth.org/66907.html
Account name: [ ] Password [ ] [Log in]
(OpenID?) (Forgot it?) [ ] Remember Me
You're viewing [personal profile] mjg59's journal
Create a Dreamwidth Account Learn More
[ ] [Interest ] [Go]
Reload page in style: site light
Matthew Garrett
Roots of Trust are difficult
Roots of Trust are difficult
Jul. 11th, 2023 12:58 am
[personal profile] mjg59
The phrase "Root of Trust" turns up at various points in discussions
about verified boot and measured boot, and to a first approximation
nobody is able to give you a coherent explanation of what it means
[1]. The Trusted Computing Group has a fairly wordy definition, but
(a) it's a lot of words and (b) I don't like it, so instead I'm going
to start by defining a root of trust as "A thing that has to be
trustworthy for anything else on your computer to be trustworthy".
(An aside: when I say "trustworthy", it is very easy to interpret
this in a cynical manner and assume that "trust" means "trusted by
someone I do not necessarily trust to act in my best interest". I
want to be absolutely clear that when I say "trustworthy" I mean
"trusted by the owner of the computer", and that as far as I'm
concerned selling devices that do not allow the owner to define
what's trusted is an extremely bad thing in the general case)
Let's take an example. In verified boot, a cryptographic signature of
a component is verified before it's allowed to boot. A
straightforward implementation of a verified boot implementation has
the firmware verify the signature on the bootloader or kernel before
executing it. In this scenario, the firmware is the root of trust -
it's the first thing that makes a determination about whether
something should be allowed to run or not[2]. As long as the firmware
behaves correctly, and as long as there aren't any vulnerabilities in
our boot chain, we know that we booted an OS that was signed with a
key we trust.
But what guarantees that the firmware behaves correctly? What if
someone replaces our firmware with firmware that trusts different
keys, or hot-patches the OS as it's booting it? We can't just ask the
firmware whether it's trustworthy - trustworthy firmware will say
yes, but the thing about malicious firmware is that it can just lie
to us (either directly, or by modifying the OS components it boots to
lie instead). This is probably not sufficiently trustworthy!
Ok, so let's have the firmware be verified before it's executed. On
Intel this is "Boot Guard", on AMD this is "Platform Secure Boot",
everywhere else it's just "Secure Boot". Code on the CPU (either in
ROM or signed with a key controlled by the CPU vendor) verifies the
firmware[3] before executing it. Now the CPU itself is the root of
trust, and, well, that seems reasonable - we have to place trust in
the CPU, otherwise we can't actually do computing. We can now say
with a reasonable degree of confidence (again, in the absence of
vulnerabilities) that we booted an OS that we trusted. Hurrah!
Except. How do we know that the CPU actually did that verification?
CPUs are generally manufactured without verification being enabled -
different system vendors use different signing keys, so those keys
can't be installed in the CPU at CPU manufacture time, and vendors
need to do code development without signing everything so you can't
require that keys be installed before a CPU will work. So, out of the
box, a new CPU will boot anything without doing verification[4], and
development units will frequently have no verification.
As a device owner, how do you tell whether or not your CPU has this
verification enabled? Well, you could ask the CPU, but if you're
doing that on a device that booted a compromised OS then maybe it's
just hotpatching your OS so when you do that you just get
RET_TRUST_ME_BRO even if the CPU is desperately waving its arms
around trying to warn you it's a trap. This is, unfortunately, a
problem that's basically impossible to solve using verified boot
alone - if any component in the chain fails to enforce verification,
the trust you're placing in the chain is misplaced and you are going
to have a bad day.
So how do we solve it? The answer is that we can't simply ask the OS,
we need a mechanism to query the root of trust itself. There's a few
ways to do that, but fundamentally they depend on the ability of the
root of trust to provide proof of what happened. This requires that
the root of trust be able to sign (or cause to be signed) an
"attestation" of the system state, a cryptographically verifiable
representation of the security-critical configuration and code. The
most common form of this is called "measured boot" or "trusted boot",
and involves generating a "measurement" of each boot component or
configuration (generally a cryptographic hash of it), and storing
that measurement somewhere. The important thing is that it must not
be possible for the running OS (or any pre-OS component) to
arbitrarily modify these measurements, since otherwise a compromised
environment could simply go back and rewrite history. One frequently
used solution to this is to segregate the storage of the measurements
(and the attestation of them) into a separate hardware component that
can't be directly manipulated by the OS, such as a Trusted Platform
Module. Each part of the boot chain measures relevant security
configuration and the next component before executing it and sends
that measurement to the TPM, and later the TPM can provide a signed
attestation of the measurements it was given. So, an SoC that
implements verified boot should create a measurement telling us
whether verification is enabled - and, critically, should also create
a measurement if it isn't. This is important because failing to
measure the disabled state leaves us with the same problem as before;
someone can replace the mutable firmware code with code that creates
a fake measurement asserting that verified boot was enabled, and if
we trust that we're going to have a bad time.
(Of course, simply measuring the fact that verified boot was enabled
isn't enough - what if someone replaces the CPU with one that has
verified boot enabled, but trusts keys under their control? We also
need to measure the keys that were used in order to ensure that the
device trusted only the keys we expected, otherwise again we're going
to have a bad time)
So, an effective root of trust needs to:
1) Create a measurement of its verified boot policy before running
any mutable code
2) Include the trusted signing key in that measurement
3) Actually perform that verification before executing any mutable
code
and from then on we're in the hands of the verified code actually
being trustworthy, and it's probably written in C so that's almost
certainly false, but let's not try to solve every problem today.
Does anything do this today? As far as I can tell, Intel's Boot Guard
implementation does. Based on publicly available documentation I
can't find any evidence that AMD's Platform Secure Boot does (it does
the verification, but it doesn't measure the policy beforehand, so it
seems spoofable), but I could be wrong there. I haven't found any
general purpose non-x86 parts that do, but this is in the realm of
things that SoC vendors seem to believe is some sort of value-add
that can only be documented under NDAs, so please do prove me wrong.
And then there are add-on solutions like Titan, where we delegate the
initial measurement and validation to a separate piece of hardware
that measures the firmware as the CPU reads it, rather than requiring
that the CPU do it.
But, overall, the situation isn't great. On many platforms there's
simply no way to prove that you booted the code you expected to boot.
People have designed elaborate security implementations that can be
bypassed in a number of ways.
[1] In this respect it is extremely similar to "Zero Trust"
[2] This is a bit of an oversimplification - once we get into dynamic
roots of trust like Intel's TXT this story gets more complicated, but
let's stick to the simple case today
[3] I'm kind of using "firmware" in an x86ish manner here, so for
embedded devices just think of "firmware" as "the first code executed
out of flash and signed by someone other than the SoC vendor"
[4] In the Intel case this isn't strictly true, since the keys are
stored in the motherboard chipset rather than the CPU, and so taking
a board with Boot Guard enabled and swapping out the CPU won't
disable Boot Guard because the CPU reads the configuration from the
chipset. But many mobile Intel parts have the chipset in the same
package as the CPU, so in theory swapping out that entire package
would disable Boot Guard. I am not good enough at soldering to
demonstrate that.
Tags:
* advogato,
* fedora
* Previous Entry
* Add Memory
* Share This Entry
* Next Entry
---------------------------------------------------------------------
* 1 comment
* Reply
---------------------------------------------------------------------
Flat | Top-Level Comments Only
Not the Apollo
Date: 2023-07-11 01:45 pm (UTC)
From: (Anonymous)
Sometimes I wonder whether having side-by-side, compatible,
separately-implemented approaches that can be independently verified
against each other at runtime could be an improvement. Ideally all
open source, although arguably there's a seed-and-flower problem
there: if the implementations happened to copy from each other then
the resulting equivalence guarantees might be lower.
Whatever the solution is, I feel like it's unlikely to be an
implementation from one vendor that has an exciting brand name and
claims to solve most previously-existing secure boot problems.
* Link
* Reply
* Previous Entry
* Add Memory
* Share This Entry
* Next Entry
* 1 comment
* Reply
Flat | Top-Level Comments Only
Profile
Matthew Garrett
About Matthew
Power management, mobile and firmware developer on Linux. Security
developer at Aurora. Ex-biologist. [personal profile] mjg59 on
Twitter. Content here should not be interpreted as the opinion of my
employer. Also on Mastodon.
Page Summary
* (Anonymous) - Not the Apollo
Expand Cut Tags
No cut tags
Top of page