tpm2_protocol/macro/
response.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2025 Opinsys Oy
3// Copyright (c) 2024-2025 Jarkko Sakkinen
4
5#[macro_export]
6macro_rules! tpm_response {
7    (
8        $(#[$meta:meta])*
9        $name:ident,
10        $cc:expr,
11        $no_sessions:expr,
12        $with_sessions:expr,
13        $(pub $handle_field:ident: $handle_type:ty,)*
14        {
15            $(pub $param_field:ident: $param_type:ty),*
16            $(,)?
17        }
18    ) => {
19        $(#[$meta])*
20        pub struct $name {
21            $(pub $handle_field: $handle_type,)*
22            $(pub $param_field: $param_type,)*
23        }
24
25        impl $crate::message::TpmHeader for $name {
26            const COMMAND: $crate::data::TpmCc = $cc;
27            const NO_SESSIONS: bool = $no_sessions;
28            const WITH_SESSIONS: bool = $with_sessions;
29            const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*;
30        }
31
32        impl $crate::TpmSized for $name {
33            const SIZE: usize = 0 $(+ <$handle_type>::SIZE)* $(+ <$param_type>::SIZE)*;
34            fn len(&self) -> usize {
35                let params_len: usize = 0 $(+ $crate::TpmSized::len(&self.$param_field))*;
36                let handles_len: usize = 0 $(+ $crate::TpmSized::len(&self.$handle_field))*;
37                let parameter_area_size_field_len: usize = core::mem::size_of::<u32>();
38                handles_len + parameter_area_size_field_len + params_len
39            }
40        }
41
42        impl $crate::TpmBuild for $name {
43            fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
44                let params_len: usize = 0 $(+ $crate::TpmSized::len(&self.$param_field))*;
45                let params_len_u32 = u32::try_from(params_len)
46                    .map_err(|_| $crate::TpmErrorKind::ValueTooLarge)?;
47
48                $($crate::TpmBuild::build(&self.$handle_field, writer)?;)*
49                $crate::TpmBuild::build(&params_len_u32, writer)?;
50                $($crate::TpmBuild::build(&self.$param_field, writer)?;)*
51
52                Ok(())
53            }
54        }
55
56        impl $crate::TpmParse for $name {
57            fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
58                #[allow(unused_mut)]
59                let mut cursor = buf;
60                $(
61                    let ($handle_field, tail) = <$handle_type>::parse(cursor)?;
62                    cursor = tail;
63                )*
64
65                #[allow(unused_mut)]
66                let (mut params, tail) = $crate::TpmParameters::new(cursor)?;
67                $(
68                    let $param_field = params.parse::<$param_type>()?;
69                )*
70                if !params.is_empty() {
71                    return Err($crate::TpmErrorKind::TrailingData);
72                }
73
74                Ok((
75                    Self {
76                        $( $handle_field, )*
77                        $( $param_field, )*
78                    },
79                    tail,
80                ))
81            }
82        }
83    };
84}