Skip to content

Latest commit

 

History

History
640 lines (500 loc) · 27.6 KB

kbs_attestation_protocol.md

File metadata and controls

640 lines (500 loc) · 27.6 KB

KBS Attestation Protocol

The Key Broker Service attestation protocol defines communication between a Key Broker Client (KBC) in a confidential guest and a trusted Key Broker Service (KBS). The protocol uses the simple, universal, and extensible "Request-Challenge-Attestation-Response" (RCAR) method to facilitate guest attestation and secret injection.

Introduction

The purpose of the attestation between KBS and KBC is to confirm whether the platform where the KBC is located is in the expected security state, i.e. if it runs in a trustworthy HW-TEE, and the software stack is measured and verifiable.

In this document, the HW-TEE attestation process is the semantics of the application layer, which is defined as a simple, universal and extensible RCAR protocol. The temporary asymmetric key generated by HW-TEE is used to encrypt the response output payload, and the standard HTTP Cookie mechanism is used to avoid the performance problems caused by multiple attestations: it's fairly typical for the KBC to require several resources, resulting in multiple Requests to the KBS. Having to do the whole attestation dance would be time consuming and have a latency impact on the guest.

In order to ensure the ease of use and security completeness of KBS, we will use HTTPS as the transport protocol to carry the application layer semantics designed in this document. This is because HTTPS provides KBC with a means to authenticate KBS identity, which effectively avoids malicious attackers from hijacking KBS address to impersonate KBS and deceive KBC. In order to achieve this, the public key of KBS needs to be transmitted to KBC through an effective way, and the specific way of public key distribution is out of this document scope.

It should be noted that the confidentiality protection provided by HTTPS alone is not enough to meet the security requirements of the KBS protocol. Therefore, as mentioned above, the key generated by HW-TEE needs to be used to encrypt and protect the confidential data.

Request-Challenge-Attestation-Response Semantics

The semantics of attestation defined by KBS is a simple and extensible four-step model, which uses JSON structure to organize information. As follows:

  1. Request: The KBC sends the initial Request payload to the KBS, in order to authenticate itself against the KBS, and eventually request resources.
  2. Challenge: After receiving the initial Request payload, the KBS responds with the Challenge payload. This is how the KBS sends the attestation challenge to the KBC. Together with the attestation challenge, the KBS also sends a session identifier to the KBC, as an HTTP Cookie. This session identifier can be used to skip steps 2 and 3 after a successful attestation.
  3. Attestation: The KBC replies to the attestation challenge from step 2 with an attestation evidence, in order to prove that its environment (HW-TEE) is safe and reliable. The KBC sends an Attestation payload to the KBS, that contains the attestation evidence and the HW-TEE generated, ephemeral public key.
  4. Response: The KBS returns a Response payload to a KBC requesting a resource if and only if the Attestation payload was successfully validated. The KBC requests resources by sending HTTP GET requests to resource specific endpoints. Within the valid time of the HTTP Cookie generated by the KBS during step 2, the KBC can directly request resources or services from KBS, without going through steps 2 and 3.

Payloads

Request

The payload format of the request is as follows:

{
    /* Attestation protocol version number used by KBC */
    "version": "0.1.0",
    /*
     * Type of HW-TEE platforms where KBC is located,
     * e.g. "intel-tdx", "amd-sev-snp", etc.
     */
    "tee": "$tee",
    /* Reserved fields to support some special requests sent by HW-TEE. */
    "extra-params": {}
}

Note: the /*...*/ comments are not valid in JSON, and must not be used.

  • version

The protocol version number supported by KBC. KBS needs to judge whether this KBC can communicate normally according to this field.

  • tee

Used to declare the type of HW-TEE platform where KBC is located, the valid values are intel-tdx, intel-sgx and amd-sev-snp.

  • extra-params

In the run-time attestation scenario (Intel TDX and SGX, AMD SEV-SNP), the extra-params field is not used, so is set to the empty string. However, for the attestation of some special HW-TEE platforms, this field may be used to transfer some specific information. For example, some attestations follow the Diffie–Hellman key exchange protocol to first build a secure channel and transfer secret messages (Such as AMD SEV(-ES) pre-attestation).

Challenge

