tpm2_protocol/basic/
buffer.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2025 Opinsys Oy
3// Copyright (c) 2024-2025 Jarkko Sakkinen
4
5use crate::{TpmMarshal, TpmProtocolError, TpmResult, TpmSized, TpmUnmarshal, TpmWriter};
6use core::{convert::TryFrom, fmt::Debug, mem::size_of, ops::Deref};
7
8/// A buffer in the TPM2B wire format.
9///
10/// The `size` field is stored in native endian and converted to big-endian
11/// only during marshaling.
12#[derive(Clone, Copy, PartialEq, Eq)]
13pub struct TpmBuffer<const CAPACITY: usize> {
14    size: u16,
15    data: [u8; CAPACITY],
16}
17
18impl<const CAPACITY: usize> TpmBuffer<CAPACITY> {
19    /// Creates a new, empty `TpmBuffer`.
20    #[must_use]
21    pub const fn new() -> Self {
22        Self {
23            size: 0,
24            data: [0; CAPACITY],
25        }
26    }
27}
28
29impl<const CAPACITY: usize> Deref for TpmBuffer<CAPACITY> {
30    type Target = [u8];
31
32    fn deref(&self) -> &Self::Target {
33        let size = self.size as usize;
34        &self.data[..size]
35    }
36}
37
38impl<const CAPACITY: usize> Default for TpmBuffer<CAPACITY> {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl<const CAPACITY: usize> TpmSized for TpmBuffer<CAPACITY> {
45    const SIZE: usize = size_of::<u16>() + CAPACITY;
46    fn len(&self) -> usize {
47        size_of::<u16>() + self.size as usize
48    }
49}
50
51impl<const CAPACITY: usize> TpmMarshal for TpmBuffer<CAPACITY> {
52    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
53        self.size.marshal(writer)?;
54        writer.write_bytes(&self.data[..self.size as usize])
55    }
56}
57
58impl<const CAPACITY: usize> TpmUnmarshal for TpmBuffer<CAPACITY> {
59    fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
60        let (native_size, remainder) = u16::unmarshal(buf)?;
61        let size_usize = native_size as usize;
62
63        if size_usize > CAPACITY {
64            return Err(TpmProtocolError::BufferTooLarge);
65        }
66
67        if remainder.len() < size_usize {
68            return Err(TpmProtocolError::UnexpectedEnd);
69        }
70
71        let mut buffer = Self::new();
72        buffer.size = native_size;
73        buffer.data[..size_usize].copy_from_slice(&remainder[..size_usize]);
74        Ok((buffer, &remainder[size_usize..]))
75    }
76}
77
78impl<'a, const CAPACITY: usize> TryFrom<&'a [u8]> for TpmBuffer<CAPACITY> {
79    type Error = TpmProtocolError;
80
81    fn try_from(slice: &'a [u8]) -> Result<Self, Self::Error> {
82        if slice.len() > CAPACITY {
83            return Err(TpmProtocolError::BufferTooLarge);
84        }
85        let mut buffer = Self::new();
86        let len_u16 = u16::try_from(slice.len()).map_err(|_| TpmProtocolError::OperationFailed)?;
87        buffer.size = len_u16;
88        buffer.data[..slice.len()].copy_from_slice(slice);
89        Ok(buffer)
90    }
91}
92
93impl<const CAPACITY: usize> AsRef<[u8]> for TpmBuffer<CAPACITY> {
94    fn as_ref(&self) -> &[u8] {
95        self
96    }
97}
98
99impl<const CAPACITY: usize> Debug for TpmBuffer<CAPACITY> {
100    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
101        write!(f, "TpmBuffer(")?;
102        for byte in self.iter() {
103            write!(f, "{byte:02X}")?;
104        }
105        write!(f, ")")
106    }
107}