Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make PCRs part of payload in Security Overview #3480

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions dev-docs/security-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,16 @@ Abstractly, a remote-attestation statement `R` from a CVM looks as follows:
R = Sig-CPU(<launch digest>, <auxiliary data>, <payload>)
```

The `payload` is controlled by the software running inside the CVM.
The field `payload` is controlled by the software running inside the CVM.
In the case of a Constellation node, the `payload` is always the public key of the respective Bootstrapper running inside the CVM.
Thus, `R` can be seen as a certificate for that public key issued by the CPU.
Based on this, nodes establish attested TLS (aTLS) connections.
aTLS is used during [cluster creation](#cluster-creation) and when [growing a cluster](#cluster-growth).

The field `auxiliary data` is populated automatically by the CVM platform and, among others, includes information like CPU firmware versions.

Note that this description of `R` is highly abstract.

### Measurements

In the ideal case, the underlying CVM platform does not inject any of its own software into a CVM.
Expand All @@ -101,7 +105,7 @@ In measured boot, in general, the software components involved in the boot proce
The values of these registers are also called "runtime measurements".
All supported CVM platforms provide TPMs to CVMs.
Constellation nodes use these to measure their boot process.
They include the 16 runtime measurements as `auxiliary data` in `R`.
They include the 16 runtime measurements as part of `payload` in `R`. Thus, abstractly, `payload` here has the following format: `payload = <PCRs> | <bootstrapper public key>`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this neither accurately describes the current nor the best case attestation flow. Though, I'm not familiar with the attestation flow COCONUT has.
@daniel-weisse likely is the expert on (most/all) current implementations in Constellation. But as far as I know, the CC attestation is used to create trust in the vTPM via the Endorsement Key/Attestation Key.
For instance see: https://github.com/edgelesssys/constellation/blob/euler/ref/pin-crane-and-npm/internal/attestation/vtpm/vtpm.go#L38
https://github.com/edgelesssys/constellation/blob/euler/ref/pin-crane-and-npm/internal/attestation/gcp/snp/snp.go#L23
https://github.com/edgelesssys/constellation/blob/euler/ref/pin-crane-and-npm/internal/attestation/azure/snp/snp.go#L10

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spoke with @daniel-weisse, he says the PCR values are included directly in the remote-attestation statement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Remote attestation" section already starts of by saying payload is the TLS public key of the node, and establishes auxiliary data and launch digest as part of R.
Further establishing payload to be public key + TPM measurements, in case we can't rely on the firmware, makes the whole set up more confusing, when really the TPM measurements replace launch digest and auxiliary data

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, as the only non-expert here, I’ll take the liberty of asking some "stupid" questions! From what I understand, every piece of code that gets loaded is tracked in the PCRs, including the initial memory content of the CVM. Since the CVM is closed-source and provided by the cloud provider, the only observable information is that it changes. This is referred to as the "launch digest."

Additionally, the code you load or boot for the nodes is also tracked in the PCRs. This is called "auxiliary data." Or is it only your code that gets tracked in the PCRs? Can the two be separated, or are they combined into a single digest? For example, is it structured like:

Launch digest = Hash(third-party code)
Auxiliary data = Hash(your code)
Or could it look more like:

Launch digest = Hash(third-party code)
Auxiliary data = Hash(your code, Hash(third-party code))?
From my understanding, these are separate digests, and the CPU signs them together with the public key. Is that correct?

Also, a second question: Are field names like "payload," "auxiliary data," and "launch digest" predefined by the format of the attestation statement? Or do you have flexibility in deciding what gets written into each field? For instance, is "launch digest" always fixed to represent the initial firmware measurement, or can this be defined differently?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PCRs track both code from the cloud provider as well as our own code, giving a total of 16 digests we can work with.
The digests can mostly be separated by our code and third-party code, though some PCRs contain a digest mixing both.
We give an overview about what is tracked by each PCR in this table of our docs.

From my understanding, these are separate digests, and the CPU signs them together with the public key.

This is true for launch digest, but not for the auxiliary data, which is signed with a key manged by the TPM.
Additionally, the TPM key signs a digest of the TLS public key.

Are field names like "payload," "auxiliary data," and "launch digest" predefined by the format of the attestation statement

launch digest is a term defined by the AMD SEV-SNP attestation report format, other technologies, e.g. Intel TDX, use different names for similar things. On AMD platforms it is fixed to measure the initial memory contents of the VM, which contain the firmware measurements.
Afaik the terms "auxilary data" and "payload" is something we decided to use for our docs and there is no preset definition. Another term for payload is "report data".

Copy link

@david-crypto david-crypto Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so it seems this is more about presentation. Terms like "auxiliary data" and "payload" aren’t actual fields in the attestation statement. For AMD, the only formal field is the "launch digest." The 16 PCR contents are signed by a CPU key, while the "launch digest" and the TLS public key are signed by a different key, specifically a TPM key.

The use of CPU-sig(...) seems to abstract this distinction, probably to simplify the explanation and make it easier to follow.

That brings me to a question: Why do we have a separate "launch digest" if the firmware is already tracked in the PCRs?

As a suggestion, perhaps we could rename "payload" to "TLS public key" if that’s the only thing it represents. Similarly, "auxiliary data" could be renamed to "node digest" for clarity, though it’s worth noting that the PCRs include more than just the node digest. Of course if they are common terms it is different.

This way, the statement would look something like this:
R = CPU-sig(launch digest, node digest, TLS public key).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I have a better understanding now. The launch digest is generated and tracked by the Confidential Computing (CC) hardware during the setup of a CVM. After the initial CVM setup (e.g., within the virtual UEFI environment), the vTPM takes over and starts tracking the boot process inside the virtual environment, recording measurements in the virtual PCRs.

One of the issues is that the vTPM logic is provided by the cloud provider and is closed-source and not verifiable. So the cloud provider could theoretically forge measurements. If this logic is implemented as part of the hypervisor, then the hypervisor becomes part of the Trusted Computing Base (TCB). This contradicts the principles of Confidential Computing, where the goal is to explicitly exclude the hypervisor from the TCB. I'm getting there...

Anyhow, I think we should consider renaming auxiliary data and payload for clarity, as suggested earlier, provided they are not reserved terms.

On each CVM platform, runtime measurements are taken differently.
Details on this are given in the [Constellation documentation](https://docs.edgeless.systems/constellation/architecture/attestation#runtime-measurements).

Expand Down
Loading