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