From 5876aaaf67bed509eec8eb9babc4f9bd4a143db1 Mon Sep 17 00:00:00 2001 From: Jesper Brynolf Date: Wed, 8 Nov 2023 22:30:30 +0100 Subject: [PATCH] Improves handling ```size_t``` FFI values. - The size_t type that is used in all the MU APIs will be dependent on the compiler that ```bindgen``` uses to generate the bindings for the library. This attempts to make the crate less dependant on that value in the public APIs. - Changes the Marshall and Unmarshall traits to use usize as input. Signed-off-by: Jesper Brynolf --- tss-esapi/src/constants/command_code.rs | 36 ++++------ tss-esapi/src/ffi.rs | 58 ++++++++++++++- .../src/interface_types/structure_tags.rs | 71 +++++++------------ tss-esapi/src/structures/buffers/private.rs | 33 ++++----- tss-esapi/src/traits.rs | 61 +++++----------- 5 files changed, 127 insertions(+), 132 deletions(-) diff --git a/tss-esapi/src/constants/command_code.rs b/tss-esapi/src/constants/command_code.rs index fb2b072b..fff48542 100644 --- a/tss-esapi/src/constants/command_code.rs +++ b/tss-esapi/src/constants/command_code.rs @@ -3,6 +3,7 @@ mod structure; use crate::{ + ffi::FfiSizeType, traits::{Marshall, UnMarshall}, tss2_esys::TPM2_CC, Error, Result, ReturnCode, WrapperErrorKind, @@ -10,7 +11,7 @@ use crate::{ use log::error; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; -use std::convert::{TryFrom, TryInto}; +use std::convert::TryFrom; use structure::CommandCodeStructure; /// Enum representing the command code constants. @@ -158,53 +159,44 @@ impl From for TPM2_CC { impl Marshall for CommandCode { const BUFFER_SIZE: usize = std::mem::size_of::(); - fn marshall_offset( - &self, - marshalled_data: &mut [u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result<()> { + fn marshall_offset(&self, marshalled_data: &mut [u8], offset: &mut usize) -> Result<()> { + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2_CC_Marshal( (*self).into(), marshalled_data.as_mut_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert size of buffer to TSS size_t type: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), ) }, |ret| { error!("Failed to marshal CommandCode: {}", ret); }, )?; + *offset = usize::try_from(ffi_offset)?; Ok(()) } } impl UnMarshall for CommandCode { - fn unmarshall_offset( - marshalled_data: &[u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result { + fn unmarshall_offset(marshalled_data: &[u8], offset: &mut usize) -> Result { let mut dest = TPM2_CC::default(); - + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2_CC_Unmarshal( marshalled_data.as_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert length of marshalled data: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), &mut dest, ) }, |ret| error!("Failed to unmarshal SensitiveCreate: {}", ret), )?; - + *offset = usize::try_from(ffi_offset)?; CommandCode::try_from(dest) } } diff --git a/tss-esapi/src/ffi.rs b/tss-esapi/src/ffi.rs index f51313f1..8edb508e 100644 --- a/tss-esapi/src/ffi.rs +++ b/tss-esapi/src/ffi.rs @@ -3,9 +3,10 @@ pub(crate) mod data_zeroize; -use crate::ffi::data_zeroize::FfiDataZeroize; +use crate::{ffi::data_zeroize::FfiDataZeroize, Error, Result, WrapperErrorKind}; +use log::error; use mbox::MBox; -use std::ops::Deref; +use std::{convert::TryFrom, ops::Deref}; /// Function that takes ownership of data that has been /// allocated with C memory allocation functions in TSS while also @@ -26,7 +27,60 @@ where owned_ffi_data } +/// Function that takes ownership of bytes that are stored in a +/// buffer that has been allocated with C memory allocation functions in TSS. +/// +/// # Arguments +/// * `ffi_bytes_ptr` - A pointer to the FFI buffer. +/// * `size` - The number of bytes to read from the buffer. +/// +/// # Returns +/// The owned bytes in the form of a Vec object. pub(crate) fn to_owned_bytes(ffi_bytes_ptr: *mut u8, size: usize) -> Vec { let ffi_bytes = unsafe { MBox::<[u8]>::from_raw_parts(ffi_bytes_ptr, size) }; return Vec::::from(ffi_bytes.as_ref()); } + +/// Type used for handling `size_t` variables +pub(crate) struct FfiSizeType(crate::tss2_esys::size_t); + +impl FfiSizeType { + /// Returns an unsafe mutable pointer to the `size_t` value. + pub(crate) fn as_mut_ptr(&mut self) -> *mut crate::tss2_esys::size_t { + &mut self.0 + } +} + +impl From for FfiSizeType { + fn from(value: crate::tss2_esys::size_t) -> Self { + Self(value) + } +} + +impl From for crate::tss2_esys::size_t { + fn from(ffi: FfiSizeType) -> crate::tss2_esys::size_t { + ffi.0 + } +} + +impl TryFrom for FfiSizeType { + type Error = Error; + fn try_from(native: usize) -> Result { + crate::tss2_esys::size_t::try_from(native) + .map(FfiSizeType) + .map_err(|err| { + error!("Failed to convert `usize` to `size_t`: {}", err); + Error::local_error(WrapperErrorKind::UnsupportedParam) + }) + } +} + +impl TryFrom for usize { + type Error = Error; + fn try_from(ffi: FfiSizeType) -> Result { + usize::try_from(ffi.0).map_err(|err| { + error!("Failed to convert `size_t` to `usize`: {}", err); + Error::local_error(WrapperErrorKind::UnsupportedParam) + }) + } +} diff --git a/tss-esapi/src/interface_types/structure_tags.rs b/tss-esapi/src/interface_types/structure_tags.rs index 0f28d587..b30f6f24 100644 --- a/tss-esapi/src/interface_types/structure_tags.rs +++ b/tss-esapi/src/interface_types/structure_tags.rs @@ -6,11 +6,12 @@ use tss_esapi_sys::TPMI_ST_COMMAND_TAG; use crate::{ constants::StructureTag, + ffi::FfiSizeType, traits::{Marshall, UnMarshall}, tss2_esys::TPMI_ST_ATTEST, Error, Result, ReturnCode, WrapperErrorKind, }; -use std::convert::{TryFrom, TryInto}; +use std::convert::TryFrom; /// Type of attestation. /// @@ -78,54 +79,44 @@ impl TryFrom for AttestationType { impl Marshall for AttestationType { const BUFFER_SIZE: usize = std::mem::size_of::(); - fn marshall_offset( - &self, - marshalled_data: &mut [u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result<()> { + fn marshall_offset(&self, marshalled_data: &mut [u8], offset: &mut usize) -> Result<()> { + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2_ST_Marshal( (*self).into(), marshalled_data.as_mut_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert size of buffer to TSS size_t type: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), ) }, |ret| { error!("Failed to marshal AttestationType: {}", ret); }, )?; - + *offset = usize::try_from(ffi_offset)?; Ok(()) } } impl UnMarshall for AttestationType { - fn unmarshall_offset( - marshalled_data: &[u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result { + fn unmarshall_offset(marshalled_data: &[u8], offset: &mut usize) -> Result { let mut dest = TPMI_ST_ATTEST::default(); - + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2_ST_Unmarshal( marshalled_data.as_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert length of marshalled data: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), &mut dest, ) }, |ret| error!("Failed to unmarshal AttestationType: {}", ret), )?; - + *offset = usize::try_from(ffi_offset)?; AttestationType::try_from(dest) } } @@ -178,54 +169,44 @@ impl TryFrom for CommandTag { impl Marshall for CommandTag { const BUFFER_SIZE: usize = std::mem::size_of::(); - fn marshall_offset( - &self, - marshalled_data: &mut [u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result<()> { + fn marshall_offset(&self, marshalled_data: &mut [u8], offset: &mut usize) -> Result<()> { + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2_ST_Marshal( (*self).into(), marshalled_data.as_mut_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert size of buffer to TSS size_t type: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), ) }, |ret| { error!("Failed to marshal CommandTag: {}", ret); }, )?; - + *offset = usize::try_from(ffi_offset)?; Ok(()) } } impl UnMarshall for CommandTag { - fn unmarshall_offset( - marshalled_data: &[u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result { + fn unmarshall_offset(marshalled_data: &[u8], offset: &mut usize) -> Result { let mut dest = TPMI_ST_COMMAND_TAG::default(); - + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2_ST_Unmarshal( marshalled_data.as_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert length of marshalled data: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), &mut dest, ) }, |ret| error!("Failed to unmarshal CommandTag: {}", ret), )?; - + *offset = usize::try_from(ffi_offset)?; CommandTag::try_from(dest) } } diff --git a/tss-esapi/src/structures/buffers/private.rs b/tss-esapi/src/structures/buffers/private.rs index 62ee5054..93528a9f 100644 --- a/tss-esapi/src/structures/buffers/private.rs +++ b/tss-esapi/src/structures/buffers/private.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ + ffi::FfiSizeType, traits::{Marshall, UnMarshall}, ReturnCode, }; @@ -14,11 +15,9 @@ impl Marshall for Private { const BUFFER_SIZE: usize = std::mem::size_of::(); /// Produce a marshalled [`TPM2B_PRIVATE`] - fn marshall_offset( - &self, - marshalled_data: &mut [u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result<()> { + fn marshall_offset(&self, marshalled_data: &mut [u8], offset: &mut usize) -> Result<()> { + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2B_PRIVATE_Marshal( @@ -27,43 +26,37 @@ impl Marshall for Private { Error::local_error(WrapperErrorKind::InvalidParam) })?, marshalled_data.as_mut_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert size of buffer to TSS size_t type: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), ) }, |ret| { error!("Failed to marshal Private: {}", ret); }, )?; - + *offset = usize::try_from(ffi_offset)?; Ok(()) } } impl UnMarshall for Private { /// Unmarshall the structure from [`TPM2B_PRIVATE`] - fn unmarshall_offset( - marshalled_data: &[u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result { + fn unmarshall_offset(marshalled_data: &[u8], offset: &mut usize) -> Result { let mut dest = TPM2B_PRIVATE::default(); + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_TPM2B_PRIVATE_Unmarshal( marshalled_data.as_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert length of marshalled data: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), &mut dest, ) }, |ret| error!("Failed to unmarshal Private: {}", ret), )?; + *offset = usize::try_from(ffi_offset)?; Private::try_from(dest) } } diff --git a/tss-esapi/src/traits.rs b/tss-esapi/src/traits.rs index 1e5b4a04..064955fa 100644 --- a/tss-esapi/src/traits.rs +++ b/tss-esapi/src/traits.rs @@ -1,11 +1,8 @@ -use std::convert::{TryFrom, TryInto}; - -use log::error; -use tss_esapi_sys::UINT32; - // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 -use crate::{Error, Result, ReturnCode, WrapperErrorKind}; +use crate::{ffi::FfiSizeType, tss2_esys::UINT32, Result, ReturnCode}; +use log::error; +use std::convert::TryFrom; /// Trait for types that can be converted into /// TPM marshalled data. @@ -18,12 +15,7 @@ pub trait Marshall: Sized { self.marshall_offset(&mut buffer, &mut offset)?; - let checked_offset = usize::try_from(offset).map_err(|e| { - error!("Failed to parse offset as usize: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?; - - buffer.truncate(checked_offset); + buffer.truncate(offset); Ok(buffer) } @@ -31,11 +23,7 @@ pub trait Marshall: Sized { /// Writes the type in the form of marshalled data to `marshalled_data`, /// and modifies the `offset` to point to the first byte in the buffer /// which was not written in the conversion. - fn marshall_offset( - &self, - _marshalled_data: &mut [u8], - _offset: &mut std::os::raw::c_ulong, - ) -> Result<()> { + fn marshall_offset(&self, _marshalled_data: &mut [u8], _offset: &mut usize) -> Result<()> { unimplemented!(); } } @@ -51,10 +39,7 @@ pub trait UnMarshall: Sized { /// Creates the type from the marshalled data, and modifies /// the `offset` to point to the first byte in the `marshalled_data` /// buffer which was not used in the conversion. - fn unmarshall_offset( - _marshalled_data: &[u8], - _offset: &mut std::os::raw::c_ulong, - ) -> Result { + fn unmarshall_offset(_marshalled_data: &[u8], _offset: &mut usize) -> Result { unimplemented!(); } } @@ -62,54 +47,44 @@ pub trait UnMarshall: Sized { impl Marshall for u32 { const BUFFER_SIZE: usize = std::mem::size_of::(); - fn marshall_offset( - &self, - marshalled_data: &mut [u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result<()> { + fn marshall_offset(&self, marshalled_data: &mut [u8], offset: &mut usize) -> Result<()> { + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_UINT32_Marshal( *self, marshalled_data.as_mut_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert size of buffer to TSS size_t type: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), ) }, |ret| { error!("Failed to marshall u32: {}", ret); }, )?; - + *offset = usize::try_from(ffi_offset)?; Ok(()) } } impl UnMarshall for u32 { - fn unmarshall_offset( - marshalled_data: &[u8], - offset: &mut std::os::raw::c_ulong, - ) -> Result { + fn unmarshall_offset(marshalled_data: &[u8], offset: &mut usize) -> Result { let mut dest = 0_u32; - + let ffi_buffer_size = FfiSizeType::try_from(marshalled_data.len())?; + let mut ffi_offset = FfiSizeType::try_from(*offset)?; ReturnCode::ensure_success( unsafe { crate::tss2_esys::Tss2_MU_UINT32_Unmarshal( marshalled_data.as_ptr(), - marshalled_data.len().try_into().map_err(|e| { - error!("Failed to convert length of marshalled data: {}", e); - Error::local_error(WrapperErrorKind::InvalidParam) - })?, - offset, + ffi_buffer_size.into(), + ffi_offset.as_mut_ptr(), &mut dest, ) }, |ret| error!("Failed to unmarshal SensitiveCreate: {}", ret), )?; - + *offset = usize::try_from(ffi_offset)?; Ok(dest) } }