1pub mod r#enum;
6pub mod integer;
7pub mod r#struct;
8
9#[macro_export]
10macro_rules! tpm_bitflags {
11 (
12 $(#[$outer:meta])*
13 $vis:vis struct $name:ident($repr:ty) {
14 $(
15 $(#[$inner:meta])*
16 const $field:ident = $value:expr, $string_name:literal;
17 )*
18 }
19 ) => {
20 $(#[$outer])*
21 $vis struct $name($repr);
22
23 impl $name {
24 $(
25 $(#[$inner])*
26 pub const $field: Self = Self($value);
27 )*
28
29 #[must_use]
30 pub const fn bits(&self) -> $repr {
31 self.0
32 }
33
34 #[must_use]
35 pub const fn from_bits_truncate(bits: $repr) -> Self {
36 Self(bits)
37 }
38
39 #[must_use]
40 pub const fn empty() -> Self {
41 Self(0)
42 }
43
44 #[must_use]
45 pub const fn contains(&self, other: Self) -> bool {
46 (self.0 & other.0) == other.0
47 }
48
49 pub fn flag_names(&self) -> impl Iterator<Item = &'static str> + '_ {
50 [
51 $(
52 (Self::$field, $string_name),
53 )*
54 ]
55 .into_iter()
56 .filter(move |(flag, _)| self.contains(*flag))
57 .map(|(_, name)| name)
58 }
59 }
60
61 impl core::ops::BitOr for $name {
62 type Output = Self;
63 fn bitor(self, rhs: Self) -> Self::Output {
64 Self(self.0 | rhs.0)
65 }
66 }
67
68 impl core::ops::BitOrAssign for $name {
69 fn bitor_assign(&mut self, rhs: Self) {
70 self.0 |= rhs.0;
71 }
72 }
73
74 impl $crate::TpmBuild for $name {
75 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
76 $crate::TpmBuild::build(&self.0, writer)
77 }
78 }
79
80 impl $crate::TpmParse for $name {
81 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
82 let (val, buf) = <$repr>::parse(buf)?;
83 Ok((Self(val), buf))
84 }
85 }
86
87 impl $crate::TpmSized for $name {
88 const SIZE: usize = core::mem::size_of::<$repr>();
89 fn len(&self) -> usize {
90 Self::SIZE
91 }
92 }
93 };
94}
95
96#[macro_export]
97macro_rules! tpm_bool {
98 (
99 $(#[$outer:meta])*
100 $vis:vis struct $name:ident(bool);
101 ) => {
102 $(#[$outer])*
103 $vis struct $name(pub bool);
104
105 impl From<bool> for $name {
106 fn from(val: bool) -> Self {
107 Self(val)
108 }
109 }
110
111 impl From<$name> for bool {
112 fn from(val: $name) -> Self {
113 val.0
114 }
115 }
116
117 impl $crate::TpmBuild for $name {
118 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
119 $crate::TpmBuild::build(&u8::from(self.0), writer)
120 }
121 }
122
123 impl $crate::TpmParse for $name {
124 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
125 let (val, buf) = u8::parse(buf)?;
126 match val {
127 0 => Ok((Self(false), buf)),
128 1 => Ok((Self(true), buf)),
129 _ => Err($crate::TpmErrorKind::NotDiscriminant (stringify!($name), TpmNotDiscriminant::Unsigned(u64::from(val)))),
130 }
131 }
132 }
133
134 impl $crate::TpmSized for $name {
135 const SIZE: usize = core::mem::size_of::<u8>();
136 fn len(&self) -> usize {
137 Self::SIZE
138 }
139 }
140 };
141}
142
143#[macro_export]
144macro_rules! tpm_dispatch {
145 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
146 macro_rules! tpm_command_parser {
147 ($value:ty, $name:ident) => {
148 (
149 <$value as $crate::message::TpmHeader>::COMMAND,
150 <$value as $crate::message::TpmHeader>::NO_SESSIONS,
151 <$value as $crate::message::TpmHeader>::WITH_SESSIONS,
152 <$value as $crate::message::TpmHeader>::HANDLES,
153 |handles, params| {
154 <$value as $crate::message::TpmCommandBodyParse>::parse_body(handles, params)
155 .map(|(c, r)| (TpmCommandBody::$name(c), r))
156 },
157 )
158 };
159 }
160
161 macro_rules! tpm_response_parser {
162 ($rsp_ty:ty, $enum_variant:ident) => {
163 (
164 <$rsp_ty as $crate::message::TpmHeader>::COMMAND,
165 <$rsp_ty as $crate::message::TpmHeader>::WITH_SESSIONS,
166 |tag, buf| {
167 <$rsp_ty as $crate::message::TpmResponseBodyParse>::parse_body(tag, buf)
168 .map(|(r, rest)| (TpmResponseBody::$enum_variant(r), rest))
169 },
170 )
171 };
172 }
173
174 #[allow(clippy::large_enum_variant)]
176 #[derive(Debug, PartialEq, Eq, Clone)]
177 pub enum TpmCommandBody {
178 $( $variant($cmd), )*
179 }
180
181 #[allow(clippy::large_enum_variant)]
183 #[derive(Debug, PartialEq, Eq, Clone)]
184 pub enum TpmResponseBody {
185 $( $variant($resp), )*
186 }
187
188 impl TpmResponseBody {
189 $(
190 #[allow(non_snake_case, clippy::result_large_err)]
196 pub fn $variant(self) -> Result<$resp, Self> {
197 if let Self::$variant(r) = self {
198 Ok(r)
199 } else {
200 Err(self)
201 }
202 }
203 )*
204 }
205
206 pub type TpmCommandParser = for<'a> fn(&'a [u8], &'a [u8]) -> $crate::TpmResult<(TpmCommandBody, &'a [u8])>;
207 pub type TpmResponseParser = for<'a> fn($crate::data::TpmSt, &'a [u8]) -> $crate::TpmResult<(TpmResponseBody, &'a [u8])>;
208
209 pub(crate) static PARSE_COMMAND_MAP: &[($crate::data::TpmCc, bool, bool, usize, TpmCommandParser)] =
210 &[$(tpm_command_parser!($cmd, $variant),)*];
211
212 pub(crate) static PARSE_RESPONSE_MAP: &[($crate::data::TpmCc, bool, TpmResponseParser)] =
213 &[$(tpm_response_parser!($resp, $variant),)*];
214
215 const _: () = {
216 let mut i = 1;
217 while i < PARSE_COMMAND_MAP.len() {
218 if PARSE_COMMAND_MAP[i - 1].0 as u32 > PARSE_COMMAND_MAP[i].0 as u32 {
219 panic!("PARSE_COMMAND_MAP must be sorted by TpmCc.");
220 }
221 i += 1;
222 }
223 };
224
225 const _: () = {
226 let mut i = 1;
227 while i < PARSE_RESPONSE_MAP.len() {
228 if PARSE_RESPONSE_MAP[i - 1].0 as u32 > PARSE_RESPONSE_MAP[i].0 as u32 {
229 panic!("PARSE_RESPONSE_MAP must be sorted by TpmCc.");
230 }
231 i += 1;
232 }
233 };
234 };
235}
236
237#[macro_export]
238macro_rules! tpm_handle {
239 (
240 $(#[$meta:meta])*
241 $name:ident
242 ) => {
243 $(#[$meta])*
244 pub struct $name(pub u32);
245
246 impl From<u32> for $name {
247 fn from(val: u32) -> Self {
248 Self(val)
249 }
250 }
251
252 impl From<$name> for u32 {
253 fn from(val: $name) -> Self {
254 val.0
255 }
256 }
257
258 impl $crate::TpmBuild for $name {
259 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
260 $crate::TpmBuild::build(&self.0, writer)
261 }
262 }
263
264 impl $crate::TpmParse for $name {
265 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
266 let (val, buf) = u32::parse(buf)?;
267 Ok((Self(val), buf))
268 }
269 }
270
271 impl $crate::TpmSized for $name {
272 const SIZE: usize = core::mem::size_of::<u32>();
273 fn len(&self) -> usize {
274 Self::SIZE
275 }
276 }
277
278 impl core::fmt::Display for $name {
279 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
280 core::fmt::Display::fmt(&self.0, f)
281 }
282 }
283
284 impl core::fmt::LowerHex for $name {
285 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
286 core::fmt::LowerHex::fmt(&self.0, f)
287 }
288 }
289
290 impl core::fmt::UpperHex for $name {
291 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
292 core::fmt::UpperHex::fmt(&self.0, f)
293 }
294 }
295 };
296}
297
298#[macro_export]
299macro_rules! tpm2b {
300 ($name:ident, $capacity:expr) => {
301 pub type $name = $crate::TpmBuffer<$capacity>;
302 };
303}
304
305#[macro_export]
306macro_rules! tpm2b_struct {
307 (
308 $(#[$meta:meta])*
309 $wrapper_ty:ident, $inner_ty:ty) => {
310 $(#[$meta])*
311 pub struct $wrapper_ty {
312 pub inner: $inner_ty,
313 }
314
315 impl $crate::TpmSized for $wrapper_ty {
316 const SIZE: usize = core::mem::size_of::<u16>() + <$inner_ty>::SIZE;
317 fn len(&self) -> usize {
318 core::mem::size_of::<u16>() + $crate::TpmSized::len(&self.inner)
319 }
320 }
321
322 impl $crate::TpmBuild for $wrapper_ty {
323 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
324 let inner_len = $crate::TpmSized::len(&self.inner);
325 u16::try_from(inner_len)
326 .map_err(|_| $crate::TpmErrorKind::ParseCapacity)?
327 .build(writer)?;
328 $crate::TpmBuild::build(&self.inner, writer)
329 }
330 }
331
332 impl $crate::TpmParse for $wrapper_ty {
333 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
334 let (inner_bytes, rest) = $crate::parse_tpm2b(buf)?;
335 let (inner_val, tail) = <$inner_ty>::parse(inner_bytes)?;
336
337 if !tail.is_empty() {
338 return Err($crate::TpmErrorKind::TrailingData);
339 }
340
341 Ok((Self { inner: inner_val }, rest))
342 }
343 }
344
345 impl From<$inner_ty> for $wrapper_ty {
346 fn from(inner: $inner_ty) -> Self {
347 Self { inner }
348 }
349 }
350
351 impl core::ops::Deref for $wrapper_ty {
352 type Target = $inner_ty;
353 fn deref(&self) -> &Self::Target {
354 &self.inner
355 }
356 }
357
358 impl core::ops::DerefMut for $wrapper_ty {
359 fn deref_mut(&mut self) -> &mut Self::Target {
360 &mut self.inner
361 }
362 }
363 };
364}
365
366#[macro_export]
367macro_rules! tpml {
368 ($name:ident, $inner_ty:ty, $capacity:expr) => {
369 pub type $name = $crate::TpmList<$inner_ty, $capacity>;
370 };
371}