Skip to content

Commit 392b170

Browse files
authored
Merge pull request #308 from Superhepper/tpml_tagged_pcr_property
Rust native TPML_TAGGED_PCR_PROPERTY type
2 parents b140090 + 66e6d86 commit 392b170

28 files changed

+909
-193
lines changed

tss-esapi/src/constants/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,15 @@ pub mod ecc;
5555
/// Constants -> TPM_CC section of the specification.
5656
pub mod command_code;
5757

58+
/// Representation of the constants defined in
59+
/// Constants -> TPM_PT_PCR section of the specification.
60+
pub mod pcr_property_tag;
61+
5862
pub use capabilities::CapabilityType;
5963
pub use command_code::CommandCode;
6064
pub use ecc::EccCurveIdentifier;
6165
pub use nv_index_type::NvIndexType;
66+
pub use pcr_property_tag::PcrPropertyTag;
6267
pub use property_tag::PropertyTag;
6368
pub use response_code::{ResponseCode, Tss2ResponseCode, Tss2ResponseCodeKind};
6469
pub use session_type::SessionType;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2022 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use crate::{
5+
constants::tss::{
6+
TPM2_PT_PCR_AUTH, TPM2_PT_PCR_DRTM_RESET, TPM2_PT_PCR_EXTEND_L0, TPM2_PT_PCR_EXTEND_L1,
7+
TPM2_PT_PCR_EXTEND_L2, TPM2_PT_PCR_EXTEND_L3, TPM2_PT_PCR_EXTEND_L4,
8+
TPM2_PT_PCR_NO_INCREMENT, TPM2_PT_PCR_POLICY, TPM2_PT_PCR_RESET_L0, TPM2_PT_PCR_RESET_L1,
9+
TPM2_PT_PCR_RESET_L2, TPM2_PT_PCR_RESET_L3, TPM2_PT_PCR_RESET_L4, TPM2_PT_PCR_SAVE,
10+
},
11+
tss2_esys::TPM2_PT_PCR,
12+
Error, Result, WrapperErrorKind,
13+
};
14+
use log::error;
15+
use num_derive::{FromPrimitive, ToPrimitive};
16+
use num_traits::{FromPrimitive, ToPrimitive};
17+
use std::convert::TryFrom;
18+
19+
#[derive(FromPrimitive, ToPrimitive, Debug, Clone, Copy, PartialEq, Eq, Hash)]
20+
#[repr(u32)]
21+
pub enum PcrPropertyTag {
22+
Save = TPM2_PT_PCR_SAVE,
23+
ExtendL0 = TPM2_PT_PCR_EXTEND_L0,
24+
ResetL0 = TPM2_PT_PCR_RESET_L0,
25+
ExtendL1 = TPM2_PT_PCR_EXTEND_L1,
26+
ResetL1 = TPM2_PT_PCR_RESET_L1,
27+
ExtendL2 = TPM2_PT_PCR_EXTEND_L2,
28+
ResetL2 = TPM2_PT_PCR_RESET_L2,
29+
ExtendL3 = TPM2_PT_PCR_EXTEND_L3,
30+
ResetL3 = TPM2_PT_PCR_RESET_L3,
31+
ExtendL4 = TPM2_PT_PCR_EXTEND_L4,
32+
ResetL4 = TPM2_PT_PCR_RESET_L4,
33+
// Reserved 0x0000000B – 0x00000010
34+
NoIncrement = TPM2_PT_PCR_NO_INCREMENT,
35+
DrtmReset = TPM2_PT_PCR_DRTM_RESET,
36+
Policy = TPM2_PT_PCR_POLICY,
37+
Auth = TPM2_PT_PCR_AUTH,
38+
}
39+
40+
impl From<PcrPropertyTag> for TPM2_PT_PCR {
41+
fn from(pcr_property_tag: PcrPropertyTag) -> Self {
42+
// The values are well defined so this cannot fail.
43+
pcr_property_tag.to_u32().unwrap()
44+
}
45+
}
46+
47+
impl TryFrom<TPM2_PT_PCR> for PcrPropertyTag {
48+
type Error = Error;
49+
50+
fn try_from(tpm_pt_pcr: TPM2_PT_PCR) -> Result<Self> {
51+
PcrPropertyTag::from_u32(tpm_pt_pcr).ok_or_else(|| {
52+
error!("value = {} did not match any PcrPropertyTag.", tpm_pt_pcr);
53+
Error::local_error(WrapperErrorKind::InvalidParam)
54+
})
55+
}
56+
}

