1#[macro_export]
6macro_rules! tpm_bitflags {
7 (
8 $(#[$outer:meta])*
9 $vis:vis struct $name:ident($repr:ty) {
10 $(
11 $(#[$inner:meta])*
12 const $field:ident = $value:expr;
13 )*
14 }
15 ) => {
16 $(#[$outer])*
17 $vis struct $name($repr);
18
19 impl $name {
20 $(
21 $(#[$inner])*
22 pub const $field: Self = Self($value);
23 )*
24
25 #[must_use]
26 pub const fn bits(&self) -> $repr {
27 self.0
28 }
29
30 #[must_use]
31 pub const fn from_bits_truncate(bits: $repr) -> Self {
32 Self(bits)
33 }
34
35 #[must_use]
36 pub const fn empty() -> Self {
37 Self(0)
38 }
39
40 #[must_use]
41 pub const fn contains(&self, other: Self) -> bool {
42 (self.0 & other.0) == other.0
43 }
44 }
45
46 impl core::ops::BitOr for $name {
47 type Output = Self;
48 fn bitor(self, rhs: Self) -> Self::Output {
49 Self(self.0 | rhs.0)
50 }
51 }
52
53 impl core::ops::BitOrAssign for $name {
54 fn bitor_assign(&mut self, rhs: Self) {
55 self.0 |= rhs.0;
56 }
57 }
58
59 impl $crate::TpmBuild for $name {
60 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
61 self.0.build(writer)
62 }
63 }
64
65 impl<'a> $crate::TpmParse<'a> for $name {
66 fn parse(buf: &'a [u8]) -> $crate::TpmResult<(Self, &'a [u8])> {
67 let (val, buf) = <$repr>::parse(buf)?;
68 Ok((Self(val), buf))
69 }
70 }
71
72 impl $crate::TpmSized for $name {
73 const SIZE: usize = core::mem::size_of::<$repr>();
74 fn len(&self) -> usize {
75 Self::SIZE
76 }
77 }
78 };
79}
80
81#[macro_export]
82macro_rules! tpm_bool {
83 (
84 $(#[$outer:meta])*
85 $vis:vis struct $name:ident(bool);
86 ) => {
87 $(#[$outer])*
88 $vis struct $name(pub bool);
89
90 impl From<bool> for $name {
91 fn from(val: bool) -> Self {
92 Self(val)
93 }
94 }
95
96 impl From<$name> for bool {
97 fn from(val: $name) -> Self {
98 val.0
99 }
100 }
101
102 impl $crate::TpmBuild for $name {
103 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
104 u8::from(self.0).build(writer)
105 }
106 }
107
108 impl<'a> $crate::TpmParse<'a> for $name {
109 fn parse(buf: &'a [u8]) -> $crate::TpmResult<(Self, &'a [u8])> {
110 let (val, buf) = u8::parse(buf)?;
111 match val {
112 0 => Ok((Self(false), buf)),
113 1 => Ok((Self(true), buf)),
114 _ => Err($crate::TpmErrorKind::InvalidDiscriminant {
115 type_name: stringify!($name),
116 value: u64::from(val),
117 }),
118 }
119 }
120 }
121
122 impl $crate::TpmSized for $name {
123 const SIZE: usize = core::mem::size_of::<u8>();
124 fn len(&self) -> usize {
125 Self::SIZE
126 }
127 }
128 };
129}
130
131#[macro_export]
132macro_rules! tpm_dispatch {
133 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
134 macro_rules! tpm_command_parser {
135 ($value:ty, $name:ident) => {
136 (
137 <$value as $crate::message::TpmHeader>::COMMAND,
138 <$value as $crate::message::TpmHeader>::NO_SESSIONS,
139 <$value as $crate::message::TpmHeader>::WITH_SESSIONS,
140 <$value as $crate::message::TpmHeader>::HANDLES,
141 |buf| <$value>::parse(buf).map(|(c, r)| (TpmCommandBody::$name(c), r)),
142 )
143 };
144 }
145
146 macro_rules! tpm_response_parser {
147 ($rsp_ty:ty, $enum_variant:ident) => {
148 (
149 <$rsp_ty as $crate::message::TpmHeader>::COMMAND,
150 <$rsp_ty as $crate::message::TpmHeader>::WITH_SESSIONS,
151 |buf| {
152 <$rsp_ty>::parse(buf)
153 .map(|(r, rest)| (TpmResponseBody::$enum_variant(r), rest))
154 },
155 )
156 };
157 }
158
159 #[derive(Debug, PartialEq, Eq, Clone)]
161 pub enum TpmCommandBody {
162 $( $variant($cmd), )*
163 }
164
165 #[allow(clippy::large_enum_variant)]
167 #[derive(Debug, PartialEq, Eq, Clone)]
168 pub enum TpmResponseBody {
169 $( $variant($resp), )*
170 }
171
172 impl TpmResponseBody {
173 $(
174 #[allow(non_snake_case, clippy::result_large_err)]
180 pub fn $variant(self) -> Result<$resp, Self> {
181 if let Self::$variant(r) = self {
182 Ok(r)
183 } else {
184 Err(self)
185 }
186 }
187 )*
188 }
189
190 pub type TpmCommandParser = for<'a> fn(&'a [u8]) -> $crate::TpmResult<(TpmCommandBody, &'a [u8])>;
191 pub type TpmResponseParser = for<'a> fn(&'a [u8]) -> $crate::TpmResult<(TpmResponseBody, &'a [u8])>;
192
193 pub(crate) static PARSE_COMMAND_MAP: &[(
194 $crate::data::TpmCc,
195 bool,
196 bool,
197 usize,
198 TpmCommandParser,
199 )] = &[
200 $( tpm_command_parser!($cmd, $variant), )*
201 ];
202
203 pub(crate) static PARSE_RESPONSE_MAP: &[(
204 $crate::data::TpmCc,
205 bool,
206 TpmResponseParser,
207 )] = &[
208 $( tpm_response_parser!($resp, $variant), )*
209 ];
210
211 const _: () = {
212 let mut i = 1;
213 while i < PARSE_COMMAND_MAP.len() {
214 if PARSE_COMMAND_MAP[i - 1].0 as u32 > PARSE_COMMAND_MAP[i].0 as u32 {
215 panic!("PARSE_COMMAND_MAP must be sorted by TpmCc.");
216 }
217 i += 1;
218 }
219 };
220
221 const _: () = {
222 let mut i = 1;
223 while i < PARSE_RESPONSE_MAP.len() {
224 if PARSE_RESPONSE_MAP[i - 1].0 as u32 > PARSE_RESPONSE_MAP[i].0 as u32 {
225 panic!("PARSE_RESPONSE_MAP must be sorted by TpmCc.");
226 }
227 i += 1;
228 }
229 };
230 };
231}
232
233#[macro_export]
234macro_rules! tpm_enum {
235 (
236 $(#[$enum_meta:meta])*
237 $vis:vis enum $name:ident($repr:ty) {
238 $(
239 $(#[$variant_meta:meta])*
240 ($variant:ident, $value:expr, $display:literal)
241 ),* $(,)?
242 }
243 ) => {
244 $(#[$enum_meta])*
245 #[repr($repr)]
246 $vis enum $name {
247 $(
248 $(#[$variant_meta])*
249 $variant = $value
250 ),*
251 }
252
253 impl TryFrom<$repr> for $name {
254 type Error = ();
255
256 #[allow(clippy::cognitive_complexity)]
257 fn try_from(value: $repr) -> Result<Self, ()> {
258 $(
259 if value == $value {
260 return Ok(Self::$variant);
261 }
262 )*
263 Err(())
264 }
265 }
266
267 impl core::fmt::Display for $name {
268 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
269 let s = match self {
270 $(Self::$variant => $display),*
271 };
272 write!(f, "{}", s)
273 }
274 }
275
276 impl core::str::FromStr for $name {
277 type Err = ();
278
279 fn from_str(s: &str) -> Result<Self, Self::Err> {
280 match s {
281 $($display => Ok(Self::$variant),)*
282 _ => Err(()),
283 }
284 }
285 }
286
287 impl $crate::TpmSized for $name {
288 const SIZE: usize = core::mem::size_of::<$repr>();
289
290 fn len(&self) -> usize {
291 Self::SIZE
292 }
293 }
294
295 impl $crate::TpmBuild for $name {
296 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
297 (*self as $repr).build(writer)
298 }
299 }
300
301 impl<'a> $crate::TpmParse<'a> for $name {
302 fn parse(buf: &'a [u8]) -> $crate::TpmResult<(Self, &'a [u8])> {
303 let (val, buf) = <$repr>::parse(buf)?;
304 let enum_val = Self::try_from(val).map_err(|()| $crate::TpmErrorKind::InvalidDiscriminant {
305 type_name: stringify!($name),
306 value: u64::from(val)
307 })?;
308 Ok((enum_val, buf))
309 }
310 }
311 };
312}
313
314#[macro_export]
315macro_rules! tpm_handle {
316 (
317 $(#[$meta:meta])*
318 $name:ident
319 ) => {
320 $(#[$meta])*
321 pub struct $name(pub u32);
322
323 impl From<u32> for $name {
324 fn from(val: u32) -> Self {
325 Self(val)
326 }
327 }
328
329 impl From<$name> for u32 {
330 fn from(val: $name) -> Self {
331 val.0
332 }
333 }
334
335 impl $crate::TpmBuild for $name {
336 fn build(&self, writer: &mut TpmWriter) -> $crate::TpmResult<()> {
337 self.0.build(writer)
338 }
339 }
340
341 impl<'a> $crate::TpmParse<'a> for $name {
342 fn parse(buf: &'a [u8]) -> $crate::TpmResult<(Self, &'a [u8])> {
343 let (val, buf) = u32::parse(buf)?;
344 Ok((Self(val), buf))
345 }
346 }
347
348 impl $crate::TpmSized for $name {
349 const SIZE: usize = core::mem::size_of::<u32>();
350 fn len(&self) -> usize {
351 Self::SIZE
352 }
353 }
354
355 impl core::fmt::Display for $name {
356 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
357 core::fmt::Display::fmt(&self.0, f)
358 }
359 }
360
361 impl core::fmt::LowerHex for $name {
362 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
363 core::fmt::LowerHex::fmt(&self.0, f)
364 }
365 }
366
367 impl core::fmt::UpperHex for $name {
368 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
369 core::fmt::UpperHex::fmt(&self.0, f)
370 }
371 }
372 };
373}
374
375#[macro_export]
376macro_rules! tpm_response {
377 (
378 $(#[$meta:meta])*
379 $name:ident,
380 $cc:expr,
381 $no_sessions:expr,
382 $with_sessions:expr,
383 $(pub $handle_field:ident: $handle_type:ty,)*
384 {
385 $(pub $param_field:ident: $param_type:ty),*
386 $(,)?
387 }
388 ) => {
389 $(#[$meta])*
390 pub struct $name {
391 $(pub $handle_field: $handle_type,)*
392 $(pub $param_field: $param_type,)*
393 }
394
395 impl $crate::message::TpmHeader<'_> for $name {
396 const COMMAND: $crate::data::TpmCc = $cc;
397 const NO_SESSIONS: bool = $no_sessions;
398 const WITH_SESSIONS: bool = $with_sessions;
399 const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*;
400 }
401
402 impl $crate::TpmSized for $name {
403 const SIZE: usize = 0 $(+ <$handle_type>::SIZE)* $(+ <$param_type>::SIZE)*;
404 fn len(&self) -> usize {
405 let params_len: usize = 0 $(+ self.$param_field.len())*;
406 let handles_len: usize = 0 $(+ self.$handle_field.len())*;
407 let parameter_area_size_field_len: usize = core::mem::size_of::<u32>();
408 handles_len + parameter_area_size_field_len + params_len
409 }
410 }
411
412 impl $crate::TpmBuild for $name {
413 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
414 let params_len: usize = 0 $(+ self.$param_field.len())*;
415 let params_len_u32 = u32::try_from(params_len)
416 .map_err(|_| $crate::TpmErrorKind::ValueTooLarge)?;
417
418 $(self.$handle_field.build(writer)?;)*
419 params_len_u32.build(writer)?;
420 $(self.$param_field.build(writer)?;)*
421
422 Ok(())
423 }
424 }
425
426 impl<'a> $crate::TpmParse<'a> for $name {
427 fn parse(buf: &'a [u8]) -> $crate::TpmResult<(Self, &'a [u8])> {
428 #[allow(unused_mut)]
429 let mut cursor = buf;
430 $(
431 let ($handle_field, tail) = <$handle_type>::parse(cursor)?;
432 cursor = tail;
433 )*
434
435 let (mut params, tail) = $crate::TpmParameters::new(cursor)?;
436 $(
437 let $param_field = params.parse::<$param_type>()?;
438 )*
439 if !params.is_empty() {
440 return Err($crate::TpmErrorKind::TrailingData);
441 }
442
443 Ok((
444 Self {
445 $( $handle_field, )*
446 $( $param_field, )*
447 },
448 tail,
449 ))
450 }
451 }
452 };
453}
454
455#[macro_export]
456macro_rules! tpm_struct {
457 (
458 $(#[$meta:meta])*
459 $name:ident,
460 $cc:expr,
461 $no_sessions:expr,
462 $with_sessions:expr,
463 $handles:expr,
464 {
465 $(pub $field_name:ident: $field_type:ty),*
466 $(,)?
467 }
468 ) => {
469 $crate::tpm_struct! {
470 $(#[$meta])*
471 pub struct $name {
472 $(pub $field_name: $field_type,)*
473 }
474 }
475
476 impl $crate::message::TpmHeader<'_> for $name {
477 const COMMAND: $crate::data::TpmCc = $cc;
478 const NO_SESSIONS: bool = $no_sessions;
479 const WITH_SESSIONS: bool = $with_sessions;
480 const HANDLES: usize = $handles;
481 }
482 };
483
484 (
485 $(#[$meta:meta])*
486 $vis:vis struct $name:ident {
487 $(pub $field_name:ident: $field_type:ty),*
488 $(,)?
489 }
490 ) => {
491 $(#[$meta])*
492 $vis struct $name {
493 $(pub $field_name: $field_type,)*
494 }
495
496 impl $crate::TpmSized for $name {
497 const SIZE: usize = 0 $(+ <$field_type>::SIZE)*;
498 fn len(&self) -> usize {
499 0 $(+ self.$field_name.len())*
500 }
501 }
502
503 impl $crate::TpmBuild for $name {
504 #[allow(unused_variables)]
505 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
506 $(self.$field_name.build(writer)?;)*
507 Ok(())
508 }
509 }
510
511 impl<'a> $crate::TpmParse<'a> for $name {
512 fn parse(buf: &'a [u8]) -> $crate::TpmResult<(Self, &'a [u8])> {
513 $(let ($field_name, buf) = <$field_type>::parse(buf)?;)*
514 Ok((
515 Self {
516 $($field_name,)*
517 },
518 buf,
519 ))
520 }
521 }
522 };
523}
524
525#[macro_export]
526macro_rules! tpm2b {
527 ($name:ident, $capacity:expr) => {
528 pub type $name = $crate::TpmBuffer<$capacity>;
529 };
530}
531
532#[macro_export]
533macro_rules! tpm2b_struct {
534 (
535 $(#[$meta:meta])*
536 $wrapper_ty:ident, $inner_ty:ty) => {
537 $(#[$meta])*
538 pub struct $wrapper_ty {
539 pub inner: $inner_ty,
540 }
541
542 impl $crate::TpmSized for $wrapper_ty {
543 const SIZE: usize = core::mem::size_of::<u16>() + <$inner_ty>::SIZE;
544 fn len(&self) -> usize {
545 core::mem::size_of::<u16>() + self.inner.len()
546 }
547 }
548
549 impl $crate::TpmBuild for $wrapper_ty {
550 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
551 let inner_len = self.inner.len();
552 u16::try_from(inner_len)
553 .map_err(|_| $crate::TpmErrorKind::ValueTooLarge)?
554 .build(writer)?;
555 self.inner.build(writer)
556 }
557 }
558
559 impl<'a> $crate::TpmParse<'a> for $wrapper_ty {
560 fn parse(buf: &'a [u8]) -> $crate::TpmResult<(Self, &'a [u8])> {
561 let (inner_bytes, rest) = $crate::parse_tpm2b(buf)?;
562 let (inner_val, tail) = <$inner_ty>::parse(inner_bytes)?;
563
564 if !tail.is_empty() {
565 return Err($crate::TpmErrorKind::TrailingData);
566 }
567
568 Ok((Self { inner: inner_val }, rest))
569 }
570 }
571
572 impl From<$inner_ty> for $wrapper_ty {
573 fn from(inner: $inner_ty) -> Self {
574 Self { inner }
575 }
576 }
577
578 impl core::ops::Deref for $wrapper_ty {
579 type Target = $inner_ty;
580 fn deref(&self) -> &Self::Target {
581 &self.inner
582 }
583 }
584
585 impl core::ops::DerefMut for $wrapper_ty {
586 fn deref_mut(&mut self) -> &mut Self::Target {
587 &mut self.inner
588 }
589 }
590 };
591}
592
593#[macro_export]
594macro_rules! tpml {
595 ($name:ident, $inner_ty:ty, $capacity:expr) => {
596 pub type $name = $crate::TpmList<$inner_ty, $capacity>;
597 };
598}