| // SPDX-License-Identifier: MIT OR Apache-2.0 |
| // Copyright (c) 2025 Opinsys Oy |
| // Copyright (c) 2024-2025 Jarkko Sakkinen |
| |
| #[macro_export] |
| macro_rules! tpm_struct { |
| ( |
| $(#[$meta:meta])* |
| kind: Command, |
| name: $name:ident, |
| cc: $cc:expr, |
| handles: { |
| $($handle_field:ident),* |
| $(,)? |
| }, |
| parameters: { |
| $(pub $param_field:ident: $param_type:ty),* |
| $(,)? |
| } |
| ) => { |
| $(#[$meta])* |
| pub struct $name { |
| $(pub $handle_field: $crate::TpmHandle,)* |
| $(pub $param_field: $param_type,)* |
| } |
| |
| impl $crate::message::TpmHeader for $name { |
| const CC: $crate::data::TpmCc = $cc; |
| const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*; |
| } |
| |
| impl $crate::TpmSized for $name { |
| const SIZE: usize = (Self::HANDLES * <$crate::TpmHandle>::SIZE) $(+ <$param_type>::SIZE)*; |
| fn len(&self) -> usize { |
| 0 $(+ $crate::TpmSized::len(&self.$handle_field))* $(+ $crate::TpmSized::len(&self.$param_field))* |
| } |
| } |
| |
| impl $crate::TpmBuild for $name { |
| #[allow(unused_variables)] |
| fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> { |
| <Self as $crate::message::TpmBodyBuild>::build_handles(self, writer)?; |
| <Self as $crate::message::TpmBodyBuild>::build_parameters(self, writer) |
| } |
| } |
| |
| impl $crate::message::TpmBodyBuild for $name { |
| #[allow(unused_variables)] |
| fn build_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> { |
| $($crate::TpmBuild::build(&self.$handle_field, writer)?;)* |
| Ok(()) |
| } |
| |
| #[allow(unused_variables)] |
| fn build_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> { |
| $($crate::TpmBuild::build(&self.$param_field, writer)?;)* |
| Ok(()) |
| } |
| } |
| |
| impl $crate::message::TpmCommandBodyParse for $name { |
| #[allow(unused_mut, unused_variables)] |
| fn parse_body<'a>( |
| handles: &'a [u8], |
| params: &'a [u8], |
| ) -> $crate::TpmResult<(Self, &'a [u8])> { |
| let mut cursor = handles; |
| $( |
| let ($handle_field, tail) = <$crate::TpmHandle as $crate::TpmParse>::parse(cursor)?; |
| cursor = tail; |
| )* |
| |
| if !cursor.is_empty() { |
| return Err($crate::TpmError::TrailingData); |
| } |
| |
| let mut cursor = params; |
| $( |
| let ($param_field, tail) = <$param_type as $crate::TpmParse>::parse(cursor)?; |
| cursor = tail; |
| )* |
| |
| Ok(( |
| Self { |
| $($handle_field,)* |
| $($param_field,)* |
| }, |
| cursor, |
| )) |
| } |
| } |
| }; |
| |
| ( |
| $(#[$meta:meta])* |
| kind: Response, |
| name: $name:ident, |
| cc: $cc:expr, |
| handles: { |
| $($handle_field:ident),* |
| $(,)? |
| }, |
| parameters: { |
| $(pub $param_field:ident: $param_type:ty),* |
| $(,)? |
| } |
| ) => { |
| $(#[$meta])* |
| pub struct $name { |
| $(pub $handle_field: $crate::TpmHandle,)* |
| $(pub $param_field: $param_type,)* |
| } |
| |
| impl $crate::message::TpmHeader for $name { |
| const CC: $crate::data::TpmCc = $cc; |
| const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*; |
| } |
| |
| impl $crate::message::TpmBodyBuild for $name { |
| #[allow(unused_variables)] |
| fn build_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> { |
| $($crate::TpmBuild::build(&self.$handle_field, writer)?;)* |
| Ok(()) |
| } |
| #[allow(unused_variables)] |
| fn build_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> { |
| $($crate::TpmBuild::build(&self.$param_field, writer)?;)* |
| Ok(()) |
| } |
| } |
| |
| impl $crate::TpmSized for $name { |
| const SIZE: usize = (Self::HANDLES * <$crate::TpmHandle>::SIZE) $(+ <$param_type>::SIZE)*; |
| fn len(&self) -> usize { |
| 0 $(+ $crate::TpmSized::len(&self.$handle_field))* $(+ $crate::TpmSized::len(&self.$param_field))* |
| } |
| } |
| |
| impl $crate::TpmBuild for $name { |
| fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> { |
| <Self as $crate::message::TpmBodyBuild>::build_handles(self, writer)?; |
| <Self as $crate::message::TpmBodyBuild>::build_parameters(self, writer) |
| } |
| } |
| |
| impl $crate::message::TpmResponseBodyParse for $name { |
| #[allow(unused_mut, unused_variables)] |
| fn parse_body( |
| tag: $crate::data::TpmSt, |
| buf: &[u8], |
| ) -> $crate::TpmResult<(Self, &[u8])> { |
| let mut cursor = buf; |
| $( |
| let ($handle_field, tail) = <$crate::TpmHandle as $crate::TpmParse>::parse(cursor)?; |
| cursor = tail; |
| )* |
| |
| if tag == $crate::data::TpmSt::Sessions { |
| let (size, buf_after_size) = <u32 as $crate::TpmParse>::parse(cursor)?; |
| let size = size as usize; |
| if buf_after_size.len() < size { |
| return Err($crate::TpmError::Underflow); |
| } |
| let (mut params_cursor, final_tail) = buf_after_size.split_at(size); |
| |
| $( |
| let ($param_field, tail) = <$param_type as $crate::TpmParse>::parse(params_cursor)?; |
| params_cursor = tail; |
| )* |
| |
| if !params_cursor.is_empty() { |
| return Err($crate::TpmError::TrailingData); |
| } |
| |
| Ok(( |
| Self { |
| $($handle_field,)* |
| $($param_field,)* |
| }, |
| final_tail, |
| )) |
| } else { |
| let mut params_cursor = cursor; |
| $( |
| let ($param_field, tail) = <$param_type as $crate::TpmParse>::parse(params_cursor)?; |
| params_cursor = tail; |
| )* |
| |
| Ok(( |
| Self { |
| $($handle_field,)* |
| $($param_field,)* |
| }, |
| params_cursor, |
| )) |
| } |
| } |
| } |
| }; |
| |
| ( |
| $(#[$meta:meta])* |
| $vis:vis struct $name:ident { |
| $(pub $field_name:ident: $field_type:ty),* |
| $(,)? |
| } |
| ) => { |
| $(#[$meta])* |
| $vis struct $name { |
| $(pub $field_name: $field_type,)* |
| } |
| |
| impl $crate::TpmSized for $name { |
| const SIZE: usize = 0 $(+ <$field_type>::SIZE)*; |
| fn len(&self) -> usize { |
| 0 $(+ $crate::TpmSized::len(&self.$field_name))* |
| } |
| } |
| |
| impl $crate::TpmBuild for $name { |
| #[allow(unused_variables)] |
| fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> { |
| $( $crate::TpmBuild::build(&self.$field_name, writer)?; )* |
| Ok(()) |
| } |
| } |
| |
| impl $crate::TpmParse for $name { |
| fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> { |
| $(let ($field_name, buf) = <$field_type>::parse(buf)?;)* |
| Ok(( |
| Self { |
| $($field_name,)* |
| }, |
| buf, |
| )) |
| } |
| } |
| }; |
| } |