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) -> TpmMarshalResult<()> {
53 TpmMarshal::marshal(&self.0, writer)
54 }
55}
56
57impl TpmUnmarshal for TpmHandle {
58 fn unmarshal(buf: &[u8]) -> TpmUnmarshalResult<(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 TpmMarshalError {
107 CapacityExceeded,
109 InvalidValue,
111}
112
113impl core::fmt::Display for TpmMarshalError {
114 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
115 match self {
116 Self::CapacityExceeded => write!(f, "capacity exceeded"),
117 Self::InvalidValue => write!(f, "invalid value"),
118 }
119 }
120}
121
122#[derive(Debug, PartialEq, Eq)]
123pub enum TpmUnmarshalError {
125 CapacityExceeded,
127 InvalidDiscriminant(&'static str, TpmDiscriminant),
129 MalformedValue,
131 TrailingData,
133 TruncatedData,
135}
136
137impl core::fmt::Display for TpmUnmarshalError {
138 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
139 match self {
140 Self::CapacityExceeded => write!(f, "capacity exceeded"),
141 Self::InvalidDiscriminant(type_name, value) => {
142 write!(f, "invalid discriminant: {type_name}: 0x{value:x}")
143 }
144 Self::MalformedValue => write!(f, "malformed value"),
145 Self::TrailingData => write!(f, "trailing data"),
146 Self::TruncatedData => write!(f, "truncated data"),
147 }
148 }
149}
150
151pub type TpmMarshalResult<T> = Result<T, TpmMarshalError>;
152pub type TpmUnmarshalResult<T> = Result<T, TpmUnmarshalError>;
153
154pub struct TpmWriter<'a> {
156 buffer: &'a mut [u8],
157 cursor: usize,
158}
159
160impl<'a> TpmWriter<'a> {
161 #[must_use]
163 pub fn new(buffer: &'a mut [u8]) -> Self {
164 Self { buffer, cursor: 0 }
165 }
166
167 #[must_use]
169 pub fn len(&self) -> usize {
170 self.cursor
171 }
172
173 #[must_use]
175 pub fn is_empty(&self) -> bool {
176 self.cursor == 0
177 }
178
179 pub fn write_bytes(&mut self, bytes: &[u8]) -> TpmMarshalResult<()> {
186 let end = self.cursor + bytes.len();
187 if end > self.buffer.len() {
188 return Err(TpmMarshalError::CapacityExceeded);
189 }
190 self.buffer[self.cursor..end].copy_from_slice(bytes);
191 self.cursor = end;
192 Ok(())
193 }
194}
195
196pub trait TpmSized {
199 const SIZE: usize;
202
203 fn len(&self) -> usize;
205
206 fn is_empty(&self) -> bool {
208 self.len() == 0
209 }
210}
211
212pub trait TpmMarshal: TpmSized {
213 fn marshal(&self, writer: &mut TpmWriter) -> TpmMarshalResult<()>;
219}
220
221pub trait TpmUnmarshal: Sized + TpmSized {
222 fn unmarshal(buf: &[u8]) -> TpmUnmarshalResult<(Self, &[u8])>;
230}
231
232pub trait TpmTagged {
234 type Tag: TpmUnmarshal + TpmMarshal + Copy;
236 type Value;
238}
239
240pub trait TpmUnmarshalTagged: Sized {
242 fn unmarshal_tagged(
250 tag: <Self as TpmTagged>::Tag,
251 buf: &[u8],
252 ) -> TpmUnmarshalResult<(Self, &[u8])>
253 where
254 Self: TpmTagged,
255 <Self as TpmTagged>::Tag: TpmUnmarshal + TpmMarshal;
256}
257
258tpm_integer!(u8, Unsigned);
259tpm_integer!(i8, Signed);
260tpm_integer!(i32, Signed);
261tpm_integer!(u16, Unsigned);
262tpm_integer!(u32, Unsigned);
263tpm_integer!(u64, Unsigned);