On Thu, Dec 12, 2024 at 11:56 AM Daniel P. Smith
<dpsmith@xxxxxxxxxxxxxxxxxxxx> wrote:
Hey Luto!
Let me try to address your concerns below.
On 11/18/24 15:02, Andy Lutomirski wrote:
On Mon, Nov 18, 2024 at 11:12 AM James Bottomley
<James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> wrote:
On Mon, 2024-11-18 at 10:43 -0800, Andy Lutomirski wrote:
Linux should not use TPM2_PCR_Extend *at all*. Instead, Linux should
exclusively use TPM2_PCR_Event. I would expect that passing, say,
the entire kernel image to TPM2_PCR_Event would be a big mistake, so
instead Linux should hash the relevant data with a reasonable
suggestion of hashes (which includes, mandatorily, SHA-384 and *does
not* include SHA-1, and may or may not be configurable at build time
to include things like SM3), concatenate them, and pass that to
TPM2_PCR_Event. And Linux should make the value that it passed to
TPM2_PCR_Event readily accessible to software using it, and should
also include some straightforward tooling to calculate it from a
given input so that software that wants to figure out what value to
expect in a PCR can easily do so.
Just for clarity, this is about how the agile log format works. Each
event entry in the log contains a list of bank hashes and the extends
occur in log event order, so replaying a log should get you to exactly
the head PCR value of each bank. If a log doesn't understand a format,
like SM3, then an entry for it doesn't appear in the log and a replay
says nothing about the PCR value.
I have no idea what the "agile log format" is or what all the formats
in existence are. I found section 4.2.4 here:
https://trustedcomputinggroup.org/wp-content/uploads/TCG_IWG_CEL_v1_r0p41_pub.pdf
It says:
This field contains the list of the digest values Extended. The Extend
method varies with TPM command, so there is
no uniform meaning of TPM Extend in this instance, and separate
descriptions are unavoidable. If using the
TPM2_PCR_Extend command, this field is the data sent to the TPM (i.e.,
not the resulting value of the PCR after the
TPM2_PCR_Extend command completes). If using the TPM2_PCR_Event
command, this field contains the digest
structure returned by the TPM2_PCR_Event command (that contains the
digest(s) submitted to each PCR bank as
the internal Extend operation). This field SHALL contain the
information from the TPML_DIGEST_VALUES used in
the Extend operation.
Let me start with providing background on the two measurement policies
that is implemented by Intel TXT (from Intel TXT Developers Guide):
- Maximum Agility PCR Extend Policy: ACM can support algorithm agile
commands TPM2_PCR_Event; TPM2_HashSequenceStart; TPM2_HashUpdate;
TPM2_EventSequenceComplete. When this policy is selected, ACM will use
the commands above if not all PCR algorithms are covered by embedded set
of algorithms and will extend all existing PCR banks. Side effect of
this policy is possible performance loss.
‒ Maximum Performance PCR Extend Policy: ACM can support several hash
algorithms via embedded SW. When this policy is selected, ACM will use
embedded SW to compute hashes and then will use TPM2_PCR_Extend commands
to extend them into PCRs. If PCRs utilizing hash algorithms not
supported by SW are discovered, they will be capped with “1” value. This
policy, when selected, will ensure maximum possible performance but has
side effect of possible capping of some of the PCRs.
What is responsible for choosing which of these policies to use?
Allow me to clarify/expand on the last statement in Maximum Agility.
There is almost certainly a performance loss as anything larger than
1024 bytes, for example the Linux kernel, the ACM will bit-banging the
bytes to the TPM using the TPM2_Hash* functions.
Surely, if Linux's stub started using TPM2_PCR_Event, it would first
hash any large inputs and then send the _hash_ to TPM2_PCR_Event
instead of, say, bit-banging the entire initramfs to the TPM. But
you're talking about the ACM and I'm talking about the Linux stub code
in this patchset.
But the capping-with-"1" does suggest that maybe one can actually cap
with "1" without preventing downstream software from consuming the
event log.
Before addressing the next point, I would also clarify how the D-CRTM
measurement taken by the CPU is done. It uses the _TPM_HASH_* functions,
Section 22.9 of TPM2 Commands specification, to store SHA256(SINIT ACM)
| EDX into all active PCR banks. For clarity, when this done, EDX holds
the 4-byte value of the SENTER parameters for which 0 is the only valid
value currently.
So we're logging the values with which we extend the PCRs. Once upon
a time, someone decided it was okay to skip extending a PCR bank:
https://google.github.io/security-research/pocs/bios/tpm-carte-blanche/writeup.html
and it was not a great idea.
Let's begin by why/how that attack occurs. The TPM Carte Blanche attack
took advantage of the fact that without BootGuard in place, the SRTM
measurements are done by the software/firmware, to include the
self-referential S-CRTM measurement. In particular, for the target
platform, it just so happens that it was possible to construct a
configuration where not a single hash would be sent to the SHA256 bank.
This allowed the attacker the ability to replay any set of measurements,
i.e. carte blanche control, into a completely empty PCR bank for which
the attestation service would accept quotes. The key to this attack
requires both, access to an empty PCR bank, and an attestation service
that will accept a quote with only the exploited bank present.
Let us return to my statements above, which will demonstrate why
TXT/DRTM completely invalidates the attack. First, as noted above, when
the CPU is processing the GETSEC[SENTER] instruction, it (the CPU) will
compute the D-CRTM as SHA256(SINIT ACM) | EDX, sending it to the TPM
using _TPM_HASH_* functions. The _TPM_HASH_* functions result in all PCR
banks to be extended with the D-CRTM value. If Maximum Performance PCR
Extend policy is in use, which is the default policy used by TrenchBoot,
any algorithm not supported by the ACM is capped by sending the value
"1" as the digest value for the extend. Therefore, after the TXT
sequence has completed and before control is given to the Linux kernel
by the ACM, all PCR banks will consist of either, the D-CRTM + all ACM
measurements, or the D-CRTM + TPM2_PCR_Extend(0x1). There will be no PCR
banks with empty DRTM PCRs, thus none of the banks would be usable for a
TPM Carte Blanche-style attack.
Sure, a "carte blanche" attack in the sense that the PCRs are entirely
blank won't happen, but if any component in the chain does not extend
a bank, then an attacker can replace the code _after_ that component
without being noticed.
(c) Upon initialization, cap the PCR banks with unsupported algorithms
using a well-known value.
A problem with (a) is that the result will be an unorthodox event,
PCR_EXTEND(H(H'(data))). An attestation verifier will have to be aware
of that this is being done, and have a way to determine which method was
used for each event. This creates a potentially expensive cost for any
existing attestation solutions to incorporate support for the unorthodox
event. At least for DRTM solutions, it seeks to solve a problem that TXT
does not experience.
For Linux Secure Launch, I would like to propose an alternative to what
the current logic does in the setup kernel. Specifically, Secure Launch
will trigger a TXT reset when an unsupported algorithm is encountered.
Instead, I would like to propose the adoption of (c), and have it
extends a well-known, fixed value for unsupported algorithms. Secure
Launch can leverage the fact that the TPM driver's extend function
already expects to be given digests for all active algorithms.
Therefore, it will record the well-known value, 0x01 to follow the ACM,
into the digest buffers of any algorithms that Secure Launch does not
support. This will result in the well-known value being extended each
time a measurement is recorded. This will not be a problem as no one
should be using those banks for attestation and can ignore those digests
in the event log.
This seems to be at least not terrible.
Or I suppose one could use TPM_HASH_ functions? The spec for them is
somewhat impenetrable to me.