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