Skip to content

Commit a5a5ad1

Browse files
authored
Merge pull request #266 from wiktor-k/add-import
Add TPM Import command
2 parents c2e2509 + f0df9cd commit a5a5ad1

File tree

2 files changed

+402
-6
lines changed

2 files changed

+402
-6
lines changed

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

Lines changed: 358 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::Context;
44
use crate::{
55
handles::ObjectHandle,
6-
structures::{Data, EncryptedSecret, Private, SymmetricDefinitionObject},
6+
structures::{Data, EncryptedSecret, Private, Public, SymmetricDefinitionObject},
77
tss2_esys::*,
88
Error, Result,
99
};
@@ -23,7 +23,8 @@ impl Context {
2323
/// # Arguments
2424
/// * `object_to_duplicate` - An [ObjectHandle] of the object that will be duplicated.
2525
/// * `new_parent_handle` - An [ObjectHandle] of the new parent.
26-
/// * `encryption_key_in` - An optional encryption key.
26+
/// * `encryption_key_in` - An optional encryption key. If this parameter is `None`
27+
/// then a [default value][Default::default] is used.
2728
/// * `symmetric_alg` - Symmetric algorithm to be used for the inner wrapper.
2829
///
2930
/// The `object_to_duplicate` need to be have Fixed TPM and Fixed Parent attributes set to `false`.
@@ -35,6 +36,8 @@ impl Context {
3536
/// * `duplicate` - Private area that may be encrypted.
3637
/// * `out_sym_seed` - Seed protected by the asymmetric algorithms of new parent.
3738
///
39+
/// # Example
40+
///
3841
/// ```rust
3942
/// # use std::convert::{TryFrom, TryInto};
4043
/// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder};
@@ -331,5 +334,357 @@ impl Context {
331334
}
332335

333336
// Missing function: Rewrap
334-
// Missing function: Import
337+
338+
/// Import attaches imported object to a new parent.
339+
///
340+
/// # Details
341+
/// This command allows an object to be encrypted using the symmetric
342+
/// encryption values of a Storage Key. After encryption, the
343+
/// object may be loaded and used in the new hierarchy. The
344+
/// imported object (duplicate) may be singly encrypted, multiply
345+
/// encrypted, or unencrypted.
346+
///
347+
/// # Arguments
348+
/// * `parent_handle` - An [ObjectHandle] of the new parent for the object.
349+
/// * `encryption_key` - An optional symmetric encryption key used as the inner wrapper.
350+
/// If `encryption_key` is `None` then a [default value][Default::default] is used.
351+
/// * `public` - A [Public] of the imported object.
352+
/// * `duplicate` - A symmetrically encrypted duplicated object.
353+
/// * `encrypted_secret` - The seed for the symmetric key and HMAC key.
354+
/// * `symmetric_alg` - Symmetric algorithm to be used for the inner wrapper.
355+
///
356+
/// The `public` is needed to check the integrity value for `duplicate`.
357+
///
358+
/// # Returns
359+
/// The command returns the sensitive area encrypted with the symmetric key of `parent_handle`.
360+
///
361+
/// # Example
362+
///
363+
/// ```rust
364+
/// # use std::convert::{TryFrom, TryInto};
365+
/// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder};
366+
/// # use tss_esapi::constants::{tss::TPM2_CC_Duplicate, SessionType};
367+
/// # use tss_esapi::handles::ObjectHandle;
368+
/// # use tss_esapi::interface_types::{
369+
/// # algorithm::{HashingAlgorithm, PublicAlgorithm},
370+
/// # key_bits::RsaKeyBits,
371+
/// # resource_handles::Hierarchy,
372+
/// # session_handles::PolicySession,
373+
/// # };
374+
/// # use tss_esapi::structures::SymmetricDefinition;
375+
/// # use tss_esapi::structures::{
376+
/// # PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme,
377+
/// # RsaExponent,
378+
/// # };
379+
/// use tss_esapi::structures::SymmetricDefinitionObject;
380+
/// # use tss_esapi::abstraction::cipher::Cipher;
381+
/// # use tss_esapi::{Context, TctiNameConf};
382+
/// #
383+
/// # let mut context = // ...
384+
/// # Context::new(
385+
/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
386+
/// # ).expect("Failed to create Context");
387+
/// #
388+
/// # let trial_session = context
389+
/// # .start_auth_session(
390+
/// # None,
391+
/// # None,
392+
/// # None,
393+
/// # SessionType::Trial,
394+
/// # SymmetricDefinition::AES_256_CFB,
395+
/// # HashingAlgorithm::Sha256,
396+
/// # )
397+
/// # .expect("Start auth session failed")
398+
/// # .expect("Start auth session returned a NONE handle");
399+
/// #
400+
/// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) =
401+
/// # SessionAttributesBuilder::new()
402+
/// # .with_decrypt(true)
403+
/// # .with_encrypt(true)
404+
/// # .build();
405+
/// # context
406+
/// # .tr_sess_set_attributes(
407+
/// # trial_session,
408+
/// # policy_auth_session_attributes,
409+
/// # policy_auth_session_attributes_mask,
410+
/// # )
411+
/// # .expect("tr_sess_set_attributes call failed");
412+
/// #
413+
/// # let policy_session = PolicySession::try_from(trial_session)
414+
/// # .expect("Failed to convert auth session into policy session");
415+
/// #
416+
/// # context
417+
/// # .policy_auth_value(policy_session)
418+
/// # .expect("Policy auth value");
419+
/// #
420+
/// # context
421+
/// # .policy_command_code(policy_session, TPM2_CC_Duplicate)
422+
/// # .expect("Policy command code");
423+
/// #
424+
/// # /// Digest of the policy that allows duplication
425+
/// # let digest = context
426+
/// # .policy_get_digest(policy_session)
427+
/// # .expect("Could retrieve digest");
428+
/// #
429+
/// # drop(context);
430+
/// # let mut context = // ...
431+
/// # Context::new(
432+
/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
433+
/// # ).expect("Failed to create Context");
434+
/// #
435+
/// # let session = context
436+
/// # .start_auth_session(
437+
/// # None,
438+
/// # None,
439+
/// # None,
440+
/// # SessionType::Hmac,
441+
/// # SymmetricDefinition::AES_256_CFB,
442+
/// # HashingAlgorithm::Sha256,
443+
/// # )
444+
/// # .expect("Start auth session failed")
445+
/// # .expect("Start auth session returned a NONE handle");
446+
/// #
447+
/// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
448+
/// # .with_decrypt(true)
449+
/// # .with_encrypt(true)
450+
/// # .build();
451+
/// #
452+
/// # context.tr_sess_set_attributes(
453+
/// # session,
454+
/// # session_attributes,
455+
/// # session_attributes_mask,
456+
/// # ).unwrap();
457+
/// #
458+
/// # context.set_sessions((Some(session), None, None));
459+
/// #
460+
/// # // Attributes of parent objects. The `restricted` attribute need
461+
/// # // to be `true` so that parents can act as storage keys.
462+
/// # let parent_object_attributes = ObjectAttributesBuilder::new()
463+
/// # .with_fixed_tpm(true)
464+
/// # .with_fixed_parent(true)
465+
/// # .with_sensitive_data_origin(true)
466+
/// # .with_user_with_auth(true)
467+
/// # .with_decrypt(true)
468+
/// # .with_sign_encrypt(false)
469+
/// # .with_restricted(true)
470+
/// # .build()
471+
/// # .unwrap();
472+
/// #
473+
/// # let parent_public = PublicBuilder::new()
474+
/// # .with_public_algorithm(PublicAlgorithm::Rsa)
475+
/// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
476+
/// # .with_object_attributes(parent_object_attributes)
477+
/// # .with_rsa_parameters(
478+
/// # PublicRsaParametersBuilder::new_restricted_decryption_key(
479+
/// # Cipher::aes_256_cfb().try_into().unwrap(),
480+
/// # RsaKeyBits::Rsa2048,
481+
/// # RsaExponent::default(),
482+
/// # )
483+
/// # .build()
484+
/// # .unwrap(),
485+
/// # )
486+
/// # .with_rsa_unique_identifier(&PublicKeyRsa::default())
487+
/// # .build()
488+
/// # .unwrap();
489+
/// #
490+
/// # let parent_of_object_to_duplicate_handle = context
491+
/// # .create_primary(
492+
/// # Hierarchy::Owner,
493+
/// # &parent_public,
494+
/// # None,
495+
/// # None,
496+
/// # None,
497+
/// # None,
498+
/// # )
499+
/// # .unwrap()
500+
/// # .key_handle;
501+
/// #
502+
/// # // Fixed TPM and Fixed Parent should be "false" for an object
503+
/// # // to be elligible for duplication
504+
/// # let object_attributes = ObjectAttributesBuilder::new()
505+
/// # .with_fixed_tpm(false)
506+
/// # .with_fixed_parent(false)
507+
/// # .with_sensitive_data_origin(true)
508+
/// # .with_user_with_auth(true)
509+
/// # .with_decrypt(true)
510+
/// # .with_sign_encrypt(true)
511+
/// # .with_restricted(false)
512+
/// # .build()
513+
/// # .expect("Attributes to be valid");
514+
/// #
515+
/// # let public_child = PublicBuilder::new()
516+
/// # .with_public_algorithm(PublicAlgorithm::Rsa)
517+
/// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
518+
/// # .with_object_attributes(object_attributes)
519+
/// # .with_auth_policy(&digest)
520+
/// # .with_rsa_parameters(
521+
/// # PublicRsaParametersBuilder::new()
522+
/// # .with_scheme(RsaScheme::Null)
523+
/// # .with_key_bits(RsaKeyBits::Rsa2048)
524+
/// # .with_is_signing_key(true)
525+
/// # .with_is_decryption_key(true)
526+
/// # .with_restricted(false)
527+
/// # .build()
528+
/// # .expect("Params to be valid"),
529+
/// # )
530+
/// # .with_rsa_unique_identifier(&PublicKeyRsa::default())
531+
/// # .build()
532+
/// # .expect("public to be valid");
533+
/// #
534+
/// # let result = context
535+
/// # .create(
536+
/// # parent_of_object_to_duplicate_handle,
537+
/// # &public_child,
538+
/// # None,
539+
/// # None,
540+
/// # None,
541+
/// # None,
542+
/// # )
543+
/// # .unwrap();
544+
/// #
545+
/// # let object_to_duplicate_handle: ObjectHandle = context
546+
/// # .load(
547+
/// # parent_of_object_to_duplicate_handle,
548+
/// # result.out_private.clone(),
549+
/// # &result.out_public,
550+
/// # )
551+
/// # .unwrap()
552+
/// # .into();
553+
/// #
554+
/// # let new_parent_handle: ObjectHandle = context
555+
/// # .create_primary(
556+
/// # Hierarchy::Owner,
557+
/// # &parent_public,
558+
/// # None,
559+
/// # None,
560+
/// # None,
561+
/// # None,
562+
/// # )
563+
/// # .unwrap()
564+
/// # .key_handle
565+
/// # .into();
566+
/// #
567+
/// # context.set_sessions((None, None, None));
568+
/// #
569+
/// # // Create a Policy session with the same exact attributes
570+
/// # // as the trial session so that the session digest stays
571+
/// # // the same.
572+
/// # let policy_auth_session = context
573+
/// # .start_auth_session(
574+
/// # None,
575+
/// # None,
576+
/// # None,
577+
/// # SessionType::Policy,
578+
/// # SymmetricDefinition::AES_256_CFB,
579+
/// # HashingAlgorithm::Sha256,
580+
/// # )
581+
/// # .expect("Start auth session failed")
582+
/// # .expect("Start auth session returned a NONE handle");
583+
/// #
584+
/// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) =
585+
/// # SessionAttributesBuilder::new()
586+
/// # .with_decrypt(true)
587+
/// # .with_encrypt(true)
588+
/// # .build();
589+
/// # context
590+
/// # .tr_sess_set_attributes(
591+
/// # policy_auth_session,
592+
/// # policy_auth_session_attributes,
593+
/// # policy_auth_session_attributes_mask,
594+
/// # )
595+
/// # .expect("tr_sess_set_attributes call failed");
596+
/// #
597+
/// # let policy_session = PolicySession::try_from(policy_auth_session)
598+
/// # .expect("Failed to convert auth session into policy session");
599+
/// #
600+
/// # context
601+
/// # .policy_auth_value(policy_session)
602+
/// # .expect("Policy auth value");
603+
/// #
604+
/// # context
605+
/// # .policy_command_code(policy_session, TPM2_CC_Duplicate)
606+
/// # .unwrap();
607+
/// #
608+
/// # context.set_sessions((Some(policy_auth_session), None, None));
609+
/// #
610+
/// # let (encryption_key_out, duplicate, out_sym_seed) = context
611+
/// # .duplicate(
612+
/// # object_to_duplicate_handle,
613+
/// # new_parent_handle,
614+
/// # None,
615+
/// # SymmetricDefinitionObject::Null,
616+
/// # )
617+
/// # .unwrap();
618+
/// # eprintln!("D: {:?}, P: {:?}, S: {:?}", encryption_key_out, duplicate, out_sym_seed);
619+
/// # let public = context.read_public(object_to_duplicate_handle.into()).unwrap().0;
620+
/// #
621+
/// # let session = context
622+
/// # .start_auth_session(
623+
/// # None,
624+
/// # None,
625+
/// # None,
626+
/// # SessionType::Hmac,
627+
/// # SymmetricDefinition::AES_256_CFB,
628+
/// # HashingAlgorithm::Sha256,
629+
/// # )
630+
/// # .unwrap();
631+
/// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
632+
/// # .with_decrypt(true)
633+
/// # .with_encrypt(true)
634+
/// # .build();
635+
/// # context.tr_sess_set_attributes(
636+
/// # session.unwrap(),
637+
/// # session_attributes,
638+
/// # session_attributes_mask,
639+
/// # )
640+
/// # .unwrap();
641+
/// # context.set_sessions((session, None, None));
642+
///
643+
/// // `encryption_key_out`, `duplicate` and `out_sym_seed` are generated
644+
/// // by `duplicate` function
645+
/// let private = context.import(
646+
/// new_parent_handle,
647+
/// Some(encryption_key_out),
648+
/// public,
649+
/// duplicate,
650+
/// out_sym_seed,
651+
/// SymmetricDefinitionObject::Null,
652+
/// ).unwrap();
653+
/// #
654+
/// # eprintln!("P: {:?}", private);
655+
/// ```
656+
pub fn import(
657+
&mut self,
658+
parent_handle: ObjectHandle,
659+
encryption_key: Option<Data>,
660+
public: Public,
661+
duplicate: Private,
662+
encrypted_secret: EncryptedSecret,
663+
symmetric_alg: SymmetricDefinitionObject,
664+
) -> Result<Private> {
665+
let mut out_private = null_mut();
666+
let ret = unsafe {
667+
Esys_Import(
668+
self.mut_context(),
669+
parent_handle.into(),
670+
self.required_session_1()?,
671+
self.optional_session_2(),
672+
self.optional_session_3(),
673+
&encryption_key.unwrap_or_default().into(),
674+
&public.into(),
675+
&duplicate.into(),
676+
&encrypted_secret.into(),
677+
&symmetric_alg.into(),
678+
&mut out_private,
679+
)
680+
};
681+
let ret = Error::from_tss_rc(ret);
682+
683+
if ret.is_success() {
684+
Ok(unsafe { Private::try_from(*out_private)? })
685+
} else {
686+
error!("Error when performing import: {}", ret);
687+
Err(ret)
688+
}
689+
}
335690
}

0 commit comments

Comments
 (0)