Design
Author | Period | State |
---|---|---|
Nathaniel McCallum Richard Zak Harald Hoyer Dmitri Pal |
November-December, 2022 | 🔴 Draft |
This document is the continuation of the discussion about the attestation flow, started in the Attestation Concept document. It focuses on the entity that receives the attestation report from a Keep, inspects it and validates that the Keep was properly created on the hardware which keys are still trusted.
An attestation report is difficult to consume. It requires careful analysis of a signature hierarchy along with platform state. Likewise, managing the cryptographic measurements of supported applications is tedious and error-prone. Attestation validation, on the other hand, needs to be simple and auditable.
Most attestation validators really only care to answer the question "What is the name and version of the application?"
There are multiple hardware vendors that offer the ability to run workloads within the encrypted memory. While in general the capability is the same, the implementation is quite different. The relying party that receives and validates the attestation report, has to be intimately familiar with the details of the specific attestation process and know how to review and validate provided data.
It would have been great, if there were a universal interpreter that on one side could process the raw attestation data delivered by the keep and on the other could produce a simpler and more conventional report that can be easily verified by already existing tools and protocols.
Steward is an attestation-aware certification authority designed to act as such interpreter. The Keep generates a key pair and produces an attestation report proving that the private-public key pair was generated inside of a keep. Steward receives this attestation report as input and, if validation is successful, issues a certificate for the generated key pair. This allows us to convert a proprietary attestation report into a standard X.509 certificate for use with protocols like TLS.
To improve interoperability, Keep uses a self-signed certificate as a vehicle of delivery of the attestation report and related metadata to Steward.
One of the goals of Steward is to reduce the amount of validation that is required by third parties. Enarx deploys WebAssembly workloads into Keeps. So this means there are effectively three kinds of validation that must occur:
Steward validates both the hardware platform and the Enarx runtime. Steward DOES NOT validate the workload. However, Steward issues a certificate, that the Keep presents to the workload registry. Registry releases the signed workload to the Keep and the Keep does the validation of the workload.
For more details about this part of the flow see Full Provisioning Flow with Attestation document.
Enarx shims provide a syscall extension named get_attestation()
. It is defined as follows (see the previous link for full documentation):
This takes an opaque blob as input (i.e. nonce
) and writes the attestation into the provided buffer (i.e. buf
). This function also outputs a technology
identifier (i.e. SGX or SEV). This call is not currently exposed to WebAssembly code.
This section is connected to the section of the Full Attestation Workflow document and focuses on the Steward side of processing the attestation
The reports contain a lot of information regarding the model, revision, and firmware version for the CPU. Some items aren't of concern to Steward, some things need to be checked to ensure safety, and other fields need to be customizable based on some criteria.
What makes this complicated is that SGX and SNP don't have the same fields, so it makes it more difficult to be consistent.
Goals for attestation configuration:
Non-negiotable aspects of attestation validation in Steward:
Below are fields for SNP we which are configurable due to being relevent to security.
u32
, must be 1
u32
, should be 1 since we provide signing info[u8; 48]
, hash of Enarx in memory
[u8; 48]
, signing key of the Enarx binary, optionally don't care[u8; 48]
, signs ID key above
u8
for each
[u8; 32]
[u8; 16]
, not lower than some configured value
[u8; 2]
Nil
?