blob: 2739c5231548c37774f01122889dc5dd9eaddde0 [file] [log] [blame]
// 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,
))
}
}
};
}