1
1
// Copyright 2021 Contributors to the Parsec project.
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
use crate :: {
4
+ constants:: tss:: TPM2_RH_UNASSIGNED ,
4
5
context:: handle_manager:: HandleDropAction ,
6
+ ffi:: to_owned_bytes,
5
7
handles:: ObjectHandle ,
6
8
handles:: { handle_conversion:: TryIntoNotNone , TpmHandle } ,
7
9
structures:: Auth ,
8
10
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 ,
11
16
} ;
12
17
use log:: error;
13
- use std:: convert:: TryFrom ;
18
+ use std:: convert:: { TryFrom , TryInto } ;
14
19
use std:: ptr:: null_mut;
15
20
use zeroize:: Zeroize ;
16
21
@@ -372,7 +377,7 @@ impl Context {
372
377
#[ cfg( has_esys_tr_get_tpm_handle) ]
373
378
/// Retrieve the `TpmHandle` stored in the given object.
374
379
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 ;
376
381
let mut tpm_handle = TPM2_RH_UNASSIGNED ;
377
382
ReturnCode :: ensure_success (
378
383
unsafe {
@@ -388,6 +393,147 @@ impl Context {
388
393
TpmHandle :: try_from ( tpm_handle)
389
394
}
390
395
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
+ }
393
539
}
0 commit comments