1use crate::{
5 cli::SubCommand, command::CommandError, device::with_device, io::read_file_input, job::Job,
6 key::Tpm2shAlgId, parse_hex_u32, pcr::pcr_get_bank_list,
7};
8use clap::Args;
9use tpm2_protocol::{
10 data::{Tpm2bEvent, TpmCc, TpmuHa},
11 message::TpmPcrEventCommand,
12 TpmHandle,
13};
14
15fn parse_pcr_index(handle_str: &str) -> Result<TpmHandle, String> {
16 parse_hex_u32(handle_str)
17 .map(TpmHandle)
18 .map_err(|_| "malformed value".to_string())
19}
20
21#[derive(Args, Debug)]
23#[command(name = "pcr-event")]
24pub struct PcrEvent {
25 #[arg(value_name = "pcr-index", value_parser = parse_pcr_index)]
27 pub pcr_index: TpmHandle,
28}
29
30impl SubCommand for PcrEvent {
31 fn run(&self, job: &mut Job) -> Result<(), CommandError> {
32 with_device(job.device.clone(), |device| {
33 let banks = pcr_get_bank_list(device)?;
34 let handles = [self.pcr_index.0];
35
36 let auths = vec![job.auth_list.first().cloned().unwrap_or_default()];
37
38 let data_bytes = read_file_input(None)?;
39
40 let event_data = Tpm2bEvent::try_from(data_bytes.as_slice())?;
41 let command = TpmPcrEventCommand {
42 pcr_handle: handles[0].into(),
43 event_data,
44 };
45
46 let (resp, _) = job.execute(device, &command, &handles, &auths)?;
47
48 let pcr_resp = resp
49 .PcrEvent()
50 .map_err(|_| CommandError::ResponseMismatch(TpmCc::PcrEvent))?;
51
52 let clauses: Vec<String> = banks
53 .iter()
54 .zip(pcr_resp.digests.iter())
55 .filter_map(|(bank, digest_struct)| {
56 if let TpmuHa::Digest(bytes) = digest_struct.digest {
57 Some(format!(
58 "{}:{}:{}",
59 Tpm2shAlgId(bank.alg),
60 self.pcr_index.0,
61 hex::encode(bytes)
62 ))
63 } else {
64 None
65 }
66 })
67 .collect();
68
69 writeln!(job.writer, "{}", clauses.join("+"))?;
70
71 Ok(())
72 })
73 }
74}