1#![cfg_attr(not(test), no_std)]
22#![deny(unsafe_code)]
23#![deny(clippy::all)]
24#![deny(clippy::pedantic)]
25#![recursion_limit = "256"]
26
27pub mod basic;
28pub mod constant;
29pub mod data;
30#[macro_use]
31pub mod r#macro;
32pub mod frame;
33
34#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
36#[repr(transparent)]
37pub struct TpmHandle(pub u32);
38
39impl core::convert::From<u32> for TpmHandle {
40 fn from(val: u32) -> Self {
41 Self(val)
42 }
43}
44
45impl core::convert::From<TpmHandle> for u32 {
46 fn from(val: TpmHandle) -> Self {
47 val.0
48 }
49}
50
51impl TpmMarshal for TpmHandle {
52 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
53 TpmMarshal::marshal(&self.0, writer)
54 }
55}
56
57impl TpmUnmarshal for TpmHandle {
58 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
59 let (val, buf) = u32::unmarshal(buf)?;
60 Ok((Self(val), buf))
61 }
62}
63
64impl TpmSized for TpmHandle {
65 const SIZE: usize = size_of::<u32>();
66 fn len(&self) -> usize {
67 Self::SIZE
68 }
69}
70
71impl core::fmt::Display for TpmHandle {
72 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73 core::fmt::Display::fmt(&self.0, f)
74 }
75}
76
77impl core::fmt::LowerHex for TpmHandle {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 core::fmt::LowerHex::fmt(&self.0, f)
80 }
81}
82
83impl core::fmt::UpperHex for TpmHandle {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85 core::fmt::UpperHex::fmt(&self.0, f)
86 }
87}
88
89#[derive(Debug, PartialEq, Eq)]
90pub enum TpmDiscriminant {
91 Signed(i64),
92 Unsigned(u64),
93}
94
95impl core::fmt::LowerHex for TpmDiscriminant {
96 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
97 match self {
98 TpmDiscriminant::Signed(v) => write!(f, "{v:x}"),
99 TpmDiscriminant::Unsigned(v) => write!(f, "{v:x}"),
100 }
101 }
102}
103
104#[derive(Debug, PartialEq, Eq)]
105pub enum TpmError {
107 CapacityExceeded,
109 InvalidDiscriminant(&'static str, TpmDiscriminant),
111 Malformed,
113 Trailing,
115 Truncated,
117}
118
119impl core::fmt::Display for TpmError {
120 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121 match self {
122 Self::CapacityExceeded => write!(f, "capacity has been exceeded"),
123 Self::InvalidDiscriminant(type_name, value) => {
124 write!(f, "unknown discriminant: {type_name}: 0x{value:x}")
125 }
126 Self::Malformed => write!(f, "data is malformed"),
127 Self::Trailing => write!(f, "trailing data left"),
128 Self::Truncated => write!(f, "data is truncated"),
129 }
130 }
131}
132
133pub type TpmResult<T> = Result<T, TpmError>;
134
135pub struct TpmWriter<'a> {
137 buffer: &'a mut [u8],
138 cursor: usize,
139}
140
141impl<'a> TpmWriter<'a> {
142 #[must_use]
144 pub fn new(buffer: &'a mut [u8]) -> Self {
145 Self { buffer, cursor: 0 }
146 }
147
148 #[must_use]
150 pub fn len(&self) -> usize {
151 self.cursor
152 }
153
154 #[must_use]
156 pub fn is_empty(&self) -> bool {
157 self.cursor == 0
158 }
159
160 pub fn write_bytes(&mut self, bytes: &[u8]) -> TpmResult<()> {
167 let end = self.cursor + bytes.len();
168 if end > self.buffer.len() {
169 return Err(TpmError::CapacityExceeded);
170 }
171 self.buffer[self.cursor..end].copy_from_slice(bytes);
172 self.cursor = end;
173 Ok(())
174 }
175}
176
177pub trait TpmSized {
180 const SIZE: usize;
183
184 fn len(&self) -> usize;
186
187 fn is_empty(&self) -> bool {
189 self.len() == 0
190 }
191}
192
193pub trait TpmMarshal: TpmSized {
194 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()>;
200}
201
202pub trait TpmUnmarshal: Sized + TpmSized {
203 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])>;
211}
212
213pub trait TpmTagged {
215 type Tag: TpmUnmarshal + TpmMarshal + Copy;
217 type Value;
219}
220
221pub trait TpmUnmarshalTagged: Sized {
223 fn unmarshal_tagged(tag: <Self as TpmTagged>::Tag, buf: &[u8]) -> TpmResult<(Self, &[u8])>
231 where
232 Self: TpmTagged,
233 <Self as TpmTagged>::Tag: TpmUnmarshal + TpmMarshal;
234}
235
236tpm_integer!(u8, Unsigned);
237tpm_integer!(i8, Signed);
238tpm_integer!(i32, Signed);
239tpm_integer!(u16, Unsigned);
240tpm_integer!(u32, Unsigned);
241tpm_integer!(u64, Unsigned);