// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 mod test_ctx_save { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::Auth}; #[test] fn test_ctx_save() { let mut context = create_ctx_with_session(); let mut random_digest = vec![0u8; 16]; getrandom::getrandom(&mut random_digest).unwrap(); let key_auth = Auth::try_from(random_digest).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; let _ = context.context_save(key_handle.into()).unwrap(); } #[test] fn test_ctx_save_leaf() { let mut context = create_ctx_with_session(); let mut random_digest = vec![0u8; 16]; getrandom::getrandom(&mut random_digest).unwrap(); let key_auth = Auth::try_from(random_digest).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(key_auth.clone()), None, None, None, ) .unwrap() .key_handle; let result = context .create( prim_key_handle, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap(); let key_handle = context .load(prim_key_handle, result.out_private, result.out_public) .unwrap(); context.flush_context(prim_key_handle.into()).unwrap(); let _ = context.context_save(key_handle.into()).unwrap(); } } mod test_ctx_load { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{ handles::KeyHandle, interface_types::resource_handles::Hierarchy, structures::Auth, }; #[test] fn test_ctx_load() { let mut context = create_ctx_with_session(); let mut random_digest = vec![0u8; 16]; getrandom::getrandom(&mut random_digest).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(Auth::try_from(random_digest.clone()).unwrap()), None, None, None, ) .unwrap() .key_handle; let result = context .create( prim_key_handle, signing_key_pub(), Some(Auth::try_from(random_digest).unwrap()), None, None, None, ) .unwrap(); let key_handle = context .load(prim_key_handle, result.out_private, result.out_public) .unwrap(); context.flush_context(prim_key_handle.into()).unwrap(); let key_ctx = context.context_save(key_handle.into()).unwrap(); let key_handle = context.context_load(key_ctx).map(KeyHandle::from).unwrap(); let _ = context.read_public(key_handle).unwrap(); } } mod test_flush_context { use crate::common::{create_ctx_with_session, decryption_key_pub, signing_key_pub}; use std::convert::TryFrom; use tss_esapi::{interface_types::resource_handles::Hierarchy, structures::Auth}; #[test] fn test_flush_ctx() { let mut context = create_ctx_with_session(); let mut random_digest = vec![0u8; 16]; getrandom::getrandom(&mut random_digest).unwrap(); let key_auth = Auth::try_from(random_digest).unwrap(); let key_handle = context .create_primary( Hierarchy::Owner, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap() .key_handle; context.flush_context(key_handle.into()).unwrap(); assert!(context.read_public(key_handle).is_err()); } #[test] fn test_flush_parent_ctx() { let mut context = create_ctx_with_session(); let mut random_digest = vec![0u8; 16]; getrandom::getrandom(&mut random_digest).unwrap(); let key_auth = Auth::try_from(random_digest).unwrap(); let prim_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(key_auth.clone()), None, None, None, ) .unwrap() .key_handle; let result = context .create( prim_key_handle, signing_key_pub(), Some(key_auth), None, None, None, ) .unwrap(); let key_handle = context .load(prim_key_handle, result.out_private, result.out_public) .unwrap(); context.flush_context(prim_key_handle.into()).unwrap(); let _ = context.read_public(key_handle).unwrap(); } } mod test_evict_control { use crate::common::{create_ctx_without_session, decryption_key_pub}; use std::convert::TryFrom; use tss_esapi::{ constants::{tss::TPM2_PERSISTENT_FIRST, CapabilityType}, handles::{ObjectHandle, PersistentTpmHandle, TpmHandle}, interface_types::{ dynamic_handles::Persistent, resource_handles::{Hierarchy, Provision}, session_handles::AuthSession, }, structures::{Auth, CapabilityData}, tss2_esys::TPM2_HANDLE, }; fn remove_persitent_handle(persistent_tpm_handle: PersistentTpmHandle) { let mut context = create_ctx_without_session(); let mut property = TPM2_PERSISTENT_FIRST; while let Ok((capability_data, more_data_available)) = context.get_capability(CapabilityType::Handles, property, 1) { if let CapabilityData::Handles(persistent_handles) = capability_data { if let Some(&retrieved_persistent_handle) = persistent_handles.first() { if retrieved_persistent_handle == persistent_tpm_handle.into() { let handle = context .tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) .expect("Failed to retrieve handle from TPM"); context .evict_control( Provision::Owner, handle, Persistent::Persistent(persistent_tpm_handle), ) .expect("Failed to evict persistent handle"); return; } if more_data_available { property = TPM2_HANDLE::from(retrieved_persistent_handle) + 1; } } } if !more_data_available { return; } } } #[test] fn test_basic_evict_control() { // Create persistent TPM handle with let persistent_tpm_handle = PersistentTpmHandle::new(u32::from_be_bytes([0x81, 0x00, 0x00, 0x01])) .expect("Failed to create persitent tpm handle"); // Create interface type Persistent by using the handle. let persistent = Persistent::Persistent(persistent_tpm_handle); // Make sure the handle is not already persistent remove_persitent_handle(persistent_tpm_handle); // Create context let mut context = create_ctx_without_session(); // Set Password session context.set_sessions((Some(AuthSession::Password), None, None)); // Create primary key handle let auth_value_primary = Auth::try_from(vec![1, 2, 3, 4, 5]) .expect("Failed to crate auth value for primary key"); let primary_key_handle = context .create_primary( Hierarchy::Owner, decryption_key_pub(), Some(auth_value_primary), None, None, None, ) .expect("Failed to create primary key") .key_handle; // Evict control to make primary_key_handle persistent let mut persistent_primary_key_handle = context .evict_control(Provision::Owner, primary_key_handle.into(), persistent) .expect("Failed to make the primary key handle persistent"); assert_ne!(persistent_primary_key_handle, ObjectHandle::Null); assert_ne!(persistent_primary_key_handle, ObjectHandle::None); // Flush out the primary_key_handle context .flush_context(ObjectHandle::from(primary_key_handle)) .expect("Failed to flush context"); // Close the persistent_handle returned by evict_control context .tr_close(&mut persistent_primary_key_handle) .expect("Failed to close persistent handle"); // Retrieve the handle from the tpm again. let retrieved_persistent_handle = context.execute_without_session(|ctx| { ctx.tr_from_tpm_public(TpmHandle::Persistent(persistent_tpm_handle)) .expect("Failed to load the persistent handle") }); // Evict the persitent handle from the tpm context .evict_control(Provision::Owner, retrieved_persistent_handle, persistent) .expect("Failed to evict persistent handle"); context.clear_sessions(); assert_ne!(retrieved_persistent_handle, ObjectHandle::None); } }