diff --git a/0082-optimize-ima-verify.patch b/0082-optimize-ima-verify.patch new file mode 100644 index 0000000000000000000000000000000000000000..9dbd8fc179eaef7ba4b3763abcbac9a482c5e43c --- /dev/null +++ b/0082-optimize-ima-verify.patch @@ -0,0 +1,243 @@ +From 7d54eae7dbfdbad1de6bac40468c8de9a7260a8b Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Mon, 26 Aug 2024 20:13:49 +0800 +Subject: [PATCH 1/2] optimize ima verify + +Signed-off-by: houmingyong +--- + .../attestation-service/service/src/lib.rs | 17 +++- + .../attestation-service/verifier/src/lib.rs | 20 ---- + .../verifier/src/virtcca/ima.rs | 93 +++++++++---------- + .../verifier/src/virtcca/mod.rs | 13 ++- + 4 files changed, 69 insertions(+), 74 deletions(-) + +diff --git a/service/attestation/attestation-service/service/src/lib.rs b/service/attestation/attestation-service/service/src/lib.rs +index cc3f4328..3ec73d3d 100644 +--- a/service/attestation/attestation-service/service/src/lib.rs ++++ b/service/attestation/attestation-service/service/src/lib.rs +@@ -100,11 +100,20 @@ impl AttestationService { + let verifier = Verifier::default(); + let claims_evidence = verifier.verify_evidence(user_data, evidence).await?; + +- let mut passed = false; +- let ima_result = verifier.verify_ima(evidence, &claims_evidence).await; +- if ima_result.is_ok() { +- passed = true; ++ let mut passed = true; ++ log::debug!("claims evidece ima: {:?}", claims_evidence["ima"].clone()); ++ match claims_evidence["ima"].clone() { ++ serde_json::Value::Object(obj) => { ++ for (_k, v) in obj { ++ if v == Value::Bool(false) { ++ passed = false; ++ break; ++ } ++ } ++ } ++ _ => log::debug!("no ima result"), + } ++ + // get reference by keys in claims_evidence + let mut ops_refs = ReferenceOps::default(); + let refs_of_claims = ops_refs.query(&claims_evidence["payload"].to_string()); +diff --git a/service/attestation/attestation-service/verifier/src/lib.rs b/service/attestation/attestation-service/verifier/src/lib.rs +index 58df3bd4..0b776c29 100644 +--- a/service/attestation/attestation-service/verifier/src/lib.rs ++++ b/service/attestation/attestation-service/verifier/src/lib.rs +@@ -34,10 +34,6 @@ pub struct Verifier {} + #[async_trait] + pub trait VerifierAPIs { + async fn verify_evidence(&self, user_data: &[u8], evidence: &[u8]) -> Result; +- async fn verify_ima(&self, +- evidence: &[u8], +- claim: &serde_json::Value, +- ) -> Result<()>; + } + + const MAX_CHALLENGE_LEN: usize = 64; +@@ -61,20 +57,4 @@ impl VerifierAPIs for Verifier { + _ => bail!("unsupported tee type:{:?}", tee_type), + } + } +- async fn verify_ima(&self, +- evidence: &[u8], +- claim: &serde_json::Value, +- ) -> Result<()> { +- let aa_evidence: Evidence = serde_json::from_slice(evidence)?; +- let tee_type = aa_evidence.tee; +- let digest_list_file = "/etc/attestation/attestation-service/verifier/digest_list_file".to_string(); +- match tee_type { +- #[cfg(feature = "virtcca-verifier")] +- TeeType::Virtcca => virtcca::ima::ImaVerify::default().ima_verify(evidence, claim, digest_list_file), +- _ => { +- log::info!("unsupported ima type:{:?}", tee_type); +- Ok(()) +- }, +- } +- } + } +diff --git a/service/attestation/attestation-service/verifier/src/virtcca/ima.rs b/service/attestation/attestation-service/verifier/src/virtcca/ima.rs +index 44292e83..30a151fa 100644 +--- a/service/attestation/attestation-service/verifier/src/virtcca/ima.rs ++++ b/service/attestation/attestation-service/verifier/src/virtcca/ima.rs +@@ -12,46 +12,20 @@ + use anyhow::{Result, bail}; + use ima_measurements::{Event, EventData, Parser}; + use fallible_iterator::FallibleIterator; +-use std::fs; +-use std::process::Command; +-use serde_json::Value; +-use rand::Rng; ++use serde_json::{Value, Map, json}; + +-use attestation_types::{Evidence, VirtccaEvidence}; ++const IMA_REFERENCE_FILE: &str = "/etc/attestation/attestation-service/verifier/virtcca/ima/digest_list_file"; + +-#[derive(Debug)] +-pub struct ImaVerify { +- log_path: String, +-} +- +-impl Default for ImaVerify { +- fn default() -> Self { +- let mut rng = rand::thread_rng(); +- let n: u64 = rng.gen(); +- ImaVerify { +- // log_path: format!("/tmp/attestation-service/ima-log-{}", n), // todo fs::write depends attestation-service dir exist +- log_path: format!("/tmp/ima-log-{}", n), +- } +- } +-} ++#[derive(Debug, Default)] ++pub struct ImaVerify {} + + impl ImaVerify { +- // todo return detail verify result list with policy +- pub fn ima_verify(&self, evidence: &[u8], claim: &Value, digest_list_file: String) -> Result<()> { +- let aa_evidence: Evidence = serde_json::from_slice(evidence)?; +- let evidence = aa_evidence.evidence.as_bytes(); +- let virtcca_ev: VirtccaEvidence = serde_json::from_slice(evidence)?; +- let ima_log = match virtcca_ev.ima_log { +- Some(ima_log) => ima_log, +- _ => {log::info!("no ima log"); return Ok(())}, +- }; +- +- fs::write(&self.log_path, &ima_log).expect("write img log failed"); +- let f = fs::File::open(&self.log_path).expect("ima log file not found"); +- +- let claim_ima_log_hash = claim["payload"]["cvm"]["rem"][0].clone(); +- let mut parser = Parser::new(f); ++ pub fn ima_verify(&self, ima_log: &[u8], ima_log_hash: Vec) -> Result { ++ if ima_log.to_vec().is_empty() { ++ return Ok(json!({})); ++ } + ++ let mut parser = Parser::new(ima_log); + let mut events: Vec = Vec::new(); + while let Some(event) = parser.next()? { + events.push(event); +@@ -60,32 +34,55 @@ impl ImaVerify { + let pcr_values = parser.pcr_values(); + let pcr_10 = pcr_values.get(&10).expect("PCR 10 not measured"); + let string_pcr_sha256 = hex::encode(pcr_10.sha256); ++ let string_ima_log_hash = hex::encode(ima_log_hash); + +- if Value::String(string_pcr_sha256.clone()) != claim_ima_log_hash { +- log::error!("ima log verify failed string_pcr_sha256 {}, string_claim_ima_log_hash {}", string_pcr_sha256, claim_ima_log_hash); ++ if string_pcr_sha256.clone() != string_ima_log_hash { ++ log::error!("ima log verify failed string_pcr_sha256 {}, string_ima_log_hash {}", ++ string_pcr_sha256, string_ima_log_hash); + bail!("ima log hash verify failed"); + } + ++ let ima_refs: Vec<_> = file_reader(IMA_REFERENCE_FILE)? ++ .into_iter() ++ .map(String::from) ++ .collect(); ++ ++ let mut ima_detail = Map::new(); + // parser each file digest in ima log, and compare with reference base value + for event in events { +- let file_digest = match event.data { +- EventData::ImaNg{digest, name} => {drop(name); digest.digest}, ++ let (name ,file_digest) = match event.data { ++ EventData::ImaNg{digest, name} => (name, digest.digest), + _ => bail!("Inalid event {:?}", event), + }; + let hex_str_digest = hex::encode(file_digest); +- //log::info!("hex_str_digest {}", hex_str_digest); +- let output = Command::new("grep") +- .arg("-E") +- .arg("-i") +- .arg(&hex_str_digest) +- .arg(&digest_list_file) +- .output()?; +- if output.stdout.is_empty() { ++ if ima_refs.contains(&hex_str_digest) { ++ ima_detail.insert(name, Value::Bool(true)); ++ } else { + log::error!("there is no refernce base value of file digest {:?}", hex_str_digest); ++ ima_detail.insert(name, Value::Bool(false)); + } + } ++ let js_ima_detail: Value = ima_detail.into(); ++ log::debug!("ima verify detail result: {:?}", js_ima_detail); + +- Ok(()) ++ Ok(js_ima_detail) + } + } + ++use std::io::BufRead; ++use std::io::BufReader; ++fn file_reader(file_path: &str) -> ::std::io::Result> { ++ let file = std::fs::File::open(file_path)?; ++ let mut strings = Vec::::new(); ++ let mut reader = BufReader::new(file); ++ let mut buf = String::new(); ++ let mut n: usize; ++ loop { ++ n = reader.read_line(&mut buf)?; ++ if n == 0 { break; } ++ buf.pop(); ++ strings.push(buf.clone()); ++ buf.clear(); ++ } ++ Ok(strings) ++} +diff --git a/service/attestation/attestation-service/verifier/src/virtcca/mod.rs b/service/attestation/attestation-service/verifier/src/virtcca/mod.rs +index 3ececb78..a99f9358 100644 +--- a/service/attestation/attestation-service/verifier/src/virtcca/mod.rs ++++ b/service/attestation/attestation-service/verifier/src/virtcca/mod.rs +@@ -103,10 +103,18 @@ impl Evidence { + // verify cvm token + evidence.verify_cvm_token(user_data)?; + ++ // verify ima ++ let ima_log = match virtcca_ev.ima_log { ++ Some(ima_log) => ima_log, ++ _ => {log::info!("no ima log"); vec![]}, ++ }; ++ let ima: serde_json::Value = ima::ImaVerify::default() ++ .ima_verify(&ima_log, evidence.cvm_token.rem[0].clone())?; ++ + // todo parsed TeeClaim +- evidence.parse_claim_from_evidence() ++ evidence.parse_claim_from_evidence(ima) + } +- fn parse_claim_from_evidence(&self) -> Result { ++ fn parse_claim_from_evidence(&self, ima: serde_json::Value) -> Result { + let payload = json!({ + "vcca.cvm.challenge": hex::encode(self.cvm_token.challenge.clone()), + "vcca.cvm.rpv": hex::encode(self.cvm_token.rpv.clone()), +@@ -120,6 +128,7 @@ impl Evidence { + let claim = json!({ + "tee": "vcca", + "payload" : payload, ++ "ima": ima, + }); + Ok(claim as TeeClaim) + } +-- +2.46.0 + diff --git a/0083-optimize-log-level.patch b/0083-optimize-log-level.patch new file mode 100644 index 0000000000000000000000000000000000000000..04944ec75f5a1074487f461ce44245029844dd9e --- /dev/null +++ b/0083-optimize-log-level.patch @@ -0,0 +1,222 @@ +From 93b932412c210f10464502d81c2973065ae1e614 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Fri, 30 Aug 2024 19:42:37 +0800 +Subject: [PATCH 2/2] optimize log level + +Signed-off-by: houmingyong +--- + .../agent/src/bin/aa-test/main.rs | 43 +++++++++++-------- + .../attestation-agent/agent/src/lib.rs | 4 +- + .../attestation-agent/agent/src/main.rs | 2 +- + .../verifier/src/virtcca/mod.rs | 2 +- + 4 files changed, 28 insertions(+), 23 deletions(-) + +diff --git a/service/attestation/attestation-agent/agent/src/bin/aa-test/main.rs b/service/attestation/attestation-agent/agent/src/bin/aa-test/main.rs +index 58fc389d..89a301bf 100644 +--- a/service/attestation/attestation-agent/agent/src/bin/aa-test/main.rs ++++ b/service/attestation/attestation-agent/agent/src/bin/aa-test/main.rs +@@ -21,7 +21,7 @@ const TEST_THREAD_NUM: i64 = 1; // multi thread num + + #[tokio::main] + async fn main() { +- env_logger::init(); ++ env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + let mut handles = Vec::with_capacity(TEST_THREAD_NUM as usize); + for i in 0..TEST_THREAD_NUM { + let t = tokio::spawn(async move {aa_proc(i).await;}); +@@ -31,13 +31,14 @@ async fn main() { + for handle in handles { + let _ = tokio::join!(handle); + } +- println!("main stop"); ++ log::info!("main stop"); + } + + async fn aa_proc(i: i64) { +- println!("attestation_proc {} start", i); ++ log::info!("attestation_proc thread {} start", i); + + // get challenge ++ log::info!("thread {} case1 get challenge", i); + let client = reqwest::Client::new(); + let challenge_endpoint = "http://127.0.0.1:8081/challenge"; + let res = client +@@ -52,11 +53,11 @@ async fn aa_proc(i: i64) { + let challenge = match res.status() { + reqwest::StatusCode::OK => { + let respone = res.text().await.unwrap(); +- println!("get challenge success, AA Response: {:?}", respone); ++ log::info!("thread {} case1 get challenge success response: {:?}", i, respone); + respone + } + status => { +- println!("get challenge Failed, AA Response: {:?}", status); ++ log::error!("thread {} case1 get challenge failed response: {:?}", i, status); + return; + } + }; +@@ -66,7 +67,7 @@ async fn aa_proc(i: i64) { + "challenge": challenge, + "uuid": String::from("f68fd704-6eb1-4d14-b218-722850eb3ef0"), + }); +- ++ log::info!("thread {} case2 get evidence, request body: {}", i, request_body); + let attest_endpoint = "http://127.0.0.1:8081/evidence"; + let res = client + .get(attest_endpoint) +@@ -79,11 +80,12 @@ async fn aa_proc(i: i64) { + let evidence = match res.status() { + reqwest::StatusCode::OK => { + let respone = res.text().await.unwrap(); +- println!("get evidence success, AA Response: {:?}", respone); ++ log::info!("thread {} case2 get evidence success", i); ++ log::debug!("thread {} response: {:?}", i, respone); + respone + } + status => { +- println!("get evidence Failed, AA Response: {:?}", status); ++ log::error!("thread {} case2 get evidence failed response: {:?}", i, status); + return; + } + }; +@@ -94,7 +96,7 @@ async fn aa_proc(i: i64) { + "challenge": "", + "evidence": evidence, + }); +- ++ log::info!("thread {} case3 verify evidence with no challenge", i); + let res = client + .post(attest_endpoint) + .header("Content-Type", "application/json") +@@ -106,10 +108,10 @@ async fn aa_proc(i: i64) { + match res.status() { + reqwest::StatusCode::OK => { + let respone = res.text().await.unwrap(); +- println!("verify evidence with no challenge success, AA Response: {:?}", respone); ++ log::info!("thread {} case3 verify evidence with no challenge success response: {:?}", i, respone); + } + status => { +- println!("verify evidence with no challenge Failed, AA Response: {:?}", status); ++ log::error!("thread {} case3 verify evidence with no challenge failed response: {:?}", i, status); + } + } + } +@@ -118,7 +120,7 @@ async fn aa_proc(i: i64) { + "challenge": challenge, + "evidence": evidence, + }); +- ++ log::info!("thread {} case4 verify evidence with challenge", i); + let res = client + .post(attest_endpoint) + .header("Content-Type", "application/json") +@@ -130,10 +132,10 @@ async fn aa_proc(i: i64) { + match res.status() { + reqwest::StatusCode::OK => { + let respone = res.text().await.unwrap(); +- println!("verify evidence success, AA Response: {:?}", respone); ++ log::info!("thread {} case4 verify evidence success response: {:?}", i, respone); + } + status => { +- println!("verify evidence Failed, AA Response: {:?}", status); ++ log::error!("thread {} case4 verify evidence failed response: {:?}", i, status); + } + } + +@@ -145,6 +147,7 @@ async fn aa_proc(i: i64) { + "challenge": challenge, + "uuid": String::from("f68fd704-6eb1-4d14-b218-722850eb3ef0"), + }); ++ log::info!("thread {} case5 get token, request body: {}", i, request_body); + + let res = client + .get(token_endpoint) +@@ -157,11 +160,12 @@ async fn aa_proc(i: i64) { + let token = match res.status() { + reqwest::StatusCode::OK => { + let respone = res.text().await.unwrap(); +- println!("get token success, AA Response: {:?}", respone); ++ log::info!("thread {} case5 get token success", i); ++ log::debug!("thread {} response: {:?}", i, respone); + respone + } + status => { +- println!("get token Failed, AA Response: {:?}", status); ++ log::error!("thread {} case5 get token failed response: {:?}", i, status); + return; + } + }; +@@ -171,6 +175,7 @@ async fn aa_proc(i: i64) { + "token": token, + }); + ++ log::info!("thread {} case6 verify token", i); + let res = client + .post(token_endpoint) + .header("Content-Type", "application/json") +@@ -182,14 +187,14 @@ async fn aa_proc(i: i64) { + match res.status() { + reqwest::StatusCode::OK => { + let respone = res.text().await.unwrap(); +- println!("verify token success, AA Response: {:?}", respone); ++ log::info!("thread {} case6 verify token success response: {:?}", i, respone); + } + status => { +- println!("verify token Failed, AA Response: {:?}", status); ++ log::error!("thread {} case6 verify token failed response: {:?}", i, status); + } + } + } + + +- println!("attestation_proc {} end", i); ++ log::info!("attestation_proc thread {} end", i); + } +\ No newline at end of file +diff --git a/service/attestation/attestation-agent/agent/src/lib.rs b/service/attestation/attestation-agent/agent/src/lib.rs +index 4ff9b585..c4d913b6 100644 +--- a/service/attestation/attestation-agent/agent/src/lib.rs ++++ b/service/attestation/attestation-agent/agent/src/lib.rs +@@ -266,11 +266,11 @@ impl AttestationAgent { + let challenge = match res.status() { + reqwest::StatusCode::OK => { + let respone = res.json().await.unwrap(); +- log::info!("get challenge success, AS Response: {:?}", respone); ++ log::debug!("get challenge success, AS Response: {:?}", respone); + respone + } + status => { +- log::info!("get challenge Failed, AS Response: {:?}", status); ++ log::error!("get challenge Failed, AS Response: {:?}", status); + bail!("get challenge Failed") + } + }; +diff --git a/service/attestation/attestation-agent/agent/src/main.rs b/service/attestation/attestation-agent/agent/src/main.rs +index 76e63dc4..62a4b4d2 100644 +--- a/service/attestation/attestation-agent/agent/src/main.rs ++++ b/service/attestation/attestation-agent/agent/src/main.rs +@@ -43,7 +43,7 @@ struct Cli { + + #[actix_web::main] + async fn main() -> Result<()> { +- env_logger::init_from_env(env_logger::Env::new().default_filter_or("debug")); ++ env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + let cli = Cli::parse(); + let server = AttestationAgent::new(Some(cli.config)).unwrap(); +diff --git a/service/attestation/attestation-service/verifier/src/virtcca/mod.rs b/service/attestation/attestation-service/verifier/src/virtcca/mod.rs +index a99f9358..3de7c9f4 100644 +--- a/service/attestation/attestation-service/verifier/src/virtcca/mod.rs ++++ b/service/attestation/attestation-service/verifier/src/virtcca/mod.rs +@@ -264,7 +264,7 @@ impl Evidence { + + let ret = evidence.cvm_envelop.init_decoder(None); + match ret { +- Ok(_) => log::info!("decode COSE success"), ++ Ok(_) => log::debug!("decode COSE success"), + Err(e) => { + log::error!("decode COSE failed, {:?}", e); + bail!("decode COSE failed"); +-- +2.46.0 + diff --git a/secGear.spec b/secGear.spec index 846a4ddfa67d2ee0213e85c0985b0de33314c334..f4fb1204a02458b95e51a1380695345d4b13e392 100644 --- a/secGear.spec +++ b/secGear.spec @@ -1,6 +1,6 @@ Name: secGear Version: 0.1.0 -Release: 53 +Release: 54 Summary: secGear is an SDK to develop confidential computing apps based on hardware enclave features Group: OS Security @@ -90,6 +90,8 @@ Patch77: 0078-register-shared-memory-by-open-session.patch Patch78: 0079-Optimize-the-registration-shared-memory.patch Patch79: 0080-add-attestation-service.patch Patch80: 0081-modify-default-agent-config.patch +Patch81: 0082-optimize-ima-verify.patch +Patch82: 0083-optimize-log-level.patch BuildRequires: gcc python automake autoconf libtool @@ -290,6 +292,9 @@ popd systemctl restart rsyslog %changelog +* Sat Aug 31 2024 houmingyong - 0.1.0-54 +- optimize ima verfiy and log level + * Fri Aug 23 2024 houmingyong - 0.1.0-53 - modify default agent config