From 47fbb1a6e3a8df5977656f51be36d6015a01f4d8 Mon Sep 17 00:00:00 2001 From: Qi Feng Huo Date: Wed, 6 Mar 2024 15:23:49 +0800 Subject: [PATCH] Verifier: IBM SE add generate_challenge_extra_params Signed-off-by: Qi Feng Huo --- Cargo.lock | 21 ++++++--- Cargo.toml | 2 +- .../attestation-service/Cargo.toml | 1 + .../attestation-service/src/bin/grpc/mod.rs | 1 + .../src/bin/restful/mod.rs | 1 + .../attestation-service/src/lib.rs | 4 +- attestation-service/docs/parsed_claims.md | 3 ++ attestation-service/protos/attestation.proto | 1 + attestation-service/verifier/src/lib.rs | 14 +++--- attestation-service/verifier/src/se/mod.rs | 43 +++++++++++-------- .../verifier/src/se/seattest.rs | 36 ++++++++-------- kbs/src/api/src/attestation/coco/builtin.rs | 8 ++++ kbs/src/api/src/attestation/coco/grpc.rs | 5 +++ .../attestation/intel_trust_authority/mod.rs | 4 ++ kbs/src/api/src/attestation/mod.rs | 19 +++++--- kbs/src/api/src/http/attest.rs | 21 +++------ kbs/src/api/src/session.rs | 19 ++++++-- 17 files changed, 126 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4029bcd158..49db2ea53d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,7 +412,7 @@ dependencies = [ "env_logger 0.10.2", "jsonwebtoken", "jwt-simple", - "kbs-types", + "kbs-types 0.5.3 (git+https://github.com/huoqifeng/kbs-types.git?branch=s390x-se)", "lazy_static", "log", "mobc", @@ -535,7 +535,7 @@ dependencies = [ "env_logger 0.10.2", "futures", "hex", - "kbs-types", + "kbs-types 0.5.3 (git+https://github.com/huoqifeng/kbs-types.git?branch=s390x-se)", "lazy_static", "log", "openssl", @@ -575,7 +575,7 @@ dependencies = [ "csv-rs", "hyper", "hyper-tls", - "kbs-types", + "kbs-types 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "log", "nix", "occlum_dcap", @@ -1283,7 +1283,7 @@ dependencies = [ "anyhow", "base64 0.21.7", "ctr", - "kbs-types", + "kbs-types 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand", "rsa 0.9.6", "serde", @@ -2429,6 +2429,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "kbs-types" +version = "0.5.3" +source = "git+https://github.com/huoqifeng/kbs-types.git?branch=s390x-se#681d9ea3bea0e4465d67f004234f628dbced1007" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "kbs_protocol" version = "0.1.0" @@ -2440,7 +2449,7 @@ dependencies = [ "base64 0.21.7", "crypto", "jwt-simple", - "kbs-types", + "kbs-types 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "log", "reqwest", "resource_uri", @@ -5276,7 +5285,7 @@ dependencies = [ "eventlog-rs", "hex", "jsonwebtoken", - "kbs-types", + "kbs-types 0.5.3 (git+https://github.com/huoqifeng/kbs-types.git?branch=s390x-se)", "log", "openssl", "rstest", diff --git a/Cargo.toml b/Cargo.toml index 7e56286c9a..c8d8797e7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ clap = { version = "4", features = ["derive"] } config = "0.13.3" env_logger = "0.10.0" hex = "0.4.3" -kbs-types = "0.5.3" // TODO, update to pick new TEE type for IBM Secure Eexcution (SE) in https://github.com/virtee/kbs-types/blob/main/src/lib.rs#L24 +kbs-types = { git = "https://github.com/huoqifeng/kbs-types.git", branch = "s390x-se" } jsonwebtoken = "9" log = "0.4.17" prost = "0.11.0" diff --git a/attestation-service/attestation-service/Cargo.toml b/attestation-service/attestation-service/Cargo.toml index d3bda03d33..9717dc19f2 100644 --- a/attestation-service/attestation-service/Cargo.toml +++ b/attestation-service/attestation-service/Cargo.toml @@ -13,6 +13,7 @@ az-tdx-vtpm-verifier = [ "verifier/az-tdx-vtpm-verifier" ] snp-verifier = [ "verifier/snp-verifier" ] csv-verifier = [ "verifier/csv-verifier" ] cca-verifier = [ "verifier/cca-verifier" ] +se-verifier = [ "verifier/se-verifier" ] # Only for testing and CI rvps-builtin = [ "reference-value-provider-service" ] diff --git a/attestation-service/attestation-service/src/bin/grpc/mod.rs b/attestation-service/attestation-service/src/bin/grpc/mod.rs index cd22fa7617..722475d986 100644 --- a/attestation-service/attestation-service/src/bin/grpc/mod.rs +++ b/attestation-service/attestation-service/src/bin/grpc/mod.rs @@ -37,6 +37,7 @@ fn to_kbs_tee(tee: GrpcTee) -> Tee { GrpcTee::AzSnpVtpm => Tee::AzSnpVtpm, GrpcTee::Cca => Tee::Cca, GrpcTee::AzTdxVtpm => Tee::AzTdxVtpm, + GrpcTee::Se => Tee::Se, } } diff --git a/attestation-service/attestation-service/src/bin/restful/mod.rs b/attestation-service/attestation-service/src/bin/restful/mod.rs index 20d840ee3e..0f25202b78 100644 --- a/attestation-service/attestation-service/src/bin/restful/mod.rs +++ b/attestation-service/attestation-service/src/bin/restful/mod.rs @@ -62,6 +62,7 @@ fn to_tee(tee: &str) -> anyhow::Result { "csv" => Tee::Csv, "sample" => Tee::Sample, "aztdxvtpm" => Tee::AzTdxVtpm, + "se" => Tee::Se, other => bail!("tee `{other} not supported`"), }; diff --git a/attestation-service/attestation-service/src/lib.rs b/attestation-service/attestation-service/src/lib.rs index d7daeb739c..901abed2e7 100644 --- a/attestation-service/attestation-service/src/lib.rs +++ b/attestation-service/attestation-service/src/lib.rs @@ -240,9 +240,9 @@ impl AttestationService { self.rvps.verify_and_extract(message).await } - pub async fn generate_challenge(&self, tee: Tee, nonce: &str) -> Result { + pub async fn generate_challenge_extra_params(&self, tee: Tee) -> Result { let verifier = verifier::to_verifier(&tee)?; - verifier.generate_challenge(nonce) + verifier.generate_challenge_extra_params().await } } diff --git a/attestation-service/docs/parsed_claims.md b/attestation-service/docs/parsed_claims.md index b783fcfdbe..72d7c25b54 100644 --- a/attestation-service/docs/parsed_claims.md +++ b/attestation-service/docs/parsed_claims.md @@ -88,3 +88,6 @@ The claim inherit the fields from the SEV-SNP claim with and additional `tpm` hi - `tpm.pcr{01,..,n}`: SHA256 PCR registers for the TEE's vTPM quote. Note: The TD Report and TD Quote are fetched during early boot in this TEE. Kernel, Initrd and rootfs are measured into the vTPM's registers. + +## IBM Secure Execution (SE) +TBD \ No newline at end of file diff --git a/attestation-service/protos/attestation.proto b/attestation-service/protos/attestation.proto index 405aad923c..fb33a057c6 100644 --- a/attestation-service/protos/attestation.proto +++ b/attestation-service/protos/attestation.proto @@ -12,6 +12,7 @@ enum Tee { CSV = 6; CCA = 7; AzTdxVtpm = 8; + Se = 9; } message AttestationRequest { diff --git a/attestation-service/verifier/src/lib.rs b/attestation-service/verifier/src/lib.rs index cd22ac3369..d5618d47ac 100644 --- a/attestation-service/verifier/src/lib.rs +++ b/attestation-service/verifier/src/lib.rs @@ -2,7 +2,7 @@ use std::cmp::Ordering; use anyhow::*; use async_trait::async_trait; -use kbs_types::{Challenge, Tee}; +use kbs_types::Tee; use log::warn; pub mod sample; @@ -106,7 +106,7 @@ pub fn to_verifier(tee: &Tee) -> Result> { Tee::Se => { cfg_if::cfg_if! { if #[cfg(feature = "se-verifier")] { - Ok(Box::::default() as Box) + Ok(Box::::default() as Box) } else { bail!("feature `se-verifier` is not enabled for `verifier` crate.") } @@ -167,14 +167,10 @@ pub trait Verifier { expected_init_data_hash: &InitDataHash, ) -> Result; - async fn generate_challenge( + async fn generate_challenge_extra_params( &self, - nonce: &str) -> Result { - - Result::Ok(Challenge { - nonce, - extra_params: String::new(), - }) + ) -> Result { + Ok(String::new()) } } diff --git a/attestation-service/verifier/src/se/mod.rs b/attestation-service/verifier/src/se/mod.rs index 0e42ca9e2b..87223b9daf 100644 --- a/attestation-service/verifier/src/se/mod.rs +++ b/attestation-service/verifier/src/se/mod.rs @@ -3,12 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 // +use super::*; use async_trait::async_trait; use anyhow::anyhow; use base64::prelude::*; -use kbs_types::{Challenge, Tee}; use crate::{InitDataHash, ReportData}; -use super::{TeeEvidenceParsedClaim, Verifier}; use crate::se::seattest::FakeSeAttest; use crate::se::seattest::SeFakeVerifier; @@ -25,38 +24,46 @@ impl Verifier for SeVerifier { expected_report_data: &ReportData, expected_init_data_hash: &InitDataHash, ) -> Result { + verify_evidence(evidence, expected_report_data, expected_init_data_hash) .await .map_err(|e| anyhow!("Se Verifier: {:?}", e)) } - async fn generate_challenge(&self, tee: Tee, nonce: &str) -> Result { - /// TODO replace FakeSeAttest with real crate + async fn generate_challenge_extra_params( + &self, + ) -> Result { + + // TODO replace FakeSeAttest with real crate let attester = FakeSeAttest::default(); let hkds: Vec = vec![String::new(); 2]; - let certk = String::new(); - let signk = String::new(); - let arpk = String::new(); - Result::Ok(Challenge { - nonce, - extra_params: BASE64_STANDARD.encode(attester.create(hkds, certk, signk, arpk)), - }) + let certk = "cert_file_path"; + let signk = "sign_file_path"; + let arpk = "arpk_file_path"; + + let extra_params = attester.create(hkds, certk, signk, arpk) + .await + .context("Create SE attestation request failed: {:?}")?; + + Ok(BASE64_STANDARD.encode(extra_params)) } } async fn verify_evidence( evidence: &[u8], - expected_report_data: &ReportData<'_>, - expected_init_data_hash: &InitDataHash<'_>, + _expected_report_data: &ReportData<'_>, + _expected_init_data_hash: &InitDataHash<'_>, ) -> Result { - /// TODO replace FakeSeAttest with real crate + // TODO replace FakeSeAttest with real crate let attester = FakeSeAttest::default(); - let arpk = String::new(); - let hdr = String::new(); - let se = attester.verify(evidence, arpk, hdr); + let arpk = "arpk_file_path"; + let hdr = "hdr_file_path"; + let se = attester.verify(evidence, arpk, hdr) + .await + .context("Verify SE attestation evidence failed: {:?}")?; - let v = serde_json::to_value(se?).context("build json value from the se evidence")?; + let v = serde_json::to_value(se).context("build json value from the se evidence")?; Ok(v as TeeEvidenceParsedClaim) } \ No newline at end of file diff --git a/attestation-service/verifier/src/se/seattest.rs b/attestation-service/verifier/src/se/seattest.rs index 2830f5cd28..113cd6938e 100644 --- a/attestation-service/verifier/src/se/seattest.rs +++ b/attestation-service/verifier/src/se/seattest.rs @@ -11,39 +11,39 @@ pub struct FakeSeAttest {} #[async_trait::async_trait] pub trait SeFakeVerifier { - async fn create( + async fn create<'a, 'b, 'c>( &self, - hkdFiles: Vec, - certFile: &String, - signingFile: &String, - arpkFile: &String + _hkd_files: Vec, + _cert_file: &'a str, + _signing_file: &'b str, + _arpk_file: &'c str, ) -> Result>; - async fn verify( + async fn verify<'a, 'b>( &self, - evidence: Vec, - arpkFile: &String, - hdr: Vec + _evidence: &[u8], + _arpk_file: &'a str, + _hdr_file: &'b str, ) -> Result>; } #[async_trait::async_trait] impl SeFakeVerifier for FakeSeAttest { - async fn create( + async fn create<'a, 'b, 'c>( &self, - hkdFiles: Vec, - certFile: &String, - signingFile: &String, - arpkFile: &String + _hkd_files: Vec, + _cert_file: &'a str, + _signing_file: &'b str, + _arpk_file: &'c str, ) -> Result> { Result::Ok(Vec::new()) } - async fn verify( + async fn verify<'a, 'b>( &self, - evidence: Vec, - arpkFile: &String, - hdr: Vec + _evidence: &[u8], + _arpk_file: &'a str, + _hkd_files: &'b str, ) -> Result> { Result::Ok(Vec::new()) } diff --git a/kbs/src/api/src/attestation/coco/builtin.rs b/kbs/src/api/src/attestation/coco/builtin.rs index 3f8eb4bac5..b9d017f60e 100644 --- a/kbs/src/api/src/attestation/coco/builtin.rs +++ b/kbs/src/api/src/attestation/coco/builtin.rs @@ -45,6 +45,14 @@ impl Attest for BuiltInCoCoAs { ) .await } + + async fn generate_challenge_extra_params(&self, tee: Tee) -> Result { + self.inner + .read() + .await + .generate_challenge_extra_params(tee) + .await + } } impl BuiltInCoCoAs { diff --git a/kbs/src/api/src/attestation/coco/grpc.rs b/kbs/src/api/src/attestation/coco/grpc.rs index 174d76b492..e478df8d31 100644 --- a/kbs/src/api/src/attestation/coco/grpc.rs +++ b/kbs/src/api/src/attestation/coco/grpc.rs @@ -39,6 +39,7 @@ fn to_grpc_tee(tee: Tee) -> GrpcTee { Tee::Sgx => GrpcTee::Sgx, Tee::Snp => GrpcTee::Snp, Tee::Tdx => GrpcTee::Tdx, + Tee::Se => GrpcTee::Se, } } @@ -125,6 +126,10 @@ impl Attest for GrpcClientPool { Ok(token) } + + async fn generate_challenge_extra_params(&self, _tee: Tee) -> Result { + Ok(String::new()) + } } pub struct GrpcManager { diff --git a/kbs/src/api/src/attestation/intel_trust_authority/mod.rs b/kbs/src/api/src/attestation/intel_trust_authority/mod.rs index f77d51a0a7..dc9012419c 100644 --- a/kbs/src/api/src/attestation/intel_trust_authority/mod.rs +++ b/kbs/src/api/src/attestation/intel_trust_authority/mod.rs @@ -122,6 +122,10 @@ impl Attest for IntelTrustAuthority { Ok(resp_data.token.clone()) } + + async fn generate_challenge_extra_params(&self, _tee: Tee) -> Result { + Ok(String::new()) + } } impl IntelTrustAuthority { diff --git a/kbs/src/api/src/attestation/mod.rs b/kbs/src/api/src/attestation/mod.rs index c37d3d64ca..0fdefed9bf 100644 --- a/kbs/src/api/src/attestation/mod.rs +++ b/kbs/src/api/src/attestation/mod.rs @@ -10,7 +10,7 @@ use attestation_service::config::Config as AsConfig; use coco::grpc::*; #[cfg(feature = "intel-trust-authority-as")] use intel_trust_authority::*; -use kbs_types::{Challenge, Request, Tee}; +use kbs_types::Tee; #[cfg(feature = "coco-as")] #[allow(missing_docs)] @@ -34,7 +34,7 @@ pub trait Attest: Send + Sync { async fn verify(&self, tee: Tee, nonce: &str, attestation: &str) -> Result; /// generate the challenge payload to pass to attester based on Tee and nonce - async fn generate_challenge(&self, tee: Tee, nonce: &str) -> Result; + async fn generate_challenge_extra_params(&self, tee: Tee) -> Result; } /// Attestation Service @@ -93,14 +93,21 @@ impl AttestationService { } } - pub async fn generate_challenge(&self, tee: Tee, nonce: &str) -> Result { + pub async fn generate_challenge_extra_params(&self, tee: Tee) -> Result { match self { #[cfg(feature = "coco-as-grpc")] - AttestationService::CoCoASgRPC(inner) => inner.generate_challenge(tee, nonce).await, + AttestationService::CoCoASgRPC(inner) => { + inner.generate_challenge_extra_params(tee).await + } + AttestationService::CoCoASgRPC(inner) => { + inner.generate_challenge_extra_params(tee).await + } #[cfg(any(feature = "coco-as-builtin", feature = "coco-as-builtin-no-verifier"))] - AttestationService::CoCoASBuiltIn(inner) => inner.generate_challenge(tee, nonce, attestation).await, + AttestationService::CoCoASBuiltIn(inner) => { + inner.generate_challenge_extra_params(tee).await + } #[cfg(feature = "intel-trust-authority-as")] - AttestationService::IntelTA(inner) => inner.generate_challenge(tee, nonce).await, + AttestationService::IntelTA(inner) => inner.generate_challenge_extra_params(tee).await, } } } diff --git a/kbs/src/api/src/http/attest.rs b/kbs/src/api/src/http/attest.rs index b46f3b08c8..6f2c9b0150 100644 --- a/kbs/src/api/src/http/attest.rs +++ b/kbs/src/api/src/http/attest.rs @@ -7,22 +7,12 @@ use crate::{raise_error, session::SessionStatus}; use super::*; use anyhow::anyhow; -use base64::engine::general_purpose::URL_SAFE_NO_PAD; +use base64::engine::general_purpose::{STANDARD, URL_SAFE_NO_PAD}; use base64::Engine; +use kbs_types::Challenge; use log::{error, info}; -use rand::{thread_rng, Rng}; use serde_json::json; -fn nonce() -> Result { - let mut nonce: Vec = vec![0; 32]; - - thread_rng() - .try_fill(&mut nonce[..]) - .map_err(anyhow::Error::from)?; - - Ok(STANDARD.encode(&nonce)) -} - /// POST /auth pub(crate) async fn auth( request: web::Json, @@ -32,9 +22,12 @@ pub(crate) async fn auth( ) -> Result { info!("request: {:?}", &request); - let challenge = attestation_service.generate_challenge(nonce()?); + let extra_params = attestation_service + .generate_challenge_extra_params(request.tee) + .await + .unwrap(); - let session = SessionStatus::auth(request.0, **timeout, challenge) + let session = SessionStatus::auth(request.0, **timeout, extra_params) .map_err(|e| Error::FailedAuthentication(format!("Session: {e}")))?; let response = HttpResponse::Ok() diff --git a/kbs/src/api/src/session.rs b/kbs/src/api/src/session.rs index accc59a71e..41c1997dfc 100644 --- a/kbs/src/api/src/session.rs +++ b/kbs/src/api/src/session.rs @@ -11,12 +11,22 @@ use base64::engine::general_purpose::STANDARD; use base64::Engine; use kbs_types::{Challenge, Request}; use log::warn; -// use rand::{thread_rng, Rng}; +use rand::{thread_rng, Rng}; use semver::Version; use uuid::Uuid; pub(crate) static KBS_SESSION_ID: &str = "kbs-session-id"; +fn nonce() -> Result { + let mut nonce: Vec = vec![0; 32]; + + thread_rng() + .try_fill(&mut nonce[..]) + .map_err(anyhow::Error::from)?; + + Ok(STANDARD.encode(&nonce)) +} + /// Finite State Machine model for RCAR handshake pub(crate) enum SessionStatus { Authed { @@ -53,7 +63,7 @@ macro_rules! impl_member { } impl SessionStatus { - pub fn auth(request: Request, timeout: i64, challenge: &Challenge) -> Result { + pub fn auth(request: Request, timeout: i64, extra_params: String) -> Result { let version = Version::parse(&request.version).map_err(anyhow::Error::from)?; if !crate::VERSION_REQ.matches(&version) { bail!("Invalid Request version {}", request.version); @@ -64,7 +74,10 @@ impl SessionStatus { Ok(Self::Authed { request, - challenge, + challenge: Challenge { + nonce: nonce()?, + extra_params, + }, id, timeout, })