Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rust sdk eventlog support #64

Merged
merged 6 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions common/rust/cctrusted_base/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::api_data::Algorithm;
use crate::api_data::*;
use crate::eventlog::TcgEventLog;
use crate::tcg::EventLogEntry;
use crate::tcg::TcgDigest;
use core::result::Result;

Expand Down Expand Up @@ -64,7 +64,7 @@ pub trait CCTrustedApi {
Returns:
TcgDigest struct
*/
fn get_cc_measurement(index: u8, algo_id: u8) -> Result<TcgDigest, anyhow::Error>;
fn get_cc_measurement(index: u8, algo_id: u16) -> Result<TcgDigest, anyhow::Error>;

/***
Get eventlog for given index and count.
Expand All @@ -76,9 +76,12 @@ pub trait CCTrustedApi {
OS type and cloud native type event beyond the measured-boot.

Returns:
TcgEventLog struct
EventLogEntry struct
*/
fn get_cc_eventlog(_start: u16, _count: u16) -> TcgEventLog;
fn get_cc_eventlog(
start: Option<u32>,
count: Option<u32>,
) -> Result<Vec<EventLogEntry>, anyhow::Error>;

/***
Get the default Digest algorithms supported by trusted foundation.
Expand Down
2 changes: 1 addition & 1 deletion common/rust/cctrusted_base/src/api_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct CcReport {
*/
// return structure for get_default_algorithm
pub struct Algorithm {
pub algo_id: u8,
pub algo_id: u16,
pub algo_id_str: String,
}

Expand Down
12 changes: 12 additions & 0 deletions common/rust/cctrusted_base/src/binary_blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,15 @@ pub fn dump_data(data: &Vec<u8>) {
info!("{} {}", linestr, printstr);
}
}

pub fn get_u8(data: Vec<u8>) -> u8 {
u8::from_le_bytes(data[0..1].try_into().unwrap())
}

pub fn get_u16(data: Vec<u8>) -> u16 {
u16::from_le_bytes(data[0..2].try_into().unwrap())
}

pub fn get_u32(data: Vec<u8>) -> u32 {
u32::from_le_bytes(data[0..4].try_into().unwrap())
}
306 changes: 304 additions & 2 deletions common/rust/cctrusted_base/src/eventlog.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,304 @@
// struct for standard TCG eventlog
pub struct TcgEventLog {}
use crate::binary_blob::*;
use crate::tcg::EventLogEntry;
use crate::tcg::TcgDigest;
use crate::tcg::TcgEfiSpecIdEvent;
use crate::tcg::TcgEfiSpecIdEventAlgorithmSize;
use crate::tcg::TcgImrEvent;
use crate::tcg::TcgPcClientImrEvent;
use crate::tcg::EV_NO_ACTION;
use anyhow::anyhow;

/***
TcgEventLog struct.
This class contains the event logs following TCG specification.
Attributes:
data: raw data containing all boot time event logs
event_logs: all parsed event logs
count: total number of event logs
*/
pub struct TcgEventLog {
pub spec_id_header_event: TcgEfiSpecIdEvent,
pub data: Vec<u8>,
pub event_logs: Vec<EventLogEntry>,
pub count: u32,
}

