Skip to content

Commit 07e0bb9

Browse files
authored
Merge pull request #317 from Superhepper/pcr_select_bugs
Fixes some pcr issues.
2 parents a32bfb1 + 16564cf commit 07e0bb9

31 files changed

+777
-404
lines changed

tss-esapi/src/abstraction/pcr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ pub use data::PcrData;
5353
/// PcrSlot::Slot20,
5454
/// PcrSlot::Slot21,
5555
/// ])
56-
/// .build();
56+
/// .build()
57+
/// .expect("Failed to build PcrSelectionList");
5758
/// let _pcr_data = tss_esapi::abstraction::pcr::read_all(&mut context, pcr_selection_list)
5859
/// .expect("pcr::read_all failed");
5960
/// ```

tss-esapi/src/abstraction/pcr/bank.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl PcrBank {
2222
/// # Details
2323
/// The order of pcr slots are assumed to match the order of the Digests.
2424
///
25-
/// # Error
25+
/// # Errors
2626
/// - If number of pcr slots does not match the number of pcr digests
2727
/// InconsistentParams error is returned.
2828
///
@@ -88,7 +88,7 @@ impl PcrBank {
8888

8989
/// Inserts [Digest] value associated with a [PcrSlot] into the bank.
9090
///
91-
/// # Error
91+
/// # Errors
9292
/// Returns an error if a [Digest] is already associated with the
9393
/// provided [PcrSlot].
9494
pub fn insert_digest(&mut self, pcr_slot: PcrSlot, digest: Digest) -> Result<()> {
@@ -99,7 +99,7 @@ impl PcrBank {
9999

100100
/// Attempts to extend the [PcrBank] with `other`.
101101
///
102-
/// # Error
102+
/// # Errors
103103
/// Returns an error if the a value in `other` already
104104
/// exists.
105105
pub fn try_extend(&mut self, other: PcrBank) -> Result<()> {

tss-esapi/src/attributes/locality.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl LocalityAttributes {
3838

3939
/// Returns the LocalityAttributes as a number.
4040
///
41-
/// # Error
41+
/// # Errors
4242
/// If the attributes are not extended en InvalidParams error
4343
/// is returned.
4444
pub fn as_extended(&self) -> Result<u8> {

tss-esapi/src/context/handle_manager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl HandleManager {
5050

5151
/// Sets the handle as flushed which removes it from the manager.
5252
///
53-
/// # Error
53+
/// # Errors
5454
/// If the handle was not set to be flushed then this will cause an
5555
/// error but the handle will still be removed from the handler.
5656
pub fn set_as_flushed(&mut self, handle: ObjectHandle) -> Result<()> {
@@ -75,7 +75,7 @@ impl HandleManager {
7575

7676
/// Sets the handles as closed which removes it from the handler.
7777
///
78-
/// # Error
78+
/// # Errors
7979
/// If the handle was set to be flushed then this will cause an
8080
/// error but the handle will still be removed from the handler.
8181
pub fn set_as_closed(&mut self, handle: ObjectHandle) -> Result<()> {

tss-esapi/src/context/tpm_commands/integrity_collection_pcr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ impl Context {
146146
/// // that is going to be read.
147147
/// let pcr_selection_list = PcrSelectionListBuilder::new()
148148
/// .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1])
149-
/// .build();
149+
/// .build()
150+
/// .expect("Failed to build PcrSelectionList");
150151
///
151152
/// let (update_counter, read_pcr_list, digest_list) = context.pcr_read(pcr_selection_list)
152153
/// .expect("Call to pcr_read failed");

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

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::convert::TryFrom;
1010

1111
/// A struct representing a pcr selection list. This
1212
/// corresponds to the TSS TPML_PCR_SELECTION.
13-
#[derive(Debug, Clone, PartialEq, Eq)]
13+
#[derive(Debug, Clone, PartialEq, Eq, Default)]
1414
pub struct PcrSelectionList {
1515
items: Vec<PcrSelection>,
1616
}
@@ -56,7 +56,7 @@ impl PcrSelectionList {
5656
///
5757
/// This returns an empty list if None is passed
5858
pub fn list_from_option(pcr_list: Option<PcrSelectionList>) -> PcrSelectionList {
59-
pcr_list.unwrap_or_else(|| PcrSelectionListBuilder::new().build())
59+
pcr_list.unwrap_or_default()
6060
}
6161

6262
/// Private methods for removing pcr selections that are empty.
@@ -89,7 +89,7 @@ impl PcrSelectionList {
8989
}
9090

9191
impl From<PcrSelectionList> for TPML_PCR_SELECTION {
92-
fn from(pcr_selections: PcrSelectionList) -> TPML_PCR_SELECTION {
92+
fn from(pcr_selections: PcrSelectionList) -> Self {
9393
let mut tss_pcr_selection_list: TPML_PCR_SELECTION = Default::default();
9494
for pcr_selection in pcr_selections.items {
9595
tss_pcr_selection_list.pcrSelections[tss_pcr_selection_list.count as usize] =
@@ -178,17 +178,20 @@ impl PcrSelectionListBuilder {
178178
/// provided.
179179
///
180180
/// If no size of select have been provided then it will
181-
/// be defaulted to 3. This may not be the correct size for
181+
/// be defaulted to to the most suitable with regard to TPM2_PCR_SELECT_MAX.
182+
/// This may not be the correct size for
182183
/// the current platform. The correct values can be obtained
183184
/// by querying the tpm for its capabilities.
184-
pub fn build(self) -> PcrSelectionList {
185+
pub fn build(self) -> Result<PcrSelectionList> {
185186
let size_of_select = self.size_of_select.unwrap_or_default();
186-
PcrSelectionList {
187-
items: self
188-
.items
189-
.iter()
190-
.map(|(k, v)| PcrSelection::new(*k, size_of_select, v.as_slice()))
191-
.collect(),
192-
}
187+
self.items
188+
.iter()
189+
.try_fold(Vec::<PcrSelection>::new(), |mut acc, (&k, v)| {
190+
PcrSelection::create(k, size_of_select, v.as_slice()).map(|pcr_select| {
191+
acc.push(pcr_select);
192+
acc
193+
})
194+
})
195+
.map(|items| PcrSelectionList { items })
193196
}
194197
}

tss-esapi/src/structures/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ pub use self::command_code_attributes_list::CommandCodeAttributesList;
130130
pub mod command_code_attributes_list {
131131
pub use super::lists::command_code_attributes::*;
132132
}
133+
134+
pub(crate) use pcr::slot_collection::PcrSlotCollection;
133135
/////////////////////////////////////////////////////////
134136
/// The parameters section
135137
/////////////////////////////////////////////////////////

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ pub mod select;
44
pub mod select_size;
55
pub mod selection;
66
pub mod slot;
7+
pub mod slot_collection;
Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
// Copyright 2020 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33
use crate::{
4-
structures::{PcrSelectSize, PcrSlot},
5-
tss2_esys::{TPM2_PCR_SELECT_MAX, TPMS_PCR_SELECT},
6-
Error, Result, WrapperErrorKind,
4+
structures::{PcrSelectSize, PcrSlot, PcrSlotCollection},
5+
tss2_esys::TPMS_PCR_SELECT,
6+
Error, Result,
77
};
88

9-
use enumflags2::BitFlags;
10-
use log::error;
11-
129
use std::convert::TryFrom;
1310
/// This module contains necessary representations
1411
/// of the items belonging to the TPMS_PCR_SELECT
@@ -21,17 +18,15 @@ use std::convert::TryFrom;
2118
/// not adhering to a platform-specific specification.
2219
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2320
pub struct PcrSelect {
24-
size_of_select: PcrSelectSize,
25-
selected_pcrs: BitFlags<PcrSlot>,
21+
pcr_slot_collection: PcrSlotCollection,
2622
}
2723

2824
impl PcrSelect {
2925
/// Creates a new PcrSelect
30-
pub fn new(size_of_select: PcrSelectSize, pcr_slots: &[PcrSlot]) -> Self {
31-
PcrSelect {
32-
size_of_select,
33-
selected_pcrs: pcr_slots.iter().copied().collect(),
34-
}
26+
pub fn create(pcr_select_size: PcrSelectSize, pcr_slots: &[PcrSlot]) -> Result<Self> {
27+
PcrSlotCollection::create(pcr_select_size, pcr_slots).map(|pcr_slot_collection| PcrSelect {
28+
pcr_slot_collection,
29+
})
3530
}
3631

3732
/// Returns the size of the select.
@@ -41,46 +36,32 @@ impl PcrSelect {
4136
/// octets that are needed to hold the bit field
4237
/// that indicate what slots that are selected.
4338
pub fn size_of_select(&self) -> PcrSelectSize {
44-
self.size_of_select
39+
self.pcr_slot_collection.size_of_select()
4540
}
4641

4742
/// Returns the selected PCRs in the select.
4843
pub fn selected_pcrs(&self) -> Vec<PcrSlot> {
49-
self.selected_pcrs.iter().collect()
44+
self.pcr_slot_collection.collection()
5045
}
5146
}
5247

5348
impl TryFrom<TPMS_PCR_SELECT> for PcrSelect {
5449
type Error = Error;
5550
fn try_from(tss_pcr_select: TPMS_PCR_SELECT) -> Result<Self> {
56-
// Parse the sizeofSelect into a SelectSize.
57-
let size_of_select = PcrSelectSize::try_from(tss_pcr_select.sizeofSelect)?;
58-
59-
// Select only the octets indicated by sizeofSelect
60-
let mut selected_octets = [0u8; TPM2_PCR_SELECT_MAX as usize];
61-
let number_of_selected_octets: usize = size_of_select.into();
62-
selected_octets[..number_of_selected_octets]
63-
.copy_from_slice(&tss_pcr_select.pcrSelect[..number_of_selected_octets]);
64-
65-
// Parse selected pcrs into BitFlags
66-
let selected_pcrs = BitFlags::<PcrSlot>::try_from(u32::from_le_bytes(selected_octets))
67-
.map_err(|e| {
68-
error!("Error parsing pcrSelect to a BitFlags<PcrSlot>: {}.", e);
69-
Error::local_error(WrapperErrorKind::UnsupportedParam)
70-
})?;
71-
72-
Ok(PcrSelect {
73-
size_of_select,
74-
selected_pcrs,
75-
})
51+
PcrSlotCollection::try_from((tss_pcr_select.sizeofSelect, tss_pcr_select.pcrSelect)).map(
52+
|pcr_slot_collection| PcrSelect {
53+
pcr_slot_collection,
54+
},
55+
)
7656
}
7757
}
7858

7959
impl From<PcrSelect> for TPMS_PCR_SELECT {
8060
fn from(pcr_select: PcrSelect) -> Self {
61+
let (size_of_select, pcr_select) = pcr_select.pcr_slot_collection.into();
8162
TPMS_PCR_SELECT {
82-
sizeofSelect: pcr_select.size_of_select.into(),
83-
pcrSelect: pcr_select.selected_pcrs.bits().to_le_bytes(),
63+
sizeofSelect: size_of_select,
64+
pcrSelect: pcr_select,
8465
}
8566
}
8667
}
Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2022 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
3-
use crate::{Error, Result, WrapperErrorKind};
3+
use crate::{tss2_esys::TPM2_PCR_SELECT_MAX, Error, Result, WrapperErrorKind};
44

55
use num_derive::{FromPrimitive, ToPrimitive};
66
use num_traits::{FromPrimitive, ToPrimitive};
@@ -12,47 +12,105 @@ use std::convert::TryFrom;
1212
#[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone, PartialEq, Eq)]
1313
#[repr(u8)]
1414
pub enum PcrSelectSize {
15-
OneByte = 1,
16-
TwoBytes = 2,
17-
ThreeBytes = 3,
18-
FourBytes = 4,
15+
OneOctet = 1,
16+
TwoOctets = 2,
17+
ThreeOctets = 3,
18+
FourOctets = 4,
1919
}
2020

21-
/// The default for PcrSelectSize is three bytes.
21+
impl PcrSelectSize {
22+
/// Returns the PcrSelectSize value as u8
23+
pub fn as_u8(&self) -> u8 {
24+
// The value is well defined so unwrap will
25+
// never cause panic.
26+
self.to_u8().unwrap()
27+
}
28+
29+
/// Returns the PcrSelectSize value as u32
30+
pub fn as_u32(&self) -> u32 {
31+
// The value is well defined so unwrap will
32+
// never cause panic.
33+
self.to_u32().unwrap()
34+
}
35+
36+
/// Returns the PcrSelectSize value as usize
37+
pub fn as_usize(&self) -> usize {
38+
// The value is well defined so unwrap will
39+
// never cause panic.
40+
self.to_usize().unwrap()
41+
}
42+
43+
/// Parses the u8 value as PcrSelectSize
44+
pub fn try_parse_u8(value: u8) -> Result<Self> {
45+
PcrSelectSize::from_u8(value).ok_or_else(|| {
46+
error!(
47+
"Error converting sizeofSelect to a SelectSize: Invalid value {}",
48+
value
49+
);
50+
Error::local_error(WrapperErrorKind::InvalidParam)
51+
})
52+
}
53+
54+
/// Parses the u32 value as PcrSelectSize
55+
pub fn try_parse_u32(value: u32) -> Result<Self> {
56+
PcrSelectSize::from_u32(value).ok_or_else(|| {
57+
error!(
58+
"Error converting sizeofSelect to a SelectSize: Invalid value {}",
59+
value
60+
);
61+
Error::local_error(WrapperErrorKind::InvalidParam)
62+
})
63+
}
64+
65+
/// Parses the usize value as PcrSelectSize
66+
pub fn try_parse_usize(value: usize) -> Result<Self> {
67+
PcrSelectSize::from_usize(value).ok_or_else(|| {
68+
error!(
69+
"Error converting sizeofSelect to a SelectSize: Invalid value {}",
70+
value
71+
);
72+
Error::local_error(WrapperErrorKind::InvalidParam)
73+
})
74+
}
75+
}
76+
77+
/// The default for PcrSelectSize is three octets.
2278
/// A value for the sizeofSelect that works
2379
/// on most platforms.
2480
impl Default for PcrSelectSize {
2581
fn default() -> PcrSelectSize {
26-
PcrSelectSize::ThreeBytes
82+
match TPM2_PCR_SELECT_MAX {
83+
1 => PcrSelectSize::OneOctet,
84+
2 => PcrSelectSize::TwoOctets,
85+
_ => PcrSelectSize::ThreeOctets,
86+
}
2787
}
2888
}
2989

3090
impl TryFrom<u8> for PcrSelectSize {
3191
type Error = Error;
3292

3393
fn try_from(value: u8) -> Result<Self> {
34-
PcrSelectSize::from_u8(value).ok_or_else(|| {
94+
if u32::from(value) > TPM2_PCR_SELECT_MAX {
3595
error!(
36-
"Error converting sizeofSelect to a SelectSize: Invalid value {}",
37-
value
96+
"Found size of select value(= {}) that is larger then TPM2_PCR_SELECT_MAX(={}",
97+
value, TPM2_PCR_SELECT_MAX
3898
);
39-
Error::local_error(WrapperErrorKind::InvalidParam)
40-
})
41-
}
42-
}
99+
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
100+
}
43101

44-
impl From<PcrSelectSize> for u8 {
45-
fn from(pcr_select_size: PcrSelectSize) -> Self {
46-
// The value is well defined so unwrap will
47-
// never cause panic.
48-
pcr_select_size.to_u8().unwrap()
102+
PcrSelectSize::try_parse_u8(value)
49103
}
50104
}
51105

52-
impl From<PcrSelectSize> for usize {
53-
fn from(pcr_select_size: PcrSelectSize) -> Self {
54-
// The value is well defined so unwrap will
55-
// never cause panic.
56-
pcr_select_size.to_usize().unwrap()
106+
impl TryFrom<PcrSelectSize> for u8 {
107+
type Error = Error;
108+
109+
fn try_from(pcr_select_size: PcrSelectSize) -> Result<Self> {
110+
if pcr_select_size.as_u32() > TPM2_PCR_SELECT_MAX {
111+
error!("The number of octets specified by PcrSelectSize value us greater then TPM2_PCR_SELECT_MAX");
112+
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
113+
}
114+
Ok(pcr_select_size.as_u8())
57115
}
58116
}

0 commit comments

Comments
 (0)