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 Result, ReturnCode,
6 handles::ObjectHandle,
7 structures::{Data, EncryptedSecret, Name, Private, Public, SymmetricDefinitionObject},
8 tss2_esys::{Esys_Duplicate, Esys_Import, Esys_Rewrap},
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 /// Re-wrap an already duplicated object for a new parent.
337 ///
338 /// # Arguments
339 ///
340 /// * `old_parent` - An [ObjectHandle] of the parent that protects `in_duplicate`.
341 /// * `new_parent` - An [ObjectHandle] of the parent that will protect the result.
342 /// * `in_duplicate` - The [Private] area encrypted using a key derived from `in_sym_seed`.
343 /// * `name` - The [Name] of the object being re-wrapped.
344 /// * `in_sym_seed` - The [EncryptedSecret] seed protected by `old_parent`.
345 ///
346 /// # Details
347 ///
348 /// *From the specification*
349 /// > This command allows the TPM to serve in the role as a Duplication Authority.
350 ///
351 /// # Returns
352 ///
353 /// A tuple containing the re-wrapped [Private] area and the [EncryptedSecret]
354 /// seed protected by `new_parent`.
355 ///
356 /// # Example
357 ///
358 /// ```rust
359 /// # use std::convert::{TryFrom, TryInto};
360 /// # use tss_esapi::{Context, TctiNameConf};
361 /// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder};
362 /// # use tss_esapi::constants::SessionType;
363 /// # use tss_esapi::handles::{ObjectHandle, SessionHandle};
364 /// # use tss_esapi::interface_types::{
365 /// # algorithm::{HashingAlgorithm, PublicAlgorithm},
366 /// # ecc::EccCurve,
367 /// # key_bits::RsaKeyBits,
368 /// # reserved_handles::Hierarchy,
369 /// # session_handles::PolicySession,
370 /// # };
371 /// # use tss_esapi::structures::{
372 /// # EccPoint, EccScheme, KeyDerivationFunctionScheme, PublicBuilder,
373 /// # PublicEccParametersBuilder, RsaExponent, SymmetricDefinition,
374 /// # SymmetricDefinitionObject,
375 /// # };
376 /// # use tss_esapi::utils::create_restricted_decryption_rsa_public;
377 /// # let mut context = Context::new(
378 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
379 /// # )
380 /// # .expect("Failed to create Context");
381 /// # let old_parent_public = create_restricted_decryption_rsa_public(
382 /// # SymmetricDefinitionObject::AES_128_CFB,
383 /// # RsaKeyBits::Rsa2048,
384 /// # RsaExponent::default(),
385 /// # )
386 /// # .expect("Failed to create old parent public area");
387 /// # let new_parent_public = create_restricted_decryption_rsa_public(
388 /// # SymmetricDefinitionObject::AES_256_CFB,
389 /// # RsaKeyBits::Rsa2048,
390 /// # RsaExponent::default(),
391 /// # )
392 /// # .expect("Failed to create new parent public area");
393 /// # let old_parent = context
394 /// # .execute_with_nullauth_session(|ctx| {
395 /// # ctx.create_primary(
396 /// # Hierarchy::Owner,
397 /// # old_parent_public,
398 /// # None,
399 /// # None,
400 /// # None,
401 /// # None,
402 /// # )
403 /// # })
404 /// # .expect("Failed to create old parent")
405 /// # .key_handle;
406 /// # let new_parent = context
407 /// # .execute_with_nullauth_session(|ctx| {
408 /// # ctx.create_primary(
409 /// # Hierarchy::Owner,
410 /// # new_parent_public,
411 /// # None,
412 /// # None,
413 /// # None,
414 /// # None,
415 /// # )
416 /// # })
417 /// # .expect("Failed to create new parent")
418 /// # .key_handle;
419 /// # let old_parent_name = context
420 /// # .read_public(old_parent)
421 /// # .expect("Failed to read old parent")
422 /// # .1;
423 /// # let trial_session = context
424 /// # .start_auth_session(
425 /// # None,
426 /// # None,
427 /// # None,
428 /// # SessionType::Trial,
429 /// # SymmetricDefinition::AES_256_CFB,
430 /// # HashingAlgorithm::Sha256,
431 /// # )
432 /// # .expect("Failed to create trial session")
433 /// # .expect("Received invalid handle");
434 /// # let trial_policy =
435 /// # PolicySession::try_from(trial_session).expect("Failed to convert trial session");
436 /// # context
437 /// # .policy_duplication_select(
438 /// # trial_policy,
439 /// # Vec::<u8>::new().try_into().expect("Failed to create empty Name"),
440 /// # old_parent_name.clone(),
441 /// # false,
442 /// # )
443 /// # .expect("Failed to compute duplication policy");
444 /// # let policy_digest = context
445 /// # .policy_get_digest(trial_policy)
446 /// # .expect("Failed to get policy digest");
447 /// # context
448 /// # .flush_context(SessionHandle::from(trial_session).into())
449 /// # .expect("Failed to flush trial session");
450 /// # let child_attributes = ObjectAttributesBuilder::new()
451 /// # .with_fixed_tpm(false)
452 /// # .with_fixed_parent(false)
453 /// # .with_sensitive_data_origin(true)
454 /// # .with_user_with_auth(true)
455 /// # .with_decrypt(true)
456 /// # .with_sign_encrypt(true)
457 /// # .with_restricted(false)
458 /// # .build()
459 /// # .expect("Failed to create child attributes");
460 /// # let child_public = PublicBuilder::new()
461 /// # .with_public_algorithm(PublicAlgorithm::Ecc)
462 /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
463 /// # .with_object_attributes(child_attributes)
464 /// # .with_auth_policy(policy_digest)
465 /// # .with_ecc_parameters(
466 /// # PublicEccParametersBuilder::new()
467 /// # .with_ecc_scheme(EccScheme::Null)
468 /// # .with_curve(EccCurve::NistP256)
469 /// # .with_is_signing_key(false)
470 /// # .with_is_decryption_key(true)
471 /// # .with_restricted(false)
472 /// # .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
473 /// # .build()
474 /// # .expect("Failed to create child parameters"),
475 /// # )
476 /// # .with_ecc_unique_identifier(EccPoint::default())
477 /// # .build()
478 /// # .expect("Failed to create child public area");
479 /// # let create_result = context
480 /// # .execute_with_nullauth_session(|ctx| {
481 /// # ctx.create(new_parent, child_public, None, None, None, None)
482 /// # })
483 /// # .expect("Failed to create child object");
484 /// # let child_public = create_result.out_public.clone();
485 /// # let child = context
486 /// # .execute_with_nullauth_session(|ctx| {
487 /// # ctx.load(new_parent, create_result.out_private, create_result.out_public)
488 /// # })
489 /// # .expect("Failed to load child object");
490 /// # let child_name = context
491 /// # .read_public(child)
492 /// # .expect("Failed to read child object")
493 /// # .1;
494 /// # let policy_session = context
495 /// # .start_auth_session(
496 /// # None,
497 /// # None,
498 /// # None,
499 /// # SessionType::Policy,
500 /// # SymmetricDefinition::AES_256_CFB,
501 /// # HashingAlgorithm::Sha256,
502 /// # )
503 /// # .expect("Failed to create policy session")
504 /// # .expect("Received invalid handle");
505 /// # let (attributes, mask) = SessionAttributesBuilder::new()
506 /// # .with_decrypt(true)
507 /// # .with_encrypt(true)
508 /// # .build();
509 /// # context
510 /// # .tr_sess_set_attributes(policy_session, attributes, mask)
511 /// # .expect("Failed to set policy session attributes");
512 /// # let policy =
513 /// # PolicySession::try_from(policy_session).expect("Failed to convert policy session");
514 /// # context
515 /// # .policy_duplication_select(policy, child_name.clone(), old_parent_name, false)
516 /// # .expect("Failed to satisfy duplication policy");
517 /// # context.set_sessions((Some(policy_session), None, None));
518 /// # let (encryption_key, duplicate, in_sym_seed) = context
519 /// # .duplicate(
520 /// # child.into(),
521 /// # old_parent.into(),
522 /// # None,
523 /// # SymmetricDefinitionObject::Null,
524 /// # )
525 /// # .expect("Failed to duplicate child object");
526 /// # context.clear_sessions();
527 /// # context
528 /// # .flush_context(SessionHandle::from(policy_session).into())
529 /// # .expect("Failed to flush policy session");
530 /// let (out_duplicate, out_sym_seed) = context
531 /// .execute_with_nullauth_session(|ctx| {
532 /// ctx.rewrap(
533 /// old_parent.into(),
534 /// new_parent.into(),
535 /// duplicate,
536 /// child_name,
537 /// in_sym_seed,
538 /// )
539 /// })
540 /// .expect("Failed to re-wrap duplicated object");
541 /// # context
542 /// # .flush_context(child.into())
543 /// # .expect("Failed to flush child");
544 /// # let imported_private = context
545 /// # .execute_with_nullauth_session(|ctx| {
546 /// # ctx.import(
547 /// # new_parent.into(),
548 /// # Some(encryption_key),
549 /// # child_public.clone(),
550 /// # out_duplicate,
551 /// # out_sym_seed,
552 /// # SymmetricDefinitionObject::Null,
553 /// # )
554 /// # })
555 /// # .expect("Failed to import re-wrapped object");
556 /// # let imported_child = context
557 /// # .execute_with_nullauth_session(|ctx| {
558 /// # ctx.load(new_parent, imported_private, child_public)
559 /// # })
560 /// # .expect("Failed to load imported object");
561 /// # context
562 /// # .flush_context(imported_child.into())
563 /// # .expect("Failed to flush imported child");
564 /// # context
565 /// # .flush_context(old_parent.into())
566 /// # .expect("Failed to flush old parent");
567 /// # context
568 /// # .flush_context(new_parent.into())
569 /// # .expect("Failed to flush new parent");
570 /// ```
571 pub fn rewrap(
572 &mut self,
573 old_parent: ObjectHandle,
574 new_parent: ObjectHandle,
575 in_duplicate: Private,
576 name: Name,
577 in_sym_seed: EncryptedSecret,
578 ) -> Result<(Private, EncryptedSecret)> {
579 let mut out_duplicate_ptr = null_mut();
580 let mut out_sym_seed_ptr = null_mut();
581 ReturnCode::ensure_success(
582 unsafe {
583 Esys_Rewrap(
584 self.mut_context(),
585 old_parent.into(),
586 new_parent.into(),
587 self.required_session_1()?,
588 self.optional_session_2(),
589 self.optional_session_3(),
590 &in_duplicate.into(),
591 &name.into(),
592 &in_sym_seed.into(),
593 &mut out_duplicate_ptr,
594 &mut out_sym_seed_ptr,
595 )
596 },
597 |ret| {
598 error!("Error when performing rewrap: {:#010X}", ret);
599 },
600 )?;
601
602 Ok((
603 Private::try_from(Context::ffi_data_to_owned(out_duplicate_ptr)?)?,
604 EncryptedSecret::try_from(Context::ffi_data_to_owned(out_sym_seed_ptr)?)?,
605 ))
606 }
607
608 /// Import attaches imported object to a new parent.
609 ///
610 /// # Details
611 /// This command allows an object to be encrypted using the symmetric
612 /// encryption values of a Storage Key. After encryption, the
613 /// object may be loaded and used in the new hierarchy. The
614 /// imported object (duplicate) may be singly encrypted, multiply
615 /// encrypted, or unencrypted.
616 ///
617 /// # Arguments
618 /// * `parent_handle` - An [ObjectHandle] of the new parent for the object.
619 /// * `encryption_key` - An optional symmetric encryption key used as the inner wrapper.
620 /// If `encryption_key` is `None` then a [default value][Default::default] is used.
621 /// * `public` - A [Public] of the imported object.
622 /// * `duplicate` - A symmetrically encrypted duplicated object.
623 /// * `encrypted_secret` - The seed for the symmetric key and HMAC key.
624 /// * `symmetric_alg` - Symmetric algorithm to be used for the inner wrapper.
625 ///
626 /// The `public` is needed to check the integrity value for `duplicate`.
627 ///
628 /// # Returns
629 /// The command returns the sensitive area encrypted with the symmetric key of `parent_handle`.
630 ///
631 /// # Example
632 ///
633 /// ```rust
634 /// # use std::convert::{TryFrom, TryInto};
635 /// # use tss_esapi::attributes::{ObjectAttributesBuilder, SessionAttributesBuilder};
636 /// # use tss_esapi::constants::{CommandCode, SessionType};
637 /// # use tss_esapi::handles::ObjectHandle;
638 /// # use tss_esapi::interface_types::{
639 /// # algorithm::{HashingAlgorithm, PublicAlgorithm},
640 /// # key_bits::RsaKeyBits,
641 /// # reserved_handles::Hierarchy,
642 /// # session_handles::PolicySession,
643 /// # };
644 /// # use tss_esapi::structures::SymmetricDefinition;
645 /// # use tss_esapi::structures::{
646 /// # PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme,
647 /// # RsaExponent,
648 /// # };
649 /// use tss_esapi::structures::SymmetricDefinitionObject;
650 /// # use tss_esapi::abstraction::cipher::Cipher;
651 /// # use tss_esapi::{Context, TctiNameConf};
652 /// #
653 /// # let mut context = // ...
654 /// # Context::new(
655 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
656 /// # ).expect("Failed to create Context");
657 /// #
658 /// # let trial_session = context
659 /// # .start_auth_session(
660 /// # None,
661 /// # None,
662 /// # None,
663 /// # SessionType::Trial,
664 /// # SymmetricDefinition::AES_256_CFB,
665 /// # HashingAlgorithm::Sha256,
666 /// # )
667 /// # .expect("Start auth session failed")
668 /// # .expect("Start auth session returned a NONE handle");
669 /// #
670 /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) =
671 /// # SessionAttributesBuilder::new()
672 /// # .with_decrypt(true)
673 /// # .with_encrypt(true)
674 /// # .build();
675 /// # context
676 /// # .tr_sess_set_attributes(
677 /// # trial_session,
678 /// # policy_auth_session_attributes,
679 /// # policy_auth_session_attributes_mask,
680 /// # )
681 /// # .expect("tr_sess_set_attributes call failed");
682 /// #
683 /// # let policy_session = PolicySession::try_from(trial_session)
684 /// # .expect("Failed to convert auth session into policy session");
685 /// #
686 /// # context
687 /// # .policy_auth_value(policy_session)
688 /// # .expect("Policy auth value");
689 /// #
690 /// # context
691 /// # .policy_command_code(policy_session, CommandCode::Duplicate)
692 /// # .expect("Policy command code");
693 /// #
694 /// # /// Digest of the policy that allows duplication
695 /// # let digest = context
696 /// # .policy_get_digest(policy_session)
697 /// # .expect("Could retrieve digest");
698 /// #
699 /// # drop(context);
700 /// # let mut context = // ...
701 /// # Context::new(
702 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
703 /// # ).expect("Failed to create Context");
704 /// #
705 /// # let session = context
706 /// # .start_auth_session(
707 /// # None,
708 /// # None,
709 /// # None,
710 /// # SessionType::Hmac,
711 /// # SymmetricDefinition::AES_256_CFB,
712 /// # HashingAlgorithm::Sha256,
713 /// # )
714 /// # .expect("Start auth session failed")
715 /// # .expect("Start auth session returned a NONE handle");
716 /// #
717 /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
718 /// # .with_decrypt(true)
719 /// # .with_encrypt(true)
720 /// # .build();
721 /// #
722 /// # context.tr_sess_set_attributes(
723 /// # session,
724 /// # session_attributes,
725 /// # session_attributes_mask,
726 /// # ).unwrap();
727 /// #
728 /// # context.set_sessions((Some(session), None, None));
729 /// #
730 /// # // Attributes of parent objects. The `restricted` attribute need
731 /// # // to be `true` so that parents can act as storage keys.
732 /// # let parent_object_attributes = ObjectAttributesBuilder::new()
733 /// # .with_fixed_tpm(true)
734 /// # .with_fixed_parent(true)
735 /// # .with_sensitive_data_origin(true)
736 /// # .with_user_with_auth(true)
737 /// # .with_decrypt(true)
738 /// # .with_sign_encrypt(false)
739 /// # .with_restricted(true)
740 /// # .build()
741 /// # .unwrap();
742 /// #
743 /// # let parent_public = PublicBuilder::new()
744 /// # .with_public_algorithm(PublicAlgorithm::Rsa)
745 /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
746 /// # .with_object_attributes(parent_object_attributes)
747 /// # .with_rsa_parameters(
748 /// # PublicRsaParametersBuilder::new_restricted_decryption_key(
749 /// # Cipher::aes_256_cfb().try_into().unwrap(),
750 /// # RsaKeyBits::Rsa2048,
751 /// # RsaExponent::default(),
752 /// # )
753 /// # .build()
754 /// # .unwrap(),
755 /// # )
756 /// # .with_rsa_unique_identifier(PublicKeyRsa::default())
757 /// # .build()
758 /// # .unwrap();
759 /// #
760 /// # let parent_of_object_to_duplicate_handle = context
761 /// # .create_primary(
762 /// # Hierarchy::Owner,
763 /// # parent_public.clone(),
764 /// # None,
765 /// # None,
766 /// # None,
767 /// # None,
768 /// # )
769 /// # .unwrap()
770 /// # .key_handle;
771 /// #
772 /// # // Fixed TPM and Fixed Parent should be "false" for an object
773 /// # // to be eligible for duplication
774 /// # let object_attributes = ObjectAttributesBuilder::new()
775 /// # .with_fixed_tpm(false)
776 /// # .with_fixed_parent(false)
777 /// # .with_sensitive_data_origin(true)
778 /// # .with_user_with_auth(true)
779 /// # .with_decrypt(true)
780 /// # .with_sign_encrypt(true)
781 /// # .with_restricted(false)
782 /// # .build()
783 /// # .expect("Attributes to be valid");
784 /// #
785 /// # let public_child = PublicBuilder::new()
786 /// # .with_public_algorithm(PublicAlgorithm::Rsa)
787 /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
788 /// # .with_object_attributes(object_attributes)
789 /// # .with_auth_policy(digest)
790 /// # .with_rsa_parameters(
791 /// # PublicRsaParametersBuilder::new()
792 /// # .with_scheme(RsaScheme::Null)
793 /// # .with_key_bits(RsaKeyBits::Rsa2048)
794 /// # .with_is_signing_key(true)
795 /// # .with_is_decryption_key(true)
796 /// # .with_restricted(false)
797 /// # .build()
798 /// # .expect("Params to be valid"),
799 /// # )
800 /// # .with_rsa_unique_identifier(PublicKeyRsa::default())
801 /// # .build()
802 /// # .expect("public to be valid");
803 /// #
804 /// # let result = context
805 /// # .create(
806 /// # parent_of_object_to_duplicate_handle,
807 /// # public_child,
808 /// # None,
809 /// # None,
810 /// # None,
811 /// # None,
812 /// # )
813 /// # .unwrap();
814 /// #
815 /// # let object_to_duplicate_handle: ObjectHandle = context
816 /// # .load(
817 /// # parent_of_object_to_duplicate_handle,
818 /// # result.out_private.clone(),
819 /// # result.out_public,
820 /// # )
821 /// # .unwrap()
822 /// # .into();
823 /// #
824 /// # let new_parent_handle: ObjectHandle = context
825 /// # .create_primary(
826 /// # Hierarchy::Owner,
827 /// # parent_public,
828 /// # None,
829 /// # None,
830 /// # None,
831 /// # None,
832 /// # )
833 /// # .unwrap()
834 /// # .key_handle
835 /// # .into();
836 /// #
837 /// # context.set_sessions((None, None, None));
838 /// #
839 /// # // Create a Policy session with the same exact attributes
840 /// # // as the trial session so that the session digest stays
841 /// # // the same.
842 /// # let policy_auth_session = context
843 /// # .start_auth_session(
844 /// # None,
845 /// # None,
846 /// # None,
847 /// # SessionType::Policy,
848 /// # SymmetricDefinition::AES_256_CFB,
849 /// # HashingAlgorithm::Sha256,
850 /// # )
851 /// # .expect("Start auth session failed")
852 /// # .expect("Start auth session returned a NONE handle");
853 /// #
854 /// # let (policy_auth_session_attributes, policy_auth_session_attributes_mask) =
855 /// # SessionAttributesBuilder::new()
856 /// # .with_decrypt(true)
857 /// # .with_encrypt(true)
858 /// # .build();
859 /// # context
860 /// # .tr_sess_set_attributes(
861 /// # policy_auth_session,
862 /// # policy_auth_session_attributes,
863 /// # policy_auth_session_attributes_mask,
864 /// # )
865 /// # .expect("tr_sess_set_attributes call failed");
866 /// #
867 /// # let policy_session = PolicySession::try_from(policy_auth_session)
868 /// # .expect("Failed to convert auth session into policy session");
869 /// #
870 /// # context
871 /// # .policy_auth_value(policy_session)
872 /// # .expect("Policy auth value");
873 /// #
874 /// # context
875 /// # .policy_command_code(policy_session, CommandCode::Duplicate)
876 /// # .unwrap();
877 /// #
878 /// # context.set_sessions((Some(policy_auth_session), None, None));
879 /// #
880 /// # let (encryption_key_out, duplicate, out_sym_seed) = context
881 /// # .duplicate(
882 /// # object_to_duplicate_handle,
883 /// # new_parent_handle,
884 /// # None,
885 /// # SymmetricDefinitionObject::Null,
886 /// # )
887 /// # .unwrap();
888 /// # eprintln!("D: {:?}, P: {:?}, S: {:?}", encryption_key_out, duplicate, out_sym_seed);
889 /// # let public = context.read_public(object_to_duplicate_handle.into()).unwrap().0;
890 /// #
891 /// # let session = context
892 /// # .start_auth_session(
893 /// # None,
894 /// # None,
895 /// # None,
896 /// # SessionType::Hmac,
897 /// # SymmetricDefinition::AES_256_CFB,
898 /// # HashingAlgorithm::Sha256,
899 /// # )
900 /// # .unwrap();
901 /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
902 /// # .with_decrypt(true)
903 /// # .with_encrypt(true)
904 /// # .build();
905 /// # context.tr_sess_set_attributes(
906 /// # session.unwrap(),
907 /// # session_attributes,
908 /// # session_attributes_mask,
909 /// # )
910 /// # .unwrap();
911 /// # context.set_sessions((session, None, None));
912 ///
913 /// // `encryption_key_out`, `duplicate` and `out_sym_seed` are generated
914 /// // by `duplicate` function
915 /// let private = context.import(
916 /// new_parent_handle,
917 /// Some(encryption_key_out),
918 /// public,
919 /// duplicate,
920 /// out_sym_seed,
921 /// SymmetricDefinitionObject::Null,
922 /// ).unwrap();
923 /// #
924 /// # eprintln!("P: {:?}", private);
925 /// ```
926 pub fn import(
927 &mut self,
928 parent_handle: ObjectHandle,
929 encryption_key: Option<Data>,
930 public: Public,
931 duplicate: Private,
932 encrypted_secret: EncryptedSecret,
933 symmetric_alg: SymmetricDefinitionObject,
934 ) -> Result<Private> {
935 let mut out_private_ptr = null_mut();
936 ReturnCode::ensure_success(
937 unsafe {
938 Esys_Import(
939 self.mut_context(),
940 parent_handle.into(),
941 self.required_session_1()?,
942 self.optional_session_2(),
943 self.optional_session_3(),
944 &encryption_key.unwrap_or_default().into(),
945 &public.try_into()?,
946 &duplicate.into(),
947 &encrypted_secret.into(),
948 &symmetric_alg.into(),
949 &mut out_private_ptr,
950 )
951 },
952 |ret| {
953 error!("Error when performing import: {:#010X}", ret);
954 },
955 )?;
956 Private::try_from(Context::ffi_data_to_owned(out_private_ptr)?)
957 }
958}