If the KBC does not own any KBS generated HTTP Cookie, or if the Cookie validity has expired, the KBC can not directly request resources and the KBS respond with an error to the KBC requests. The KBC must first go through the attestation process and send an initial Request payload to the KBS. The KBS will then respond to it with an attestation challenge described in the following format:

{
    /* Evidence freshness. */
    "nonce": "$nonce",
    /* Extra parameters to support some special HW-TEE attestation. */
    "extra-params": {}
}

Note: the /*...*/ comments are not valid in JSON, and must not be used.

  • nonce

The freshness number passed to KBC. KBC needs to place it in the evidence sent to the KBS in the next step to prevent replay attacks.

  • extra-params

The reserved extra parameter field which is used to pass the additional information provided by the KBS when some specific HW-TEE needs to be attested.

Attestation

After receiving the attestation challenge, the KBC builds an attestation evidence from the HW-TEE platform and organizes it into the following payload:

{
    /*
     * A JWK-formatted public key, generated by the KBC running in the HW-TEE.
     * It is valid until the next time an attestation is required. Its hash must
     * be included in the HW-TEE evidence and signed by the HW-TEE hardware.
     */
    "tee-pubkey": $pubkey

    /* The attestation evidence. Its format is specified by Attestation-Service. */
    "tee-evidence": {}
}

Note: the /*...*/ comments are not valid in JSON, and must not be used.

The KBS matches the attestation evidence to an attestation challenge with the HTTP Cookie that the KBC includes in the HTTP request that contains the Attestation payload.

  • tee-pubkey

After KBC receives the attestation challenge, an ephemeral asymmetric key pair is generated in HW-TEE. The private key is stored in HW-TEE. The public key and its description information are exported and placed in the tee-pubkey field and sent to the KBS together with the attestation evidence. The hash of the tee-pubkey field must be included in the custom field of HW-TEE evidence and signed by HW-TEE hardware. This public key is valid until the next time the KBC receives an attestation challenge from the KBS.

The tee-pubkey follows the JSON Web Key format, as described in the key format section.

  • tee-evidence

The attestation evidence is generated by the HW-TEE platform software and hardware in the KBC's execution environment. The tee-evidence formats depend on the TEE and are typically defined by the Attestation-Service.

The KBS does not parse or analyze the attestation evidence, it forwards it to the Attestation-Service for verification.

Response

Upon successful attestation, the KBC can request resources from the KBS, by sending HTTP GET requests to it.

If the KBS approves the request, it responds to the KBC by sending a Response payload that follows the JSON Web Encryption flattened serialization format:

{
    "protected": "$jose_header",
    "encrypted_key": "$encrypted_key",
    "iv": "$iv",
    "ciphertext": "$ciphertext",
    "tag": "$tag"
}

The above JWE JSON fields are defined as follows:

