tss_esapi/abstraction/pcr/
data.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    abstraction::pcr::PcrBank,
6    interface_types::algorithm::HashingAlgorithm,
7    structures::{Digest, DigestList, PcrSelectionList},
8    tss2_esys::TPML_DIGEST,
9    Error, Result, WrapperErrorKind,
10};
11use log::error;
12/// Struct holding pcr banks and their associated
13/// hashing algorithm
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct PcrData {
16    data: Vec<(HashingAlgorithm, PcrBank)>,
17}
18
19impl PcrData {
20    /// Creates new empty PcrData
21    pub const fn new() -> Self {
22        PcrData { data: Vec::new() }
23    }
24
25    /// Function for creating PcrData from a pcr selection list and pcr digests list.
26    pub fn create(
27        pcr_selection_list: &PcrSelectionList,
28        digest_list: &DigestList,
29    ) -> Result<PcrData> {
30        Ok(PcrData {
31            data: Self::create_data(pcr_selection_list, digest_list.value().to_vec())?,
32        })
33    }
34
35    /// Adds data to the PcrData
36    pub fn add(
37        &mut self,
38        pcr_selection_list: &PcrSelectionList,
39        digest_list: &DigestList,
40    ) -> Result<()> {
41        Self::create_data(pcr_selection_list, digest_list.value().to_vec())?
42            .drain(..)
43            .try_for_each(|(hashing_algorithm, pcr_bank)| {
44                if let Some(existing_pcr_bank) = self.pcr_bank_mut(hashing_algorithm) {
45                    existing_pcr_bank.try_extend(pcr_bank)?;
46                } else {
47                    self.data.push((hashing_algorithm, pcr_bank));
48                }
49                Ok(())
50            })
51    }
52
53    /// Function for turning a pcr selection list and pcr digests values
54    /// into the format in which data is stored in PcrData.
55    fn create_data(
56        pcr_selection_list: &PcrSelectionList,
57        mut digests: Vec<Digest>,
58    ) -> Result<Vec<(HashingAlgorithm, PcrBank)>> {
59        pcr_selection_list
60            .get_selections()
61            .iter()
62            .map(|pcr_selection| {
63                let pcr_slots = pcr_selection.selected();
64                if pcr_slots.len() > digests.len() {
65                    error!("More pcr slots in selection then available digests");
66                    return Err(Error::local_error(WrapperErrorKind::InconsistentParams));
67                }
68                let digests_in_bank = digests.drain(..pcr_slots.len()).collect();
69                Ok((
70                    pcr_selection.hashing_algorithm(),
71                    PcrBank::create(pcr_slots, digests_in_bank)?,
72                ))
73            })
74            .collect()
75    }
76
77    /// Function for retrieving the first PCR values associated with hashing_algorithm.
78    pub fn pcr_bank(&self, hashing_algorithm: HashingAlgorithm) -> Option<&PcrBank> {
79        self.data
80            .iter()
81            .find(|(alg, _)| *alg == hashing_algorithm)
82            .map(|(_, bank)| bank)
83    }
84
85    /// Function for retrieving the number of banks in the data.
86    pub fn len(&self) -> usize {
87        self.data.len()
88    }
89
90    /// Returns true if there are no banks in the data.
91    pub fn is_empty(&self) -> bool {
92        self.data.is_empty()
93    }
94
95    /// Private method for finding a PCR bank.
96    fn pcr_bank_mut(&mut self, hashing_algorithm: HashingAlgorithm) -> Option<&mut PcrBank> {
97        self.data
98            .iter_mut()
99            .find(|(alg, _)| *alg == hashing_algorithm)
100            .map(|(_, bank)| bank)
101    }
102}
103
104impl Default for PcrData {
105    fn default() -> Self {
106        Self::new()
107    }
108}
109
110impl IntoIterator for PcrData {
111    type Item = (HashingAlgorithm, PcrBank);
112    type IntoIter = ::std::vec::IntoIter<(HashingAlgorithm, PcrBank)>;
113
114    fn into_iter(self) -> Self::IntoIter {
115        self.data.into_iter()
116    }
117}
118
119impl From<PcrData> for Vec<TPML_DIGEST> {
120    fn from(pcr_data: PcrData) -> Self {
121        pcr_data
122            .data
123            .iter()
124            .flat_map(|(_, pcr_bank)| pcr_bank.into_iter())
125            .map(|(_, digest)| digest)
126            .collect::<Vec<&Digest>>()
127            .chunks(DigestList::MAX_SIZE)
128            .map(|digests| {
129                let mut tpml_digest: TPML_DIGEST = Default::default();
130                for (index, digest) in digests.iter().enumerate() {
131                    tpml_digest.count += 1;
132                    tpml_digest.digests[index].size = digest.len() as u16;
133                    tpml_digest.digests[index].buffer[..digest.len()]
134                        .copy_from_slice(digest.value());
135                }
136                tpml_digest
137            })
138            .collect()
139    }
140}