diff --git a/Cargo.lock b/Cargo.lock index 88b37d218..a09a99add 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -499,14 +499,15 @@ dependencies = [ [[package]] name = "attestation-agent" version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components.git?rev=9bd6f06a9704e01808e91abde130dffb20e632a5#9bd6f06a9704e01808e91abde130dffb20e632a5" +source = "git+https://github.com/confidential-containers/guest-components.git?rev=cd16b445291ad401b4b53664266983f4927a370e#cd16b445291ad401b4b53664266983f4927a370e" dependencies = [ "anyhow", "async-trait", "attester", - "base64 0.21.7", + "base64 0.22.1", "config", "const_format", + "kbs-types", "log", "serde", "serde_json", @@ -562,13 +563,13 @@ dependencies = [ [[package]] name = "attester" version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components.git?rev=9bd6f06a9704e01808e91abde130dffb20e632a5#9bd6f06a9704e01808e91abde130dffb20e632a5" +source = "git+https://github.com/confidential-containers/guest-components.git?rev=cd16b445291ad401b4b53664266983f4927a370e#cd16b445291ad401b4b53664266983f4927a370e" dependencies = [ "anyhow", "async-trait", "az-snp-vtpm 0.6.0", "az-tdx-vtpm 0.6.0", - "base64 0.21.7", + "base64 0.22.1", "codicon", "csv-rs", "hex", @@ -1368,11 +1369,11 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto" version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components.git?rev=9bd6f06a9704e01808e91abde130dffb20e632a5#9bd6f06a9704e01808e91abde130dffb20e632a5" +source = "git+https://github.com/confidential-containers/guest-components.git?rev=cd16b445291ad401b4b53664266983f4927a370e#cd16b445291ad401b4b53664266983f4927a370e" dependencies = [ "aes-gcm", "anyhow", - "base64 0.21.7", + "base64 0.22.1", "ctr", "kbs-types", "rand", @@ -2769,9 +2770,9 @@ dependencies = [ [[package]] name = "kbs-types" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "febd73b2b1df274ea454d81ddf76f596af9754410b7ed6f988f2e1782a175da3" +checksum = "9b6441ed73b0faa50707d4de41c6b45c76654b661b96aaf7b26a41331eedc0a5" dependencies = [ "serde", "serde_json", @@ -2780,12 +2781,12 @@ dependencies = [ [[package]] name = "kbs_protocol" version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components.git?rev=9bd6f06a9704e01808e91abde130dffb20e632a5#9bd6f06a9704e01808e91abde130dffb20e632a5" +source = "git+https://github.com/confidential-containers/guest-components.git?rev=cd16b445291ad401b4b53664266983f4927a370e#cd16b445291ad401b4b53664266983f4927a370e" dependencies = [ "anyhow", "async-trait", "attester", - "base64 0.21.7", + "base64 0.22.1", "crypto", "jwt-simple 0.12.9", "kbs-types", @@ -2804,12 +2805,12 @@ dependencies = [ [[package]] name = "kms" version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components.git?rev=9bd6f06a9704e01808e91abde130dffb20e632a5#9bd6f06a9704e01808e91abde130dffb20e632a5" +source = "git+https://github.com/confidential-containers/guest-components.git?rev=cd16b445291ad401b4b53664266983f4927a370e#cd16b445291ad401b4b53664266983f4927a370e" dependencies = [ "anyhow", "async-trait", "attestation-agent", - "base64 0.21.7", + "base64 0.22.1", "chrono", "const_format", "hex", @@ -2952,9 +2953,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "matchit" @@ -4297,7 +4298,7 @@ dependencies = [ [[package]] name = "resource_uri" version = "0.1.0" -source = "git+https://github.com/confidential-containers/guest-components.git?rev=9bd6f06a9704e01808e91abde130dffb20e632a5#9bd6f06a9704e01808e91abde130dffb20e632a5" +source = "git+https://github.com/confidential-containers/guest-components.git?rev=cd16b445291ad401b4b53664266983f4927a370e#cd16b445291ad401b4b53664266983f4927a370e" dependencies = [ "anyhow", "serde", diff --git a/Cargo.toml b/Cargo.toml index 3c75c979c..0fb08e68e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/kbs/docs/kbs_attestation_protocol.md b/kbs/docs/kbs_attestation_protocol.md index 797696ee0..8a77e84b8 100644 --- a/kbs/docs/kbs_attestation_protocol.md +++ b/kbs/docs/kbs_attestation_protocol.md @@ -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", /* * Type of HW-TEE platforms where KBC is located, * e.g. "intel-tdx", "amd-sev-snp", etc. @@ -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 diff --git a/kbs/src/attestation/coco/builtin.rs b/kbs/src/attestation/coco/builtin.rs index c5a194e8f..cc0bdcf9d 100644 --- a/kbs/src/attestation/coco/builtin.rs +++ b/kbs/src/attestation/coco/builtin.rs @@ -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, @@ -45,13 +45,17 @@ impl Attest for BuiltInCoCoAs { .await } - async fn generate_challenge(&self, tee: Tee, tee_parameters: String) -> Result { + async fn generate_challenge( + &self, + tee: Tee, + tee_parameters: serde_json::Value, + ) -> Result { 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?, @@ -59,7 +63,7 @@ impl Attest for BuiltInCoCoAs { let challenge = Challenge { nonce, - extra_params: String::new(), + extra_params: serde_json::Value::String(String::new()), }; Ok(challenge) diff --git a/kbs/src/attestation/coco/grpc.rs b/kbs/src/attestation/coco/grpc.rs index 0d61f271b..903dbf344 100644 --- a/kbs/src/attestation/coco/grpc.rs +++ b/kbs/src/attestation/coco/grpc.rs @@ -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)), @@ -124,12 +124,16 @@ impl Attest for GrpcClientPool { Ok(token) } - async fn generate_challenge(&self, tee: Tee, tee_parameters: String) -> Result { + async fn generate_challenge( + &self, + tee: Tee, + tee_parameters: serde_json::Value, + ) -> Result { 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? }; @@ -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) diff --git a/kbs/src/attestation/intel_trust_authority/mod.rs b/kbs/src/attestation/intel_trust_authority/mod.rs index 2eac0ac65..616b036ba 100644 --- a/kbs/src/attestation/intel_trust_authority/mod.rs +++ b/kbs/src/attestation/intel_trust_authority/mod.rs @@ -66,7 +66,7 @@ impl Attest for IntelTrustAuthority { let attestation = serde_json::from_str::(attestation) .map_err(|e| anyhow!("Deserialize Attestation failed: {:?}", e))?; let evidence = - serde_json::from_str::(&attestation.tee_evidence) + serde_json::from_value::(attestation.tee_evidence) .map_err(|e| anyhow!("Deserialize supported TEE Evidence failed: {:?}", e))?; let runtime_data = json!({ diff --git a/kbs/src/attestation/mod.rs b/kbs/src/attestation/mod.rs index bacdd5640..e306f7803 100644 --- a/kbs/src/attestation/mod.rs +++ b/kbs/src/attestation/mod.rs @@ -55,12 +55,16 @@ pub trait Attest: Send + Sync { async fn verify(&self, tee: Tee, nonce: &str, attestation: &str) -> Result; /// generate the Challenge to pass to attester based on Tee and nonce - async fn generate_challenge(&self, _tee: Tee, _tee_parameters: String) -> Result { + async fn generate_challenge( + &self, + _tee: Tee, + _tee_parameters: serde_json::Value, + ) -> Result { let nonce = make_nonce().await?; Ok(Challenge { nonce, - extra_params: String::new(), + extra_params: serde_json::Value::String(String::new()), }) } } @@ -121,7 +125,11 @@ impl AttestationService { } } - pub async fn generate_challenge(&self, tee: Tee, tee_parameters: String) -> Result { + pub async fn generate_challenge( + &self, + tee: Tee, + tee_parameters: serde_json::Value, + ) -> Result { match self { #[cfg(feature = "coco-as-grpc")] AttestationService::CoCoASgRPC(inner) => { diff --git a/kbs/src/http/attest.rs b/kbs/src/http/attest.rs index 5089fc00d..f4de7e87d 100644 --- a/kbs/src/http/attest.rs +++ b/kbs/src/http/attest.rs @@ -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; lazy_static! { static ref VERSION_REQ: VersionReq = { @@ -28,7 +28,7 @@ lazy_static! { build: BuildMetadata::EMPTY, }; - VersionReq::parse(&format!("<={kbs_version}")).unwrap() + VersionReq::parse(&format!("={kbs_version}")).unwrap() }; } diff --git a/kbs/src/http/resource.rs b/kbs/src/http/resource.rs index c0f17265b..abf8aed54 100644 --- a/kbs/src/http/resource.rs +++ b/kbs/src/http/resource.rs @@ -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) -> Result { - 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 ))); } @@ -207,11 +214,11 @@ pub(crate) fn jwe(tee_pub_key: TeePubKey, payload_data: Vec) -> Result