Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump kbs-types and kbs_protocol with a KBS protocol version change #445

Merged
merged 3 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ config = "0.13.3"
env_logger = "0.10.0"
hex = "0.4.3"
jwt-simple = "0.11"
kbs_protocol = { git = "https://github.com/confidential-containers/guest-components.git", rev="9bd6f06a9704e01808e91abde130dffb20e632a5", default-features = false }
kbs-types = "0.6.0"
kms = { git = "https://github.com/confidential-containers/guest-components.git", rev="9bd6f06a9704e01808e91abde130dffb20e632a5", default-features = false }
kbs_protocol = { git = "https://github.com/confidential-containers/guest-components.git", rev="cd16b445291ad401b4b53664266983f4927a370e", default-features = false }
kbs-types = "0.7.0"
kms = { git = "https://github.com/confidential-containers/guest-components.git", rev="cd16b445291ad401b4b53664266983f4927a370e", default-features = false }
jsonwebtoken = { version = "9", default-features = false }
log = "0.4.17"
prost = "0.12"
Expand Down
8 changes: 6 additions & 2 deletions kbs/docs/kbs_attestation_protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ The payload format of the request is as follows:

```json
{
/* Attestation protocol version number used by KBC */
"version": "0.1.0",
/* KBS protocol version number used by KBC */
"version": "0.1.1",
mythi marked this conversation as resolved.
Show resolved Hide resolved
/*
* Type of HW-TEE platforms where KBC is located,
* e.g. "intel-tdx", "amd-sev-snp", etc.
Expand Down Expand Up @@ -286,6 +286,10 @@ The authentication service is provided by the KBS through two endpoints:
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](#challenge) JSON payload.
3. In case of an error (such as if the KBS rejects the [KBS Request](#request) based
on `version` compatibility), an HTTP response with a 401 (`Unauthorized`) status code
together with ErrorInformation JSON payload.

2. `/kbs/v0/attest` only accepts `POST` requests whose body is a [KBS Attestation](#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
Expand Down
12 changes: 8 additions & 4 deletions kbs/src/attestation/coco/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Attest for BuiltInCoCoAs {
.read()
.await
.evaluate(
attestation.tee_evidence.into_bytes(),
attestation.tee_evidence.to_string().into_bytes(),
tee,
Some(Data::Structured(runtime_data_plaintext)),
HashAlgorithm::Sha384,
Expand All @@ -45,21 +45,25 @@ impl Attest for BuiltInCoCoAs {
.await
}

async fn generate_challenge(&self, tee: Tee, tee_parameters: String) -> Result<Challenge> {
async fn generate_challenge(
&self,
tee: Tee,
tee_parameters: serde_json::Value,
) -> Result<Challenge> {
let nonce = match tee {
Tee::Se => {
self.inner
.read()
.await
.generate_supplemental_challenge(tee, tee_parameters)
.generate_supplemental_challenge(tee, tee_parameters.to_string())
.await?
}
_ => make_nonce().await?,
};

let challenge = Challenge {
nonce,
extra_params: String::new(),
extra_params: serde_json::Value::String(String::new()),
};

Ok(challenge)
Expand Down
12 changes: 8 additions & 4 deletions kbs/src/attestation/coco/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl Attest for GrpcClientPool {
.to_string();
let req = tonic::Request::new(AttestationRequest {
tee,
evidence: URL_SAFE_NO_PAD.encode(attestation.tee_evidence),
evidence: URL_SAFE_NO_PAD.encode(attestation.tee_evidence.to_string()),
runtime_data_hash_algorithm: COCO_AS_HASH_ALGORITHM.into(),
init_data_hash_algorithm: COCO_AS_HASH_ALGORITHM.into(),
runtime_data: Some(RuntimeData::StructuredRuntimeData(runtime_data_plaintext)),
Expand All @@ -124,12 +124,16 @@ impl Attest for GrpcClientPool {
Ok(token)
}

async fn generate_challenge(&self, tee: Tee, tee_parameters: String) -> Result<Challenge> {
async fn generate_challenge(
&self,
tee: Tee,
tee_parameters: serde_json::Value,
) -> Result<Challenge> {
let nonce = match tee {
Tee::Se => {
let mut inner = HashMap::new();
inner.insert(String::from("tee"), String::from("se"));
inner.insert(String::from("tee_params"), tee_parameters);
inner.insert(String::from("tee_params"), tee_parameters.to_string());
let req = tonic::Request::new(ChallengeRequest { inner });

let mut client = { self.pool.lock().await.get().await? };
Expand All @@ -145,7 +149,7 @@ impl Attest for GrpcClientPool {

let challenge = Challenge {
nonce,
extra_params: String::new(),
extra_params: serde_json::Value::String(String::new()),
};

Ok(challenge)
Expand Down
2 changes: 1 addition & 1 deletion kbs/src/attestation/intel_trust_authority/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Attest for IntelTrustAuthority {
let attestation = serde_json::from_str::<Attestation>(attestation)
.map_err(|e| anyhow!("Deserialize Attestation failed: {:?}", e))?;
let evidence =
serde_json::from_str::<IntelTrustAuthorityTeeEvidence>(&attestation.tee_evidence)
serde_json::from_value::<IntelTrustAuthorityTeeEvidence>(attestation.tee_evidence)
.map_err(|e| anyhow!("Deserialize supported TEE Evidence failed: {:?}", e))?;

let runtime_data = json!({
Expand Down
14 changes: 11 additions & 3 deletions kbs/src/attestation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,16 @@ pub trait Attest: Send + Sync {
async fn verify(&self, tee: Tee, nonce: &str, attestation: &str) -> Result<String>;

/// generate the Challenge to pass to attester based on Tee and nonce
async fn generate_challenge(&self, _tee: Tee, _tee_parameters: String) -> Result<Challenge> {
async fn generate_challenge(
&self,
_tee: Tee,
_tee_parameters: serde_json::Value,
) -> Result<Challenge> {
let nonce = make_nonce().await?;

Ok(Challenge {
nonce,
extra_params: String::new(),
extra_params: serde_json::Value::String(String::new()),
})
}
}
Expand Down Expand Up @@ -121,7 +125,11 @@ impl AttestationService {
}
}

pub async fn generate_challenge(&self, tee: Tee, tee_parameters: String) -> Result<Challenge> {
pub async fn generate_challenge(
&self,
tee: Tee,
tee_parameters: serde_json::Value,
) -> Result<Challenge> {
match self {
#[cfg(feature = "coco-as-grpc")]
AttestationService::CoCoASgRPC(inner) => {
Expand Down
4 changes: 2 additions & 2 deletions kbs/src/http/attest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use serde_json::json;

static KBS_MAJOR_VERSION: u64 = 0;
static KBS_MINOR_VERSION: u64 = 1;
static KBS_PATCH_VERSION: u64 = 0;
static KBS_PATCH_VERSION: u64 = 1;
mythi marked this conversation as resolved.
Show resolved Hide resolved

lazy_static! {
static ref VERSION_REQ: VersionReq = {
Expand All @@ -28,7 +28,7 @@ lazy_static! {
build: BuildMetadata::EMPTY,
};

VersionReq::parse(&format!("<={kbs_version}")).unwrap()
VersionReq::parse(&format!("={kbs_version}")).unwrap()
};
}

Expand Down
15 changes: 11 additions & 4 deletions kbs/src/http/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,17 @@ const RSA_ALGORITHM: &str = "RSA1_5";
const AES_GCM_256_ALGORITHM: &str = "A256GCM";

pub(crate) fn jwe(tee_pub_key: TeePubKey, payload_data: Vec<u8>) -> Result<Response> {
if tee_pub_key.alg != *RSA_ALGORITHM {
let TeePubKey::RSA { alg, k_mod, k_exp } = tee_pub_key else {
raise_error!(Error::JWEFailed(format!(
"key type is not TeePubKey::RSA but {:?}",
tee_pub_key
)));
};

if alg != *RSA_ALGORITHM {
raise_error!(Error::JWEFailed(format!(
"algorithm is not {RSA_ALGORITHM} but {}",
tee_pub_key.alg
alg
)));
}

Expand All @@ -207,11 +214,11 @@ pub(crate) fn jwe(tee_pub_key: TeePubKey, payload_data: Vec<u8>) -> Result<Respo
.map_err(|e| Error::JWEFailed(format!("AES encrypt Resource payload failed: {e:?}")))?;

let k_mod = URL_SAFE_NO_PAD
.decode(&tee_pub_key.k_mod)
.decode(k_mod)
.map_err(|e| Error::JWEFailed(format!("base64 decode k_mod failed: {e:?}")))?;
let n = BigUint::from_bytes_be(&k_mod);
let k_exp = URL_SAFE_NO_PAD
.decode(&tee_pub_key.k_exp)
.decode(k_exp)
.map_err(|e| Error::JWEFailed(format!("base64 decode k_exp failed: {e:?}")))?;
let e = BigUint::from_bytes_be(&k_exp);

Expand Down
Loading