Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

20240604 506 create loaded #529

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tss-esapi-sys/src/bindings/x86_64-unknown-linux-gnu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down
91 changes: 86 additions & 5 deletions tss-esapi/src/context/tpm_commands/object_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@
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},
interface_types::reserved_handles::Hierarchy,
structures::{
Auth, CreateKeyResult, 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_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,
};
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};
Expand Down Expand Up @@ -338,5 +345,79 @@ 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.
/// * `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.
///
/// # 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,
auth_value: Option<Auth>,
sensitive_data: Option<SensitiveData>,
public: Public,
) -> Result<CreateLoadedKeyResult> {
let input_parameters = CreateLoadedCommandInputHandler::create(
parent_handle,
auth_value,
sensitive_data,
public,
)?;

let mut output_parameters = CreateLoadedCommandOutputHandler::new();

ReturnCode::ensure_success(
unsafe {
Esys_CreateLoaded(
// 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
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| {
error!("Error in creating derived key: {:#010X}", ret);
},
)?;

output_parameters.try_into()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2024 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0

use crate::{
ffi::data_zeroize::FfiDataZeroize,
handles::KeyHandle,
structures::{Auth, Public, SensitiveCreate, SensitiveData},
tss2_esys::{ESYS_TR, TPM2B_SENSITIVE_CREATE, TPM2B_TEMPLATE},
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,
// 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 CreateLoadedCommandInputHandler {
/// Creates the CreateLoadedCommandInputHandler 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 CreateLoadedCommandInputHandler.
///
/// # Errors
/// WrapperErrors if the conversions to the TSS types fails.
pub(crate) fn create(
parent_handle: KeyHandle,
auth_value: Option<Auth>,
sensitive_data: Option<SensitiveData>,
public: Public,
) -> Result<Self> {
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()?,
})
}

/// 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_TEMPLATE {
&self.ffi_in_public
}
}

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();
}
}

impl Drop for CreateLoadedCommandInputHandler {
fn drop(&mut self) {
self.zeroize();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2024 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0

use crate::{
handles::ObjectHandle,
structures::{CreateLoadedKeyResult, Private, Public},
tss2_esys::{ESYS_TR, TPM2B_PRIVATE, TPM2B_PUBLIC},
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: 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 CreateLoadedCommandOutputHandler
impl CreateLoadedCommandOutputHandler {
pub(crate) fn new() -> Self {
let ffi_out_object_handle = ObjectHandle::None.into();
Self {
ffi_out_object_handle,
ffi_out_public_ptr: null_mut(),
ffi_out_private_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
}

/// 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 '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<CreateLoadedCommandOutputHandler> for CreateLoadedKeyResult {
type Error = Error;

fn try_from(
ffi_data_handler: CreateLoadedCommandOutputHandler,
) -> Result<CreateLoadedKeyResult> {
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 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)?,
// out_name: Name::try_from(out_name_owned)?,
})
}
}
3 changes: 2 additions & 1 deletion tss-esapi/src/ffi/data_zeroize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tss-esapi/src/structures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion tss-esapi/src/structures/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
handles::KeyHandle,
handles::{KeyHandle, ObjectHandle},
structures::{CreationData, CreationTicket, Digest, Private, Public},
};

Expand All @@ -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,
Expand Down
39 changes: 38 additions & 1 deletion tss-esapi/src/structures/tagged/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -567,3 +567,40 @@ impl TryFrom<Public> for TPM2B_PUBLIC {
})
}
}

impl TryFrom<Public> for TPM2B_TEMPLATE {
type Error = Error;

fn try_from(public: Public) -> Result<Self> {
// 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,
})
}
}
Loading
Loading