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
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 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.
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.
{
"kty": "RSA",
"alg": "$key_algorithm",
"n": "$pubkey_modulus",
"e": "$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. 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 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:
- 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 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:
- 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. 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",
"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
.
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.
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.
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)