244 lines
9.8 KiB
Diff
244 lines
9.8 KiB
Diff
From 7d54eae7dbfdbad1de6bac40468c8de9a7260a8b Mon Sep 17 00:00:00 2001
|
|
From: houmingyong <houmingyong@huawei.com>
|
|
Date: Mon, 26 Aug 2024 20:13:49 +0800
|
|
Subject: [PATCH 1/2] optimize ima verify
|
|
|
|
Signed-off-by: houmingyong <houmingyong@huawei.com>
|
|
---
|
|
.../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<TeeClaim>;
|
|
- 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<u8>) -> Result<Value> {
|
|
+ if ima_log.to_vec().is_empty() {
|
|
+ return Ok(json!({}));
|
|
+ }
|
|
|
|
+ let mut parser = Parser::new(ima_log);
|
|
let mut events: Vec<Event> = 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<Vec<String>> {
|
|
+ let file = std::fs::File::open(file_path)?;
|
|
+ let mut strings = Vec::<String>::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<TeeClaim> {
|
|
+ fn parse_claim_from_evidence(&self, ima: serde_json::Value) -> Result<TeeClaim> {
|
|
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
|
|
|