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.
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.
The semantics of attestation defined by KBS is a simple and extensible four-step model, which uses JSON structure to organize information. As follows:
- Request: The KBC sends the initial
Requestpayload to the KBS, in order to authenticate itself against the KBS, and eventually request resources. - Challenge: After receiving the initial
Requestpayload, the KBS responds with theChallengepayload. 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. - 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
Attestationpayload to the KBS, that contains the attestation evidence and the HW-TEE generated, ephemeral public key. - Response: After successful attestation, the KBS returns an
AttestationTokenin the response to the/kbs/v0/attestendpoint. Subsequently, the KBC can request resources by sending HTTPGETrequests to resource specific endpoints. The KBS responds with encrypted resource data in JWE format. 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.
The payload format of the request is as follows:
{
/* KBS protocol version number used by KBC */
"version": "0.1.1",
/*
* Type of HW-TEE platforms where KBC is located,
* e.g. "tdx", "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. Currently, known HW-TEE platforms are:
| TEE | Description |
|---|---|
az-snp-vtpm |
Microsoft Azure AMD SNP VTPM |
az-tdx-vtpm |
Microsoft Azure TDX VTPM |
sev |
AMD SEV |
snp |
AMD SNP |
sgx |
Intel SGX |
tdx |
Intel TDX |
cca |
Arm Confidential Compute Architecture |
csv |
China Secure Virtualization |
se |
IBM Z Secure Execution |
tpm |
Trusted Platform Module |
sample |
Value which should be only used for testing an attestation server |
Up-to-date list can be found here.
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).
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.
After receiving the attestation challenge, the KBC builds an attestation evidence from the HW-TEE platform and organizes it into the following payload:
{
"init-data": {
"format": "json",
"body": "..."
},
"runtime-data": {
"nonce": "$nonce",
"tee-pubkey": {
"kty": "EC",
"crv": "$curve_name",
"alg": "$key_algorithm",
"x": "$x_coordinate",
"y": "$y_coordinate"
}
},
"tee-evidence": {
"primary_evidence": {},
"additional_evidence": "{}"
}
}Note: The
init-datafield is optional. Thetee-pubkeycan be either RSA or EC format (see Key Format section). Theadditional_evidenceis a JSON string representation of a mapping of TEE type to evidence pairs.
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.
-
init-dataInit data is an OPTIONAL structured document associated with a TEE instance, typically containing measured configuration settings. -
init-data.formatThe format of init data insideinit-data.bodyfield. Nowjsonandtomlare supported. The serialization logic please refer to the doc. -
init-data.bodyThe plaintext of init data. -
runtime-dataRuntime data is a structured JSON document, and the hash of this data is bound to HW-TEE evidence, ensuring cryptographic integrity and authenticity. It must include:nonce: The nonce string from theChallenge.noncereceived from the KBS in step 2.tee-pubkey: A JWK-formatted public key generated by the KBC running in the HW-TEE.
-
runtime-data.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 and can be either RSA or Elliptic Curve (EC) 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 is a composite evidence structure containing:
primary_evidence: Primary TEE evidence. Its format depends on the TEE and is typically defined by the Attestation-Service.additional_evidence: Additional evidence for secondary TEE devices within a client. This is a JSON string mapping of TEE type to (TEE class, TEE evidence) pairs, represented as a string to avoid serialization inconsistencies.
Complex guests may be represented by more than one type of attester and more than one format of TEE evidence. TEE evidence from multiple attesters can be combined together. The method for combining and decomposing evidence should be shared between the Attestation-Agent and Attestation-Service or KBS.
Typically, the KBS does not parse or analyze the attestation evidence. Instead,it forwards it to the Attestation-Service for verification. When dealing with combined evidence, the KBS may be responsible for unwrapping multiple pieces of hardware evidence and forwarding them to the Attestation-Service individually. Alternatively, the Attestation-Service could be responsible for unpacking the combined evidence. Either way, the format of the evidence is beyond the scope of this document.
The KBS protocol defines two types of responses:
- Attestation Results Token: Returned by the
/kbs/v0/attestendpoint upon successful attestation. - Resource Response: Returned when requesting resources, encrypted using JWE format.
Upon successful attestation, the /kbs/v0/attest endpoint returns an AttestationToken in the response body:
{
"token": "<JWT_token_string>"
}The token is a serialized JSON Web Token (JWT) that contains attestation results and endorsements. For detailed information about the token, see the Attestation Token and the simple token claim in JSON.
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 resource response payload that follows the JSON Web Encryption flattened serialization format:
{
"protected": "$jose_header",
"encrypted_key": "$encrypted_key",
"aad": "$aad",
"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 aad = base64_url::encode(additional_authenticated_data);
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);protected.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.
protected.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.
aad(Required if AEAD is used)
An input to an AEAD operation that is integrity protected but not encrypted.
Due to JSON Web Encryption, AAD field should be calculated by ASCII(BASE64URL(UTF8(JWE Protected Header))).
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.
tag
The authentication tag is used to authenticate the ciphertext. If the algorithm
described by enc used does not need it, this field is left blank.
The Attestation runtime-data.tee-pubkey field and the Token Resource
tee-pubkey claim contain a public key from a HW-TEE generated asymmetric key pair.
This field follows the JSON Web Key format and supports both RSA and Elliptic Curve (EC) key types.
{
"kty": "RSA",
"alg": "$key_algorithm",
"n": "$pubkey_modulus",
"e": "$pubkey_exponent"
}{
"kty": "EC",
"crv": "$curve_name",
"alg": "$key_algorithm",
"x": "$x_coordinate",
"y": "$y_coordinate"
}The kty field determines which format is used. For RSA keys, n and e represent the modulus and exponent respectively. For EC keys, crv specifies the curve name (e.g., "P-256", "P-384"), and x and y are the coordinates of the public key point.
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.
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:
-
/kbs/v0/authonly acceptsPOSTrequests 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:- A
Set-Cookieheader set tokbs-session-id=<session>. The KBS tracks the attester and its attestation results with that cookie. - An attestation challenge for the attester to take. This is the content of the response, set to a KBS Challenge JSON payload.
- In case of an error (such as if the KBS rejects the KBS Request based
on
versioncompatibility), an HTTP response with a 401 (Unauthorized) status code together with ErrorInformation JSON payload.
- A
-
/kbs/v0/attestonly acceptsPOSTrequests whose body is a KBS Attestation JSON payload and the header contains aCookieset 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
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.
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 Resource Response JSON payload (JWE format):
┌──────────┐ ┌─────┐
│ 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:
- 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. - 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. - The requested resource does not exist. The KBS implementation sends an HTTP
response with a 404 (
Not Found) status code.
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 Resource Response JSON payload (JWE format). The
symmetric key inside the Resource 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:
- 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. - 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. - The requested resource does not exist. The KBS implementation sends an HTTP
response with a 404 (
Not Found) status code.
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.<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.
A POST request with the content of resource to /kbs/v0/resource/<repository>/<type>/<tag> can register the resource
into the KBS.
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.
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"
}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. The tee-pubkey follows
the JSON Web Key format and can be either
RSA or Elliptic Curve (EC) format, as described in the Key Format section.
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.
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": "<Base64EncodedPolicy>"
}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.
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": "<Base64EncodedPolicy>"
}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.
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.
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);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"
}The KBS HTTP endpoints and payloads are formally described in an OpenAPI compliant format.
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)