Skip to content

Commit

Permalink
Adds proper native types for TPMS_CONTEXT.
Browse files Browse the repository at this point in the history
- Adds TPM context data structures.
- Moves TpmsContext into structures and renames it
  to SavedTpmContext.

Signed-off-by: Jesper Brynolf <jesper.brynolf@gmail.com>
  • Loading branch information
Superhepper committed Mar 9, 2024
1 parent f579dc8 commit 1ac96b7
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 88 deletions.
7 changes: 4 additions & 3 deletions tss-esapi/src/abstraction/transient/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ use crate::{
structures::{
Auth, CreateKeyResult, Data, Digest, EccPoint, EccScheme, Public, PublicBuilder,
PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent,
RsaScheme, Signature, SignatureScheme, SymmetricDefinitionObject, VerifiedTicket,
RsaScheme, SavedTpmContext, Signature, SignatureScheme, SymmetricDefinitionObject,
VerifiedTicket,
},
tcti_ldr::TctiNameConf,
utils::{create_restricted_decryption_rsa_public, PublicKey, TpmsContext},
utils::{create_restricted_decryption_rsa_public, PublicKey},
Context, Error, Result, ReturnCode, WrapperErrorKind as ErrorKind,
};

Expand Down Expand Up @@ -336,7 +337,7 @@ impl TransientKeyContext {
/// just a public key.
pub fn migrate_key_from_ctx(
&mut self,
context: TpmsContext,
context: SavedTpmContext,
auth: Option<Auth>,
) -> Result<KeyMaterial> {
self.set_session_attrs()?;
Expand Down
19 changes: 7 additions & 12 deletions tss-esapi/src/context/tpm_commands/context_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use crate::{
context::handle_manager::HandleDropAction,
handles::{handle_conversion::TryIntoNotNone, AuthHandle, ObjectHandle, PersistentTpmHandle},
interface_types::{data_handles::Persistent, reserved_handles::Provision},
structures::SavedTpmContext,
tss2_esys::{Esys_ContextLoad, Esys_ContextSave, Esys_EvictControl, Esys_FlushContext},
utils::TpmsContext,
Context, Result, ReturnCode,
};
use log::error;
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;
use std::ptr::null_mut;

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

/// Load a previously saved context into the TPM and return the object handle.
///
/// # Errors
/// * if conversion from `TpmsContext` to the native `TPMS_CONTEXT` fails, a `WrongParamSize`
/// error will be returned
pub fn context_load(&mut self, context: TpmsContext) -> Result<ObjectHandle> {
pub fn context_load(&mut self, context: SavedTpmContext) -> Result<ObjectHandle> {
let mut esys_loaded_handle = ObjectHandle::None.into();
let tpm_context = context.into();
ReturnCode::ensure_success(
unsafe {
Esys_ContextLoad(
self.mut_context(),
&context.try_into()?,
&mut esys_loaded_handle,
)
},
unsafe { Esys_ContextLoad(self.mut_context(), &tpm_context, &mut esys_loaded_handle) },
|ret| {
error!("Error in loading context: {:#010X}", ret);
},
Expand Down
12 changes: 12 additions & 0 deletions tss-esapi/src/interface_types/data_handles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,15 @@ impl TryFrom<TPMI_DH_SAVED> for Saved {
})
}
}

impl From<Saved> for TPMI_DH_SAVED {
fn from(native: Saved) -> TPMI_DH_SAVED {
match native {
Saved::Hmac(handle) => handle.into(),
Saved::Policy(handle) => handle.into(),
Saved::Transient => TransientTpmHandle::SavedTransient.into(),
Saved::Sequence => TransientTpmHandle::SavedSequence.into(),
Saved::TransientClear => TransientTpmHandle::SavedTransientClear.into(),
}
}
}
9 changes: 9 additions & 0 deletions tss-esapi/src/structures/buffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,12 @@ pub mod symmetric_key {
pub mod timeout {
buffer_type!(Timeout, 8, TPM2B_TIMEOUT);
}

pub mod tpm_context_data {
use crate::tss2_esys::TPMS_CONTEXT_DATA;
buffer_type!(
TpmContextData,
std::mem::size_of::<TPMS_CONTEXT_DATA>(),
TPM2B_CONTEXT_DATA
);
}
7 changes: 6 additions & 1 deletion tss-esapi/src/structures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use self::buffers::{
private_key_rsa::PrivateKeyRsa, private_vendor_specific::PrivateVendorSpecific,
public::PublicBuffer, public_key_rsa::PublicKeyRsa, sensitive::SensitiveBuffer,
sensitive_create::SensitiveCreateBuffer, sensitive_data::SensitiveData,
symmetric_key::SymmetricKey, timeout::Timeout,
symmetric_key::SymmetricKey, timeout::Timeout, tpm_context_data::TpmContextData,
};
/////////////////////////////////////////////////////////
/// The creation section
Expand Down Expand Up @@ -212,3 +212,8 @@ pub use nv::storage::{NvPublic, NvPublicBuilder};
/////////////////////////////////////////////////////////
mod algorithm;
pub use algorithm::symmetric::sensitive_create::SensitiveCreate;
/////////////////////////////////////////////////////////
/// TPM context structures
/////////////////////////////////////////////////////////
mod tpm_context;
pub use tpm_context::SavedTpmContext;
2 changes: 1 addition & 1 deletion tss-esapi/src/structures/tagged/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ impl TryFrom<TPMT_PUBLIC> for Public {
impl_mu_standard!(Public, TPMT_PUBLIC);

impl Serialize for Public {
/// Serialise the [Public] data into it's bytes representation of the TCG
/// Serialize the [Public] data into it's bytes representation of the TCG
/// TPMT_PUBLIC structure.
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
Expand Down
104 changes: 104 additions & 0 deletions tss-esapi/src/structures/tpm_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2024 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
use crate::{
handles::TpmHandle,
interface_types::{data_handles::Saved, reserved_handles::Hierarchy},
structures::TpmContextData,
traits::impl_mu_standard,
traits::{Marshall, UnMarshall},
tss2_esys::TPMS_CONTEXT,
Error, Result,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::convert::TryFrom;

/// Structure holding the content of a TPM context.
#[derive(Debug, Clone)]
pub struct SavedTpmContext {
sequence: u64,
saved_handle: Saved,
hierarchy: Hierarchy,
context_blob: TpmContextData,
}

impl SavedTpmContext {
/// The sequence parameter
///
/// # Details
/// "The sequence parameter is used to differentiate the contexts and to allow the TPM to create a different
/// encryption key for each context."
pub const fn sequence(&self) -> u64 {
self.sequence
}

/// The saved handle.
pub const fn saved_handle(&self) -> Saved {
self.saved_handle
}

/// The hierarchy for the saved context.
pub const fn hierarchy(&self) -> Hierarchy {
self.hierarchy
}

/// The context blob.
///
/// # Details
/// "This is the hierarchy ([Hierarchy]) for the saved context and determines the proof value used
/// in the construction of the encryption and integrity values for the context. For session and sequence
/// contexts, the hierarchy is [Hierarchy::Null]. The hierarchy for a transient object may be [Hierarchy::Null]
/// but it is not required."
pub fn context_blob(&self) -> &TpmContextData {
&self.context_blob
}
}

impl TryFrom<TPMS_CONTEXT> for SavedTpmContext {
type Error = Error;

fn try_from(tss: TPMS_CONTEXT) -> Result<SavedTpmContext> {
Ok(SavedTpmContext {
sequence: tss.sequence,
saved_handle: Saved::try_from(tss.savedHandle)?,
hierarchy: TpmHandle::try_from(tss.hierarchy).and_then(Hierarchy::try_from)?,
context_blob: TpmContextData::try_from(tss.contextBlob)?,
})
}
}

impl From<SavedTpmContext> for TPMS_CONTEXT {
fn from(native: SavedTpmContext) -> TPMS_CONTEXT {
TPMS_CONTEXT {
sequence: native.sequence,
savedHandle: native.saved_handle.into(),
hierarchy: TpmHandle::from(native.hierarchy).into(),
contextBlob: native.context_blob.into(),
}
}
}

impl_mu_standard!(SavedTpmContext, TPMS_CONTEXT);

impl Serialize for SavedTpmContext {
/// Serialize the [SavedTpmContext] data into it's bytes representation of the TCG
/// TPMS_CONTEXT structure.
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
let bytes = self.marshall().map_err(serde::ser::Error::custom)?;
serializer.serialize_bytes(&bytes)
}
}

impl<'de> Deserialize<'de> for SavedTpmContext {
/// Deserialize the [SavedTpmContext] data from it's bytes representation of the TCG
/// TPMS_CONTEXT structure.
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let bytes = <Vec<u8>>::deserialize(deserializer)?;
Self::unmarshall(&bytes).map_err(serde::de::Error::custom)
}
}
70 changes: 2 additions & 68 deletions tss-esapi/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,76 +19,10 @@ use crate::structures::{
EccPoint, EccScheme, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa,
PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject,
};
use crate::tss2_esys::*;
use crate::{Context, Error, Result, WrapperErrorKind};
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
use zeroize::{Zeroize, ZeroizeOnDrop};

/// Rust native wrapper for `TPMS_CONTEXT` objects.
///
/// This structure is intended to help with persisting object contexts. As the main reason for
/// saving the context of an object is to be able to reuse it later, on demand, a serializable
/// structure is most commonly needed. `TpmsContext` implements the `Serialize` and `Deserialize`
/// defined by `serde`.
#[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)]
pub struct TpmsContext {
sequence: u64,
saved_handle: TPMI_DH_CONTEXT,
hierarchy: TPMI_RH_HIERARCHY,
context_blob: Vec<u8>,
}

impl TpmsContext {
/// Get a reference to the `context_blob` field
pub fn context_blob(&self) -> &Vec<u8> {
&self.context_blob
}
}

// TODO: Replace with `From`
impl TryFrom<TPMS_CONTEXT> for TpmsContext {
type Error = Error;

fn try_from(tss2_context: TPMS_CONTEXT) -> Result<Self> {
let mut context = TpmsContext {
sequence: tss2_context.sequence,
saved_handle: tss2_context.savedHandle,
hierarchy: tss2_context.hierarchy,
context_blob: tss2_context.contextBlob.buffer.to_vec(),
};
context
.context_blob
.truncate(tss2_context.contextBlob.size.into());
Ok(context)
}
}

#[allow(clippy::needless_update)]
impl TryFrom<TpmsContext> for TPMS_CONTEXT {
type Error = Error;

fn try_from(context: TpmsContext) -> Result<Self> {
let buffer_size = context.context_blob.len();
if buffer_size > 5188 {
return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
}
let mut buffer = [0_u8; 5188];
for (i, val) in context.context_blob.iter().enumerate() {
buffer[i] = *val;
}
Ok(TPMS_CONTEXT {
sequence: context.sequence,
savedHandle: context.saved_handle,
hierarchy: context.hierarchy,
contextBlob: TPM2B_CONTEXT_DATA {
size: buffer_size.try_into().unwrap(), // should not panic given the check above
buffer,
},
..Default::default()
})
}
}
use std::convert::TryFrom;
use zeroize::Zeroize;

/// Create the [Public] structure for a restricted decryption key.
///
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright 2022 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
use tss_esapi::tss2_esys::{
TPM2B_AUTH, TPM2B_DATA, TPM2B_DIGEST, TPM2B_MAX_NV_BUFFER, TPM2B_NAME, TPM2B_SENSITIVE_CREATE,
TPM2B_SENSITIVE_DATA,
TPM2B_AUTH, TPM2B_CONTEXT_DATA, TPM2B_DATA, TPM2B_DIGEST, TPM2B_MAX_NV_BUFFER, TPM2B_NAME,
TPM2B_SENSITIVE_CREATE, TPM2B_SENSITIVE_DATA,
};

macro_rules! ensure_sized_buffer_equality {
Expand Down Expand Up @@ -60,3 +60,10 @@ pub fn ensure_tpm2b_sensitive_create_equality(
);
crate::common::ensure_tpms_sensitive_create_equality(&expected.sensitive, &actual.sensitive);
}

pub fn ensure_tpm2b_context_data_equality(
expected: &TPM2B_CONTEXT_DATA,
actual: &TPM2B_CONTEXT_DATA,
) {
ensure_sized_buffer_equality!(expected, actual, buffer, TPM2B_CONTEXT_DATA);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tss_esapi::{
},
tss2_esys::{
TPMS_ALG_PROPERTY, TPMS_ATTEST, TPMS_CERTIFY_INFO, TPMS_CLOCK_INFO,
TPMS_COMMAND_AUDIT_INFO, TPMS_CREATION_INFO, TPMS_ECC_PARMS, TPMS_EMPTY,
TPMS_COMMAND_AUDIT_INFO, TPMS_CONTEXT, TPMS_CREATION_INFO, TPMS_ECC_PARMS, TPMS_EMPTY,
TPMS_KEYEDHASH_PARMS, TPMS_NV_CERTIFY_INFO, TPMS_PCR_SELECTION, TPMS_QUOTE_INFO,
TPMS_RSA_PARMS, TPMS_SCHEME_ECDAA, TPMS_SCHEME_HASH, TPMS_SCHEME_HMAC, TPMS_SCHEME_XOR,
TPMS_SENSITIVE_CREATE, TPMS_SESSION_AUDIT_INFO, TPMS_SYMCIPHER_PARMS,
Expand Down Expand Up @@ -316,3 +316,19 @@ pub fn ensure_tpms_empty_equality(expected: &TPMS_EMPTY, actual: &TPMS_EMPTY) {
"'empty' value TPMS_EMPTY, mismatch between actual and expected."
);
}

pub fn ensure_tpms_context_equality(expected: &TPMS_CONTEXT, actual: &TPMS_CONTEXT) {
assert_eq!(
expected.sequence, actual.sequence,
"'sequence' value TPMS_CONTEXT, mismatch between actual and expected"
);
assert_eq!(
expected.savedHandle, actual.savedHandle,
"'savedHandle' value TPMS_CONTEXT, mismatch between actual and expected"
);
assert_eq!(
expected.hierarchy, actual.hierarchy,
"'hierarchy' value TPMS_CONTEXT, mismatch between actual and expected"
);
crate::common::ensure_tpm2b_context_data_equality(&expected.contextBlob, &actual.contextBlob);
}
1 change: 1 addition & 0 deletions tss-esapi/tests/integration_tests/structures_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ mod tagged_property_tests;
mod tagged_tests;
mod time_attest_info_tests;
mod time_info_tests;
mod tpm_context_tests;
Loading

0 comments on commit 1ac96b7

Please sign in to comment.