diff --git a/tss-esapi/src/context/general_esys_tr.rs b/tss-esapi/src/context/general_esys_tr.rs index efd7d52c..f87b9d45 100644 --- a/tss-esapi/src/context/general_esys_tr.rs +++ b/tss-esapi/src/context/general_esys_tr.rs @@ -1,16 +1,20 @@ // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ + constants::tss::TPM2_RH_UNASSIGNED, context::handle_manager::HandleDropAction, handles::ObjectHandle, handles::{handle_conversion::TryIntoNotNone, TpmHandle}, structures::Auth, structures::Name, - tss2_esys::{Esys_TR_Close, Esys_TR_FromTPMPublic, Esys_TR_GetName, Esys_TR_SetAuth}, - Context, Result, ReturnCode, + tss2_esys::{ + Esys_TR_Close, Esys_TR_Deserialize, Esys_TR_FromTPMPublic, Esys_TR_GetName, + Esys_TR_Serialize, Esys_TR_SetAuth, + }, + Context, Error, Result, ReturnCode, WrapperErrorKind, }; use log::error; -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use std::ptr::null_mut; use zeroize::Zeroize; @@ -372,7 +376,7 @@ impl Context { #[cfg(has_esys_tr_get_tpm_handle)] /// Retrieve the `TpmHandle` stored in the given object. pub fn tr_get_tpm_handle(&mut self, object_handle: ObjectHandle) -> Result { - use crate::{constants::tss::TPM2_RH_UNASSIGNED, tss2_esys::Esys_TR_GetTpmHandle}; + use crate::tss2_esys::Esys_TR_GetTpmHandle; let mut tpm_handle = TPM2_RH_UNASSIGNED; ReturnCode::ensure_success( unsafe { @@ -388,6 +392,45 @@ impl Context { TpmHandle::try_from(tpm_handle) } - // Missing function: Esys_TR_Serialize - // Missing function: Esys_TR_Deserialize + /// Store the `ObjectHandle` in a buffer + pub fn tr_serialize(&mut self, handle: ObjectHandle) -> Result> { + let mut len = 0; + let mut buffer: *mut u8 = null_mut(); + let mut result = vec![]; + ReturnCode::ensure_success( + unsafe { Esys_TR_Serialize(self.mut_context(), handle.into(), &mut buffer, &mut len) }, + |ret| { + error!("Error while serializing handle: {}", ret); + }, + )?; + unsafe { + let data = std::slice::from_raw_parts(&buffer, len.try_into().unwrap()); + result.extend_from_slice(data); + // free buffer + Context::ffi_data_to_owned(buffer); + }; + Ok(result) + } + + /// Retrieve the `ObjectHandle` stored in a buffer + pub fn tr_deserialize(&mut self, buffer: &Vec) -> Result { + let mut handle = TPM2_RH_UNASSIGNED; + ReturnCode::ensure_success( + unsafe { + Esys_TR_Deserialize( + self.mut_context(), + buffer.as_ptr(), + buffer.len().try_into().map_err(|e| { + error!("Failed to convert buffer len to usize: {}", e); + Error::local_error(WrapperErrorKind::InvalidParam) + })?, + &mut handle, + ) + }, + |ret| { + error!("Error while deserializing buffer: {}", ret); + }, + )?; + Ok(ObjectHandle::from(handle)) + } } diff --git a/tss-esapi/tests/integration_tests/context_tests/general_esys_tr_tests.rs b/tss-esapi/tests/integration_tests/context_tests/general_esys_tr_tests.rs index 3a3c474e..ffdfdeaf 100644 --- a/tss-esapi/tests/integration_tests/context_tests/general_esys_tr_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/general_esys_tr_tests.rs @@ -1,20 +1,22 @@ +use crate::common::{create_ctx_with_session, create_ctx_without_session, decryption_key_pub}; +use tss_esapi::{ + attributes::NvIndexAttributesBuilder, + constants::{tss::TPM2_NV_INDEX_FIRST, CapabilityType}, + handles::{NvIndexHandle, NvIndexTpmHandle, ObjectHandle}, + interface_types::{ + algorithm::HashingAlgorithm, + resource_handles::{Hierarchy, NvAuth, Provision}, + session_handles::AuthSession, + }, + structures::{Auth, CapabilityData, MaxNvBuffer, NvPublicBuilder}, + tss2_esys::TPM2_HANDLE, + Context, +}; + +use std::convert::TryFrom; + mod test_tr_from_tpm_public { - use crate::common::create_ctx_without_session; - use tss_esapi::{ - attributes::NvIndexAttributesBuilder, - constants::{tss::TPM2_NV_INDEX_FIRST, CapabilityType}, - handles::{NvIndexHandle, NvIndexTpmHandle, ObjectHandle}, - interface_types::{ - algorithm::HashingAlgorithm, - resource_handles::{NvAuth, Provision}, - session_handles::AuthSession, - }, - structures::{Auth, CapabilityData, MaxNvBuffer, NvPublicBuilder}, - tss2_esys::TPM2_HANDLE, - Context, - }; - - use std::convert::TryFrom; + use super::*; fn remove_nv_index_handle_from_tpm(nv_index_tpm_handle: NvIndexTpmHandle, nv_auth: Provision) { let mut context = create_ctx_without_session(); @@ -445,3 +447,31 @@ mod test_tr_from_tpm_public { assert_eq!(expected, actual); } } + +mod test_tr_serialize_tr_deserialize { + use super::*; + + #[test] + fn test_tr_serialize_tr_deserialize() { + let mut context = create_ctx_with_session(); + let random_digest = context.get_random(16).unwrap(); + let key_auth = Auth::from_bytes(random_digest.as_bytes()).unwrap(); + let key_handle = context + .create_primary( + Hierarchy::Owner, + decryption_key_pub(), + Some(key_auth), + None, + None, + None, + ) + .unwrap() + .key_handle; + let data = context.tr_serialize(key_handle.into()).unwrap(); + let new_handle = context.tr_deserialize(&data).unwrap().into(); + assert_eq!( + context.read_public(key_handle).unwrap(), + context.read_public(new_handle).unwrap() + ); + } +}