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
RACR
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
Request
payload to the KBS, in order to authenticate itself against the KBS, and eventually request resources. - Challenge: After receiving the initial
Request
payload, the KBS responds with theChallenge
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. - 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. - Response: The KBS returns a
Response
payload to a KBC requesting a resource if and only if theAttestation
payload was successfully validated. The KBC requests resources by sending HTTPGET
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.
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).
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:
{
/*
* 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 requests 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 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.
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
.
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.
{
"alg": "$key_algorithm",
"k-mod": "$pubkey modulus",
"k-exp": "$pubkey exponent"
}
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/auth
only acceptsPOST
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:- A
Set-Cookie
header 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.
- A
/kbs/v0/attest
only acceptsPOST
requests whose body is a KBS Attestation JSON payload and the header contains aCookie
set to the value received in step 1.i. This is how the attester replies to attestation challenge received in step 1.ii. The KBS replies to that request with an empty HTTP response (no content), which HTTP status indicates if the attestation was successful or not.
┌──────────┐ ┌─────┐
│ 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: N/A │ ┃
┃ └───────────────────────────────────────┘ ┃
┃ ┃
┃ ┃
┃ ┃
▽ ▽
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.
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 ▽
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.
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.
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",
"tee-pubkey": $pubkey
<Custom Claims>
}
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
' and iss
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/ |
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.
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
.
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);
The KBS is configured with a specific Attestation Results Token Broker. The
Broker generates and signs Attestation Results token that can be returned by the
/kbs/v0/attest
endpoint. In order for Relying Parties to
authenticate the KBS Broker and validate the Attestation Results, the Broker
certificate chain is made available by the KBS at the following endpoint:
/kbs/v0/token-certificate-chain
The Broker certificate chain is represented as a JWKS (https://www.rfc-editor.org/rfc/rfc7517#appendix-B).
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)