Skip to main content

tss_esapi/structures/buffers/
public.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    structures::Public,
6    traits::{Marshall, UnMarshall},
7    tss2_esys::{TPM2B_PUBLIC, TPMT_PUBLIC},
8    Error, Result, WrapperErrorKind,
9};
10use log::error;
11use std::{
12    convert::{TryFrom, TryInto},
13    mem::size_of,
14    ops::Deref,
15};
16use zeroize::Zeroize;
17
18/// Public data buffer.
19///
20/// # Details
21/// Corresponds to `TPM2B_PUBLIC`. The contents of
22/// the buffer can be unmarshalled into a [Public]
23/// structure.
24#[derive(Debug, Clone, PartialEq, Eq, Zeroize)]
25#[zeroize(drop)]
26pub struct PublicBuffer(Vec<u8>);
27
28impl PublicBuffer {
29    #[allow(unused_qualifications)]
30    pub const MAX_SIZE: usize = size_of::<TPMT_PUBLIC>();
31
32    pub fn value(&self) -> &[u8] {
33        &self.0
34    }
35}
36
37impl Deref for PublicBuffer {
38    type Target = Vec<u8>;
39
40    fn deref(&self) -> &Self::Target {
41        &self.0
42    }
43}
44
45impl TryFrom<Vec<u8>> for PublicBuffer {
46    type Error = Error;
47
48    fn try_from(bytes: Vec<u8>) -> Result<Self> {
49        if bytes.len() > Self::MAX_SIZE {
50            error!(
51                "Error: Invalid Vec<u8> size ({} > {})",
52                bytes.len(),
53                Self::MAX_SIZE
54            );
55            return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
56        }
57        Ok(PublicBuffer(bytes))
58    }
59}
60
61impl TryFrom<&[u8]> for PublicBuffer {
62    type Error = Error;
63
64    fn try_from(bytes: &[u8]) -> Result<Self> {
65        if bytes.len() > Self::MAX_SIZE {
66            error!(
67                "Error: Invalid &[u8] size ({} > {})",
68                bytes.len(),
69                Self::MAX_SIZE
70            );
71            return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
72        }
73        Ok(PublicBuffer(bytes.to_vec()))
74    }
75}
76
77impl TryFrom<TPM2B_PUBLIC> for PublicBuffer {
78    type Error = Error;
79
80    fn try_from(tss: TPM2B_PUBLIC) -> Result<Self> {
81        let size = tss.size as usize;
82        if size > Self::MAX_SIZE {
83            error!("Error: Invalid buffer size ({} > {})", size, Self::MAX_SIZE);
84            return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
85        }
86        let public = Public::try_from(tss.publicArea)?;
87        Ok(PublicBuffer(public.marshall()?))
88    }
89}
90
91impl TryFrom<PublicBuffer> for TPM2B_PUBLIC {
92    type Error = Error;
93
94    fn try_from(native: PublicBuffer) -> Result<Self> {
95        let mut buffer = TPM2B_PUBLIC {
96            size: native.0.len() as u16,
97            ..Default::default()
98        };
99        let public = Public::unmarshall(&native.0)?;
100        buffer.publicArea = public.into();
101        Ok(buffer)
102    }
103}
104
105impl TryFrom<PublicBuffer> for Public {
106    type Error = Error;
107
108    fn try_from(buf: PublicBuffer) -> Result<Self> {
109        Public::unmarshall(&buf.0)
110    }
111}
112
113impl TryFrom<Public> for PublicBuffer {
114    type Error = Error;
115
116    fn try_from(public: Public) -> Result<PublicBuffer> {
117        Ok(PublicBuffer(public.marshall()?))
118    }
119}
120
121impl Marshall for PublicBuffer {
122    const BUFFER_SIZE: usize = size_of::<TPM2B_PUBLIC>();
123
124    /// Produce a marshalled [`TPM2B_PUBLIC`]
125    fn marshall(&self) -> Result<Vec<u8>> {
126        let mut buffer = vec![0; Self::BUFFER_SIZE];
127        let mut offset = 0;
128
129        let ret = Error::from_tss_rc(unsafe {
130            crate::tss2_esys::Tss2_MU_TPM2B_PUBLIC_Marshal(
131                &self.clone().try_into()?,
132                buffer.as_mut_ptr(),
133                Self::BUFFER_SIZE.try_into().map_err(|e| {
134                    error!("Failed to convert size of buffer to TSS size_t type: {}", e);
135                    Error::local_error(WrapperErrorKind::InvalidParam)
136                })?,
137                &mut offset,
138            )
139        });
140
141        if !ret.is_success() {
142            return Err(ret);
143        }
144
145        let checked_offset = usize::try_from(offset).map_err(|e| {
146            error!("Failed to parse offset as usize: {}", e);
147            Error::local_error(WrapperErrorKind::InvalidParam)
148        })?;
149
150        buffer.truncate(checked_offset);
151
152        Ok(buffer)
153    }
154}
155
156impl UnMarshall for PublicBuffer {
157    /// Unmarshall the structure from [`TPM2B_PUBLIC`]
158    fn unmarshall(marshalled_data: &[u8]) -> Result<Self> {
159        let mut dest = TPM2B_PUBLIC::default();
160        let mut offset = 0;
161
162        let ret = Error::from_tss_rc(unsafe {
163            crate::tss2_esys::Tss2_MU_TPM2B_PUBLIC_Unmarshal(
164                marshalled_data.as_ptr(),
165                marshalled_data.len().try_into().map_err(|e| {
166                    error!("Failed to convert length of marshalled data: {}", e);
167                    Error::local_error(WrapperErrorKind::InvalidParam)
168                })?,
169                &mut offset,
170                &mut dest,
171            )
172        });
173
174        if !ret.is_success() {
175            return Err(ret);
176        }
177
178        PublicBuffer::try_from(dest)
179    }
180}