Skip to content

Commit 880053e

Browse files
committed
Adds CommandCodeAttributesList type.
Adds the CommandCodeAttributesList type this corresponds to the TPML_CCA structure. Signed-off-by: Jesper Brynolf <[email protected]>
1 parent 44370cd commit 880053e

File tree

9 files changed

+290
-2
lines changed

9 files changed

+290
-2
lines changed

tss-esapi/src/structures/lists/command_code.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct CommandCodeList {
1616
}
1717

1818
impl CommandCodeList {
19-
pub const MAX_SIZE: usize = TPM2_MAX_CAP_CC as usize;
19+
pub const MAX_SIZE: usize = Self::calculate_max_size();
2020
/// Creates a new CommandCodeList
2121
pub const fn new() -> Self {
2222
CommandCodeList {
@@ -41,6 +41,12 @@ impl CommandCodeList {
4141
pub fn into_inner(self) -> Vec<CommandCode> {
4242
self.command_codes
4343
}
44+
45+
/// Private function that calculates the maximum number
46+
/// elements allowed in internal storage.
47+
const fn calculate_max_size() -> usize {
48+
TPM2_MAX_CAP_CC as usize
49+
}
4450
}
4551

4652
impl TryFrom<TPML_CC> for CommandCodeList {
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2022 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use crate::{
4+
attributes::CommandCodeAttributes,
5+
tss2_esys::{TPM2_CAP, TPM2_MAX_CAP_BUFFER, TPMA_CC, TPML_CCA},
6+
Error, Result, WrapperErrorKind,
7+
};
8+
use log::error;
9+
use 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 strucutre.
15+
#[derive(Debug, Clone, PartialEq, Eq)]
16+
pub struct CommandCodeAttributesList {
17+
command_code_attributes: Vec<CommandCodeAttributes>,
18+
}
19+
20+
impl 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+
// According to the specification the size is vendor specific.
35+
// So if someone is using modified values in their TSS libraries
36+
// it is picked up here.
37+
(TPM2_MAX_CAP_BUFFER as usize
38+
- std::mem::size_of::<TPM2_CAP>()
39+
- std::mem::size_of::<u32>())
40+
/ std::mem::size_of::<TPMA_CC>()
41+
}
42+
}
43+
44+
impl Deref for CommandCodeAttributesList {
45+
type Target = Vec<CommandCodeAttributes>;
46+
47+
fn deref(&self) -> &Self::Target {
48+
&self.command_code_attributes
49+
}
50+
}
51+
52+
impl AsRef<[CommandCodeAttributes]> for CommandCodeAttributesList {
53+
fn as_ref(&self) -> &[CommandCodeAttributes] {
54+
self.command_code_attributes.as_slice()
55+
}
56+
}
57+
58+
impl TryFrom<Vec<CommandCodeAttributes>> for CommandCodeAttributesList {
59+
type Error = Error;
60+
61+
fn try_from(command_code_attributes: Vec<CommandCodeAttributes>) -> Result<Self> {
62+
if command_code_attributes.len() > Self::MAX_SIZE {
63+
error!("Failed to convert Vec<CommandCodeAttributes> into CommandCodeAttributesList, to many items (> {})", Self::MAX_SIZE);
64+
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
65+
}
66+
Ok(CommandCodeAttributesList {
67+
command_code_attributes,
68+
})
69+
}
70+
}
71+
72+
impl IntoIterator for CommandCodeAttributesList {
73+
type Item = CommandCodeAttributes;
74+
type IntoIter = std::vec::IntoIter<Self::Item>;
75+
76+
fn into_iter(self) -> Self::IntoIter {
77+
self.command_code_attributes.into_iter()
78+
}
79+
}
80+
81+
impl TryFrom<TPML_CCA> for CommandCodeAttributesList {
82+
type Error = Error;
83+
84+
fn try_from(tpml_cca: TPML_CCA) -> Result<Self> {
85+
let count = usize::try_from(tpml_cca.count).map_err(|e| {
86+
error!("Failed to parse count in TPML_CCA as usize: {}", e);
87+
Error::local_error(WrapperErrorKind::InvalidParam)
88+
})?;
89+
90+
if count > Self::MAX_SIZE {
91+
error!("Invalid size value in TPML_CCA (> {})", Self::MAX_SIZE,);
92+
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
93+
}
94+
95+
tpml_cca.commandAttributes[..count]
96+
.iter()
97+
.map(|&tp| CommandCodeAttributes::try_from(tp))
98+
.collect::<Result<Vec<CommandCodeAttributes>>>()
99+
.map(|command_code_attributes| CommandCodeAttributesList {
100+
command_code_attributes,
101+
})
102+
}
103+
}
104+
105+
impl From<CommandCodeAttributesList> for TPML_CCA {
106+
fn from(command_code_attributes_list: CommandCodeAttributesList) -> Self {
107+
let mut tpml_cca: TPML_CCA = Default::default();
108+
for command_code_attributes in command_code_attributes_list {
109+
tpml_cca.commandAttributes[tpml_cca.count as usize] = command_code_attributes.into();
110+
tpml_cca.count += 1;
111+
}
112+
tpml_cca
113+
}
114+
}

tss-esapi/src/structures/lists/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
pub mod algorithm_property;
44
pub mod command_code;
5+
pub mod command_code_attributes;
56
pub mod digest;
67
pub mod digest_values;
78
pub mod ecc_curves;

tss-esapi/src/structures/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ pub use tagged_pcr_property_list::TaggedPcrPropertyList;
125125
pub mod tagged_pcr_property_list {
126126
pub use super::lists::tagged_pcr_property::*;
127127
}
128+
129+
pub use self::command_code_attributes_list::CommandCodeAttributesList;
130+
pub mod command_code_attributes_list {
131+
pub use super::lists::command_code_attributes::*;
132+
}
128133
/////////////////////////////////////////////////////////
129134
/// The parameters section
130135
/////////////////////////////////////////////////////////

tss-esapi/tests/integration_tests/common/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ use tss_esapi::{
3232
};
3333

3434
mod marshall;
35+
mod tpma_types_equality_checks;
3536
mod tpml_types_equality_checks;
3637
mod tpms_types_equality_checks;
3738
pub use marshall::*;
39+
pub use tpma_types_equality_checks::*;
3840
pub use tpml_types_equality_checks::*;
3941
pub use tpms_types_equality_checks::*;
4042

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2022 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use tss_esapi::tss2_esys::TPMA_CC;
5+
6+
pub fn ensure_tpma_cc_equality(expected: &TPMA_CC, actual: &TPMA_CC) {
7+
assert_eq!(
8+
expected, actual,
9+
"mismatch between actual and expected TPMA_CC value"
10+
);
11+
}

tss-esapi/tests/integration_tests/common/tpml_types_equality_checks.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// Copyright 2021 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33
use tss_esapi::tss2_esys::{
4-
TPML_ALG_PROPERTY, TPML_PCR_SELECTION, TPML_TAGGED_PCR_PROPERTY, TPML_TAGGED_TPM_PROPERTY,
4+
TPML_ALG_PROPERTY, TPML_CCA, TPML_PCR_SELECTION, TPML_TAGGED_PCR_PROPERTY,
5+
TPML_TAGGED_TPM_PROPERTY,
56
};
67

78
macro_rules! ensure_list_equality {
@@ -50,3 +51,10 @@ ensure_list_equality!(
5051
pcrProperty,
5152
ensure_tpms_tagged_pcr_select_equality
5253
);
54+
55+
ensure_list_equality!(
56+
ensure_tpml_cca_equality,
57+
TPML_CCA,
58+
commandAttributes,
59+
ensure_tpma_cc_equality
60+
);
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// Copyright 2022 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::convert::{TryFrom, TryInto};
5+
use tss_esapi::{
6+
attributes::CommandCodeAttributes, constants::CommandCode,
7+
structures::CommandCodeAttributesList, tss2_esys::TPML_CCA, Error, WrapperErrorKind,
8+
};
9+
10+
#[test]
11+
fn test_valid_conversions() {
12+
let expected_command_code_attributes = vec![
13+
CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect(
14+
"Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecia",
15+
),
16+
CommandCodeAttributes::try_from(u32::from(CommandCode::EvictControl))
17+
.expect("Failed to create CommandCodeAttributes using CommandCode::EvictControl"),
18+
CommandCodeAttributes::try_from(u32::from(CommandCode::PcrRead))
19+
.expect("Failed to create CommandCodeAttributes using CommandCode::PcrRead"),
20+
];
21+
22+
let expected_tpml_cca: TPML_CCA =
23+
expected_command_code_attributes
24+
.iter()
25+
.fold(Default::default(), |mut acc, &v| {
26+
acc.commandAttributes[acc.count as usize] = v.into();
27+
acc.count += 1;
28+
acc
29+
});
30+
31+
let command_code_attributes_list_from_vec: CommandCodeAttributesList =
32+
expected_command_code_attributes
33+
.clone()
34+
.try_into()
35+
.expect("Failed to convert Vec<CommandCodeAttributes> to CommandCodeAttributesList");
36+
37+
assert_eq!(
38+
expected_command_code_attributes.len(),
39+
command_code_attributes_list_from_vec.len(),
40+
"Mismatch in 'len()' between the Vec<CommandCodeAttributes> and the CommandCodeAttributesList(from vec)"
41+
);
42+
43+
expected_command_code_attributes
44+
.iter()
45+
.zip(command_code_attributes_list_from_vec.as_ref())
46+
.for_each(|(expected, actual)| {
47+
assert_eq!(expected, actual, "Mismatch between an expected CommandCodeAttributes in the Vec<CommandCodeAttributes> the actual command code attributes in CommandCodeAttributesList(from vec)");
48+
});
49+
50+
let command_code_attributes_list_from_tss: CommandCodeAttributesList = expected_tpml_cca
51+
.try_into()
52+
.expect("Failed to convert expected_tpml_cca into CommandCodeAttributesList");
53+
54+
assert_eq!(
55+
expected_command_code_attributes.len(),
56+
command_code_attributes_list_from_tss.len(),
57+
"Mismatch in 'len()' between the Vec<CommandCodeAttributes> and the CommandCodeAttributesList(from tss)"
58+
);
59+
60+
expected_command_code_attributes
61+
.iter()
62+
.zip(command_code_attributes_list_from_tss.as_ref())
63+
.for_each(|(expected, actual)| {
64+
assert_eq!(expected, actual, "Mismatch between an expected CommandCodeAttributes in the Vec<CommandCodeAttributes> the actual tagged property in CommandCodeAttributesList(from tss)");
65+
});
66+
67+
let actual_tpml_cca: TPML_CCA = command_code_attributes_list_from_vec.into();
68+
69+
crate::common::ensure_tpml_cca_equality(&expected_tpml_cca, &actual_tpml_cca);
70+
}
71+
72+
#[test]
73+
fn test_invalid_conversions() {
74+
assert_eq!(
75+
Err(Error::WrapperError(WrapperErrorKind::InvalidParam)),
76+
CommandCodeAttributesList::try_from(vec![CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect(
77+
"Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecia",
78+
); CommandCodeAttributesList::MAX_SIZE + 1]),
79+
"Converting a vector with to many elements into a CommandCodeAttributesList did not produce the expected error",
80+
);
81+
82+
assert_eq!(
83+
Err(Error::WrapperError(WrapperErrorKind::InvalidParam)),
84+
CommandCodeAttributesList::try_from(TPML_CCA {
85+
count: CommandCodeAttributesList::MAX_SIZE as u32 + 1u32,
86+
commandAttributes: [Default::default(); 256],
87+
}),
88+
"Converting a TPML_CCA with an invalid 'count' value into a CommandCodeAttributesList did not produce the expected error",
89+
);
90+
}
91+
92+
#[test]
93+
fn test_find() {
94+
let command_code_attributes_list = CommandCodeAttributesList::try_from(vec![
95+
CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect(
96+
"Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecial",
97+
),
98+
CommandCodeAttributes::try_from(u32::from(CommandCode::EvictControl))
99+
.expect("Failed to create CommandCodeAttributes using CommandCode::EvictControl"),
100+
CommandCodeAttributes::try_from(u32::from(CommandCode::PcrRead))
101+
.expect("Failed to create CommandCodeAttributes using CommandCode::PcrRead"),
102+
])
103+
.expect("Failed to convert Vec<CommandCodeAttributes> to CommandCodeAttributesList");
104+
105+
assert_eq!(
106+
&CommandCodeAttributes::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial)).expect(
107+
"Failed to create CommandCodeAttributes using CommandCode::NvUndefineSpaceSpecial",
108+
),
109+
command_code_attributes_list
110+
.find(
111+
u16::try_from(u32::from(CommandCode::NvUndefineSpaceSpecial))
112+
.expect("Failed to convert CommandCode::NvUndefineSpaceSpecial into command code index")
113+
)
114+
.expect("Calling 'find' using CommandCode::NvUndefineSpaceSpecial as command code index returned an unexpected 'None'"),
115+
"Calling 'find' using CommandCode::NvUndefineSpaceSpecial as command code index did not return the expected CommandCodeAttributes value"
116+
);
117+
118+
assert_eq!(
119+
&CommandCodeAttributes::try_from(u32::from(CommandCode::EvictControl)).expect(
120+
"Failed to create CommandCodeAttributes using CommandCode::EvictControl",
121+
),
122+
command_code_attributes_list
123+
.find(
124+
u16::try_from(u32::from(CommandCode::EvictControl))
125+
.expect("Failed to convert CommandCode::EvictControl into command code index")
126+
)
127+
.expect("Calling 'find' using CommandCode::NvUndefineSpaceSpecial as command code index returned an unexpected 'None'"),
128+
"Calling 'find' using CommandCode::EvictControl as command code index did not return the expected CommandCodeAttributes value"
129+
);
130+
131+
assert!(
132+
command_code_attributes_list
133+
.find(
134+
u16::try_from(u32::from(CommandCode::PcrAllocate))
135+
.expect("Failed to convert CommandCode::PcrRead into command code index")
136+
)
137+
.is_none(),
138+
"A value that should not exist was found in the CommandCodeAttributesList"
139+
);
140+
}

tss-esapi/tests/integration_tests/structures_tests/lists_tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2021 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33
mod algorithm_property_list_tests;
4+
mod command_code_attributes_list_tests;
45
mod command_code_list_tests;
56
mod digest_list_tests;
67
mod ecc_curve_list_tests;

0 commit comments

Comments
 (0)