diff --git a/lib/src/tpmevents/combine.rs b/lib/src/tpmevents/combine.rs index 47503eb..2c0986a 100644 --- a/lib/src/tpmevents/combine.rs +++ b/lib/src/tpmevents/combine.rs @@ -77,7 +77,7 @@ mod tests; #[derive(Clone, Debug)] pub struct EventCombinationError {} -pub type EventNode = tree::ResultNode; +pub type EventNode = tree::ResultNode, EventCombinationError>; pub fn combine_images(images: &[Vec]) -> Vec> { if images.len() == 1 { @@ -101,7 +101,7 @@ pub fn combine(this: &[TPMEvent], that: &[TPMEvent]) -> Vec> { Some(st) => st .iter() .flat_map(|t| t.valid_branches()) - .map(|e| compile_pcrs(&e)) + .map(|e| compile_pcrs(&e.into_iter().flatten().collect::>())) .collect(), None => vec![], } @@ -109,8 +109,8 @@ pub fn combine(this: &[TPMEvent], that: &[TPMEvent]) -> Vec> { fn event_subtree( event_id: &TPMEventID, - map_this: &HashMap, - map_that: &HashMap, + map_this: &HashMap>, + map_that: &HashMap>, group_this: u32, group_that: u32, ) -> Option> { @@ -119,7 +119,7 @@ fn event_subtree( let opt_this = map_this.get(event_id); let opt_that = map_that.get(event_id); // Divergences contains tuples with events, and this/that masked groups - let mut divs: Vec<(&TPMEvent, u32, u32)> = vec![]; + let mut divs: Vec<(&Vec, u32, u32)> = vec![]; let mut nodes: Vec = vec![]; let mut event_required = false; let event_groups = event_id.groups(); @@ -182,8 +182,8 @@ fn event_subtree( } } - for (event, g_this, g_that) in divs { - let mut node = EventNode::new_ok(event.clone()); + for (events, g_this, g_that) in divs { + let mut node = EventNode::new_ok(events.clone()); if let Some(children) = event_subtree(&event_id.next()?, map_this, map_that, g_this, g_that) { for c in children { @@ -196,6 +196,14 @@ fn event_subtree( Some(nodes) } -fn tpm_event_id_hashmap(events: &[TPMEvent]) -> HashMap { - events.iter().map(|e| (e.id.clone(), e.clone())).collect() +fn tpm_event_id_hashmap(events: &[TPMEvent]) -> HashMap> { + let mut lookup = HashMap::>::new(); + for event in events { + lookup + .entry(event.id.clone()) + .or_default() + .push(event.clone()); + } + + lookup } diff --git a/lib/src/tpmevents/combine/tests.rs b/lib/src/tpmevents/combine/tests.rs index 9afcf2f..c5c921c 100644 --- a/lib/src/tpmevents/combine/tests.rs +++ b/lib/src/tpmevents/combine/tests.rs @@ -30,15 +30,21 @@ fn test_tpm_event_id_hashmap() { hash: vec![1, 2, 3, 4, 5], id: TPMEventID::Pcr11UnameContent, }; - let events = vec![foo.clone(), bar.clone(), foobar.clone()]; + let foobaz = TPMEvent { + name: "FOOBAR".into(), + pcr: 0xe8, + hash: vec![6, 7, 8, 9, 10], + id: TPMEventID::Pcr11UnameContent, + }; + let events = vec![foo.clone(), bar.clone(), foobar.clone(), foobaz.clone()]; let res = tpm_event_id_hashmap(&events); assert_eq!( res, HashMap::from([ - (TPMEventID::PcrRootNodeEvent, foo), - (TPMEventID::Pcr11Sbat, bar), - (TPMEventID::Pcr11UnameContent, foobar), + (TPMEventID::PcrRootNodeEvent, vec![foo]), + (TPMEventID::Pcr11Sbat, vec![bar]), + (TPMEventID::Pcr11UnameContent, vec![foobar, foobaz]), ]) ); } @@ -1682,3 +1688,58 @@ fn test_all_pcrs_2_images() { ] ); } + +#[test] +fn test_combine_multiple_events_same_id() { + let this = vec![ + TPMEvent { + pcr: 4, + name: "EV_EFI_ACTION".to_string(), + hash: hex::decode("0000000000000000000000000000000000000000000000000000000000000000") + .unwrap(), + id: TPMEventID::Pcr4EfiCall, + }, + TPMEvent { + pcr: 4, + name: "EV_EFI_ACTION".to_string(), + hash: hex::decode("1111111111111111111111111111111111111111111111111111111111111111") + .unwrap(), + id: TPMEventID::Pcr4EfiCall, + }, + ]; + let that = vec![ + TPMEvent { + pcr: 4, + name: "EV_EFI_ACTION".to_string(), + hash: hex::decode("2222222222222222222222222222222222222222222222222222222222222222") + .unwrap(), + id: TPMEventID::Pcr4EfiCall, + }, + TPMEvent { + pcr: 4, + name: "EV_EFI_ACTION".to_string(), + hash: hex::decode("3333333333333333333333333333333333333333333333333333333333333333") + .unwrap(), + id: TPMEventID::Pcr4EfiCall, + }, + ]; + let foobar = vec![this, that]; + + let res = combine_images(&foobar); + let pcr_values: Vec> = res + .iter() + .map(|i| { + i.iter() + .map(|p| hex::encode(p.value.clone())) + .collect::>() + }) + .collect(); + + assert_eq!( + pcr_values, + vec![ + vec!["4cb4c04374037e0ddde15a714a4295501e2cbc3b0971e4c3eebce23ef433dc4d",], + vec!["22d0d408147e904fa9fe6feba5fc51374e44f07101e208e62fd5453841595ade",], + ], + ); +}