forked from confidential-containers/guest-components
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch fixes the idempotence of eventlog. Before this, when AA restarts and eventlog is activated, the originally recorded aael will be truncated and the INIT event will be recorded repeatedly. This patch will check whether there is an existing AAEL when AA is restarted. If so, it will skip creating and recording the INIT event. At the same time, a synchronization mechanism is used to ensure that RTMR expansion will not occur repeatedly after AA abnormally interrupts execution. Signed-off-by: Xynnn007 <xynnn@linux.alibaba.com>
- Loading branch information
Showing
9 changed files
with
504 additions
and
235 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
104 changes: 104 additions & 0 deletions
104
attestation-agent/attestation-agent/src/eventlog/event.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Copyright (c) 2024 Alibaba Cloud | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
use std::str::FromStr; | ||
|
||
use anyhow::{anyhow, bail, Context, Result}; | ||
use crypto::HashAlgorithm; | ||
use sha2::{digest::FixedOutput, Digest, Sha256, Sha384, Sha512}; | ||
|
||
#[derive(Clone)] | ||
pub struct AAEventlog { | ||
pub hash_algorithm: HashAlgorithm, | ||
pub init_state: Vec<u8>, | ||
pub events: Vec<Vec<u8>>, | ||
} | ||
|
||
impl FromStr for AAEventlog { | ||
type Err = anyhow::Error; | ||
|
||
fn from_str(input: &str) -> Result<Self> { | ||
let all_lines = input.lines().collect::<Vec<&str>>(); | ||
|
||
let (initline, eventlines) = all_lines | ||
.split_first() | ||
.ok_or(anyhow!("at least one line should be included in AAEL"))?; | ||
|
||
// Init line looks like | ||
// INIT sha256/0000000000000000000000000000000000000000000000000000000000000000 | ||
let init_line_items = initline.split_ascii_whitespace().collect::<Vec<&str>>(); | ||
if init_line_items.len() != 2 { | ||
bail!("Illegal INIT event record."); | ||
} | ||
|
||
if init_line_items[0] != "INIT" { | ||
bail!("INIT event should start with `INIT` key word"); | ||
} | ||
|
||
let (hash_algorithm, init_state) = init_line_items[1].split_once('/').ok_or(anyhow!( | ||
"INIT event should have `<sha-algorithm>/<init-PCR-value>` as content after `INIT`" | ||
))?; | ||
|
||
let hash_algorithm = HashAlgorithm::from_str(hash_algorithm) | ||
.context("parse Hash Algorithm in INIT entry")?; | ||
let init_state = hex::decode(init_state).context("parse init state in INIT entry")?; | ||
|
||
let events = eventlines | ||
.iter() | ||
.map(|line| line.as_bytes().to_vec()) | ||
.collect(); | ||
|
||
Ok(Self { | ||
events, | ||
hash_algorithm, | ||
init_state, | ||
}) | ||
} | ||
} | ||
|
||
impl AAEventlog { | ||
fn accumulate_hash<D: Digest + FixedOutput>(&self) -> Vec<u8> { | ||
let mut state = self.init_state.clone(); | ||
|
||
let mut init_event_hasher = D::new(); | ||
let init_event = format!( | ||
"INIT {}/{}", | ||
self.hash_algorithm.as_ref(), | ||
hex::encode(&self.init_state) | ||
); | ||
Digest::update(&mut init_event_hasher, init_event.as_bytes()); | ||
let init_event_hash = init_event_hasher.finalize(); | ||
|
||
let mut hasher = D::new(); | ||
Digest::update(&mut hasher, &state); | ||
|
||
Digest::update(&mut hasher, init_event_hash); | ||
state = hasher.finalize().to_vec(); | ||
|
||
self.events.iter().for_each(|event| { | ||
let mut event_hasher = D::new(); | ||
Digest::update(&mut event_hasher, &event); | ||
let event_hash = event_hasher.finalize(); | ||
|
||
let mut hasher = D::new(); | ||
Digest::update(&mut hasher, &state); | ||
Digest::update(&mut hasher, event_hash); | ||
state = hasher.finalize().to_vec(); | ||
}); | ||
|
||
state | ||
} | ||
|
||
/// Check the integrity of the AAEL, and gets a digest. Return whether the rtmr is the same as the digest. | ||
pub fn integrity_check(&self, rtmr: &[u8]) -> bool { | ||
let result = match self.hash_algorithm { | ||
HashAlgorithm::Sha256 => self.accumulate_hash::<Sha256>(), | ||
HashAlgorithm::Sha384 => self.accumulate_hash::<Sha384>(), | ||
HashAlgorithm::Sha512 => self.accumulate_hash::<Sha512>(), | ||
}; | ||
|
||
rtmr == result | ||
} | ||
} |
Oops, something went wrong.