Skip to content

Commit

Permalink
Merge pull request #549 from Superhepper/buffer-max-size-bug
Browse files Browse the repository at this point in the history
Fixes issue wrong max size in some sized buffer types.
  • Loading branch information
Superhepper authored Sep 30, 2024
2 parents 97ccc11 + bf24797 commit 2faf073
Show file tree
Hide file tree
Showing 19 changed files with 377 additions and 223 deletions.
106 changes: 72 additions & 34 deletions tss-esapi/src/structures/buffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,30 @@ pub mod sensitive;
pub mod sensitive_create;

pub mod auth {
buffer_type!(Auth, 64, TPM2B_AUTH);
// Same size as TPM2B_DIGEST according to the specification.
use crate::tss2_esys::TPMU_HA;
use std::mem::size_of;
const TPM2B_AUTH_BUFFER_SIZE: usize = size_of::<TPMU_HA>();
buffer_type!(Auth, TPM2B_AUTH_BUFFER_SIZE, TPM2B_AUTH);
}

pub mod data {
buffer_type!(Data, 64, TPM2B_DATA);
// This should, according to the specification, be
// size_of::<TPMT_HA>() but due to a bug in tpm2-tss
// (https://github.com/tpm2-software/tpm2-tss/issues/2888)
// it is the size of TPMU_HA
use crate::tss2_esys::TPMU_HA;
use std::mem::size_of;
const TPM2B_DATA_BUFFER_SIZE: usize = size_of::<TPMU_HA>();
buffer_type!(Data, TPM2B_DATA_BUFFER_SIZE, TPM2B_DATA);
}

