From a759dcbc6e066d598cd8cfc21ab5befad38f33c7 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 5 Jun 2024 10:33:18 +1000 Subject: [PATCH 1/5] Progress --- .../src/bindings/x86_64-unknown-linux-gnu.rs | 1 + .../context/tpm_commands/object_commands.rs | 87 ++++++++++++++- .../create_loaded_command_input.rs | 100 ++++++++++++++++++ .../create_loaded_command_output.rs | 83 +++++++++++++++ .../tpm_commands/object_commands_tests.rs | 25 +++++ 5 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs create mode 100644 tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs diff --git a/tss-esapi-sys/src/bindings/x86_64-unknown-linux-gnu.rs b/tss-esapi-sys/src/bindings/x86_64-unknown-linux-gnu.rs index 05d3f51c..73683ac7 100644 --- a/tss-esapi-sys/src/bindings/x86_64-unknown-linux-gnu.rs +++ b/tss-esapi-sys/src/bindings/x86_64-unknown-linux-gnu.rs @@ -11538,6 +11538,7 @@ extern "C" { objectHandle: *mut ESYS_TR, outPrivate: *mut *mut TPM2B_PRIVATE, outPublic: *mut *mut TPM2B_PUBLIC, + // Is this missing NAME? ) -> TSS2_RC; } extern "C" { diff --git a/tss-esapi/src/context/tpm_commands/object_commands.rs b/tss-esapi/src/context/tpm_commands/object_commands.rs index 4feefea2..2ddea4ce 100644 --- a/tss-esapi/src/context/tpm_commands/object_commands.rs +++ b/tss-esapi/src/context/tpm_commands/object_commands.rs @@ -3,6 +3,10 @@ mod create_command_input; mod create_command_output; +mod create_loaded_command_input; +mod create_loaded_command_output; + + use crate::{ context::handle_manager::HandleDropAction, handles::{KeyHandle, ObjectHandle, TpmHandle}, @@ -19,6 +23,10 @@ use crate::{ }; use create_command_input::CreateCommandInputHandler; use create_command_output::CreateCommandOutputHandler; + +use create_loaded_command_input::CreateLoadedCommandInputHandler; +use create_loaded_command_output::CreateLoadedCommandOutputHandler; + use log::error; use std::convert::{TryFrom, TryInto}; use std::ptr::{null, null_mut}; @@ -338,5 +346,82 @@ impl Context { Private::try_from(Context::ffi_data_to_owned(out_private_ptr)) } - // Missing function: CreateLoaded + /// Create a key and load it in the TPM. + /// + /// This function allows the creation of three distinct object types. This is determined + /// by the type of [KeyHandle] that is provided to the `parent_handle` argument. The key + /// types are: + /// + /// * Primary - Created when [KeyHandle] is a primary seed + /// * Ordinary - Created when [KeyHandle] is a storage parent + /// * Derived - Created when [KeyHandle] is a derivation parent + /// + /// _notes_ + /// + /// When creating a derived key, the value for `sensitive_data_origin` in `public` must be + /// `false`. + /// + /// # Parameters + /// * `parent_handle` - The [KeyHandle] of the parent for the new object that is being created. + /// * `sensitive_data` - The data that is to be sealed, a key or derivation values. + /// * `public` - The public part of the object that is being created. + /// + /// # Errors + /// * if either of the slices is larger than the maximum size of the native objects, a + /// `WrongParamSize` wrapper error is returned + // TODO: Fix when compacting the arguments into a struct + #[allow(clippy::too_many_arguments)] + pub fn create_loaded( + &mut self, + parent_handle: KeyHandle, + sensitive_data: Option, + public: Public, + ) -> Result { + + let input_parameters = CreateCommandInputHandler::create( + parent_handle, + public, + auth_value, + sensitive_data, + outside_info, + creation_pcrs, + )?; + + let mut output_parameters = CreateCommandOutputHandler::new(); + + let mut object_handle = ObjectHandle::None.into(); + + ReturnCode::ensure_success( + unsafe { + Esys_Create( + // esysContext + self.mut_context(), + // parent_handle + input_parameters.ffi_in_parent_handle(), + // session handles + self.optional_session_1(), + self.optional_session_2(), + self.optional_session_3(), + + // inSensitive + input_parameters.ffi_in_sensitive(), + // inPublic + input_parameters.ffi_in_public(), + + // objectHandle + &mut object_handle, + + // outPrivate + output_parameters.ffi_out_private_ptr(), + // outPublic + output_parameters.ffi_out_public_ptr(), + ) + }, + |ret| { + error!("Error in creating derived key: {:#010X}", ret); + }, + )?; + + output_parameters.try_into() + } } diff --git a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs new file mode 100644 index 00000000..222bd33d --- /dev/null +++ b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs @@ -0,0 +1,100 @@ +// Copyright 2024 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + ffi::data_zeroize::FfiDataZeroize, + handles::KeyHandle, + structures::{Auth, Data, PcrSelectionList, Public, SensitiveCreate, SensitiveData}, + tss2_esys::{ESYS_TR, TPM2B_DATA, TPM2B_PUBLIC, TPM2B_SENSITIVE_CREATE, TPML_PCR_SELECTION}, + Result, +}; +use std::convert::TryInto; +use zeroize::Zeroize; + +/// Struct that handles the input of the +/// to the Esys_CreateLoaded command and zeroizes +/// the data when it gets dropped. +pub struct CreateLoadedCommandInputHandler { + ffi_in_parent_handle: ESYS_TR, + ffi_in_sensitive: TPM2B_SENSITIVE_CREATE, + ffi_in_public: TPM2B_PUBLIC, +} + +impl CreateCommandInputHandler { + /// Creates the CreateCommandInputHandler from the inputs + /// of the 'create' [crate::Context] method. + /// + /// # Details + /// Consumes the input parameters and converts them into their + /// TSS counterpart and zeroizes all the data when dropped. + /// + /// # Arguments + /// See the input arguments of 'crate' [crate::Context] method. + /// + /// # Returns + /// The created CreateCommandInputHandler. + /// + /// # Errors + /// WrapperErrors if the conversions to the TSS types fails. + pub(crate) fn create( + parent_handle: KeyHandle, + public: Public, + auth_value: Option, + sensitive_data: Option, + outside_info: Option, + creation_pcrs: Option, + ) -> Result { + Ok(Self { + ffi_in_parent_handle: parent_handle.into(), + ffi_in_sensitive: SensitiveCreate::new( + auth_value.unwrap_or_default(), + sensitive_data.unwrap_or_default(), + ) + .try_into()?, + ffi_in_public: public.try_into()?, + ffi_outside_info: outside_info.unwrap_or_default().into(), + ffi_creation_pcr: PcrSelectionList::list_from_option(creation_pcrs).into(), + }) + } + + /// The 'parentHandle' input parameter + pub const fn ffi_in_parent_handle(&self) -> ESYS_TR { + self.ffi_in_parent_handle + } + + /// The 'inSensitive' input parameter. + pub const fn ffi_in_sensitive(&self) -> &TPM2B_SENSITIVE_CREATE { + &self.ffi_in_sensitive + } + + /// The 'inPublic' input parameter. + pub const fn ffi_in_public(&self) -> &TPM2B_PUBLIC { + &self.ffi_in_public + } + + /// The 'outsideInfo' input parameter. + pub const fn ffi_outside_info(&self) -> &TPM2B_DATA { + &self.ffi_outside_info + } + + /// The 'creationPCR' input parameter. + pub const fn ffi_creation_pcr(&self) -> &TPML_PCR_SELECTION { + &self.ffi_creation_pcr + } +} + +impl Zeroize for CreateCommandInputHandler { + fn zeroize(&mut self) { + self.ffi_in_parent_handle.zeroize(); + self.ffi_in_sensitive.ffi_data_zeroize(); + self.ffi_in_public.ffi_data_zeroize(); + self.ffi_outside_info.ffi_data_zeroize(); + self.ffi_creation_pcr.ffi_data_zeroize(); + } +} + +impl Drop for CreateCommandInputHandler { + fn drop(&mut self) { + self.zeroize(); + } +} diff --git a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs new file mode 100644 index 00000000..61c4b6b9 --- /dev/null +++ b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs @@ -0,0 +1,83 @@ +// Copyright 2024 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + structures::{CreateKeyResult, CreationData, CreationTicket, Digest, Private, Public}, + tss2_esys::{TPM2B_CREATION_DATA, TPM2B_DIGEST, TPM2B_PRIVATE, TPM2B_PUBLIC, TPMT_TK_CREATION}, + Error, Result, +}; +use std::convert::TryFrom; +use std::ptr::null_mut; + +/// Struct that handles the output of the +/// Create Esys_CreateLoaded command and zeroizes +/// the FFI data. +pub(crate) struct CreateLoadedCommandOutputHandler { + ffi_out_object_handle_ptr: *mut ESYS_TR, + // object + ffi_out_public_ptr: *mut TPM2B_PUBLIC, + ffi_out_private_ptr: *mut TPM2B_PRIVATE, + // name + ffi_out_name_ptr: *mut TPM2B_NAME, +} + +/// Creates a new CreateCommandOutputHandler +impl CreateCommandOutputHandler { + pub(crate) fn new() -> Self { + Self { + ffi_out_object_handle_ptr: null_mut(), + ffi_out_public_ptr: null_mut(), + ffi_out_private_ptr: null_mut(), + ffi_out_name_ptr: null_mut(), + } + } + + /// A reference to the where 'outPrivate' output parameter pointer shall be stored. + pub fn ffi_out_private_ptr(&mut self) -> &mut *mut TPM2B_PRIVATE { + &mut self.ffi_out_private_ptr + } + + /// A reference to the where 'outPublic' output parameter pointer shall be stored. + pub fn ffi_out_public_ptr(&mut self) -> &mut *mut TPM2B_PUBLIC { + &mut self.ffi_out_public_ptr + } + + /// A reference to the where 'creationData' output parameter pointer shall be stored. + pub fn ffi_creation_data_ptr(&mut self) -> &mut *mut TPM2B_CREATION_DATA { + &mut self.ffi_creation_data_ptr + } + + /// A reference to the where 'creationHash' output parameter pointer shall be stored. + pub fn ffi_creation_hash_ptr(&mut self) -> &mut *mut TPM2B_DIGEST { + &mut self.ffi_creation_hash_ptr + } + + /// A reference to the where 'creationTicket' output parameter pointer shall be stored. + pub fn ffi_creation_ticket_ptr(&mut self) -> &mut *mut TPMT_TK_CREATION { + &mut self.ffi_creation_ticket_ptr + } +} + +impl TryFrom for CreateKeyResult { + type Error = Error; + + fn try_from(ffi_data_handler: CreateCommandOutputHandler) -> Result { + let out_private_owned = + crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_out_private_ptr); + let out_public_owned = + crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_out_public_ptr); + let creation_data_owned = + crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_creation_data_ptr); + let creation_hash_owned = + crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_creation_hash_ptr); + let creation_ticket_owned = + crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_creation_ticket_ptr); + Ok(CreateKeyResult { + out_private: Private::try_from(out_private_owned)?, + out_public: Public::try_from(out_public_owned)?, + creation_data: CreationData::try_from(creation_data_owned)?, + creation_hash: Digest::try_from(creation_hash_owned)?, + creation_ticket: CreationTicket::try_from(creation_ticket_owned)?, + }) + } +} diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs index a6b037ed..b0fe6388 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs @@ -427,3 +427,28 @@ mod test_unseal { assert!(unsealed == testbytes); } } + +mod test_create_loaded_2 { + /* + use crate::common::{create_ctx_with_session, decryption_key_pub}; + use std::convert::{TryFrom, TryInto}; + use tss_esapi::{ + attributes::SessionAttributesBuilder, + constants::SessionType, + interface_types::{algorithm::HashingAlgorithm, reserved_handles::Hierarchy}, + structures::{Digest, SymmetricDefinition}, + }; + */ + + #[test] + fn test_create_loaded_2_() { + let mut context = create_ctx_with_session(); + + let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); + + + + + } +} + From d2f3a0f8f4f60ae611fdf35a8d364f47bd346f67 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 5 Jun 2024 11:34:24 +1000 Subject: [PATCH 2/5] Mostly thele. --- .../context/tpm_commands/object_commands.rs | 25 +++---- .../create_loaded_command_input.rs | 44 +++++-------- .../create_loaded_command_output.rs | 65 +++++++++---------- tss-esapi/src/structures/mod.rs | 1 + tss-esapi/src/structures/result.rs | 10 ++- 5 files changed, 74 insertions(+), 71 deletions(-) diff --git a/tss-esapi/src/context/tpm_commands/object_commands.rs b/tss-esapi/src/context/tpm_commands/object_commands.rs index 2ddea4ce..24c18fa4 100644 --- a/tss-esapi/src/context/tpm_commands/object_commands.rs +++ b/tss-esapi/src/context/tpm_commands/object_commands.rs @@ -12,11 +12,11 @@ use crate::{ handles::{KeyHandle, ObjectHandle, TpmHandle}, interface_types::reserved_handles::Hierarchy, structures::{ - Auth, CreateKeyResult, Data, Digest, EncryptedSecret, IdObject, Name, PcrSelectionList, + Auth, CreateKeyResult, CreateLoadedKeyResult, Data, Digest, EncryptedSecret, IdObject, Name, PcrSelectionList, Private, Public, Sensitive, SensitiveData, }, tss2_esys::{ - Esys_ActivateCredential, Esys_Create, Esys_Load, Esys_LoadExternal, Esys_MakeCredential, + Esys_ActivateCredential, Esys_Create, Esys_CreateLoaded, Esys_Load, Esys_LoadExternal, Esys_MakeCredential, Esys_ObjectChangeAuth, Esys_ReadPublic, Esys_Unseal, }, Context, Result, ReturnCode, @@ -363,6 +363,7 @@ impl Context { /// /// # Parameters /// * `parent_handle` - The [KeyHandle] of the parent for the new object that is being created. + /// * `auth_value` - The value used to be used for authorize usage of the object. /// * `sensitive_data` - The data that is to be sealed, a key or derivation values. /// * `public` - The public part of the object that is being created. /// @@ -374,26 +375,24 @@ impl Context { pub fn create_loaded( &mut self, parent_handle: KeyHandle, + auth_value: Option, sensitive_data: Option, public: Public, - ) -> Result { + ) -> Result { - let input_parameters = CreateCommandInputHandler::create( + let input_parameters = CreateLoadedCommandInputHandler::create( parent_handle, - public, auth_value, sensitive_data, - outside_info, - creation_pcrs, + public, )?; - let mut output_parameters = CreateCommandOutputHandler::new(); + let mut output_parameters = CreateLoadedCommandOutputHandler::new(); - let mut object_handle = ObjectHandle::None.into(); ReturnCode::ensure_success( unsafe { - Esys_Create( + Esys_CreateLoaded( // esysContext self.mut_context(), // parent_handle @@ -409,12 +408,16 @@ impl Context { input_parameters.ffi_in_public(), // objectHandle - &mut object_handle, + output_parameters.ffi_out_object_handle(), // outPrivate output_parameters.ffi_out_private_ptr(), // outPublic output_parameters.ffi_out_public_ptr(), + + // Per TPM Part3 12.9.2 Table 35, name is an output + // value, but appears not to be in our bindings that are generated. + // output_parameters.ffi_out_name_ptr(), ) }, |ret| { diff --git a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs index 222bd33d..61ecd8bf 100644 --- a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs +++ b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs @@ -4,8 +4,8 @@ use crate::{ ffi::data_zeroize::FfiDataZeroize, handles::KeyHandle, - structures::{Auth, Data, PcrSelectionList, Public, SensitiveCreate, SensitiveData}, - tss2_esys::{ESYS_TR, TPM2B_DATA, TPM2B_PUBLIC, TPM2B_SENSITIVE_CREATE, TPML_PCR_SELECTION}, + structures::{Auth, Public, SensitiveCreate, SensitiveData}, + tss2_esys::{ESYS_TR, TPM2B_TEMPLATE, TPM2B_SENSITIVE_CREATE}, Result, }; use std::convert::TryInto; @@ -17,11 +17,19 @@ use zeroize::Zeroize; pub struct CreateLoadedCommandInputHandler { ffi_in_parent_handle: ESYS_TR, ffi_in_sensitive: TPM2B_SENSITIVE_CREATE, - ffi_in_public: TPM2B_PUBLIC, + // Per Part 3 12.9.1 note 1: + // In the general descriptions of TPM2_Create() and TPM2_CreatePrimary() the validations refer to a + // TPMT_PUBLIC structure that is in inPublic. For TPM2_CreateLoaded(), inPublic is a + // TPM2B_TEMPLATE that may contain a TPMT_PUBLIC that is used for object creation. For object + // derivation, the unique field can contain a label and context that are used in the derivation process. + // To allow both the TPMT_PUBLIC and the derivation variation, a TPM2B_TEMPLATE is used. When + // referring to the checks in TPM2_Create() and TPM2_CreatePrimary(), TPM2B_TEMPLATE should + // be assumed to contain a TPMT_PUBLIC. + ffi_in_public: TPM2B_TEMPLATE, } -impl CreateCommandInputHandler { - /// Creates the CreateCommandInputHandler from the inputs +impl CreateLoadedCommandInputHandler { + /// Creates the CreateLoadedCommandInputHandler from the inputs /// of the 'create' [crate::Context] method. /// /// # Details @@ -32,17 +40,15 @@ impl CreateCommandInputHandler { /// See the input arguments of 'crate' [crate::Context] method. /// /// # Returns - /// The created CreateCommandInputHandler. + /// The created CreateLoadedCommandInputHandler. /// /// # Errors /// WrapperErrors if the conversions to the TSS types fails. pub(crate) fn create( parent_handle: KeyHandle, - public: Public, auth_value: Option, sensitive_data: Option, - outside_info: Option, - creation_pcrs: Option, + public: Public, ) -> Result { Ok(Self { ffi_in_parent_handle: parent_handle.into(), @@ -52,8 +58,6 @@ impl CreateCommandInputHandler { ) .try_into()?, ffi_in_public: public.try_into()?, - ffi_outside_info: outside_info.unwrap_or_default().into(), - ffi_creation_pcr: PcrSelectionList::list_from_option(creation_pcrs).into(), }) } @@ -68,32 +72,20 @@ impl CreateCommandInputHandler { } /// The 'inPublic' input parameter. - pub const fn ffi_in_public(&self) -> &TPM2B_PUBLIC { + pub const fn ffi_in_public(&self) -> &TPM2B_TEMPLATE { &self.ffi_in_public } - - /// The 'outsideInfo' input parameter. - pub const fn ffi_outside_info(&self) -> &TPM2B_DATA { - &self.ffi_outside_info - } - - /// The 'creationPCR' input parameter. - pub const fn ffi_creation_pcr(&self) -> &TPML_PCR_SELECTION { - &self.ffi_creation_pcr - } } -impl Zeroize for CreateCommandInputHandler { +impl Zeroize for CreateLoadedCommandInputHandler { fn zeroize(&mut self) { self.ffi_in_parent_handle.zeroize(); self.ffi_in_sensitive.ffi_data_zeroize(); self.ffi_in_public.ffi_data_zeroize(); - self.ffi_outside_info.ffi_data_zeroize(); - self.ffi_creation_pcr.ffi_data_zeroize(); } } -impl Drop for CreateCommandInputHandler { +impl Drop for CreateLoadedCommandInputHandler { fn drop(&mut self) { self.zeroize(); } diff --git a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs index 61c4b6b9..44e2a8d6 100644 --- a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs +++ b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs @@ -2,8 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - structures::{CreateKeyResult, CreationData, CreationTicket, Digest, Private, Public}, - tss2_esys::{TPM2B_CREATION_DATA, TPM2B_DIGEST, TPM2B_PRIVATE, TPM2B_PUBLIC, TPMT_TK_CREATION}, + handles::ObjectHandle, + structures::{CreateLoadedKeyResult, Private, Public}, + tss2_esys::{ESYS_TR, TPM2B_PRIVATE, TPM2B_PUBLIC}, Error, Result, }; use std::convert::TryFrom; @@ -13,25 +14,31 @@ use std::ptr::null_mut; /// Create Esys_CreateLoaded command and zeroizes /// the FFI data. pub(crate) struct CreateLoadedCommandOutputHandler { - ffi_out_object_handle_ptr: *mut ESYS_TR, + ffi_out_object_handle: ESYS_TR, // object ffi_out_public_ptr: *mut TPM2B_PUBLIC, ffi_out_private_ptr: *mut TPM2B_PRIVATE, // name - ffi_out_name_ptr: *mut TPM2B_NAME, + // ffi_out_name_ptr: *mut TPM2B_NAME, } -/// Creates a new CreateCommandOutputHandler -impl CreateCommandOutputHandler { +/// Creates a new CreateLoadedCommandOutputHandler +impl CreateLoadedCommandOutputHandler { pub(crate) fn new() -> Self { + let ffi_out_object_handle = ObjectHandle::None.into(); Self { - ffi_out_object_handle_ptr: null_mut(), + ffi_out_object_handle, ffi_out_public_ptr: null_mut(), ffi_out_private_ptr: null_mut(), - ffi_out_name_ptr: null_mut(), + // ffi_out_name_ptr: null_mut(), } } + /// A reference to the where 'objectHandle' output parameter pointer shall be stored. + pub fn ffi_out_object_handle(&mut self) -> &mut ESYS_TR { + &mut self.ffi_out_object_handle + } + /// A reference to the where 'outPrivate' output parameter pointer shall be stored. pub fn ffi_out_private_ptr(&mut self) -> &mut *mut TPM2B_PRIVATE { &mut self.ffi_out_private_ptr @@ -42,42 +49,34 @@ impl CreateCommandOutputHandler { &mut self.ffi_out_public_ptr } - /// A reference to the where 'creationData' output parameter pointer shall be stored. - pub fn ffi_creation_data_ptr(&mut self) -> &mut *mut TPM2B_CREATION_DATA { - &mut self.ffi_creation_data_ptr - } - - /// A reference to the where 'creationHash' output parameter pointer shall be stored. - pub fn ffi_creation_hash_ptr(&mut self) -> &mut *mut TPM2B_DIGEST { - &mut self.ffi_creation_hash_ptr - } - - /// A reference to the where 'creationTicket' output parameter pointer shall be stored. - pub fn ffi_creation_ticket_ptr(&mut self) -> &mut *mut TPMT_TK_CREATION { - &mut self.ffi_creation_ticket_ptr + /* + /// A reference to the where 'name' output parameter pointer shall be stored. + pub fn ffi_out_name_ptr(&mut self) -> &mut *mut TPM2B_NAME { + &mut self.ffi_out_name_ptr } + */ } -impl TryFrom for CreateKeyResult { +impl TryFrom for CreateLoadedKeyResult { type Error = Error; - fn try_from(ffi_data_handler: CreateCommandOutputHandler) -> Result { + fn try_from(ffi_data_handler: CreateLoadedCommandOutputHandler) -> Result { + + let object_handle = ObjectHandle::from(ffi_data_handler.ffi_out_object_handle); + let out_private_owned = crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_out_private_ptr); let out_public_owned = crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_out_public_ptr); - let creation_data_owned = - crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_creation_data_ptr); - let creation_hash_owned = - crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_creation_hash_ptr); - let creation_ticket_owned = - crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_creation_ticket_ptr); - Ok(CreateKeyResult { + + // let out_name_owned = + // crate::ffi::to_owned_with_zeroized_source(ffi_data_handler.ffi_out_name_ptr); + + Ok(CreateLoadedKeyResult { + object_handle, out_private: Private::try_from(out_private_owned)?, out_public: Public::try_from(out_public_owned)?, - creation_data: CreationData::try_from(creation_data_owned)?, - creation_hash: Digest::try_from(creation_hash_owned)?, - creation_ticket: CreationTicket::try_from(creation_ticket_owned)?, + // out_name: Name::try_from(out_name_owned)?, }) } } diff --git a/tss-esapi/src/structures/mod.rs b/tss-esapi/src/structures/mod.rs index 734f3bd5..7de8ae6b 100644 --- a/tss-esapi/src/structures/mod.rs +++ b/tss-esapi/src/structures/mod.rs @@ -29,6 +29,7 @@ pub use names::name::Name; ///////////////////////////////////////////////////////// mod result; pub use result::CreateKeyResult; +pub use result::CreateLoadedKeyResult; pub use result::CreatePrimaryKeyResult; ///////////////////////////////////////////////////////// /// The sized buffers section diff --git a/tss-esapi/src/structures/result.rs b/tss-esapi/src/structures/result.rs index 4bdc2dc3..e7d64450 100644 --- a/tss-esapi/src/structures/result.rs +++ b/tss-esapi/src/structures/result.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - handles::KeyHandle, + handles::{KeyHandle, ObjectHandle}, structures::{CreationData, CreationTicket, Digest, Private, Public}, }; @@ -15,6 +15,14 @@ pub struct CreateKeyResult { pub creation_ticket: CreationTicket, } +#[allow(missing_debug_implementations)] +pub struct CreateLoadedKeyResult { + pub object_handle: ObjectHandle, + pub out_private: Private, + pub out_public: Public, + // pub out_name: Name, +} + #[allow(missing_debug_implementations)] pub struct CreatePrimaryKeyResult { pub key_handle: KeyHandle, From dfaeffdbd070dc6a6c8fd436a09983eac6792178 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 5 Jun 2024 12:01:32 +1000 Subject: [PATCH 3/5] So far so good. Not sure about the buffer though. --- .../context/tpm_commands/object_commands.rs | 15 ++----- .../create_loaded_command_input.rs | 2 +- .../create_loaded_command_output.rs | 5 ++- tss-esapi/src/ffi/data_zeroize.rs | 3 +- tss-esapi/src/structures/tagged/public.rs | 39 ++++++++++++++++++- .../tpm_commands/object_commands_tests.rs | 5 --- 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/tss-esapi/src/context/tpm_commands/object_commands.rs b/tss-esapi/src/context/tpm_commands/object_commands.rs index 24c18fa4..7251a7f4 100644 --- a/tss-esapi/src/context/tpm_commands/object_commands.rs +++ b/tss-esapi/src/context/tpm_commands/object_commands.rs @@ -6,18 +6,17 @@ mod create_command_output; mod create_loaded_command_input; mod create_loaded_command_output; - use crate::{ context::handle_manager::HandleDropAction, handles::{KeyHandle, ObjectHandle, TpmHandle}, interface_types::reserved_handles::Hierarchy, structures::{ - Auth, CreateKeyResult, CreateLoadedKeyResult, Data, Digest, EncryptedSecret, IdObject, Name, PcrSelectionList, - Private, Public, Sensitive, SensitiveData, + Auth, CreateKeyResult, CreateLoadedKeyResult, Data, Digest, EncryptedSecret, IdObject, + Name, PcrSelectionList, Private, Public, Sensitive, SensitiveData, }, tss2_esys::{ - Esys_ActivateCredential, Esys_Create, Esys_CreateLoaded, Esys_Load, Esys_LoadExternal, Esys_MakeCredential, - Esys_ObjectChangeAuth, Esys_ReadPublic, Esys_Unseal, + Esys_ActivateCredential, Esys_Create, Esys_CreateLoaded, Esys_Load, Esys_LoadExternal, + Esys_MakeCredential, Esys_ObjectChangeAuth, Esys_ReadPublic, Esys_Unseal, }, Context, Result, ReturnCode, }; @@ -379,7 +378,6 @@ impl Context { sensitive_data: Option, public: Public, ) -> Result { - let input_parameters = CreateLoadedCommandInputHandler::create( parent_handle, auth_value, @@ -389,7 +387,6 @@ impl Context { let mut output_parameters = CreateLoadedCommandOutputHandler::new(); - ReturnCode::ensure_success( unsafe { Esys_CreateLoaded( @@ -401,20 +398,16 @@ impl Context { self.optional_session_1(), self.optional_session_2(), self.optional_session_3(), - // inSensitive input_parameters.ffi_in_sensitive(), // inPublic input_parameters.ffi_in_public(), - // objectHandle output_parameters.ffi_out_object_handle(), - // outPrivate output_parameters.ffi_out_private_ptr(), // outPublic output_parameters.ffi_out_public_ptr(), - // Per TPM Part3 12.9.2 Table 35, name is an output // value, but appears not to be in our bindings that are generated. // output_parameters.ffi_out_name_ptr(), diff --git a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs index 61ecd8bf..b14a85b6 100644 --- a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs +++ b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_input.rs @@ -5,7 +5,7 @@ use crate::{ ffi::data_zeroize::FfiDataZeroize, handles::KeyHandle, structures::{Auth, Public, SensitiveCreate, SensitiveData}, - tss2_esys::{ESYS_TR, TPM2B_TEMPLATE, TPM2B_SENSITIVE_CREATE}, + tss2_esys::{ESYS_TR, TPM2B_SENSITIVE_CREATE, TPM2B_TEMPLATE}, Result, }; use std::convert::TryInto; diff --git a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs index 44e2a8d6..090c03b6 100644 --- a/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs +++ b/tss-esapi/src/context/tpm_commands/object_commands/create_loaded_command_output.rs @@ -60,8 +60,9 @@ impl CreateLoadedCommandOutputHandler { impl TryFrom for CreateLoadedKeyResult { type Error = Error; - fn try_from(ffi_data_handler: CreateLoadedCommandOutputHandler) -> Result { - + fn try_from( + ffi_data_handler: CreateLoadedCommandOutputHandler, + ) -> Result { let object_handle = ObjectHandle::from(ffi_data_handler.ffi_out_object_handle); let out_private_owned = diff --git a/tss-esapi/src/ffi/data_zeroize.rs b/tss-esapi/src/ffi/data_zeroize.rs index 0c4a1d71..0d876ed4 100644 --- a/tss-esapi/src/ffi/data_zeroize.rs +++ b/tss-esapi/src/ffi/data_zeroize.rs @@ -10,7 +10,7 @@ use crate::{ TPM2B_ID_OBJECT, TPM2B_IV, TPM2B_MAX_BUFFER, TPM2B_MAX_NV_BUFFER, TPM2B_NAME, TPM2B_PRIVATE, TPM2B_PRIVATE_KEY_RSA, TPM2B_PRIVATE_VENDOR_SPECIFIC, TPM2B_PUBLIC, TPM2B_PUBLIC_KEY_RSA, TPM2B_SENSITIVE_CREATE, TPM2B_SENSITIVE_DATA, TPM2B_SYM_KEY, - TPML_PCR_SELECTION, TPMS_CREATION_DATA, TPMS_ECC_PARMS, TPMS_ECC_POINT, + TPM2B_TEMPLATE, TPML_PCR_SELECTION, TPMS_CREATION_DATA, TPMS_ECC_PARMS, TPMS_ECC_POINT, TPMS_KEYEDHASH_PARMS, TPMS_PCR_SELECTION, TPMS_RSA_PARMS, TPMS_SCHEME_ECDAA, TPMS_SCHEME_HASH, TPMS_SCHEME_XOR, TPMS_SENSITIVE_CREATE, TPMS_SYMCIPHER_PARMS, TPMT_ECC_SCHEME, TPMT_KDF_SCHEME, TPMT_KEYEDHASH_SCHEME, TPMT_PUBLIC, TPMT_RSA_SCHEME, @@ -121,6 +121,7 @@ implement_ffi_data_zeroizer_trait_for_buffer_type!(TPM2B_PRIVATE_VENDOR_SPECIFIC implement_ffi_data_zeroizer_trait_for_buffer_type!(TPM2B_PUBLIC_KEY_RSA); implement_ffi_data_zeroizer_trait_for_buffer_type!(TPM2B_SENSITIVE_DATA); implement_ffi_data_zeroizer_trait_for_buffer_type!(TPM2B_SYM_KEY); +implement_ffi_data_zeroizer_trait_for_buffer_type!(TPM2B_TEMPLATE); implement_ffi_data_zeroizer_trait_for_named_field_structured_buffer_type!( TPM2B_CREATION_DATA, creationData diff --git a/tss-esapi/src/structures/tagged/public.rs b/tss-esapi/src/structures/tagged/public.rs index 693d86d6..1bfbb10a 100644 --- a/tss-esapi/src/structures/tagged/public.rs +++ b/tss-esapi/src/structures/tagged/public.rs @@ -9,7 +9,7 @@ use crate::{ interface_types::algorithm::{HashingAlgorithm, PublicAlgorithm}, structures::{Digest, EccPoint, PublicKeyRsa, SymmetricCipherParameters}, traits::{impl_mu_standard, Marshall, UnMarshall}, - tss2_esys::{TPM2B_PUBLIC, TPMT_PUBLIC}, + tss2_esys::{TPM2B_PUBLIC, TPM2B_TEMPLATE, TPMT_PUBLIC}, Error, Result, ReturnCode, WrapperErrorKind, }; @@ -567,3 +567,40 @@ impl TryFrom for TPM2B_PUBLIC { }) } } + +impl TryFrom for TPM2B_TEMPLATE { + type Error = Error; + + fn try_from(public: Public) -> Result { + // Now sure how to handle this better. + let mut size = 0; + let mut buffer: [u8; 612usize] = [0; 612]; + let public_area = TPMT_PUBLIC::from(public); + + ReturnCode::ensure_success( + unsafe { + crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Marshal( + &public_area, + buffer.as_mut_ptr(), + Public::BUFFER_SIZE.try_into().map_err(|e| { + error!("Failed to convert size of buffer to TSS size_t type: {}", e); + Error::local_error(WrapperErrorKind::InvalidParam) + })?, + &mut size, + ) + }, + |ret| error!("Failed to marshal Public: {}", ret), + )?; + + Ok(TPM2B_TEMPLATE { + size: size.try_into().map_err(|e| { + error!( + "Failed to convert size of buffer from TSS size_t type: {}", + e + ); + Error::local_error(WrapperErrorKind::InvalidParam) + })?, + buffer, + }) + } +} diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs index b0fe6388..3fba2f4f 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs @@ -445,10 +445,5 @@ mod test_create_loaded_2 { let mut context = create_ctx_with_session(); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); - - - - } } - From 41ca84368518562f12566d25df6c991197035f5c Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 5 Jun 2024 12:09:37 +1000 Subject: [PATCH 4/5] Havent broken anything yet! --- .../tpm_commands/object_commands_tests.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs index 3fba2f4f..64a0536e 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs @@ -428,8 +428,7 @@ mod test_unseal { } } -mod test_create_loaded_2 { - /* +mod test_create_loaded { use crate::common::{create_ctx_with_session, decryption_key_pub}; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ @@ -438,12 +437,17 @@ mod test_create_loaded_2 { interface_types::{algorithm::HashingAlgorithm, reserved_handles::Hierarchy}, structures::{Digest, SymmetricDefinition}, }; - */ #[test] - fn test_create_loaded_2_() { + fn test_create_loaded_() { let mut context = create_ctx_with_session(); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); + + // + + + } } + From d7e368fd0fd6910f16a2c71150f80f833ac789d2 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 5 Jun 2024 14:56:34 +1000 Subject: [PATCH 5/5] Not sure what next --- .../tpm_commands/object_commands_tests.rs | 139 +++++++++++++++++- 1 file changed, 133 insertions(+), 6 deletions(-) diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs index 64a0536e..db723ac3 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/object_commands_tests.rs @@ -432,22 +432,149 @@ mod test_create_loaded { use crate::common::{create_ctx_with_session, decryption_key_pub}; use std::convert::{TryFrom, TryInto}; use tss_esapi::{ - attributes::SessionAttributesBuilder, + attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}, constants::SessionType, - interface_types::{algorithm::HashingAlgorithm, reserved_handles::Hierarchy}, - structures::{Digest, SymmetricDefinition}, + interface_types::{ + algorithm::{HashingAlgorithm, PublicAlgorithm, SymmetricMode}, + key_bits::AesKeyBits, + reserved_handles::Hierarchy, + }, + structures::{ + CreateLoadedKeyResult, Digest, KeyedHashScheme, PublicBuilder, + PublicKeyedHashParameters, SymmetricCipherParameters, SymmetricDefinition, + SymmetricDefinitionObject, + }, }; #[test] - fn test_create_loaded_() { + fn test_create_loaded_tpm_alg_kdf1_sp800_108() { let mut context = create_ctx_with_session(); let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); - // + let object_attributes = ObjectAttributesBuilder::new() + .with_fixed_tpm(true) + .with_fixed_parent(true) + .with_st_clear(false) + .with_sensitive_data_origin(true) + .with_user_with_auth(true) + .with_sign_encrypt(false) + .with_decrypt(true) + .with_restricted(true) + .build() + .expect("Failed to build object attributes"); + let primary_pub = PublicBuilder::new() + // This key is a symmetric key. + .with_public_algorithm(PublicAlgorithm::SymCipher) + .with_name_hashing_algorithm(HashingAlgorithm::Sha256) + .with_object_attributes(object_attributes) + .with_symmetric_cipher_parameters(SymmetricCipherParameters::new( + SymmetricDefinitionObject::AES_128_CFB, + )) + .with_symmetric_cipher_unique_identifier(Digest::default()) + .build() + .unwrap(); + + // Create primary. + let primary_key_handle = context + .create_primary(Hierarchy::Owner, primary_pub, None, None, None, None) + .unwrap() + .key_handle; + + // Create Derivation Parent + // - How to mark an object as a derivation parent? From what I read + // in the spec, a derivation parent is just when != (primary || storage) + let derive_parent_object_attributes = ObjectAttributesBuilder::new() + .with_fixed_tpm(true) + .with_fixed_parent(true) + .with_st_clear(false) + .with_sensitive_data_origin(true) + .with_user_with_auth(true) + // Architecture 25.1.5 table 24. + .with_sign_encrypt(false) + .with_decrypt(true) + .with_restricted(true) + .build() + .expect("Failed to build object attributes"); + // How can I set this to KeyDerivationFunctionScheme::Kdf1Sp800_108(HashScheme::Sha256) + let derive_parent_public = PublicBuilder::new() + .with_public_algorithm(PublicAlgorithm::KeyedHash) + .with_name_hashing_algorithm(HashingAlgorithm::Sha256) + .with_object_attributes(derive_parent_object_attributes) + .with_keyed_hash_parameters(PublicKeyedHashParameters::new( + KeyedHashScheme::HMAC_SHA_256, + )) + .with_keyed_hash_unique_identifier(Digest::default()) + .build() + .expect("Failed to build derive parent public"); + + // We should be able to create and load this now. And look, like magic, + // it's created and loaded in one operation! + let create_loaded_result = context + .create_loaded(primary_key_handle, None, None, derive_parent_public) + .expect("Failed to create derivation parent."); + + let CreateLoadedKeyResult { + object_handle: derive_parent_handle, + out_private: derive_parent_private, + out_public: derive_parent_public, + } = create_loaded_result; + + context + .flush_context(primary_key_handle.into()) + .expect("Unable to unload primary key"); + + // Create the derived key + let derived_object_attributes = ObjectAttributesBuilder::new() + .with_fixed_tpm(true) + .with_fixed_parent(true) + .with_st_clear(false) + // Must be false on a derived key. + .with_sensitive_data_origin(false) + .with_user_with_auth(true) + // The key is used only for signing. + .with_sign_encrypt(true) + .with_decrypt(true) + .with_restricted(false) + .build() + .expect("Failed to build object attributes"); + + let aes_params = SymmetricCipherParameters::new(SymmetricDefinitionObject::Aes { + key_bits: AesKeyBits::Aes128, + mode: SymmetricMode::Cbc, + }); + + let derivation_params = Digest::try_from(b"testinputs".to_vec()).unwrap(); + + let derived_public = PublicBuilder::new() + .with_public_algorithm(PublicAlgorithm::SymCipher) + .with_name_hashing_algorithm(HashingAlgorithm::Sha256) + .with_object_attributes(derived_object_attributes) + .with_symmetric_cipher_parameters(aes_params) + .with_symmetric_cipher_unique_identifier(derivation_params) + .build() + .expect("Failed to build derive parent public"); + + // We should be able to create and load this now. And look, like magic, + // it's created and loaded in one operation! + let create_loaded_result = context + .create_loaded(derive_parent_handle.into(), None, None, derived_public) + .expect("Failed to create derivation parent."); + + let CreateLoadedKeyResult { + object_handle: derived_handle, + out_private: derived_private, + out_public: derived_public, + } = create_loaded_result; + + // Derivation params are in the inPublic.unique Field, or inPrivate.data + + // Sensitive dataOrigin must be clear for derivation. + + // TPM_ALG_KDF1_SP800_56A == ECDH + // TPM_ALG_KDF1_SP800_108 == CMAC/HMAC/KMAC derivation } } -