Skip to content

Commit 52f3563

Browse files
committed
Adds proper native types for TPMS_CONTEXT.
- Adds TPM context data structures. - Moves TpmsContext into structures and renames it to SavedTpmContext. Signed-off-by: Jesper Brynolf <jesper.brynolf@gmail.com>
1 parent 067702d commit 52f3563

File tree

12 files changed

+222
-91
lines changed

12 files changed

+222
-91
lines changed

tss-esapi/src/abstraction/transient/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ use crate::{
2020
structures::{
2121
Auth, CreateKeyResult, Data, Digest, EccPoint, EccScheme, Name, Public, PublicBuilder,
2222
PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent,
23-
RsaScheme, Signature, SignatureScheme, SymmetricDefinitionObject, VerifiedTicket,
23+
RsaScheme, SavedTpmContext, Signature, SignatureScheme, SymmetricDefinitionObject,
24+
VerifiedTicket,
2425
},
2526
tcti_ldr::TctiNameConf,
26-
utils::{create_restricted_decryption_rsa_public, PublicKey, TpmsContext},
27+
utils::{create_restricted_decryption_rsa_public, PublicKey},
2728
Context, Error, Result, ReturnCode, WrapperErrorKind as ErrorKind,
2829
};
2930

@@ -341,7 +342,7 @@ impl TransientKeyContext {
341342
/// just a public key.
342343
pub fn migrate_key_from_ctx(
343344
&mut self,
344-
context: TpmsContext,
345+
context: SavedTpmContext,
345346
auth: Option<Auth>,
346347
) -> Result<KeyMaterial> {
347348
self.set_session_attrs()?;

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

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use crate::{
44
context::handle_manager::HandleDropAction,
55
handles::{handle_conversion::TryIntoNotNone, AuthHandle, ObjectHandle, PersistentTpmHandle},
66
interface_types::{data_handles::Persistent, reserved_handles::Provision},
7+
structures::SavedTpmContext,
78
tss2_esys::{Esys_ContextLoad, Esys_ContextSave, Esys_EvictControl, Esys_FlushContext},
8-
utils::TpmsContext,
99
Context, Result, ReturnCode,
1010
};
1111
use log::error;
12-
use std::convert::{TryFrom, TryInto};
12+
use std::convert::TryFrom;
1313
use std::ptr::null_mut;
1414

1515
impl Context {
@@ -18,32 +18,27 @@ impl Context {
1818
/// # Errors
1919
/// * if conversion from `TPMS_CONTEXT` to `TpmsContext` fails, a `WrongParamSize` error will
2020
/// be returned
21-
pub fn context_save(&mut self, handle: ObjectHandle) -> Result<TpmsContext> {
21+
pub fn context_save(&mut self, handle: ObjectHandle) -> Result<SavedTpmContext> {
2222
let mut context_ptr = null_mut();
2323
ReturnCode::ensure_success(
2424
unsafe { Esys_ContextSave(self.mut_context(), handle.into(), &mut context_ptr) },
2525
|ret| {
2626
error!("Error in saving context: {:#010X}", ret);
2727
},
2828
)?;
29-
TpmsContext::try_from(Context::ffi_data_to_owned(context_ptr))
29+
SavedTpmContext::try_from(Context::ffi_data_to_owned(context_ptr))
3030
}
3131

3232
/// Load a previously saved context into the TPM and return the object handle.
3333
///
3434
/// # Errors
3535
/// * if conversion from `TpmsContext` to the native `TPMS_CONTEXT` fails, a `WrongParamSize`
3636
/// error will be returned
37-
pub fn context_load(&mut self, context: TpmsContext) -> Result<ObjectHandle> {
37+
pub fn context_load(&mut self, context: SavedTpmContext) -> Result<ObjectHandle> {
3838
let mut esys_loaded_handle = ObjectHandle::None.into();
39+
let tpm_context = context.into();
3940
ReturnCode::ensure_success(
40-
unsafe {
41-
Esys_ContextLoad(
42-
self.mut_context(),
43-
&context.try_into()?,
44-
&mut esys_loaded_handle,
45-
)
46-
},
41+
unsafe { Esys_ContextLoad(self.mut_context(), &tpm_context, &mut esys_loaded_handle) },
4742
|ret| {
4843
error!("Error in loading context: {:#010X}", ret);
4944
},

tss-esapi/src/interface_types/data_handles.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Copyright 2020 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
13
/// This module contains native representations of the TPMI_DH types.
24
use crate::{
35
handles::{
@@ -8,6 +10,7 @@ use crate::{
810
Error, Result, WrapperErrorKind,
911
};
1012
use std::convert::TryFrom;
13+
1114
/// Enum representing the 'Object' data handles interface type.
1215
///
1316
/// # Details
@@ -70,8 +73,7 @@ pub enum Pcr {
7073
/// Enum representing the 'Context' data handles interface type.
7174
///
7275
/// # Details
73-
/// This corresponds to the TPMI_DH_CONTEXT interface type.
74-
/// This corresponds to the TPMI_DH_CONTEXT interface type. This only
76+
/// This corresponds to the `TPMI_DH_CONTEXT` interface type. This only
7577
/// exist for compatibility purposes the specification is not entirely
7678
/// clear on whether this should still be used or be completely replaced by
7779
/// [Saved].
@@ -116,13 +118,18 @@ impl TryFrom<TPMI_DH_CONTEXT> for ContextDataHandle {
116118
/// Enum representing the 'Saved' data handles interface type.
117119
///
118120
/// # Details
119-
/// This corresponds to the TPMI_DH_SAVED interface type.
121+
/// This corresponds to the `TPMI_DH_SAVED` interface type.
120122
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
121123
pub enum Saved {
124+
/// A HMAC session context.
122125
Hmac(HmacSessionTpmHandle),
126+
/// A policy session context.
123127
Policy(PolicySessionTpmHandle),
128+
/// An ordinary transient object.
124129
Transient,
130+
/// A sequence object.
125131
Sequence,
132+
/// A transient object with stClear attribute SET.
126133
TransientClear,
127134
}
128135

@@ -162,3 +169,15 @@ impl TryFrom<TPMI_DH_SAVED> for Saved {
162169
})
163170
}
164171
}
172+
173+
impl From<Saved> for TPMI_DH_SAVED {
174+
fn from(native: Saved) -> TPMI_DH_SAVED {
175+
match native {
176+
Saved::Hmac(handle) => handle.into(),
177+
Saved::Policy(handle) => handle.into(),
178+
Saved::Transient => TransientTpmHandle::SavedTransient.into(),
179+
Saved::Sequence => TransientTpmHandle::SavedSequence.into(),
180+
Saved::TransientClear => TransientTpmHandle::SavedTransientClear.into(),
181+
}
182+
}
183+
}

tss-esapi/src/structures/buffers.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,12 @@ pub mod symmetric_key {
390390
pub mod timeout {
391391
buffer_type!(Timeout, 8, TPM2B_TIMEOUT);
392392
}
393+
394+
pub mod tpm_context_data {
395+
use crate::tss2_esys::TPMS_CONTEXT_DATA;
396+
buffer_type!(
397+
TpmContextData,
398+
std::mem::size_of::<TPMS_CONTEXT_DATA>(),
399+
TPM2B_CONTEXT_DATA
400+
);
401+
}

tss-esapi/src/structures/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub use self::buffers::{
4141
private_key_rsa::PrivateKeyRsa, private_vendor_specific::PrivateVendorSpecific,
4242
public::PublicBuffer, public_key_rsa::PublicKeyRsa, sensitive::SensitiveBuffer,
4343
sensitive_create::SensitiveCreateBuffer, sensitive_data::SensitiveData,
44-
symmetric_key::SymmetricKey, timeout::Timeout,
44+
symmetric_key::SymmetricKey, timeout::Timeout, tpm_context_data::TpmContextData,
4545
};
4646
/////////////////////////////////////////////////////////
4747
/// The creation section
@@ -212,3 +212,8 @@ pub use nv::storage::{NvPublic, NvPublicBuilder};
212212
/////////////////////////////////////////////////////////
213213
mod algorithm;
214214
pub use algorithm::symmetric::sensitive_create::SensitiveCreate;
215+
/////////////////////////////////////////////////////////
216+
/// TPM context structures
217+
/////////////////////////////////////////////////////////
218+
mod tpm_context;
219+
pub use tpm_context::SavedTpmContext;

tss-esapi/src/structures/tagged/public.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ impl TryFrom<TPMT_PUBLIC> for Public {
495495
impl_mu_standard!(Public, TPMT_PUBLIC);
496496

497497
impl Serialize for Public {
498-
/// Serialise the [Public] data into it's bytes representation of the TCG
498+
/// Serialize the [Public] data into it's bytes representation of the TCG
499499
/// TPMT_PUBLIC structure.
500500
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
501501
where
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright 2024 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use crate::{
4+
handles::TpmHandle,
5+
interface_types::{data_handles::Saved, reserved_handles::Hierarchy},
6+
structures::TpmContextData,
7+
traits::impl_mu_standard,
8+
traits::{Marshall, UnMarshall},
9+
tss2_esys::TPMS_CONTEXT,
10+
Error, Result,
11+
};
12+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
13+
use std::convert::TryFrom;
14+
15+
/// Structure holding the content of a TPM context.
16+
#[derive(Debug, Clone)]
17+
pub struct SavedTpmContext {
18+
sequence: u64,
19+
saved_handle: Saved,
20+
hierarchy: Hierarchy,
21+
context_blob: TpmContextData,
22+
}
23+
24+
impl SavedTpmContext {
25+
/// The sequence parameter
26+
///
27+
/// # Details
28+
/// "The sequence parameter is used to differentiate the contexts and to allow the TPM to create a different
29+
/// encryption key for each context."
30+
pub const fn sequence(&self) -> u64 {
31+
self.sequence
32+
}
33+
34+
/// The saved handle.
35+
pub const fn saved_handle(&self) -> Saved {
36+
self.saved_handle
37+
}
38+
39+
/// The hierarchy for the saved context.
40+
pub const fn hierarchy(&self) -> Hierarchy {
41+
self.hierarchy
42+
}
43+
44+
/// The context blob.
45+
///
46+
/// # Details
47+
/// "This is the hierarchy ([Hierarchy]) for the saved context and determines the proof value used
48+
/// in the construction of the encryption and integrity values for the context. For session and sequence
49+
/// contexts, the hierarchy is [Hierarchy::Null]. The hierarchy for a transient object may be [Hierarchy::Null]
50+
/// but it is not required."
51+
pub fn context_blob(&self) -> &TpmContextData {
52+
&self.context_blob
53+
}
54+
}
55+
56+
impl TryFrom<TPMS_CONTEXT> for SavedTpmContext {
57+
type Error = Error;
58+
59+
fn try_from(tss: TPMS_CONTEXT) -> Result<SavedTpmContext> {
60+
Ok(SavedTpmContext {
61+
sequence: tss.sequence,
62+
saved_handle: Saved::try_from(tss.savedHandle)?,
63+
hierarchy: TpmHandle::try_from(tss.hierarchy).and_then(Hierarchy::try_from)?,
64+
context_blob: TpmContextData::try_from(tss.contextBlob)?,
65+
})
66+
}
67+
}
68+
69+
impl From<SavedTpmContext> for TPMS_CONTEXT {
70+
fn from(native: SavedTpmContext) -> TPMS_CONTEXT {
71+
TPMS_CONTEXT {
72+
sequence: native.sequence,
73+
savedHandle: native.saved_handle.into(),
74+
hierarchy: TpmHandle::from(native.hierarchy).into(),
75+
contextBlob: native.context_blob.into(),
76+
}
77+
}
78+
}
79+
80+
impl_mu_standard!(SavedTpmContext, TPMS_CONTEXT);
81+
82+
impl Serialize for SavedTpmContext {
83+
/// Serialize the [SavedTpmContext] data into it's bytes representation of the TCG
84+
/// TPMS_CONTEXT structure.
85+
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
86+
where
87+
S: Serializer,
88+
{
89+
let bytes = self.marshall().map_err(serde::ser::Error::custom)?;
90+
serializer.serialize_bytes(&bytes)
91+
}
92+
}
93+
94+
impl<'de> Deserialize<'de> for SavedTpmContext {
95+
/// Deserialize the [SavedTpmContext] data from it's bytes representation of the TCG
96+
/// TPMS_CONTEXT structure.
97+
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
98+
where
99+
D: Deserializer<'de>,
100+
{
101+
let bytes = <Vec<u8>>::deserialize(deserializer)?;
102+
Self::unmarshall(&bytes).map_err(serde::de::Error::custom)
103+
}
104+
}

tss-esapi/src/utils/mod.rs

Lines changed: 2 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -19,76 +19,10 @@ use crate::structures::{
1919
EccPoint, EccScheme, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa,
2020
PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject,
2121
};
22-
use crate::tss2_esys::*;
2322
use crate::{Context, Error, Result, WrapperErrorKind};
2423
use serde::{Deserialize, Serialize};
25-
use std::convert::{TryFrom, TryInto};
26-
use zeroize::{Zeroize, ZeroizeOnDrop};
27-
28-
/// Rust native wrapper for `TPMS_CONTEXT` objects.
29-
///
30-
/// This structure is intended to help with persisting object contexts. As the main reason for
31-
/// saving the context of an object is to be able to reuse it later, on demand, a serializable
32-
/// structure is most commonly needed. `TpmsContext` implements the `Serialize` and `Deserialize`
33-
/// defined by `serde`.
34-
#[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)]
35-
pub struct TpmsContext {
36-
sequence: u64,
37-
saved_handle: TPMI_DH_CONTEXT,
38-
hierarchy: TPMI_RH_HIERARCHY,
39-
context_blob: Vec<u8>,
40-
}
41-
42-
impl TpmsContext {
43-
/// Get a reference to the `context_blob` field
44-
pub fn context_blob(&self) -> &Vec<u8> {
45-
&self.context_blob
46-
}
47-
}
48-
49-
// TODO: Replace with `From`
50-
impl TryFrom<TPMS_CONTEXT> for TpmsContext {
51-
type Error = Error;
52-
53-
fn try_from(tss2_context: TPMS_CONTEXT) -> Result<Self> {
54-
let mut context = TpmsContext {
55-
sequence: tss2_context.sequence,
56-
saved_handle: tss2_context.savedHandle,
57-
hierarchy: tss2_context.hierarchy,
58-
context_blob: tss2_context.contextBlob.buffer.to_vec(),
59-
};
60-
context
61-
.context_blob
62-
.truncate(tss2_context.contextBlob.size.into());
63-
Ok(context)
64-
}
65-
}
66-
67-
#[allow(clippy::needless_update)]
68-
impl TryFrom<TpmsContext> for TPMS_CONTEXT {
69-
type Error = Error;
70-
71-
fn try_from(context: TpmsContext) -> Result<Self> {
72-
let buffer_size = context.context_blob.len();
73-
if buffer_size > 5188 {
74-
return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
75-
}
76-
let mut buffer = [0_u8; 5188];
77-
for (i, val) in context.context_blob.iter().enumerate() {
78-
buffer[i] = *val;
79-
}
80-
Ok(TPMS_CONTEXT {
81-
sequence: context.sequence,
82-
savedHandle: context.saved_handle,
83-
hierarchy: context.hierarchy,
84-
contextBlob: TPM2B_CONTEXT_DATA {
85-
size: buffer_size.try_into().unwrap(), // should not panic given the check above
86-
buffer,
87-
},
88-
..Default::default()
89-
})
90-
}
91-
}
24+
use std::convert::TryFrom;
25+
use zeroize::Zeroize;
9226

9327
/// Create the [Public] structure for a restricted decryption key.
9428
///

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Copyright 2022 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33
use tss_esapi::tss2_esys::{
4-
TPM2B_AUTH, TPM2B_DATA, TPM2B_DIGEST, TPM2B_MAX_NV_BUFFER, TPM2B_NAME, TPM2B_SENSITIVE_CREATE,
5-
TPM2B_SENSITIVE_DATA,
4+
TPM2B_AUTH, TPM2B_CONTEXT_DATA, TPM2B_DATA, TPM2B_DIGEST, TPM2B_MAX_NV_BUFFER, TPM2B_NAME,
5+
TPM2B_SENSITIVE_CREATE, TPM2B_SENSITIVE_DATA,
66
};
77

88
macro_rules! ensure_sized_buffer_equality {
@@ -60,3 +60,10 @@ pub fn ensure_tpm2b_sensitive_create_equality(
6060
);
6161
crate::common::ensure_tpms_sensitive_create_equality(&expected.sensitive, &actual.sensitive);
6262
}
63+
64+
pub fn ensure_tpm2b_context_data_equality(
65+
expected: &TPM2B_CONTEXT_DATA,
66+
actual: &TPM2B_CONTEXT_DATA,
67+
) {
68+
ensure_sized_buffer_equality!(expected, actual, buffer, TPM2B_CONTEXT_DATA);
69+
}

0 commit comments

Comments
 (0)