Skip to main content

tss_esapi/context/tpm_commands/
duplication_commands.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::Context;
4use crate::{
5    handles::ObjectHandle,
6    structures::{Data, EncryptedSecret, Private, Public, SymmetricDefinitionObject},
7    tss2_esys::{Esys_Duplicate, Esys_Import},
8    Result, ReturnCode,
9};
10use log::error;
11
12use std::convert::{TryFrom, TryInto};
13use std::ptr::null_mut;
14
15impl Context {
16    /// Duplicate a loaded object so that it may be used in a different hierarchy.
17    ///
18    /// # Details
19    /// This command duplicates a loaded object so that it may be used in a different hierarchy.
20    /// The new parent key for the duplicate may be on the same or different TPM or the Null hierarchy.
21    /// Only the public area of `new_parent_handle` is required to be loaded.
22    ///
23    /// # Arguments
24    /// * `object_to_duplicate` - An [ObjectHandle] of the object that will be duplicated.
25    /// * `new_parent_handle` - An [ObjectHandle] of the new parent.
26    /// * `encryption_key_in` - An optional encryption key. If this parameter is `None`
27    ///   then a [default value][Default::default] is used.
28    /// * `symmetric_alg` - Symmetric algorithm to be used for the inner wrapper.
29    ///
30    /// The `object_to_duplicate` need to be have Fixed TPM and Fixed Parent attributes set to `false`.
31    ///
32    /// # Returns
33    /// The command returns a tuple consisting of:
34    /// * `encryption_key_out` - TPM generated, symmetric encryption key for the inner wrapper if
35    ///   `symmetric_alg` is not `Null`.
36    /// * `duplicate` - Private area that may be encrypted.
37    /// * `out_sym_seed` - Seed protected by the asymmetric algorithms of new parent.
38    ///
39    /// # Example
40    ///
41    /// ```rust
42    /// # use std::convert::{TryFrom, TryInto};
43    /// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder};
44    /// # use tss_esapi::constants::{CommandCode, SessionType};
45    /// # use tss_esapi::handles::ObjectHandle;
46    /// # use tss_esapi::interface_types::{
47    /// #     algorithm::{HashingAlgorithm, PublicAlgorithm},
48    /// #     key_bits::RsaKeyBits,
49    /// #     reserved_handles::Hierarchy,
50    /// #     session_handles::PolicySession,
51    /// # };
52    /// # use tss_esapi::structures::SymmetricDefinition;
53    /// # use tss_esapi::structures::{
54    /// #     PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme,
55    /// #     RsaExponent,
56    /// # };
57    /// use tss_esapi::structures::SymmetricDefinitionObject;
58    /// # use tss_esapi::abstraction::cipher::Cipher;
59    /// # use tss_esapi::{Context, TctiNameConf};
60    /// #
61    /// # let mut context = // ...
62    /// #     Context::new(
63    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
64    /// #     ).expect("Failed to create Context");
65    /// #
66    /// # let trial_session = context
67    /// #     .start_auth_session(
68    /// #         None,
69    /// #         None,
70    /// #         None,
71    /// #         SessionType::Trial,
72    /// #         SymmetricDefinition::AES_256_CFB,
73    /// #         HashingAlgorithm::Sha256,
74    /// #     )
75    /// #     .expect("Start auth session failed")
76    /// #     .expect("Start auth session returned a NONE handle");
77    /// #
78    /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) =
79    /// #     SessionAttributesBuilder::new()
80    /// #         .with_decrypt(true)
81    /// #         .with_encrypt(true)
82    /// #         .build();
83    /// # context
84    /// #     .tr_sess_set_attributes(
85    /// #         trial_session,
86    /// #         policy_auth_session_attributes,
87    /// #         policy_auth_session_attributes_mask,
88    /// #     )
89    /// #     .expect("tr_sess_set_attributes call failed");
90    /// #
91    /// # let policy_session = PolicySession::try_from(trial_session)
92    /// #     .expect("Failed to convert auth session into policy session");
93    /// #
94    /// # context
95    /// #     .policy_auth_value(policy_session)
96    /// #     .expect("Policy auth value");
97    /// #
98    /// # context
99    /// #     .policy_command_code(policy_session, CommandCode::Duplicate)
100    /// #     .expect("Policy command code");
101    /// #
102    /// # /// Digest of the policy that allows duplication
103    /// # let digest = context
104    /// #     .policy_get_digest(policy_session)
105    /// #     .expect("Could retrieve digest");
106    /// #
107    /// # drop(context);
108    /// # let mut context = // ...
109    /// #     Context::new(
110    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
111    /// #     ).expect("Failed to create Context");
112    /// #
113    /// # let session = context
114    /// #     .start_auth_session(
115    /// #         None,
116    /// #         None,
117    /// #         None,
118    /// #         SessionType::Hmac,
119    /// #         SymmetricDefinition::AES_256_CFB,
120    /// #         HashingAlgorithm::Sha256,
121    /// #     )
122    /// #     .expect("Start auth session failed")
123    /// #     .expect("Start auth session returned a NONE handle");
124    /// #
125    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
126    /// #     .with_decrypt(true)
127    /// #     .with_encrypt(true)
128    /// #     .build();
129    /// #
130    /// # context.tr_sess_set_attributes(
131    /// #     session,
132    /// #     session_attributes,
133    /// #     session_attributes_mask,
134    /// # ).unwrap();
135    /// #
136    /// # context.set_sessions((Some(session), None, None));
137    /// #
138    /// # // Attributes of parent objects. The `restricted` attribute need
139    /// # // to be `true` so that parents can act as storage keys.
140    /// # let parent_object_attributes = ObjectAttributesBuilder::new()
141    /// #     .with_fixed_tpm(true)
142    /// #     .with_fixed_parent(true)
143    /// #     .with_sensitive_data_origin(true)
144    /// #     .with_user_with_auth(true)
145    /// #     .with_decrypt(true)
146    /// #     .with_sign_encrypt(false)
147    /// #     .with_restricted(true)
148    /// #     .build()
149    /// #     .unwrap();
150    /// #
151    /// # let parent_public = PublicBuilder::new()
152    /// #     .with_public_algorithm(PublicAlgorithm::Rsa)
153    /// #     .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
154    /// #     .with_object_attributes(parent_object_attributes)
155    /// #     .with_rsa_parameters(
156    /// #         PublicRsaParametersBuilder::new_restricted_decryption_key(
157    /// #             Cipher::aes_256_cfb().try_into().unwrap(),
158    /// #             RsaKeyBits::Rsa2048,
159    /// #             RsaExponent::default(),
160    /// #         )
161    /// #         .build()
162    /// #         .unwrap(),
163    /// #     )
164    /// #     .with_rsa_unique_identifier(PublicKeyRsa::default())
165    /// #     .build()
166    /// #     .unwrap();
167    /// #
168    /// # let parent_of_object_to_duplicate_handle = context
169    /// #     .create_primary(
170    /// #         Hierarchy::Owner,
171    /// #         parent_public.clone(),
172    /// #         None,
173    /// #         None,
174    /// #         None,
175    /// #         None,
176    /// #     )
177    /// #     .unwrap()
178    /// #     .key_handle;
179    /// #
180    /// # // Fixed TPM and Fixed Parent should be "false" for an object
181    /// # // to be eligible for duplication
182    /// # let object_attributes = ObjectAttributesBuilder::new()
183    /// #     .with_fixed_tpm(false)
184    /// #     .with_fixed_parent(false)
185    /// #     .with_sensitive_data_origin(true)
186    /// #     .with_user_with_auth(true)
187    /// #     .with_decrypt(true)
188    /// #     .with_sign_encrypt(true)
189    /// #     .with_restricted(false)
190    /// #     .build()
191    /// #     .expect("Attributes to be valid");
192    /// #
193    /// # let public_child = PublicBuilder::new()
194    /// #     .with_public_algorithm(PublicAlgorithm::Rsa)
195    /// #     .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
196    /// #     .with_object_attributes(object_attributes)
197    /// #     .with_auth_policy(digest)
198    /// #     .with_rsa_parameters(
199    /// #         PublicRsaParametersBuilder::new()
200    /// #             .with_scheme(RsaScheme::Null)
201    /// #             .with_key_bits(RsaKeyBits::Rsa2048)
202    /// #             .with_is_signing_key(true)
203    /// #             .with_is_decryption_key(true)
204    /// #             .with_restricted(false)
205    /// #             .build()
206    /// #             .expect("Params to be valid"),
207    /// #     )
208    /// #     .with_rsa_unique_identifier(PublicKeyRsa::default())
209    /// #     .build()
210    /// #     .expect("public to be valid");
211    /// #
212    /// # let result = context
213    /// #     .create(
214    /// #         parent_of_object_to_duplicate_handle,
215    /// #         public_child,
216    /// #         None,
217    /// #         None,
218    /// #         None,
219    /// #         None,
220    /// #     )
221    /// #     .unwrap();
222    /// #
223    /// # let object_to_duplicate_handle: ObjectHandle = context
224    /// #     .load(
225    /// #         parent_of_object_to_duplicate_handle,
226    /// #         result.out_private.clone(),
227    /// #         result.out_public,
228    /// #     )
229    /// #     .unwrap()
230    /// #     .into();
231    /// #
232    /// # let new_parent_handle: ObjectHandle = context
233    /// #     .create_primary(
234    /// #         Hierarchy::Owner,
235    /// #         parent_public,
236    /// #         None,
237    /// #         None,
238    /// #         None,
239    /// #         None,
240    /// #     )
241    /// #     .unwrap()
242    /// #     .key_handle
243    /// #     .into();
244    /// #
245    /// # context.set_sessions((None, None, None));
246    /// #
247    /// # // Create a Policy session with the same exact attributes
248    /// # // as the trial session so that the session digest stays
249    /// # // the same.
250    /// # let policy_auth_session = context
251    /// #     .start_auth_session(
252    /// #         None,
253    /// #         None,
254    /// #         None,
255    /// #         SessionType::Policy,
256    /// #         SymmetricDefinition::AES_256_CFB,
257    /// #         HashingAlgorithm::Sha256,
258    /// #     )
259    /// #     .expect("Start auth session failed")
260    /// #     .expect("Start auth session returned a NONE handle");
261    /// #
262    /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) =
263    /// #     SessionAttributesBuilder::new()
264    /// #         .with_decrypt(true)
265    /// #         .with_encrypt(true)
266    /// #         .build();
267    /// # context
268    /// #     .tr_sess_set_attributes(
269    /// #         policy_auth_session,
270    /// #         policy_auth_session_attributes,
271    /// #         policy_auth_session_attributes_mask,
272    /// #     )
273    /// #     .expect("tr_sess_set_attributes call failed");
274    /// #
275    /// # let policy_session = PolicySession::try_from(policy_auth_session)
276    /// #     .expect("Failed to convert auth session into policy session");
277    /// #
278    /// # context
279    /// #     .policy_auth_value(policy_session)
280    /// #     .expect("Policy auth value");
281    /// #
282    /// # context
283    /// #     .policy_command_code(policy_session, CommandCode::Duplicate)
284    /// #     .unwrap();
285    /// #
286    /// # context.set_sessions((Some(policy_auth_session), None, None));
287    ///
288    /// let (encryption_key_out, duplicate, out_sym_seed) = context
289    ///     .duplicate(
290    ///         object_to_duplicate_handle,
291    ///         new_parent_handle,
292    ///         None,
293    ///         SymmetricDefinitionObject::Null,
294    ///     )
295    ///     .unwrap();
296    /// # eprintln!("D: {:?}, P: {:?}, S: {:?}", encryption_key_out, duplicate, out_sym_seed);
297    /// ```
298    pub fn duplicate(
299        &mut self,
300        object_to_duplicate: ObjectHandle,
301        new_parent_handle: ObjectHandle,
302        encryption_key_in: Option<Data>,
303        symmetric_alg: SymmetricDefinitionObject,
304    ) -> Result<(Data, Private, EncryptedSecret)> {
305        let mut encryption_key_out_ptr = null_mut();
306        let mut duplicate_ptr = null_mut();
307        let mut out_sym_seed_ptr = null_mut();
308        ReturnCode::ensure_success(
309            unsafe {
310                Esys_Duplicate(
311                    self.mut_context(),
312                    object_to_duplicate.into(),
313                    new_parent_handle.into(),
314                    self.required_session_1()?,
315                    self.optional_session_2(),
316                    self.optional_session_3(),
317                    &encryption_key_in.unwrap_or_default().into(),
318                    &symmetric_alg.into(),
319                    &mut encryption_key_out_ptr,
320                    &mut duplicate_ptr,
321                    &mut out_sym_seed_ptr,
322                )
323            },
324            |ret| {
325                error!("Error when performing duplication: {:#010X}", ret);
326            },
327        )?;
328
329        Ok((
330            Data::try_from(Context::ffi_data_to_owned(encryption_key_out_ptr)?)?,
331            Private::try_from(Context::ffi_data_to_owned(duplicate_ptr)?)?,
332            EncryptedSecret::try_from(Context::ffi_data_to_owned(out_sym_seed_ptr)?)?,
333        ))
334    }
335
336    // Missing function: Rewrap
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::{CommandCode, SessionType};
367    /// # use tss_esapi::handles::ObjectHandle;
368    /// # use tss_esapi::interface_types::{
369    /// #     algorithm::{HashingAlgorithm, PublicAlgorithm},
370    /// #     key_bits::RsaKeyBits,
371    /// #     reserved_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, CommandCode::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.clone(),
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 eligible 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, CommandCode::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_ptr = null_mut();
666        ReturnCode::ensure_success(
667            unsafe {
668                Esys_Import(
669                    self.mut_context(),
670                    parent_handle.into(),
671                    self.required_session_1()?,
672                    self.optional_session_2(),
673                    self.optional_session_3(),
674                    &encryption_key.unwrap_or_default().into(),
675                    &public.try_into()?,
676                    &duplicate.into(),
677                    &encrypted_secret.into(),
678                    &symmetric_alg.into(),
679                    &mut out_private_ptr,
680                )
681            },
682            |ret| {
683                error!("Error when performing import: {:#010X}", ret);
684            },
685        )?;
686        Private::try_from(Context::ffi_data_to_owned(out_private_ptr)?)
687    }
688}