11// Copyright 2021 Contributors to the Parsec project.
22// SPDX-License-Identifier: Apache-2.0
33use crate :: {
4+ constants:: tss:: TPM2_RH_UNASSIGNED ,
45 context:: handle_manager:: HandleDropAction ,
6+ ffi:: to_owned_bytes,
57 handles:: ObjectHandle ,
68 handles:: { handle_conversion:: TryIntoNotNone , TpmHandle } ,
79 structures:: Auth ,
810 structures:: Name ,
9- tss2_esys:: { Esys_TR_Close , Esys_TR_FromTPMPublic , Esys_TR_GetName , Esys_TR_SetAuth } ,
10- Context , Result , ReturnCode ,
11+ tss2_esys:: {
12+ Esys_TR_Close , Esys_TR_Deserialize , Esys_TR_FromTPMPublic , Esys_TR_GetName ,
13+ Esys_TR_Serialize , Esys_TR_SetAuth ,
14+ } ,
15+ Context , Error , Result , ReturnCode , WrapperErrorKind ,
1116} ;
1217use log:: error;
13- use std:: convert:: TryFrom ;
18+ use std:: convert:: { TryFrom , TryInto } ;
1419use std:: ptr:: null_mut;
1520use zeroize:: Zeroize ;
1621
@@ -372,7 +377,7 @@ impl Context {
372377 #[ cfg( has_esys_tr_get_tpm_handle) ]
373378 /// Retrieve the `TpmHandle` stored in the given object.
374379 pub fn tr_get_tpm_handle ( & mut self , object_handle : ObjectHandle ) -> Result < TpmHandle > {
375- use crate :: { constants :: tss :: TPM2_RH_UNASSIGNED , tss2_esys:: Esys_TR_GetTpmHandle } ;
380+ use crate :: tss2_esys:: Esys_TR_GetTpmHandle ;
376381 let mut tpm_handle = TPM2_RH_UNASSIGNED ;
377382 ReturnCode :: ensure_success (
378383 unsafe {
@@ -388,6 +393,147 @@ impl Context {
388393 TpmHandle :: try_from ( tpm_handle)
389394 }
390395
391- // Missing function: Esys_TR_Serialize
392- // Missing function: Esys_TR_Deserialize
396+ /// Serialize the metadata of the object identified by `handle` into a new buffer.
397+ ///
398+ /// This can subsequently be used to recreate the object in the future.
399+ /// The object can only be recreated in a new context, if it was made persistent
400+ /// with `evict_control`.
401+ ///
402+ /// # Arguments
403+ /// * `handle` - A handle to the object which should be serialized.
404+ ///
405+ /// # Returns
406+ /// A buffer that can be stored and later deserialized.
407+ ///
408+ /// # Errors
409+ /// * if the TPM cannot serialize the handle, a TSS error is returned.
410+ /// * if the buffer length cannot be converted to a `usize`, an `InvalidParam`
411+ /// wrapper error is returned.
412+ ///
413+ /// ```rust
414+ /// # use tss_esapi::{
415+ /// # Context, TctiNameConf,
416+ /// # interface_types::resource_handles::Hierarchy,
417+ /// # structures::HashScheme,
418+ /// # utils::create_unrestricted_signing_ecc_public,
419+ /// # interface_types::{
420+ /// # ecc::EccCurve,
421+ /// # algorithm::HashingAlgorithm,
422+ /// # session_handles::AuthSession,
423+ /// # },
424+ /// # structures::EccScheme,
425+ /// # };
426+ /// # let mut context =
427+ /// # Context::new(
428+ /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
429+ /// # ).expect("Failed to create Context");
430+ /// # context.set_sessions((Some(AuthSession::Password), None, None));
431+ /// # let public = create_unrestricted_signing_ecc_public(
432+ /// # EccScheme::EcDsa(HashScheme::new(HashingAlgorithm::Sha256)),
433+ /// # EccCurve::NistP256)
434+ /// # .unwrap();
435+ /// let key_handle = context
436+ /// .create_primary(
437+ /// Hierarchy::Owner,
438+ /// public,
439+ /// None,
440+ /// None,
441+ /// None,
442+ /// None,
443+ /// ).unwrap()
444+ /// .key_handle;
445+ /// let data = context.tr_serialize(key_handle.into()).unwrap();
446+ /// ```
447+ pub fn tr_serialize ( & mut self , handle : ObjectHandle ) -> Result < Vec < u8 > > {
448+ let mut len = 0 ;
449+ let mut buffer: * mut u8 = null_mut ( ) ;
450+ ReturnCode :: ensure_success (
451+ unsafe { Esys_TR_Serialize ( self . mut_context ( ) , handle. into ( ) , & mut buffer, & mut len) } ,
452+ |ret| {
453+ error ! ( "Error while serializing handle: {}" , ret) ;
454+ } ,
455+ ) ?;
456+ Ok ( to_owned_bytes (
457+ buffer,
458+ len. try_into ( ) . map_err ( |e| {
459+ error ! ( "Failed to convert buffer len to usize: {}" , e) ;
460+ Error :: local_error ( WrapperErrorKind :: InvalidParam )
461+ } ) ?,
462+ ) )
463+ }
464+
465+ /// Deserialize the metadata from `buffer` into a new object.
466+ ///
467+ /// This can be used to restore an object from a context in the past.
468+ ///
469+ /// # Arguments
470+ /// * `buffer` - The buffer containing the data to restore the object.
471+ /// It can be created using [`tr_serialize`](Self::tr_serialize).
472+ ///
473+ /// # Returns
474+ /// A handle to the object that was created from the buffer.
475+ ///
476+ /// # Errors
477+ /// * if the TPM cannot deserialize the buffer, a TSS error is returned.
478+ /// * if the buffer length cannot be converted to a `usize`, an `InvalidParam`
479+ /// wrapper error is returned.
480+ ///
481+ /// ```rust
482+ /// # use tss_esapi::{
483+ /// # Context, TctiNameConf,
484+ /// # interface_types::resource_handles::Hierarchy,
485+ /// # structures::HashScheme,
486+ /// # utils::create_unrestricted_signing_ecc_public,
487+ /// # interface_types::{
488+ /// # ecc::EccCurve,
489+ /// # algorithm::HashingAlgorithm,
490+ /// # session_handles::AuthSession,
491+ /// # },
492+ /// # structures::EccScheme,
493+ /// # };
494+ /// # let mut context =
495+ /// # Context::new(
496+ /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
497+ /// # ).expect("Failed to create Context");
498+ /// # context.set_sessions((Some(AuthSession::Password), None, None));
499+ /// # let public = create_unrestricted_signing_ecc_public(
500+ /// # EccScheme::EcDsa(HashScheme::new(HashingAlgorithm::Sha256)),
501+ /// # EccCurve::NistP256)
502+ /// # .unwrap();
503+ /// let key_handle = context
504+ /// .create_primary(
505+ /// Hierarchy::Owner,
506+ /// public,
507+ /// None,
508+ /// None,
509+ /// None,
510+ /// None,
511+ /// ).unwrap()
512+ /// .key_handle;
513+ /// # context.set_sessions((None, None, None));
514+ /// let public_key = context.read_public(key_handle).unwrap();
515+ /// let data = context.tr_serialize(key_handle.into()).unwrap();
516+ /// let new_handle = context.tr_deserialize(&data).unwrap();
517+ /// assert_eq!(public_key, context.read_public(new_handle.into()).unwrap());
518+ /// ```
519+ pub fn tr_deserialize ( & mut self , buffer : & Vec < u8 > ) -> Result < ObjectHandle > {
520+ let mut handle = TPM2_RH_UNASSIGNED ;
521+ ReturnCode :: ensure_success (
522+ unsafe {
523+ Esys_TR_Deserialize (
524+ self . mut_context ( ) ,
525+ buffer. as_ptr ( ) ,
526+ buffer. len ( ) . try_into ( ) . map_err ( |e| {
527+ error ! ( "Failed to convert buffer len to usize: {}" , e) ;
528+ Error :: local_error ( WrapperErrorKind :: InvalidParam )
529+ } ) ?,
530+ & mut handle,
531+ )
532+ } ,
533+ |ret| {
534+ error ! ( "Error while deserializing buffer: {}" , ret) ;
535+ } ,
536+ ) ?;
537+ Ok ( ObjectHandle :: from ( handle) )
538+ }
393539}
0 commit comments