tss-esapi/src/constants/property_tag.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{constants::tss::*, tss2_esys::TPM2_PT, Error, Result, WrapperErrorKi
44
use log::error;
55
use num_derive::{FromPrimitive, ToPrimitive};
66
use num_traits::{FromPrimitive, ToPrimitive};
7-
use std::convert::{From, TryFrom};
7+
use std::convert::TryFrom;
88

99
#[derive(FromPrimitive, ToPrimitive, Debug, Clone, Copy, PartialEq, Eq, Hash)]
1010
#[repr(u32)]
@@ -90,12 +90,9 @@ impl From<PropertyTag> for TPM2_PT {
9090

9191
impl TryFrom<TPM2_PT> for PropertyTag {
9292
type Error = Error;
93-
fn try_from(tpm_property_tag: TPM2_PT) -> Result<PropertyTag> {
94-
PropertyTag::from_u32(tpm_property_tag).ok_or_else(|| {
95-
error!(
96-
"value = {} did not match any PropertyTag.",
97-
tpm_property_tag
98-
);
93+
fn try_from(tpm_pt: TPM2_PT) -> Result<PropertyTag> {
94+
PropertyTag::from_u32(tpm_pt).ok_or_else(|| {
95+
error!("value = {} did not match any PropertyTag.", tpm_pt);
9996
Error::local_error(WrapperErrorKind::InvalidParam)
10097
})
10198
}

tss-esapi/src/structures/capabilitydata.rs

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use crate::{
44
constants::tss::*,
55
handles::TpmHandle,
66
structures::{
7-
AlgorithmPropertyList, CommandCodeList, PcrSelect, PcrSelectionList, TaggedTpmPropertyList,
7+
AlgorithmPropertyList, CommandCodeList, PcrSelectionList, TaggedPcrPropertyList,
8+
TaggedTpmPropertyList,
89
},
910
tss2_esys::*,
1011
Error, Result, WrapperErrorKind,
1112
};
12-
use std::collections::HashMap;
1313
use std::convert::{TryFrom, TryInto};
1414
use std::mem::size_of;
1515

@@ -22,9 +22,9 @@ pub enum CapabilityData {
2222
AuditCommands(CommandCodeList),
2323
AssignedPCR(PcrSelectionList),
2424
TpmProperties(TaggedTpmPropertyList),
25-
PCRProperties(HashMap<TPM2_PT_PCR, PcrSelect>),
25+
PcrProperties(TaggedPcrPropertyList),
2626
ECCCurves(Vec<TPM2_ECC_CURVE>),
27-
// These are in the TPM TMU_CAPABILITIES, but are not defined by esapi-2.4.1
27+
// These are in the TPM TPMU_CAPABILITIES, but are not defined by esapi-2.4.1
2828
// AuthPolicies(),
2929
// ActData(),
3030
}
@@ -90,24 +90,7 @@ fn cd_from_tpm_properties(props: TPML_TAGGED_TPM_PROPERTY) -> Result<CapabilityD
9090
}
9191

9292
fn cd_from_pcr_properties(props: TPML_TAGGED_PCR_PROPERTY) -> Result<CapabilityData> {
93-
if props.count > max_cap_size::<TPMS_TAGGED_PCR_SELECT>() {
94-
return Err(Error::WrapperError(WrapperErrorKind::InvalidParam));
95-
}
96-
97-
let mut data = HashMap::new();
98-
99-
for i in 0..props.count {
100-
let prop = props.pcrProperty[i as usize];
101-
102-
let select = PcrSelect::try_from(TPMS_PCR_SELECT {
103-
sizeofSelect: prop.sizeofSelect,
104-
pcrSelect: prop.pcrSelect,
105-
})?;
106-
107-
let _ = data.insert(prop.tag, select);
108-
}
109-
110-
Ok(CapabilityData::PCRProperties(data))
93+
Ok(CapabilityData::PcrProperties(props.try_into()?))
11194
}
11295

11396
fn cd_from_ecc_curves(props: TPML_ECC_CURVE) -> Result<CapabilityData> {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ pub mod command_code;
55
pub mod digest;
66
pub mod digest_values;
77
pub mod pcr_selection;
8+
pub mod tagged_pcr_property;
89
pub mod tagged_tpm_property;
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright 2022 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use crate::{
5+
constants::PcrPropertyTag,
6+
structures::{PcrSlot, TaggedPcrSelect},
7+
tss2_esys::{TPM2_CAP, TPM2_MAX_CAP_BUFFER, TPML_TAGGED_PCR_PROPERTY, TPMS_TAGGED_PCR_SELECT},
8+
Error, Result, WrapperErrorKind,
9+
};
10+
use log::error;
11+
use std::{convert::TryFrom, iter::IntoIterator, ops::Deref};
12+
/// A structure holding a list of tagged pcr properties.
13+
///
14+
/// # Details
15+
/// This corresponds to the TPML_TAGGED_PCR_PROPERTY structure.
16+
#[derive(Debug, Clone, PartialEq, Eq)]
17+
pub struct TaggedPcrPropertyList {
18+
tagged_pcr_properties: Vec<TaggedPcrSelect>,
19+
}
20+
21+
impl TaggedPcrPropertyList {
22+
pub const MAX_SIZE: usize = Self::calculate_max_size();
23+
24+
/// Finds the first [TaggedPcrSelect] in the list that matches the provided `pcr_property_tag`.
25+
pub fn find(&self, pcr_property_tag: PcrPropertyTag) -> Option<&TaggedPcrSelect> {
26+
self.tagged_pcr_properties
27+
.iter()
28+
.find(|tps| tps.pcr_property_tag() == pcr_property_tag)
29+
}
30+
31+
/// Returns a collection [TaggedPcrSelect] references in which each referenced items
32+
/// has the specified [PcrSlot] selected.
33+
pub fn find_pcr_slot(&self, pcr_slot: PcrSlot) -> Vec<&TaggedPcrSelect> {
34+
self.tagged_pcr_properties
35+
.iter()
36+
.fold(Vec::<&TaggedPcrSelect>::new(), |mut acc, tps| {
37+
if tps.selected_pcrs().iter().any(|&ps| ps == pcr_slot) {
38+
acc.push(tps);
39+
}
40+
acc
41+
})
42+
}
43+
44+
/// Private function that calculates the maximum number
45+
/// elements allowed in internal storage.
46+
const fn calculate_max_size() -> usize {
47+
// According to the specification the size is vendor specific.
48+
// So if someone is using modified values in their TSS libraries
49+
// it is picked up here.
50+
(TPM2_MAX_CAP_BUFFER as usize
51+
- std::mem::size_of::<TPM2_CAP>()
52+
- std::mem::size_of::<u32>())
53+
/ std::mem::size_of::<TPMS_TAGGED_PCR_SELECT>()
54+
}
55+
}
56+
57+
impl Deref for TaggedPcrPropertyList {
58+
type Target = Vec<TaggedPcrSelect>;
59+
60+
fn deref(&self) -> &Self::Target {
61+
&self.tagged_pcr_properties
62+
}
63+
}
64+
65+
impl AsRef<[TaggedPcrSelect]> for TaggedPcrPropertyList {
66+
fn as_ref(&self) -> &[TaggedPcrSelect] {
67+
self.tagged_pcr_properties.as_slice()
68+
}
69+
}
70+
71+
impl TryFrom<Vec<TaggedPcrSelect>> for TaggedPcrPropertyList {
72+
type Error = Error;
73+
74+
fn try_from(tagged_pcr_properties: Vec<TaggedPcrSelect>) -> Result<Self> {
75+
if tagged_pcr_properties.len() > Self::MAX_SIZE {
76+
error!("Failed to convert Vec<TaggedPcrSelect> into TaggedPcrPropertyList, to many items (> {})", Self::MAX_SIZE);
77+
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
78+
}
79+
Ok(TaggedPcrPropertyList {
80+
tagged_pcr_properties,
81+
})
82+
}
83+
}
84+
85+
impl IntoIterator for TaggedPcrPropertyList {
86+
type Item = TaggedPcrSelect;
87+
type IntoIter = std::vec::IntoIter<Self::Item>;
88+
89+
fn into_iter(self) -> Self::IntoIter {
90+
self.tagged_pcr_properties.into_iter()
91+
}
92+
}
93+
94+
impl TryFrom<TPML_TAGGED_PCR_PROPERTY> for TaggedPcrPropertyList {
95+
type Error = Error;
96+
97+
fn try_from(tpml_tagged_pcr_property: TPML_TAGGED_PCR_PROPERTY) -> Result<Self> {
98+
let count = usize::try_from(tpml_tagged_pcr_property.count).map_err(|e| {
99+
error!(
100+
"Failed to parse count in TPML_TAGGED_PCR_PROPERTY as usize: {}",
101+
e
102+
);
103+
Error::local_error(WrapperErrorKind::InvalidParam)
104+
})?;
105+
106+
if count > Self::MAX_SIZE {
107+
error!(
108+
"Invalid size value in TPML_TAGGED_PCR_PROPERTY (> {})",
109+
Self::MAX_SIZE,
110+
);
111+
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
112+
}
113+
114+
tpml_tagged_pcr_property.pcrProperty[..count]
115+
.iter()
116+
.map(|&tp| TaggedPcrSelect::try_from(tp))
117+
.collect::<Result<Vec<TaggedPcrSelect>>>()
118+
.map(|tagged_pcr_properties| TaggedPcrPropertyList {
119+
tagged_pcr_properties,
120+
})
121+
}
122+
}
123+
124+
impl From<TaggedPcrPropertyList> for TPML_TAGGED_PCR_PROPERTY {
125+
fn from(tagged_pcr_property_list: TaggedPcrPropertyList) -> Self {
126+
let mut tpml_tagged_pcr_property = TPML_TAGGED_PCR_PROPERTY::default();
127+
for tagged_pcr_select in tagged_pcr_property_list {
128+
tpml_tagged_pcr_property.pcrProperty[tpml_tagged_pcr_property.count as usize] =
129+
tagged_pcr_select.into();
130+
tpml_tagged_pcr_property.count += 1;
131+
}
132+
tpml_tagged_pcr_property
133+
}
134+
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use crate::{
55
constants::PropertyTag,
66
structures::TaggedProperty,
7-
tss2_esys::{TPML_TAGGED_TPM_PROPERTY, TPMS_TAGGED_PROPERTY},
7+
tss2_esys::{TPM2_CAP, TPM2_MAX_CAP_BUFFER, TPML_TAGGED_TPM_PROPERTY, TPMS_TAGGED_PROPERTY},
88
Error, Result, WrapperErrorKind,
99
};
1010
use log::error;
@@ -22,7 +22,7 @@ pub struct TaggedTpmPropertyList {
2222
impl TaggedTpmPropertyList {
2323
pub const MAX_SIZE: usize = Self::calculate_max_size();
2424

25-
/// Finds a [TaggedProperty] in the list matching the provided `property_tag`.
25+
/// Finds the first [TaggedProperty] in the list matching the provided `property_tag`.
2626
pub fn find(&self, property_tag: PropertyTag) -> Option<&TaggedProperty> {
2727
self.tagged_tpm_properties
2828
.iter()
@@ -35,7 +35,9 @@ impl TaggedTpmPropertyList {
3535
// According to the specification the size is vendor specific.
3636
// So if someone is using modified values in their TSS libraries
3737
// it is picked up here.
38-
(std::mem::size_of::<TPML_TAGGED_TPM_PROPERTY>() - std::mem::size_of::<u32>())
38+
(TPM2_MAX_CAP_BUFFER as usize
39+
- std::mem::size_of::<TPM2_CAP>()
40+
- std::mem::size_of::<u32>())
3941
/ std::mem::size_of::<TPMS_TAGGED_PROPERTY>()
4042
}
4143
}
@@ -110,7 +112,7 @@ impl TryFrom<TPML_TAGGED_TPM_PROPERTY> for TaggedTpmPropertyList {
110112
impl From<TaggedTpmPropertyList> for TPML_TAGGED_TPM_PROPERTY {
111113
fn from(tagged_tpm_property_list: TaggedTpmPropertyList) -> Self {
112114
let mut tpml_tagged_tpm_property: TPML_TAGGED_TPM_PROPERTY = Default::default();
113-
for tagged_property in tagged_tpm_property_list.tagged_tpm_properties {
115+
for tagged_property in tagged_tpm_property_list {
114116
tpml_tagged_tpm_property.tpmProperty[tpml_tagged_tpm_property.count as usize] =
115117
tagged_property.into();
116118
tpml_tagged_tpm_property.count += 1;

tss-esapi/src/structures/mod.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,13 @@ pub use self::hash::agile::HashAgile;
5656
/// The pcr section
5757
/////////////////////////////////////////////////////////
5858
mod pcr;
59+
60+
pub use self::pcr_slot::PcrSlot;
61+
pub mod pcr_slot {
62+
pub use super::pcr::slot::*;
63+
}
64+
5965
pub use self::pcr_select::PcrSelect;
60-
pub use self::pcr_select::PcrSelectSize;
61-
pub use self::pcr_select::PcrSlot;
6266
pub mod pcr_select {
6367
pub use super::pcr::select::*;
6468
}
@@ -67,6 +71,11 @@ pub use self::pcr_selection::PcrSelection;
6771
pub mod pcr_selection {
6872
pub use super::pcr::selection::*;
6973
}
74+
75+
pub use self::pcr_select_size::PcrSelectSize;
76+
pub mod pcr_select_size {
77+
pub use super::pcr::select_size::*;
78+
}
7079
/////////////////////////////////////////////////////////
7180
/// The lists section
7281
/////////////////////////////////////////////////////////
@@ -101,6 +110,11 @@ pub use algorithm_property_list::AlgorithmPropertyList;
101110
pub mod algorithm_property_list {
102111
pub use super::lists::algorithm_property::*;
103112
}
113+
114+
pub use tagged_pcr_property_list::TaggedPcrPropertyList;
115+
pub mod tagged_pcr_property_list {
116+
pub use super::lists::tagged_pcr_property::*;
117+
}
104118
/////////////////////////////////////////////////////////
105119
/// The parameters section
106120
/////////////////////////////////////////////////////////
@@ -215,3 +229,8 @@ pub use tagged_property::TaggedProperty;
215229
/////////////////////////////////////////////////////////
216230
mod algorithm_property;
217231
pub use algorithm_property::AlgorithmProperty;
232+
/////////////////////////////////////////////////////////
233+
/// TaggedPcrSelect
234+
/////////////////////////////////////////////////////////
235+
mod tagged_pcr_select;
236+
pub use tagged_pcr_select::TaggedPcrSelect;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// Copyright 2020 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33
pub mod select;
4+
pub mod select_size;
45
pub mod selection;
6+
pub mod slot;

0 commit comments

Comments
 (0)