tpm2_protocol/basic/
buffer.rs1use crate::{
6 TpmCast, TpmCastMut, TpmError, TpmMarshal, TpmResult, TpmSized, TpmUnmarshal, TpmWriter,
7 basic::TpmUint16,
8};
9use core::{
10 convert::TryFrom,
11 fmt::Debug,
12 hash::{Hash, Hasher},
13 mem::{MaybeUninit, size_of},
14 ops::Deref,
15 slice,
16};
17
18const TPM2B_SIZE_LEN: usize = size_of::<TpmUint16>();
19
20#[repr(transparent)]
22pub struct Tpm2b<const CAPACITY: usize>([u8]);
23
24impl<const CAPACITY: usize> Tpm2b<CAPACITY> {
25 pub fn cast(buf: &[u8]) -> TpmResult<&Self> {
36 Self::validate(buf)?;
37
38 Ok(unsafe { Self::cast_unchecked(buf) })
41 }
42
43 #[must_use]
50 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
51 let ptr = core::ptr::from_ref(buf) as *const Self;
52
53 unsafe { &*ptr }
56 }
57
58 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
69 Self::validate(buf)?;
70
71 Ok(unsafe { Self::cast_mut_unchecked(buf) })
75 }
76
77 #[must_use]
86 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
87 let ptr = core::ptr::from_mut(buf) as *mut Self;
88
89 unsafe { &mut *ptr }
92 }
93
94 #[must_use]
96 pub const fn as_bytes(&self) -> &[u8] {
97 &self.0
98 }
99
100 #[must_use]
102 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
103 &mut self.0
104 }
105
106 #[must_use]
108 pub fn size(&self) -> usize {
109 Self::read_size(&self.0)
110 }
111
112 #[must_use]
114 pub fn data(&self) -> &[u8] {
115 &self.0[TPM2B_SIZE_LEN..]
116 }
117
118 #[must_use]
120 pub fn data_mut(&mut self) -> &mut [u8] {
121 &mut self.0[TPM2B_SIZE_LEN..]
122 }
123
124 #[must_use]
126 pub const fn len(&self) -> usize {
127 self.0.len()
128 }
129
130 #[must_use]
132 pub fn is_empty(&self) -> bool {
133 self.size() == 0
134 }
135
136 fn validate(buf: &[u8]) -> TpmResult<()> {
137 if buf.len() < TPM2B_SIZE_LEN {
138 return Err(TpmError::UnexpectedEnd(
139 crate::TpmErrorValue::new(0).size(TPM2B_SIZE_LEN, buf.len()),
140 ));
141 }
142
143 let payload_len = Self::read_size(buf);
144 if payload_len > CAPACITY {
145 return Err(TpmError::TooManyBytes(
146 crate::TpmErrorValue::new(0).limit(CAPACITY, payload_len),
147 ));
148 }
149
150 let wire_len = TPM2B_SIZE_LEN
151 .checked_add(payload_len)
152 .ok_or(TpmError::IntegerTooLarge(
153 crate::TpmErrorValue::new(0).value_usize(payload_len),
154 ))?;
155
156 if buf.len() < wire_len {
157 return Err(TpmError::UnexpectedEnd(
158 crate::TpmErrorValue::new(TPM2B_SIZE_LEN)
159 .size(payload_len, buf.len().saturating_sub(TPM2B_SIZE_LEN)),
160 ));
161 }
162
163 if buf.len() > wire_len {
164 return Err(TpmError::TrailingData(
165 crate::TpmErrorValue::new(wire_len).actual(buf.len() - wire_len),
166 ));
167 }
168
169 Ok(())
170 }
171
172 fn read_size(buf: &[u8]) -> usize {
173 usize::from(u16::from_be_bytes([buf[0], buf[1]]))
174 }
175}
176
177impl<const CAPACITY: usize> TpmCast for Tpm2b<CAPACITY> {
178 fn cast(buf: &[u8]) -> TpmResult<&Self> {
179 Self::cast(buf)
180 }
181
182 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
183 unsafe { Self::cast_unchecked(buf) }
185 }
186}
187
188impl<const CAPACITY: usize> TpmCastMut for Tpm2b<CAPACITY> {
189 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
190 Self::cast_mut(buf)
191 }
192
193 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
194 unsafe { Self::cast_mut_unchecked(buf) }
197 }
198}
199
200impl<const CAPACITY: usize> AsRef<[u8]> for Tpm2b<CAPACITY> {
201 fn as_ref(&self) -> &[u8] {
202 self.as_bytes()
203 }
204}
205
206impl<const CAPACITY: usize> AsMut<[u8]> for Tpm2b<CAPACITY> {
207 fn as_mut(&mut self) -> &mut [u8] {
208 self.as_bytes_mut()
209 }
210}
211
212#[derive(Clone, Copy)]
217pub struct TpmBuffer<const CAPACITY: usize> {
218 size: u16,
219 data: [MaybeUninit<u8>; CAPACITY],
220}
221
222impl<const CAPACITY: usize> TpmBuffer<CAPACITY> {
223 #[must_use]
225 pub const fn new() -> Self {
226 Self {
227 size: 0,
228 data: [const { MaybeUninit::uninit() }; CAPACITY],
229 }
230 }
231
232 pub fn try_push(&mut self, byte: u8) -> TpmResult<()> {
239 if (self.size as usize) >= CAPACITY || self.size == u16::MAX {
240 return Err(TpmError::BufferOverflow(
241 crate::TpmErrorValue::new(self.size as usize)
242 .limit(CAPACITY, self.size as usize + 1),
243 ));
244 }
245 self.data[self.size as usize].write(byte);
246 self.size += 1;
247 Ok(())
248 }
249
250 pub fn try_extend_from_slice(&mut self, slice: &[u8]) -> TpmResult<()> {
257 let current_len = self.size as usize;
258 let new_len = current_len
259 .checked_add(slice.len())
260 .ok_or(TpmError::BufferOverflow(
261 crate::TpmErrorValue::new(current_len)
262 .size(slice.len(), CAPACITY.saturating_sub(current_len)),
263 ))?;
264
265 if new_len > CAPACITY {
266 return Err(TpmError::BufferOverflow(
267 crate::TpmErrorValue::new(current_len).limit(CAPACITY, new_len),
268 ));
269 }
270
271 self.size = u16::try_from(new_len).map_err(|_| {
272 TpmError::BufferOverflow(
273 crate::TpmErrorValue::new(current_len).limit(u16::MAX as usize, new_len),
274 )
275 })?;
276
277 for (dest, src) in self.data[current_len..new_len].iter_mut().zip(slice) {
278 dest.write(*src);
279 }
280 Ok(())
281 }
282}
283
284impl<const CAPACITY: usize> Deref for TpmBuffer<CAPACITY> {
285 type Target = [u8];
286
287 fn deref(&self) -> &Self::Target {
288 let size = self.size as usize;
289
290 unsafe { slice::from_raw_parts(self.data.as_ptr().cast::<u8>(), size) }
293 }
294}
295
296impl<const CAPACITY: usize> Default for TpmBuffer<CAPACITY> {
297 fn default() -> Self {
298 Self::new()
299 }
300}
301
302impl<const CAPACITY: usize> PartialEq for TpmBuffer<CAPACITY> {
303 fn eq(&self, other: &Self) -> bool {
304 **self == **other
305 }
306}
307
308impl<const CAPACITY: usize> Eq for TpmBuffer<CAPACITY> {}
309
310impl<const CAPACITY: usize> Hash for TpmBuffer<CAPACITY> {
311 fn hash<H: Hasher>(&self, state: &mut H) {
312 (**self).hash(state);
313 }
314}
315
316impl<const CAPACITY: usize> TpmSized for TpmBuffer<CAPACITY> {
317 const SIZE: usize = size_of::<TpmUint16>() + CAPACITY;
318 fn len(&self) -> usize {
319 size_of::<TpmUint16>() + self.size as usize
320 }
321}
322
323impl<const CAPACITY: usize> TpmMarshal for TpmBuffer<CAPACITY> {
324 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
325 TpmUint16::from(self.size).marshal(writer)?;
326 writer.write_bytes(self)
327 }
328}
329
330impl<const CAPACITY: usize> TpmUnmarshal for TpmBuffer<CAPACITY> {
331 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
332 let (native_size, remainder) = TpmUint16::unmarshal(buf)?;
333 let size_usize = u16::from(native_size) as usize;
334
335 if size_usize > CAPACITY {
336 return Err(TpmError::TooManyBytes(
337 crate::TpmErrorValue::new(0).limit(CAPACITY, size_usize),
338 ));
339 }
340
341 if remainder.len() < size_usize {
342 return Err(TpmError::UnexpectedEnd(
343 crate::TpmErrorValue::new(TPM2B_SIZE_LEN).size(size_usize, remainder.len()),
344 ));
345 }
346
347 let mut buffer = Self::new();
348 buffer.try_extend_from_slice(&remainder[..size_usize])?;
349 Ok((buffer, &remainder[size_usize..]))
350 }
351}
352
353impl<const CAPACITY: usize> TryFrom<&[u8]> for TpmBuffer<CAPACITY> {
354 type Error = TpmError;
355
356 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
357 if slice.len() > CAPACITY {
358 return Err(TpmError::TooManyBytes(
359 crate::TpmErrorValue::new(0).limit(CAPACITY, slice.len()),
360 ));
361 }
362 let mut buffer = Self::new();
363 buffer.try_extend_from_slice(slice)?;
364 Ok(buffer)
365 }
366}
367
368impl<const CAPACITY: usize> AsRef<[u8]> for TpmBuffer<CAPACITY> {
369 fn as_ref(&self) -> &[u8] {
370 self
371 }
372}
373
374impl<const CAPACITY: usize> Debug for TpmBuffer<CAPACITY> {
375 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
376 write!(f, "TpmBuffer(")?;
377 for byte in self.iter() {
378 write!(f, "{byte:02X}")?;
379 }
380 write!(f, ")")
381 }
382}