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)]
92pub enum TpmProtocolError {
93 InvalidAttestMagic,
96
97 InvalidBoolean,
99
100 InvalidCc,
102
103 InvalidTag,
106
107 OperationFailed,
109
110 OutOfMemory,
112
113 TooManyBytes,
115
116 TooManyItems,
118
119 TrailingData,
121
122 UnexpectedEnd,
124
125 VariantMissing,
127}
128
129impl core::fmt::Display for TpmProtocolError {
130 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
131 match self {
132 Self::InvalidAttestMagic => write!(f, "invalid attestation magic"),
133 Self::InvalidBoolean => write!(f, "invalid boolean value"),
134 Self::InvalidCc => write!(f, "invalid command code"),
135 Self::InvalidTag => write!(f, "invalid tag"),
136 Self::OperationFailed => write!(f, "operation failed"),
137 Self::OutOfMemory => write!(f, "out of memory"),
138 Self::TooManyBytes => write!(f, "bytes surpass buffer capacity"),
139 Self::TooManyItems => write!(f, "items surpass list capacity"),
140 Self::TrailingData => write!(f, "trailing data"),
141 Self::UnexpectedEnd => write!(f, "unexpected end"),
142 Self::VariantMissing => write!(f, "variant missing"),
143 }
144 }
145}
146
147impl core::error::Error for TpmProtocolError {}
148
149pub type TpmResult<T> = Result<T, TpmProtocolError>;
150
151pub struct TpmWriter<'a> {
153 buffer: &'a mut [u8],
154 cursor: usize,
155}
156
157impl<'a> TpmWriter<'a> {
158 #[must_use]
160 pub fn new(buffer: &'a mut [u8]) -> Self {
161 Self { buffer, cursor: 0 }
162 }
163
164 #[must_use]
166 pub fn len(&self) -> usize {
167 self.cursor
168 }
169
170 #[must_use]
172 pub fn is_empty(&self) -> bool {
173 self.cursor == 0
174 }
175
176 pub fn write_bytes(&mut self, bytes: &[u8]) -> TpmResult<()> {
183 let end = self.cursor + bytes.len();
184 if end > self.buffer.len() {
185 return Err(TpmProtocolError::OutOfMemory);
186 }
187 self.buffer[self.cursor..end].copy_from_slice(bytes);
188 self.cursor = end;
189 Ok(())
190 }
191}
192
193pub trait TpmSized {
196 const SIZE: usize;
199
200 fn len(&self) -> usize;
202
203 fn is_empty(&self) -> bool {
205 self.len() == 0
206 }
207}
208
209pub trait TpmMarshal {
210 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()>;
216}
217
218pub trait TpmUnmarshal: Sized + TpmSized {
219 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])>;
227}
228
229pub trait TpmTagged {
231 type Tag: TpmUnmarshal + TpmMarshal + Copy;
233 type Value;
235}
236
237pub trait TpmUnmarshalTagged: Sized {
239 fn unmarshal_tagged(tag: <Self as TpmTagged>::Tag, buf: &[u8]) -> TpmResult<(Self, &[u8])>
247 where
248 Self: TpmTagged,
249 <Self as TpmTagged>::Tag: TpmUnmarshal + TpmMarshal;
250}
251
252tpm_integer!(u8);
253tpm_integer!(i8);
254tpm_integer!(i32);
255tpm_integer!(u16);
256tpm_integer!(u32);
257tpm_integer!(u64);