pub mod digest {
buffer_type!(Digest, 64, TPM2B_DIGEST);
use crate::tss2_esys::TPMU_HA;
use std::mem::size_of;
const TPM2B_DIGEST_BUFFER_SIZE: usize = size_of::<TPMU_HA>();

buffer_type!(Digest, TPM2B_DIGEST_BUFFER_SIZE, TPM2B_DIGEST);

// Some implementations to get from Digest to [u8; N] for common values of N (sha* primarily)
// This is used to work around the fact that Rust does not allow custom functions for general values of N in [T; N],
Expand Down Expand Up @@ -208,80 +223,101 @@ pub mod digest {
}

pub mod ecc_parameter {
use crate::tss2_esys::TPM2_MAX_ECC_KEY_BYTES;
const TPM2B_ECC_PARAMETER_BUFFER_SIZE: usize = TPM2_MAX_ECC_KEY_BYTES as usize;
buffer_type!(
EccParameter,
crate::tss2_esys::TPM2_MAX_ECC_KEY_BYTES as usize,
TPM2B_ECC_PARAMETER_BUFFER_SIZE,
TPM2B_ECC_PARAMETER
);
}

pub mod encrypted_secret {
named_field_buffer_type!(EncryptedSecret, 256, TPM2B_ENCRYPTED_SECRET, secret);
use crate::tss2_esys::TPMU_ENCRYPTED_SECRET;
use std::mem::size_of;
const TPM2B_ENCRYPTED_SECRET_BUFFER_SIZE: usize = size_of::<TPMU_ENCRYPTED_SECRET>();
named_field_buffer_type!(
EncryptedSecret,
TPM2B_ENCRYPTED_SECRET_BUFFER_SIZE,
TPM2B_ENCRYPTED_SECRET,
secret
);
}

pub mod id_object {
named_field_buffer_type!(IdObject, 256, TPM2B_ID_OBJECT, credential);
use crate::tss2_esys::TPMS_ID_OBJECT;
use std::mem::size_of;
const TPM2B_ID_OBJECT_BUFFER_SIZE: usize = size_of::<TPMS_ID_OBJECT>();
named_field_buffer_type!(
IdObject,
TPM2B_ID_OBJECT_BUFFER_SIZE,
TPM2B_ID_OBJECT,
credential
);
}

pub mod initial_value {
buffer_type!(
InitialValue,
crate::tss2_esys::TPM2_MAX_SYM_BLOCK_SIZE as usize,
TPM2B_IV
);
use crate::tss2_esys::TPM2_MAX_SYM_BLOCK_SIZE;
const TPM2B_IV_BUFFER_SIZE: usize = TPM2_MAX_SYM_BLOCK_SIZE as usize;
buffer_type!(InitialValue, TPM2B_IV_BUFFER_SIZE, TPM2B_IV);
}

pub mod max_buffer {
use crate::tss2_esys::TPM2_MAX_DIGEST_BUFFER;
buffer_type!(MaxBuffer, TPM2_MAX_DIGEST_BUFFER as usize, TPM2B_MAX_BUFFER);
const TPM2B_MAX_BUFFER_BUFFER_SIZE: usize = TPM2_MAX_DIGEST_BUFFER as usize;
buffer_type!(MaxBuffer, TPM2B_MAX_BUFFER_BUFFER_SIZE, TPM2B_MAX_BUFFER);
}

pub mod max_nv_buffer {
use crate::tss2_esys::TPM2_MAX_NV_BUFFER_SIZE;
const TPM2B_MAX_NV_BUFFER_BUFFER_SIZE: usize = TPM2_MAX_NV_BUFFER_SIZE as usize;
buffer_type!(
MaxNvBuffer,
TPM2_MAX_NV_BUFFER_SIZE as usize,
TPM2B_MAX_NV_BUFFER_BUFFER_SIZE,
TPM2B_MAX_NV_BUFFER
);
}

pub mod nonce {
buffer_type!(Nonce, 64, TPM2B_NONCE);
// Same size as TPM2B_DIGEST according to the specification.
use crate::tss2_esys::TPMU_HA;
use std::mem::size_of;
const TPM2B_NONCE_BUFFER_SIZE: usize = size_of::<TPMU_HA>();

buffer_type!(Nonce, TPM2B_NONCE_BUFFER_SIZE, TPM2B_NONCE);
}

pub mod private_key_rsa {
use crate::tss2_esys::TPM2_MAX_RSA_KEY_BYTES;
const TPM2B_PRIVATE_KEY_RSA_BUFFER_SIZE: usize = (TPM2_MAX_RSA_KEY_BYTES as usize) * 5 / 2;

// The maximum size is given in the spec as:
// "RSA_PRIVATE_SIZE is a vendor specific value that can be (MAX_RSA_KEY_BYTES / 2) or
// ((MAX_RSA_KEY_BYTES * 5) ./ 2. The larger size would only apply to keys that have fixedTPM parents.
// The larger size was added in revision 01.53."
// The TSS stack we use only accepts the smaller of the two sizes described above (for now).
buffer_type!(
PrivateKeyRsa,
(TPM2_MAX_RSA_KEY_BYTES / 2) as usize,
TPM2B_PRIVATE_KEY_RSA_BUFFER_SIZE,
TPM2B_PRIVATE_KEY_RSA
);
}

pub mod private_vendor_specific {
use crate::tss2_esys::TPM2_PRIVATE_VENDOR_SPECIFIC_BYTES;

const TPM2B_PRIVATE_VENDOR_SPECIFIC_BUFFER_SIZE: usize =
TPM2_PRIVATE_VENDOR_SPECIFIC_BYTES as usize;
// The spec states the maximum size as:
// "The value for PRIVATE_VENDOR_SPECIFIC_BYTES is determined by the vendor."
// Not very helpful, but the TSS exposes a generic value that we can use.
buffer_type!(
PrivateVendorSpecific,
TPM2_PRIVATE_VENDOR_SPECIFIC_BYTES as usize,
TPM2B_PRIVATE_VENDOR_SPECIFIC_BUFFER_SIZE,
TPM2B_PRIVATE_VENDOR_SPECIFIC
);
}

pub mod public_key_rsa {
use crate::{interface_types::key_bits::RsaKeyBits, tss2_esys::TPM2_MAX_RSA_KEY_BYTES};
const TPM2B_PUBLIC_KEY_RSA_BUFFER_SIZE: usize = TPM2_MAX_RSA_KEY_BYTES as usize;
buffer_type!(
PublicKeyRsa,
TPM2_MAX_RSA_KEY_BYTES as usize,
TPM2B_PUBLIC_KEY_RSA_BUFFER_SIZE,
TPM2B_PUBLIC_KEY_RSA
);

Expand Down Expand Up @@ -359,45 +395,47 @@ pub mod sensitive_data {
// versions of tpm2-tss supported by the crate so the fall back is to
// calculate the max size by removing the size of the size parameter(UINT16)
// from the total size of the buffer type.
use std::mem::size_of;
cfg_if::cfg_if! {
if #[cfg(has_tpmu_sensitive_create)] {
use crate::tss2_esys::TPMU_SENSITIVE_CREATE;
#[allow(unused_qualifications)]
const TPMU_SENSITIVE_CREATE_MEM_SIZE: usize = std::mem::size_of::<TPMU_SENSITIVE_CREATE>();
const TPM2B_SENSITIVE_DATA_BUFFER_SIZE: usize = size_of::<TPMU_SENSITIVE_CREATE>();
} else {
use crate::tss2_esys::UINT16;
#[allow(unused_qualifications)]
const TPMU_SENSITIVE_CREATE_MEM_SIZE: usize = std::mem::size_of::<TPM2B_SENSITIVE_DATA>() - std::mem::size_of::<UINT16>();
const TPM2B_SENSITIVE_DATA_BUFFER_SIZE: usize = size_of::<TPM2B_SENSITIVE_DATA>() - size_of::<UINT16>();
}
}
buffer_type!(
SensitiveData,
TPMU_SENSITIVE_CREATE_MEM_SIZE,
TPM2B_SENSITIVE_DATA_BUFFER_SIZE,
TPM2B_SENSITIVE_DATA
);
}

pub mod symmetric_key {
use crate::tss2_esys::TPM2_MAX_SYM_KEY_BYTES;

const TPM2B_SYM_KEY_BUFFER_SIZE: usize = TPM2_MAX_SYM_KEY_BYTES as usize;
// The spec states the maximum size as:
// "MAX_SYM_KEY_BYTES will be the larger of the largest symmetric key supported by the TPM and the
// largest digest produced by any hashing algorithm implemented on the TPM"
buffer_type!(SymmetricKey, TPM2_MAX_SYM_KEY_BYTES as usize, TPM2B_SYM_KEY);
buffer_type!(SymmetricKey, TPM2B_SYM_KEY_BUFFER_SIZE, TPM2B_SYM_KEY);
}

pub mod timeout {
buffer_type!(Timeout, 8, TPM2B_TIMEOUT);
use crate::tss2_esys::UINT64;
use std::mem::size_of;
const TPM2B_TIMEOUT_BUFFER_SIZE: usize = size_of::<UINT64>();
buffer_type!(Timeout, TPM2B_TIMEOUT_BUFFER_SIZE, TPM2B_TIMEOUT);
}

pub mod tpm_context_data {
use crate::tss2_esys::TPMS_CONTEXT_DATA;
use std::mem::size_of;

#[allow(unused_qualifications)]
const TPMS_CONTEXT_DATA_MEM_SIZE: usize = std::mem::size_of::<TPMS_CONTEXT_DATA>();
const TPM2B_CONTEXT_DATA_BUFFER_SIZE: usize = size_of::<TPMS_CONTEXT_DATA>();
buffer_type!(
TpmContextData,
TPMS_CONTEXT_DATA_MEM_SIZE,
TPM2B_CONTEXT_DATA_BUFFER_SIZE,
TPM2B_CONTEXT_DATA
);
}
5 changes: 4 additions & 1 deletion tss-esapi/src/structures/buffers/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// SPDX-License-Identifier: Apache-2.0

use crate::traits::impl_mu_standard;
use std::mem::size_of;
use tss_esapi_sys::_PRIVATE;

buffer_type!(Private, ::std::mem::size_of::<_PRIVATE>(), TPM2B_PRIVATE);
const TPM2B_PRIVATE_BUFFER_SIZE: usize = size_of::<_PRIVATE>();

buffer_type!(Private, TPM2B_PRIVATE_BUFFER_SIZE, TPM2B_PRIVATE);

impl_mu_standard!(Private, TPM2B_PRIVATE);

Expand Down
4 changes: 2 additions & 2 deletions tss-esapi/src/structures/buffers/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
use log::error;
use std::{
convert::{TryFrom, TryInto},
mem::size_of,
ops::Deref,
};
use zeroize::{Zeroize, ZeroizeOnDrop};
Expand All @@ -24,8 +25,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
pub struct PublicBuffer(Vec<u8>);

impl PublicBuffer {
#[allow(unused_qualifications)]
pub const MAX_SIZE: usize = std::mem::size_of::<TPMT_PUBLIC>();
pub const MAX_SIZE: usize = size_of::<TPMT_PUBLIC>();

pub fn value(&self) -> &[u8] {
&self.0
Expand Down
4 changes: 2 additions & 2 deletions tss-esapi/src/structures/buffers/sensitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
use log::error;
use std::{
convert::{TryFrom, TryInto},
mem::size_of,
ops::Deref,
};
use zeroize::{Zeroize, ZeroizeOnDrop};
Expand All @@ -23,8 +24,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
pub struct SensitiveBuffer(Vec<u8>);

impl SensitiveBuffer {
#[allow(unused_qualifications)]
pub const MAX_SIZE: usize = std::mem::size_of::<TPMT_SENSITIVE>();
pub const MAX_SIZE: usize = size_of::<TPMT_SENSITIVE>();

pub fn value(&self) -> &[u8] {
&self.0
Expand Down
4 changes: 2 additions & 2 deletions tss-esapi/src/structures/buffers/sensitive_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
use log::error;
use std::{
convert::{TryFrom, TryInto},
mem::size_of,
ops::Deref,
};
use zeroize::{Zeroize, ZeroizeOnDrop};
Expand All @@ -23,8 +24,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
pub struct SensitiveCreateBuffer(Vec<u8>);

impl SensitiveCreateBuffer {
#[allow(unused_qualifications)]
pub const MAX_SIZE: usize = std::mem::size_of::<TPMS_SENSITIVE_CREATE>();
pub const MAX_SIZE: usize = size_of::<TPMS_SENSITIVE_CREATE>();
pub const MIN_SIZE: usize = 4;

/// Returns the content of the buffer.
Expand Down
11 changes: 5 additions & 6 deletions tss-esapi/src/structures/ecc/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use tss_esapi_sys::TPM2B_ECC_POINT;
// Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
use crate::{structures::EccParameter, tss2_esys::TPMS_ECC_POINT, Error, Result};
use std::convert::{TryFrom, TryInto};
use std::{
convert::{TryFrom, TryInto},
mem::size_of,
};

/// Structure holding ecc point information
///
Expand Down Expand Up @@ -49,11 +52,7 @@ impl From<EccPoint> for TPMS_ECC_POINT {

impl From<EccPoint> for TPM2B_ECC_POINT {
fn from(ecc_point: EccPoint) -> Self {
#[allow(unused_qualifications)]
let size = std::mem::size_of::<u16>()
+ ecc_point.x().len()
+ std::mem::size_of::<u16>()
+ ecc_point.y().len();
let size = size_of::<u16>() + ecc_point.x().len() + size_of::<u16>() + ecc_point.y().len();
TPM2B_ECC_POINT {
size: size as u16,
point: ecc_point.into(),
Expand Down
8 changes: 5 additions & 3 deletions tss-esapi/src/structures/nv/storage/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use crate::{
Error, Result, WrapperErrorKind,
};
use log::error;
use std::convert::{TryFrom, TryInto};
use std::{
convert::{TryFrom, TryInto},
mem::size_of,
};

/// Representation of the public parameters of a non-volatile
/// space allocation.
Expand All @@ -27,8 +30,7 @@ pub struct NvPublic {
}

impl NvPublic {
#[allow(unused_qualifications)]
const MAX_SIZE: usize = std::mem::size_of::<TPMS_NV_PUBLIC>();
const MAX_SIZE: usize = size_of::<TPMS_NV_PUBLIC>();

pub fn nv_index(&self) -> NvIndexTpmHandle {
self.nv_index
Expand Down
2 changes: 1 addition & 1 deletion tss-esapi/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ macro_rules! impl_marshall_trait {
($native_type:ident, $tss_type:ident, $tss_mu_type:ident, $convert_expression:stmt, $( $ref_sign:tt )?) => {
paste::item! {
impl $crate::traits::Marshall for $native_type {
const BUFFER_SIZE: usize = std::mem::size_of::<$tss_type>();
const BUFFER_SIZE: usize = ::std::mem::size_of::<$tss_type>();

fn marshall_offset(
&self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,15 @@ fn test_default() {
assert_eq!(expected, actual);
}
}

#[test]
fn test_max_sized_attest_buffer_conversions() {
let expected_attestation_data = [0xffu8; AttestBuffer::MAX_SIZE];
let native = AttestBuffer::try_from(expected_attestation_data.as_slice().to_vec()).expect(
"It should be possible to convert an array of MAX size into a AttestBuffer object.",
);
let tss = TPM2B_ATTEST::from(native);
assert_eq!(AttestBuffer::MAX_SIZE, tss.size as usize);
// This will be a compiler error if the max size does not match the TSS buffer size.
assert_eq!(expected_attestation_data, tss.attestationData);
}
Loading

0 comments on commit 2faf073

Please sign in to comment.