Skip to main content

tss_esapi/structures/lists/
command_code_attributes.rs

1// Copyright 2022 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    Error, Result, WrapperErrorKind,
5    attributes::CommandCodeAttributes,
6    tss2_esys::{TPMA_CC, TPML_CCA},
7};
8use log::error;
9use std::{convert::TryFrom, iter::IntoIterator, ops::Deref};
10
11/// A structure holding a list of command code attributes.
12///
13/// # Details
14/// This corresponds to the TPML_CCA structure.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct CommandCodeAttributesList {
17    command_code_attributes: Vec<CommandCodeAttributes>,
18}
19
20impl CommandCodeAttributesList {
21    pub const MAX_SIZE: usize = Self::calculate_max_size();
22
23    /// Finds a command code attributes with a specific
24    /// command index
25    pub fn find(&self, command_index: u16) -> Option<&CommandCodeAttributes> {
26        self.command_code_attributes
27            .iter()
28            .find(|cca| cca.command_index() == command_index)
29    }
30
31    /// Private function that calculates the maximum number
32    /// elements allowed in internal storage.
33    const fn calculate_max_size() -> usize {
34        crate::structures::capability_data::max_cap_size::<TPMA_CC>()
35    }
36}
37
38impl Deref for CommandCodeAttributesList {
39    type Target = Vec<CommandCodeAttributes>;
40
41    fn deref(&self) -> &Self::Target {
42        &self.command_code_attributes
43    }
44}
45
46impl AsRef<[CommandCodeAttributes]> for CommandCodeAttributesList {
47    fn as_ref(&self) -> &[CommandCodeAttributes] {
48        self.command_code_attributes.as_slice()
49    }
50}
51
52impl TryFrom<Vec<CommandCodeAttributes>> for CommandCodeAttributesList {
53    type Error = Error;
54
55    fn try_from(command_code_attributes: Vec<CommandCodeAttributes>) -> Result<Self> {
56        if command_code_attributes.len() > Self::MAX_SIZE {
57            error!(
58                "Failed to convert Vec<CommandCodeAttributes> into CommandCodeAttributesList, to many items (> {})",
59                Self::MAX_SIZE
60            );
61            return Err(Error::local_error(WrapperErrorKind::InvalidParam));
62        }
63        Ok(CommandCodeAttributesList {
64            command_code_attributes,
65        })
66    }
67}
68
69impl IntoIterator for CommandCodeAttributesList {
70    type Item = CommandCodeAttributes;
71    type IntoIter = std::vec::IntoIter<Self::Item>;
72
73    fn into_iter(self) -> Self::IntoIter {
74        self.command_code_attributes.into_iter()
75    }
76}
77
78impl TryFrom<TPML_CCA> for CommandCodeAttributesList {
79    type Error = Error;
80
81    fn try_from(tpml_cca: TPML_CCA) -> Result<Self> {
82        let count = usize::try_from(tpml_cca.count).map_err(|e| {
83            error!("Failed to parse count in TPML_CCA as usize: {}", e);
84            Error::local_error(WrapperErrorKind::InvalidParam)
85        })?;
86
87        if count > Self::MAX_SIZE {
88            error!("Invalid size value in TPML_CCA (> {})", Self::MAX_SIZE,);
89            return Err(Error::local_error(WrapperErrorKind::InvalidParam));
90        }
91
92        tpml_cca.commandAttributes[..count]
93            .iter()
94            .map(|&tp| CommandCodeAttributes::try_from(tp))
95            .collect::<Result<Vec<CommandCodeAttributes>>>()
96            .map(|command_code_attributes| CommandCodeAttributesList {
97                command_code_attributes,
98            })
99    }
100}
101
102impl From<CommandCodeAttributesList> for TPML_CCA {
103    fn from(command_code_attributes_list: CommandCodeAttributesList) -> Self {
104        let mut tpml_cca: TPML_CCA = Default::default();
105        for command_code_attributes in command_code_attributes_list {
106            tpml_cca.commandAttributes[tpml_cca.count as usize] = command_code_attributes.into();
107            tpml_cca.count += 1;
108        }
109        tpml_cca
110    }
111}