tss_esapi/structures/
buffers.rs

1// Copyright 2020 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3
4#[allow(unused_macros)]
5macro_rules! named_field_buffer_type {
6    ($native_type:ident,$MAX:expr,$tss_type:ident,$buffer_field_name:ident) => {
7        use crate::tss2_esys::$tss_type;
8        use crate::{Error, Result, WrapperErrorKind};
9        use log::error;
10        use std::convert::TryFrom;
11        use std::ops::Deref;
12        use zeroize::Zeroizing;
13
14        #[derive(Debug, Clone, PartialEq, Eq)]
15        pub struct $native_type(Zeroizing<Vec<u8>>);
16
17        impl Default for $native_type {
18            fn default() -> Self {
19                $native_type(Vec::new().into())
20            }
21        }
22
23        impl $native_type {
24            pub const MAX_SIZE: usize = $MAX;
25
26            pub fn value(&self) -> &[u8] {
27                &self.0
28            }
29        }
30
31        impl Deref for $native_type {
32            type Target = Vec<u8>;
33            fn deref(&self) -> &Self::Target {
34                &self.0
35            }
36        }
37
38        impl TryFrom<Vec<u8>> for $native_type {
39            type Error = Error;
40
41            fn try_from(bytes: Vec<u8>) -> Result<Self> {
42                if bytes.len() > Self::MAX_SIZE {
43                    error!("Invalid Vec<u8> size(> {})", Self::MAX_SIZE);
44                    return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
45                }
46                Ok($native_type(bytes.into()))
47            }
48        }
49
50        impl TryFrom<&[u8]> for $native_type {
51            type Error = Error;
52
53            fn try_from(bytes: &[u8]) -> Result<Self> {
54                if bytes.len() > Self::MAX_SIZE {
55                    error!("Invalid &[u8] size(> {})", Self::MAX_SIZE);
56                    return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
57                }
58                Ok($native_type(bytes.to_vec().into()))
59            }
60        }
61
62        impl TryFrom<$tss_type> for $native_type {
63            type Error = Error;
64
65            fn try_from(tss: $tss_type) -> Result<Self> {
66                let size = tss.size as usize;
67                if size > Self::MAX_SIZE {
68                    error!("Invalid buffer size(> {})", Self::MAX_SIZE);
69                    return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
70                }
71                Ok($native_type(tss.$buffer_field_name[..size].to_vec().into()))
72            }
73        }
74
75        impl From<$native_type> for $tss_type {
76            fn from(native: $native_type) -> Self {
77                let mut buffer = $tss_type {
78                    size: native.0.len() as u16,
79                    ..Default::default()
80                };
81                buffer.$buffer_field_name[..native.0.len()].copy_from_slice(&native.0);
82                buffer
83            }
84        }
85    };
86}
87
88#[allow(unused_macros)]
89macro_rules! buffer_type {
90    ($native_type:ident,$MAX:expr,$tss_type:ident) => {
91        named_field_buffer_type!($native_type, $MAX, $tss_type, buffer);
92    };
93}
94
95pub mod attest;
96pub mod public;
97pub mod sensitive;
98
99pub mod auth {
100    // Same size as TPM2B_DIGEST according to the specification.
101    use crate::tss2_esys::TPMU_HA;
102    use std::mem::size_of;
103    const TPM2B_AUTH_BUFFER_SIZE: usize = size_of::<TPMU_HA>();
104    buffer_type!(Auth, TPM2B_AUTH_BUFFER_SIZE, TPM2B_AUTH);
105}
106
107pub mod data {
108    // This should, according to the specification, be
109    // size_of::<TPMT_HA>() but due to a bug in tpm2-tss
110    // (https://github.com/tpm2-software/tpm2-tss/issues/2888)
111    // it is the size of TPMU_HA
112    use crate::tss2_esys::TPMU_HA;
113    use std::mem::size_of;
114    const TPM2B_DATA_BUFFER_SIZE: usize = size_of::<TPMU_HA>();
115    buffer_type!(Data, TPM2B_DATA_BUFFER_SIZE, TPM2B_DATA);
116}
117
118pub mod digest {
119    use crate::tss2_esys::TPMU_HA;
120    use std::mem::size_of;
121    const TPM2B_DIGEST_BUFFER_SIZE: usize = size_of::<TPMU_HA>();
122
123    buffer_type!(Digest, TPM2B_DIGEST_BUFFER_SIZE, TPM2B_DIGEST);
124
125    // Some implementations to get from Digest to [u8; N] for common values of N (sha* primarily)
126    // This is used to work around the fact that Rust does not allow custom functions for general values of N in [T; N],
127    //  and the standard try_from for Slice to Array is only for LengthAtMost32.
128    use std::convert::TryInto;
129
130    // For the arrays that are LengthAtMost32, we use the built-in try_from
131    impl TryFrom<Digest> for [u8; 20] {
132        type Error = Error;
133
134        fn try_from(value: Digest) -> Result<Self> {
135            value
136                .value()
137                .try_into()
138                .map_err(|_| Error::local_error(WrapperErrorKind::WrongParamSize))
139        }
140    }
141
142    impl TryFrom<Digest> for [u8; 32] {
143        type Error = Error;
144
145        fn try_from(value: Digest) -> Result<Self> {
146            value
147                .value()
148                .try_into()
149                .map_err(|_| Error::local_error(WrapperErrorKind::WrongParamSize))
150        }
151    }
152
153    // For the others, we build our own
154    impl TryFrom<Digest> for [u8; 48] {
155        type Error = Error;
156
157        fn try_from(value: Digest) -> Result<Self> {
158            if value.value().len() != 48 {
159                return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
160            }
161
162            let mut result = [0; 48];
163
164            result.copy_from_slice(value.value());
165
166            Ok(result)
167        }
168    }
169
170    impl TryFrom<Digest> for [u8; 64] {
171        type Error = Error;
172
173        fn try_from(value: Digest) -> Result<Self> {
174            if value.value().len() != 64 {
175                return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
176            }
177
178            let mut result = [0; 64];
179
180            result.copy_from_slice(value.value());
181
182            Ok(result)
183        }
184    }
185}
186
187pub mod ecc_parameter {
188    use crate::tss2_esys::TPM2_MAX_ECC_KEY_BYTES;
189    const TPM2B_ECC_PARAMETER_BUFFER_SIZE: usize = TPM2_MAX_ECC_KEY_BYTES as usize;
190    buffer_type!(
191        EccParameter,
192        TPM2B_ECC_PARAMETER_BUFFER_SIZE,
193        TPM2B_ECC_PARAMETER
194    );
195}
196
197pub mod encrypted_secret {
198    use crate::tss2_esys::TPMU_ENCRYPTED_SECRET;
199    use std::mem::size_of;
200    const TPM2B_ENCRYPTED_SECRET_BUFFER_SIZE: usize = size_of::<TPMU_ENCRYPTED_SECRET>();
201    named_field_buffer_type!(
202        EncryptedSecret,
203        TPM2B_ENCRYPTED_SECRET_BUFFER_SIZE,
204        TPM2B_ENCRYPTED_SECRET,
205        secret
206    );
207}
208
209pub mod id_object {
210    use crate::tss2_esys::TPMS_ID_OBJECT;
211    use std::mem::size_of;
212    const TPM2B_ID_OBJECT_BUFFER_SIZE: usize = size_of::<TPMS_ID_OBJECT>();
213    named_field_buffer_type!(
214        IdObject,
215        TPM2B_ID_OBJECT_BUFFER_SIZE,
216        TPM2B_ID_OBJECT,
217        credential
218    );
219}
220
221pub mod initial_value {
222    use crate::tss2_esys::TPM2_MAX_SYM_BLOCK_SIZE;
223    const TPM2B_IV_BUFFER_SIZE: usize = TPM2_MAX_SYM_BLOCK_SIZE as usize;
224    buffer_type!(InitialValue, TPM2B_IV_BUFFER_SIZE, TPM2B_IV);
225}
226
227pub mod max_buffer {
228    use crate::tss2_esys::TPM2_MAX_DIGEST_BUFFER;
229    const TPM2B_MAX_BUFFER_BUFFER_SIZE: usize = TPM2_MAX_DIGEST_BUFFER as usize;
230    buffer_type!(MaxBuffer, TPM2B_MAX_BUFFER_BUFFER_SIZE, TPM2B_MAX_BUFFER);
231}
232
233pub mod max_nv_buffer {
234    use crate::tss2_esys::TPM2_MAX_NV_BUFFER_SIZE;
235    const TPM2B_MAX_NV_BUFFER_BUFFER_SIZE: usize = TPM2_MAX_NV_BUFFER_SIZE as usize;
236    buffer_type!(
237        MaxNvBuffer,
238        TPM2B_MAX_NV_BUFFER_BUFFER_SIZE,
239        TPM2B_MAX_NV_BUFFER
240    );
241}
242
243pub mod nonce {
244    // Same size as TPM2B_DIGEST according to the specification.
245    use crate::tss2_esys::TPMU_HA;
246    use std::mem::size_of;
247    const TPM2B_NONCE_BUFFER_SIZE: usize = size_of::<TPMU_HA>();
248
249    buffer_type!(Nonce, TPM2B_NONCE_BUFFER_SIZE, TPM2B_NONCE);
250}
251
252pub mod private {
253    use std::mem::size_of;
254    use tss_esapi_sys::_PRIVATE;
255    const TPM2B_PRIVATE_BUFFER_SIZE: usize = size_of::<_PRIVATE>();
256    buffer_type!(Private, TPM2B_PRIVATE_BUFFER_SIZE, TPM2B_PRIVATE);
257}
258
259pub mod private_key_rsa {
260    use crate::tss2_esys::TPM2_MAX_RSA_KEY_BYTES;
261
262    // The maximum size is given in the spec as:
263    // "RSA_PRIVATE_SIZE is a vendor specific value that can be (MAX_RSA_KEY_BYTES / 2) or
264    // ((MAX_RSA_KEY_BYTES * 5) ./ 2. The larger size would only apply to keys that have fixedTPM parents.
265    // The larger size was added in revision 01.53."
266    // The TSS stack we use only accepts the smaller of the two sizes described above (for now).
267    const TPM2B_PRIVATE_KEY_RSA_BUFFER_SIZE: usize = (TPM2_MAX_RSA_KEY_BYTES as usize) / 2;
268    buffer_type!(
269        PrivateKeyRsa,
270        TPM2B_PRIVATE_KEY_RSA_BUFFER_SIZE,
271        TPM2B_PRIVATE_KEY_RSA
272    );
273}
274
275pub mod private_vendor_specific {
276    use crate::tss2_esys::TPM2_PRIVATE_VENDOR_SPECIFIC_BYTES;
277    const TPM2B_PRIVATE_VENDOR_SPECIFIC_BUFFER_SIZE: usize =
278        TPM2_PRIVATE_VENDOR_SPECIFIC_BYTES as usize;
279    // The spec states the maximum size as:
280    // "The value for PRIVATE_VENDOR_SPECIFIC_BYTES is determined by the vendor."
281    // Not very helpful, but the TSS exposes a generic value that we can use.
282    buffer_type!(
283        PrivateVendorSpecific,
284        TPM2B_PRIVATE_VENDOR_SPECIFIC_BUFFER_SIZE,
285        TPM2B_PRIVATE_VENDOR_SPECIFIC
286    );
287}
288
289pub mod public_key_rsa {
290    use crate::{interface_types::key_bits::RsaKeyBits, tss2_esys::TPM2_MAX_RSA_KEY_BYTES};
291    const TPM2B_PUBLIC_KEY_RSA_BUFFER_SIZE: usize = TPM2_MAX_RSA_KEY_BYTES as usize;
292    buffer_type!(
293        PublicKeyRsa,
294        TPM2B_PUBLIC_KEY_RSA_BUFFER_SIZE,
295        TPM2B_PUBLIC_KEY_RSA
296    );
297
298    impl PublicKeyRsa {
299        pub fn new_empty_with_size(rsa_key_bits: RsaKeyBits) -> Self {
300            match rsa_key_bits {
301                RsaKeyBits::Rsa1024 => PublicKeyRsa(vec![0u8; 128].into()),
302                RsaKeyBits::Rsa2048 => PublicKeyRsa(vec![0u8; 256].into()),
303                RsaKeyBits::Rsa3072 => PublicKeyRsa(vec![0u8; 384].into()),
304                RsaKeyBits::Rsa4096 => PublicKeyRsa(vec![0u8; 512].into()),
305            }
306        }
307    }
308
309    impl TryFrom<PublicKeyRsa> for [u8; 128] {
310        type Error = Error;
311
312        fn try_from(public_key_rsa: PublicKeyRsa) -> Result<Self> {
313            if public_key_rsa.value().len() > 128 {
314                return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
315            }
316
317            let mut value = [0u8; 128];
318            value.copy_from_slice(public_key_rsa.value());
319            Ok(value)
320        }
321    }
322
323    impl TryFrom<PublicKeyRsa> for [u8; 256] {
324        type Error = Error;
325
326        fn try_from(public_key_rsa: PublicKeyRsa) -> Result<Self> {
327            if public_key_rsa.value().len() > 256 {
328                return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
329            }
330
331            let mut value = [0u8; 256];
332            value.copy_from_slice(public_key_rsa.value());
333            Ok(value)
334        }
335    }
336
337    impl TryFrom<PublicKeyRsa> for [u8; 384] {
338        type Error = Error;
339
340        fn try_from(public_key_rsa: PublicKeyRsa) -> Result<Self> {
341            if public_key_rsa.value().len() > 384 {
342                return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
343            }
344
345            let mut value = [0u8; 384];
346            value.copy_from_slice(public_key_rsa.value());
347            Ok(value)
348        }
349    }
350
351    impl TryFrom<PublicKeyRsa> for [u8; 512] {
352        type Error = Error;
353
354        fn try_from(public_key_rsa: PublicKeyRsa) -> Result<Self> {
355            if public_key_rsa.value().len() > 512 {
356                return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
357            }
358
359            let mut value = [0u8; 512];
360            value.copy_from_slice(public_key_rsa.value());
361            Ok(value)
362        }
363    }
364}
365
366pub mod sensitive_data {
367    // This should be size_of::<TPMU_SENSITIVE_CREATE>(), but this not available
368    // in old versions of tpm2-tss so the size calculated from sized buffer instead.
369    use crate::tss2_esys::UINT16;
370    use std::mem::size_of;
371    const TPM2B_SENSITIVE_DATA_BUFFER_SIZE: usize =
372        size_of::<TPM2B_SENSITIVE_DATA>() - size_of::<UINT16>();
373    buffer_type!(
374        SensitiveData,
375        TPM2B_SENSITIVE_DATA_BUFFER_SIZE,
376        TPM2B_SENSITIVE_DATA
377    );
378}
379
380pub mod symmetric_key {
381    use crate::tss2_esys::TPM2_MAX_SYM_KEY_BYTES;
382    const TPM2B_SYM_KEY_BUFFER_SIZE: usize = TPM2_MAX_SYM_KEY_BYTES as usize;
383    // The spec states the maximum size as:
384    // "MAX_SYM_KEY_BYTES will be the larger of the largest symmetric key supported by the TPM and the
385    // largest digest produced by any hashing algorithm implemented on the TPM"
386    buffer_type!(SymmetricKey, TPM2B_SYM_KEY_BUFFER_SIZE, TPM2B_SYM_KEY);
387}
388
389pub mod timeout {
390    use crate::tss2_esys::UINT64;
391    use std::mem::size_of;
392    const TPM2B_TIMEOUT_BUFFER_SIZE: usize = size_of::<UINT64>();
393    buffer_type!(Timeout, TPM2B_TIMEOUT_BUFFER_SIZE, TPM2B_TIMEOUT);
394}