impl TcgEventLog {
pub fn new(data: Vec<u8>) -> TcgEventLog {
TcgEventLog {
spec_id_header_event: TcgEfiSpecIdEvent::new(),
data,
event_logs: Vec::new(),
count: 0,
}
}

/***
Collect selected event logs according to user input.
Args:
start: index of the first event log to collect
count: total number of event logs to collect
*/
pub fn select(
&mut self,
start: Option<u32>,
count: Option<u32>,
) -> Result<Vec<EventLogEntry>, anyhow::Error> {
match self.parse() {
Ok(_) => (),
Err(e) => {
return Err(anyhow!("[select] error in parse function {:?}", e));
}
}

let begin = match start {
Some(s) => {
if s == 0 || s >= self.count {
return Err(anyhow!("[select] Invalid input start. Start must be number larger than 0 and smaller than total event log count."));
}
s - 1
}
None => 0,
};

let end = match count {
Some(c) => {
if c == 0 || c >= self.count {
return Err(anyhow!("[select] Invalid input count. count must be number larger than 0 and smaller than total event log count."));
}
(c + begin).try_into().unwrap()
}
None => self.event_logs.len(),
};

Ok((self.event_logs[begin as usize..end as usize]).to_vec())
}

/***
Parse event log data into TCG compatible forms.
Go through all event log data and parse the contents accordingly
Save the parsed event logs into TcgEventLog.
*/
fn parse(&mut self) -> Result<bool, anyhow::Error> {
if self.data.is_empty() {
return Err(anyhow!("[parse] no eventlog data provided"));
}

let mut index = 0;
while index < self.data.len() {
let start = index;
let imr = get_u32(self.data[index..index + 4].to_vec());
index += 4;
let event_type = get_u32(self.data[index..index + 4].to_vec());
if imr == 0xFFFFFFFF {
break;
}

if event_type == EV_NO_ACTION {
match self.parse_spec_id_event_log(self.data[start..].to_vec()) {
Ok((spec_id_event, event_len)) => {
index = start + event_len as usize;
self.event_logs
.push(EventLogEntry::TcgPcClientImrEvent(spec_id_event));
self.count += 1
}
Err(e) => {
return Err(anyhow!(
"[parse] error in parse_spec_id_event_log function {:?}",
e
));
}
}
} else {
match self.parse_event_log(self.data[start..].to_vec()) {
Ok((event_log, event_len)) => {
index = start + event_len as usize;
self.event_logs.push(EventLogEntry::TcgImrEvent(event_log));
self.count += 1
}
Err(e) => {
return Err(anyhow!("[parse] error in parse_event_log function {:?}", e));
}
}
}
}

Ok(true)
}

/***
Parse TCG specification Id event according to TCG spec at
https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClientSpecPlat_TPM_2p0_1p04_pub.pdf.
Event Structure:
typedef tdTCG_PCClientPCREvent {
2735 UINT32 pcrIndex;
UINT32 eventType;
BYTE digest[20];
UINT32 eventDataSize;
BYTE event[eventDataSize]; //This is actually a TCG_EfiSpecIDEventStruct
} TCG_PCClientPCREvent;
Args:
data: event log data in bytes
Returns:
A TcgPcClientImrEvent containing the Specification ID version event
An int specifying the event size
*/
fn parse_spec_id_event_log(
&mut self,
data: Vec<u8>,
) -> Result<(TcgPcClientImrEvent, u32), anyhow::Error> {
let mut index = 0;

let imr_index = get_u32(data[index..index + 4].to_vec());
index += 4;
let header_imr = imr_index - 1;
let header_event_type = get_u32(data[index..index + 4].to_vec());
index += 4;

let digest = data[index..index + 20].try_into().unwrap();
index += 20;
let header_event_size = get_u32(data[index..index + 4].to_vec());
index += 4;
let header_event = data[index..index + header_event_size as usize]
.try_into()
.unwrap();
let specification_id_header = TcgPcClientImrEvent {
imr_index: header_imr,
event_type: header_event_type,
digest,
event_size: header_event_size,
event: header_event,
};

// Parse EFI Spec Id Event structure
let spec_id_signature = data[index..index + 16].try_into().unwrap();
index += 16;
let spec_id_platform_cls = get_u32(data[index..index + 4].to_vec());
index += 4;
let spec_id_version_minor = get_u8(data[index..index + 1].to_vec());
index += 1;
let spec_id_version_major = get_u8(data[index..index + 1].to_vec());
index += 1;
let spec_id_errata = get_u8(data[index..index + 1].to_vec());
index += 1;
let spec_id_uint_size = get_u8(data[index..index + 1].to_vec());
index += 1;
let spec_id_num_of_algo = get_u32(data[index..index + 4].to_vec());
index += 4;
let mut spec_id_digest_sizes: Vec<TcgEfiSpecIdEventAlgorithmSize> = Vec::new();

for _ in 0..spec_id_num_of_algo {
let algo_id = get_u16(data[index..index + 2].to_vec());
index += 2;
let digest_size = get_u16(data[index..index + 2].to_vec());
index += 2;
spec_id_digest_sizes.push(TcgEfiSpecIdEventAlgorithmSize {
algo_id,
digest_size: digest_size.into(),
});
}

let spec_id_vendor_size = get_u8(data[index..index + 1].to_vec());
index += 1;
let mut spec_id_vendor_info = Vec::new();
if spec_id_vendor_size > 0 {
spec_id_vendor_info = data[index..index + spec_id_vendor_size as usize]
.try_into()
.unwrap();
}
index += spec_id_vendor_size as usize;

self.spec_id_header_event = TcgEfiSpecIdEvent {
signature: spec_id_signature,
platform_class: spec_id_platform_cls,
spec_version_minor: spec_id_version_minor,
spec_version_major: spec_id_version_major,
spec_errata: spec_id_errata,
uintn_ize: spec_id_uint_size,
number_of_algorithms: spec_id_num_of_algo,
digest_sizes: spec_id_digest_sizes,
vendor_info_size: spec_id_vendor_size,
vendor_info: spec_id_vendor_info,
};

Ok((specification_id_header, index.try_into().unwrap()))
}

/***
Parse TCG event log body as single event log entry (TcgImrEventLogEntry) defined at
https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClientSpecPlat_TPM_2p0_1p04_pub.pdf
typedef struct tdTCG_PCR_EVENT2{
UINT32 pcrIndex;
UINT32 eventType;
TPML_DIGEST_VALUES digests;
UINT32 eventSize;
BYTE event[eventSize];
} TCG_PCR_EVENT2;
Args:
data: event log data in bytes
Returns:
A TcgImrEvent containing the event information
An int specifying the event size
*/
fn parse_event_log(&self, data: Vec<u8>) -> Result<(TcgImrEvent, u32), anyhow::Error> {
let mut index = 0;

let mut imr_index = get_u32(data[index..index + 4].to_vec());
index += 4;
imr_index -= 1;
let event_type = get_u32(data[index..index + 4].to_vec());
index += 4;

// Fetch digest count and get each digest and its algorithm
let digest_count = get_u32(data[index..index + 4].to_vec());
index += 4;
let mut digests: Vec<TcgDigest> = Vec::new();
for _ in 0..digest_count {
let alg_id = get_u16(data[index..index + 2].to_vec());
index += 2;
let mut pos = 0;

while pos < self.spec_id_header_event.digest_sizes.len() {
if self.spec_id_header_event.digest_sizes[pos].algo_id == alg_id {
break;
}
pos += 1;
}

if pos == self.spec_id_header_event.digest_sizes.len() {
return Err(anyhow!(
"[parse_event_log] No algorithm with such algo_id {}",
alg_id
));
}

let alg = &self.spec_id_header_event.digest_sizes[pos];
let digest_size = alg.digest_size;
let digest_data = data[index..index + digest_size as usize]
.try_into()
.unwrap();
index += digest_size as usize;
let digest = TcgDigest {
algo_id: alg_id,
hash: digest_data,
};
digests.push(digest);
}

let event_size = get_u32(data[index..index + 4].to_vec());
index += 4;
let event = data[index..index + event_size as usize].try_into().unwrap();
index += event_size as usize;

Ok((
TcgImrEvent {
imr_index,
event_type,
digests,
event_size,
event,
},
index.try_into().unwrap(),
))
}
}
Loading
Loading