let jose_header_string = format!(r#"{{"alg": "{}","enc": "{}"}}"#, alg, enc);
let jose_header = base64_url::encode(&jose_header_string);
let encrypted_key = base64_url::encode(enc_kbs_symkey);
let iv = base64_url::encode(initialization_vector);
let ciphertext = base64_url::encode(response_output);

// tag is optional and depends on the encryption algorithm.
tag = base64_url::encode(authentication_tag);
  • alg

Algorithm used to encrypt the encryption key at encrypted_key. Since the key is encrypted using the HW-TEE public key, alg must be the same value as described in the Attestation's tee-pubkey field.

  • enc

Encryption algorithm used to encrypt the output of the KBS service API.

  • ciphertext

The output of the KBS service API. It must be encrypted with the KBS-generated ephemeral key.

  • iv

The input to a cryptographic primitive is used to provide the initial state. If the algorithm described by enc used does not need it, this field is left blank.

  • encrypted_key

The encrypted symmetric key is used to encrypt ciphertext. This key is encrypted with the HW-TEE's public key, using the algorithm defined in alg.

Key Format

Public Key

The Attestation and the Token Resource tee-pubkey field contains a public key from a HW-TEE generated asymmetric key pair.

This field follows the JSON Web Key format.

{
    "kty": "RSA",
    "alg": "$key_algorithm",
    "n": "$pubkey_modulus",
    "e": "$pubkey_exponent"
}

HTTP Integration

KBS uses the HTTPS transport protocol to exchange the above described attestation messages, as HTTP requests and responses payloads.

The first step in the HTTP-based KBS attestation protocol described here allows for an attester to authenticate itself against a trusted Key Brokering Service. The second step is when an attester requests one or more protected resources from the KBS. The resources are delivered by the KBS back to the attester based on the HTTP Cookie bound authentication results.

Authentication

Before being able to request a protected resource (a key, a token, etc.), an attester must authenticate itself against the remote KBS. Only after successfully authenticated itself, it can request those resources.

The authentication service is provided by the KBS through two endpoints:

  1. /kbs/v0/auth only accepts POST requests whose body is a KBS Request JSON payload. This endpoint is for the attester to initiate the attestation protocol and authenticate itself against the KBS. The KBS reply HTTP response is composed of:
    1. A Set-Cookie header set to kbs-session-id=<session>. The KBS tracks the attester and its attestation results with that cookie.
    2. An attestation challenge for the attester to take. This is the content of the response, set to a KBS Challenge JSON payload.
  2. /kbs/v0/attest only accepts POST requests whose body is a KBS Attestation JSON payload and the header contains a Cookie set to the value received in step 1.i. This is how the attester replies to attestation challenge received in step 1.ii. If the attestation was successful, the KBS replies to that request with an Attestation Results Token.
┌──────────┐                                          ┌─────┐
│ Attester │                                          │ KBS │
└────┳─────┘                                          └──┳──┘
     ┃                 ┌─────────────────┐               ┃
     ┃─────────────────│POST /kbs/v0/auth│──────────────▶┃
     ┃                ┌┴─────────────────┴┐              ┃
     ┃                │Header: No Cookie  │              ┃
     ┃                │Body: Request      │              ┃
     ┃                └───────────────────┘              ┃
     ┃                     ┌────────┐                    ┃
     ┃◀────────────────────│Response│────────────────────┃
     ┃      ┌──────────────┴────────┴───────────────┐    ┃
     ┃      │Header: "Set-Cookie kbs-session-id=123"│    ┃
     ┃      │Body: Challenge                        │    ┃
     ┃      └───────────────────────────────────────┘    ┃
     ┃                                                   ┃
     ┃                                                   ┃
     ┃                                                   ┃
     ┃                                                   ┃
     ┃                                                   ┃
     ┃                ┌───────────────────┐              ┃
     ┃────────────────│POST /kbs/v0/attest│─────────────▶┃
     ┃        ┌───────┴───────────────────┴───────┐      ┃
     ┃        │Header: "Cookie kbs-session-id=123"│      ┃
     ┃        │Body: Attestation                  │      ┃
     ┃        └───────────────────────────────────┘      ┃
     ┃                     ┌────────┐                    ┃
     ┃◀────────────────────│Response│────────────────────┃
     ┃      ┌──────────────┴────────┴───────────────┐    ┃
     ┃      │Header: "Set-Cookie kbs-session-id=123"│    ┃
     ┃      │Body: Attestation Results Token        │    ┃
     ┃      └───────────────────────────────────────┘    ┃
     ┃                                                   ┃
     ┃                                                   ┃
     ┃                                                   ┃
     ▽                                                   ▽
               Figure 1: KBS Authentication Phase

Resource Requests

The authentication phase is the first step of the overall KBS protocol, where attesters authenticate themselves against a KBS implementation. This leads to the second phase, during which authenticated attesters can request protected resources from the KBS.

Attesters can access protected resources by providing the KBS with either the HTTP cookie or the Attestation Results token returned as part of the Attestation HTTP response. The former is usually short-lived and is typically used for one-time, synchronous resources request. For longer KBS sessions, it is more convenient to use the latter.

HTTP Cookie Authentication

The KBS implementation keeps track of attestation results and binds them to a cookie identifier. During the second phase, the KBS can then decide if a specific resource could be released to a given attester, by mapping the cookie identifier the attester includes in its resource request message to its attestation results.

To request a protected resource from the KBS, the attester sends a GET request to a resource specific endpoint. If the attester is allowed to access the resource, the KBS will respond to the GET request with an HTTP response which content is set to a KBS Response JSON payload:

┌──────────┐                                         ┌─────┐
│ Attester │                                         │ KBS │
└───┳──────┘                                         └──┳──┘
    ┃            ┌─────────────────────────┐            ┃
    ┃────────────│GET /kbs/v0/<resource_id>│───────────▶┃
    ┃      ┌─────┴─────────────────────────┴────┐       ┃
    ┃      │Header: "Cookie kbs-session-id=123" │       ┃
    ┃      │Body: N/A                           │       ┃
    ┃      └────────────────────────────────────┘       ┃
    ┃                    ┌────────┐                     ┃
    ┃◀───────────────────│Response│─────────────────────┃
    ┃     ┌──────────────└────────┘───────────────┐     ┃
    ┃     │Header: "Set-Cookie kbs-session-id=123"│     ┃
    ┃     │Body: Response                         │     ┃
    ┃     └───────────────────────────────────────┘     ┃
    ┃                                                   ┃
    ┃                                                   ┃
    ┃                                                   ┃
    ▽   Figure 2: KBS Resource Request Phase - Session  ▽

A request for protected resource can fail for three reasons:

  1. The requester is not authenticated and thus can not provide the right cookie identifier. The KBS implementation sends an HTTP response with a 401 (Unauthorized) status code.
  2. The attester is authenticated but requests a resource that it's not allowed to receive. The KBS implementation sends an HTTP response with a 403 (Forbidden) status code.
  3. The requested resource does not exist. The KBS implementation sends an HTTP response with a 404 (Not Found) status code.

Attestation Results Token Authentication

As part of the Authentication process, the requester generates a TEE asymmetric key pair. Upon successful Attestation, the KBS provisions a token that contains the Attestation Results and endorsements for the TEE public key.

To request a protected resource from the KBS, the attester sends a GET request to a resource specific endpoint with the token as the bearer authorization. If the token passes verification, the KBS will respond to the GET request with an HTTP response whose content is set to a KBS Response JSON payload. The symetric key inside the KBS Response JSON payload will be wrapped by the public key inside the token.

┌──────────┐                                         ┌─────┐
│ Attester │                                         │ KBS │
└───┳──────┘                                         └──┳──┘
    ┃            ┌─────────────────────────┐            ┃
    ┃────────────│GET /kbs/v0/<resource_id>│───────────▶┃
    ┃      ┌─────┴─────────────────────────┴────┐       ┃
    ┃      │Header: Authorization Bearer        │       ┃
    ┃      │Body: N/A                           │       ┃
    ┃      └────────────────────────────────────┘       ┃
    ┃                    ┌────────┐                     ┃
    ┃◀───────────────────│Response│─────────────────────┃
    ┃     ┌──────────────└────────┘───────────────┐     ┃
    ┃     │Header: No Cookie                      │     ┃
    ┃     │Body: Response                         │     ┃
    ┃     └───────────────────────────────────────┘     ┃
    ┃                                                   ┃
    ┃                                                   ┃
    ┃                                                   ┃
    ▽    Figure 3: KBS Resource Request Phase - Token   ▽

A request for protected resource can fail for three reasons:

  1. The requester is not authenticated and thus can not provide the valid token. The KBS implementation sends an HTTP response with a 401 (Unauthorized) status code.
  2. The attester is authenticated but requests a resource that it's not allowed to receive. The KBS implementation sends an HTTP response with a 403 (Forbidden) status code.
  3. The requested resource does not exist. The KBS implementation sends an HTTP response with a 404 (Not Found) status code.

Secret Resource

KBS uses the following path format to locate secret resources:

/kbs/v0/resource/<repository>/<type>/<tag>

Where the URL path parameters are:

  • <repository>: This is similar to the concept of container image repository (docker.io/{repository}/{image_name}:{tag}), which is used to facilitate users to manage different resource groups. Its name should be completely set by users. This parameter can be empty to use the default repository of KBS.
  • <type>: To distinguish different resource types.
  • <tag>: To distinguish different resource instances.

The decision to reply successfully to an attester resource request for a specific resource instance belongs to the KBS and its underlying attestation service. The decision is typically based on both the attestation evidence, results and provisioned policies for a given attester.

Resource Registration (Experimental)

A POST request with the content of resource to /kbs/v0/resource/<repository>/<type>/<tag> can register the resource into the KBS.

Attestation Results Token

Authenticated attesters can also receive an attestation token from the KBS in the response body of /kbs/v0/attest. Attesters can use the attestation result token to request additional resources from external services, a.k.a. relying parties.

The provided attestation results token follows the JSON web token standard and format.

Header

This is the Base64url encoding of a JOSE header.

It is JSON-formatted and contains both the token standard format (typ) and the token signature algorithm (alg). For example:

{
    "typ": "JWT",
    "alg": "RS256"
}
Payload

This is the Base64url encoding of a set of JSON-formatted claims, like the following example:

{
    "exp": 1568187398,
    "iat": 1568158598,
    "iss": "https://xxxxxx",
    "jwk": $token-pubkey,

    "tee-pubkey": $pubkey,
    "tcb-status": $claims,
    "evaluation-report": $report,
}

The token payload is divided into registered and private claims sets. The KBS might also include additional public claims set.

The registered claims set must include the exp, iat', iss and jwk names, which respectively declare the expiration time, issuing time and issuer (KBS URL address) of the token:

Field Description Type Example
exp Expiration time Seconds since the epoch 99991231235959
iat Issuing time Seconds since the epoch 180322235959
iss Issuer KBS URL https://my-kbs.io/
jwk Public key to verify token signature RSA Json Web Key

The custom claims set must include the attestation result from the Attestation Service, which include the TCB status and measurements.

The custom claims set can also include a tee-pubkey claim. This claim refers to the HW-TEE's public key sent by the KBC along with the attestation evidence, which is valid within the validity period of the token.

evaluation-report is the output of the policy engine of the Attestation Service, it is AS policy's evaluation opinion on TEE evidence.

When the KBC uses this token to request resources or services from a relying party service API, then the symmetric key used to encrypt the output payload can be wrapped with the provided tee-pubkey.

Set Attestation Policy

User of KBS can set an attestation verification policy through the following endpoint:

/kbs/v0/attestation-policy

The payload of the POST request should like:

{
    "type": "rego",
    "policy_id": "default",
    "policy": <base64encoded policy>
}

Where type is the policy format (e.g. rego or opa), policy_id provides the policy ID and policy is the base64 encoded policy content. Only authenticated users can send a POST request to this endpoint. KBS verifies the user identity with the user's private key signed JSON Web Token (JWT) that must be included in the request.

Set Resource Policy

User of KBS can set an resource policy through the following endpoint:

/kbs/v0/resource-policy

The payload of the POST request should like:

{
   "policy": <base64encoded policy>
}

Where policy is the base64 encoded policy content. Only authenticated users can send a POST request to this endpoint. KBS verifies the user identity with the user's private key signed JSON Web Token (JWT) that must be included in the request.

Signature

Using the algorithm described in the token header, the KBS signs the concatenation of the token header and the token payload, separated by a dot (.). The token signature is the Base64url encoded string for that signature.

HTTP Response

The token is included in the /kbs/v0/attest POST HTTP response body:

{
    "token": <token>
}

A serialized token is built as follows:

let jwt_header = base64_url::encode(r#"{{"alg": "RS256","typ": "JWT"}}"#);

let jwt_claims_string = format!(r#"{{"exp": {}, "iat": {}, "iss": {}, {}}}}"#, exp, iat, iss, claims);
let jwt_claims = base64_url::encode(&jwt_claims_string);

let jws_signature_input = format!("{}.{}", jwt_header, jwt_claims);
let jws_signature = base64_url::encode(rs256_key_pair.sign(&jws_signature_input));

let serialized_token = format!("{}.{}.{}", jwt_header, jwt_claims, jwt_signature);

Error information

In addition to using the standard HTTPS status code to represent the returned error type, it is also necessary to provide a detailed description of the attestation error. The Problem Details for HTTP APIs format is used for that purpose:

{
    "type": "https://github.com/confidential-containers/kbs/errors/<problem-type>",
    "detail": "$detail"
}

OpenAPI Description

The KBS HTTP endpoints and payloads are formally described in an OpenAPI compliant format.

Acknowledgements

The following individuals were instrumental in the development of this protocol:

  • Ding Ma (@Xynnn007)
  • James O. D. Hunt (@jodh-intel)
  • Jia Zhang (@jiazhang0)
  • Jiale Zhang (@jialez0)
  • Samuel Ortiz (@sameo)
  • Sergio Lopez (@slp)
  • Thomas Fossati (@thomas-fossati)
  • Tobin Feldman-Fitzthum (@fitzthum)