Validate a NitroTPM Attestation Document - Amazon Elastic Compute Cloud

Validate a NitroTPM Attestation Document

Note

This topic is intended for users who are using a third-party key management service, and need to build their own Attestation Document validation mechanisms.

This topic provides a detailed overview of the entire NitroTPM attestation flow. It also discusses what is generated by the AWS Nitro system when an Attestation Document is requested, and explains how a key management service should process an Attestation Document.

The purpose of attestation is to prove that an instance is a trustworthy entity, based on the code and configuration that it is running. The root of trust for the instance resides within the AWS Nitro system, which provides Attestation Documents.

Attestation Documents are signed by the AWS Nitro Attestation Public Key Infrastructure (PKI), which includes a published certificate authority that can be incorporated into any service.

The Attestation Document

Attestation Documents are encoded in Concise Binary Object Representation (CBOR), and signed using CBOR Object Signing and Encryption (COSE).

For more information about CBOR, see RFC 8949: Concise Binary Object Representation (CBOR).

Attestation Document specification

The following shows the structure of an Attestation Document.

AttestationDocument = { module_id: text, ; issuing Nitro hypervisor module ID timestamp: uint .size 8, ; UTC time when document was created, in ; milliseconds since UNIX epoch digest: digest, ; the digest function used for calculating the ; register values nitrotpm_pcrs: { + index => pcr }, ; map of PCRs at the moment the Attestation Document was generated certificate: cert, ; the public key certificate for the public key ; that was used to sign the Attestation Document cabundle: [* cert], ; issuing CA bundle for infrastructure certificate ? public_key: user_data, ; an optional DER-encoded key the attestation ; consumer can use to encrypt data with ? user_data: user_data, ; additional signed user data, defined by protocol ? nonce: user_data, ; an optional cryptographic nonce provided by the ; attestation consumer as a proof of authenticity } cert = bytes .size (1..1024) ; DER encoded certificate user_data = bytes .size (0..1024) pcr = bytes .size (32/48/64) ; PCR content index = 0..31 digest = "SHA384"

The optional parameters in the Attestation Document (public_key, user_data, and nonce) can be used to establish a custom validation protocol between an attesting instance and the external service.

Attestation Document validation

When you request an Attestation Document from the Nitro Hypervisor, you receive a binary blob that contains the signed Attestation Document. The signed Attestation Document is a CBOR-encoded, COSE-signed (using the COSE_Sign1 signature structure) object. The overall validation process includes the following steps:

  1. Decode the CBOR object and map it to a COSE_Sign1 structure.

  2. Extract the Attestation Document from the COSE_Sign1 structure.

  3. Verify the certificate's chain.

  4. Ensure that the Attestation Document is properly signed.

Attestation Documents are signed by the AWS Nitro Attestation PKI, which includes a root certificate for the commercial AWS partitions. The root certificate can be downloaded from https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip, and it can be verified using the following fingerprint.

64:1A:03:21:A3:E2:44:EF:E4:56:46:31:95:D6:06:31:7E:D7:CD:CC:3C:17:56:E0:98:93:F3:C6:8F:79:BB:5B

The root certificate is based on an AWS Certificate Manager Private Certificate Authority (AWS Private CA) private key and it has a lifetime of 30 years. The subject of the PCA has the following format.

CN=aws.nitro-enclaves, C=US, O=Amazon, OU=AWS

COSE and CBOR

Usually, the COSE_Sign1 signature structure is used when only one signature is going to be placed on a message. The parameters dealing with the content and the signature are placed in the protected header rather than having the separation of COSE_Sign. The structure can be encoded as either tagged or untagged, depending on the context it will be used in. A tagged COSE_Sign1 structure is identified by the CBOR tag 18.

The CBOR object that carries the body, the signature, and the information about the body and signature is called the COSE_Sign1 structure. The COSE_Sign1 structure is a CBOR array. The array includes the following fields.

[ protected: Header, unprotected: Header, payload: This field contains the serialized content to be signed, signature: This field contains the computed signature value. ]

In the context of an Attestation Document, the array includes the following.

18(/* COSE_Sign1 CBOR tag is 18 */ {1: -35}, /* This is equivalent with {algorithm: ECDS 384} */ {}, /* We have nothing in unprotected */ $ATTESTATION_DOCUMENT_CONTENT /* Attestation Document */, signature /* This is the signature */ )

For more information about CBOR, see RFC 8949: Concise Binary Object Representation (CBOR).

Semantic validity

An Attestation Document will always have their CA bundle in the following order.

[ ROOT_CERT - INTERM_1 - INTERM_2 .... - INTERM_N] 0 1 2 N - 1

Keep this ordering in mind, as some existing tools, such as Java’s CertPath from Java PKI API Programmer’s Guide, might require them to be ordered differently.

To validate the certificates, start from the Attestation Document CA bundle and generate the required chain, Where TARGET_CERT is the certificate in the Attestation Document.

[TARGET_CERT, INTERM_N, ..... , INTERM_2, INTERM_1, ROOT_CERT]

Certificate validity

For all of the certificates in the chain, you must ensure that the current date falls within the validity period specified in the certificate.

Certificate chain validity

In general, a chain of multiple certificates might be needed, comprising a certificate of the public key owner signed by one CA, and zero or more additional certificates of CAs signed by other CAs. Such chains, called certification paths, are required because a public key user is only initialized with a limited number of assured CA public keys. Certification path validation procedures for the internet PKI are based on the algorithm supplied in X.509. Certification path processing verifies the binding between the subject distinguished name and/or subject alternative name and subject public key. The binding is limited by constraints that are specified in the certificates that comprise the path and inputs that are specified by the relying party. The basic constraints and policy constraint extensions allow the certification path processing logic to automate the decision making process.

Note

CRL must be disabled when doing the validation.

Using Java, starting from the root path and the generated certificate chain, the chain validation is as follows.

validateCertsPath(certChain, rootCertficate) { /* The trust anchor is the root CA to trust */ trustAnchors.add(rootCertificate); /* We need PKIX parameters to specify the trust anchors * and disable the CRL validation */ validationParameters = new PKIXParameters(trustAnchors); certPathValidator = CertPathValidator.getInstance(PKIX); validationParameters.setRevocationEnabled(false); /* We are ensuring that certificates are chained correctly */ certPathValidator.validate(certPath, validationParameters); }