tpm2_protocol/macro/
struct.rs1#[macro_export]
6macro_rules! tpm_struct {
7 (
8 $(#[$meta:meta])*
9 kind: Command,
10 name: $name:ident,
11 cc: $cc:expr,
12 no_sessions: $no_sessions:expr,
13 with_sessions: $with_sessions:expr,
14 handles: {
15 $(pub $handle_field:ident: $handle_type:ty),*
16 $(,)?
17 },
18 parameters: {
19 $(pub $param_field:ident: $param_type:ty),*
20 $(,)?
21 }
22 ) => {
23 $(#[$meta])*
24 pub struct $name {
25 $(pub $handle_field: $handle_type,)*
26 $(pub $param_field: $param_type,)*
27 }
28
29 impl $crate::TpmSized for $name {
30 const SIZE: usize = 0 $(+ <$handle_type>::SIZE)* $(+ <$param_type>::SIZE)*;
31 fn len(&self) -> usize {
32 0 $(+ $crate::TpmSized::len(&self.$handle_field))* $(+ $crate::TpmSized::len(&self.$param_field))*
33 }
34 }
35
36 impl $crate::TpmBuild for $name {
37 #[allow(unused_variables)]
38 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
39 <Self as $crate::message::TpmHeaderCommand>::build_handles(self, writer)?;
40 <Self as $crate::message::TpmHeaderCommand>::build_parameters(self, writer)
41 }
42 }
43
44 impl $crate::message::TpmHeaderCommand for $name {
45 #[allow(unused_variables)]
46 fn build_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
47 $($crate::TpmBuild::build(&self.$handle_field, writer)?;)*
48 Ok(())
49 }
50
51 #[allow(unused_variables)]
52 fn build_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
53 $($crate::TpmBuild::build(&self.$param_field, writer)?;)*
54 Ok(())
55 }
56 }
57
58 impl $crate::TpmParse for $name {
59 #[allow(unused_mut)]
60 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
61 let mut cursor = buf;
62 $(
63 let ($handle_field, tail) = <$handle_type>::parse(cursor)?;
64 cursor = tail;
65 )*
66 $(
67 let ($param_field, tail) = <$param_type>::parse(cursor)?;
68 cursor = tail;
69 )*
70 Ok((
71 Self {
72 $($handle_field,)*
73 $($param_field,)*
74 },
75 cursor,
76 ))
77 }
78 }
79
80 impl $crate::message::TpmHeader for $name {
81 const COMMAND: $crate::data::TpmCc = $cc;
82 const NO_SESSIONS: bool = $no_sessions;
83 const WITH_SESSIONS: bool = $with_sessions;
84 const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*;
85 }
86 };
87
88 (
89 $(#[$meta:meta])*
90 kind: Response,
91 name: $name:ident,
92 cc: $cc:expr,
93 no_sessions: $no_sessions:expr,
94 with_sessions: $with_sessions:expr,
95 handles: {
96 $(pub $handle_field:ident: $handle_type:ty),*
97 $(,)?
98 },
99 parameters: {
100 $(pub $param_field:ident: $param_type:ty),*
101 $(,)?
102 }
103 ) => {
104 $(#[$meta])*
105 pub struct $name {
106 $(pub $handle_field: $handle_type,)*
107 $(pub $param_field: $param_type,)*
108 }
109
110 impl $crate::TpmSized for $name {
111 const SIZE: usize = 0 $(+ <$handle_type>::SIZE)* $(+ <$param_type>::SIZE)*;
112 fn len(&self) -> usize {
113 let params_len: usize = 0 $(+ $crate::TpmSized::len(&self.$param_field))*;
114 let handles_len: usize = 0 $(+ $crate::TpmSized::len(&self.$handle_field))*;
115 let parameter_area_size_field_len: usize = if $with_sessions {
116 core::mem::size_of::<u32>()
117 } else {
118 0
119 };
120 handles_len + parameter_area_size_field_len + params_len
121 }
122 }
123
124 impl $crate::TpmBuild for $name {
125 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
126 let params_len: usize = 0 $(+ $crate::TpmSized::len(&self.$param_field))*;
127 $($crate::TpmBuild::build(&self.$handle_field, writer)?;)*
128 if $with_sessions {
129 let params_len_u32 = u32::try_from(params_len)
130 .map_err(|_| $crate::TpmErrorKind::BuildCapacity)?;
131 $crate::TpmBuild::build(¶ms_len_u32, writer)?;
132 }
133 $($crate::TpmBuild::build(&self.$param_field, writer)?;)*
134 Ok(())
135 }
136 }
137
138 impl $crate::TpmParse for $name {
139 #[allow(unused_mut)]
140 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
141 let mut cursor = buf;
142 $(
143 let ($handle_field, tail) = <$handle_type>::parse(cursor)?;
144 cursor = tail;
145 )*
146
147 if $with_sessions {
148 let (size, buf_after_size) = u32::parse(cursor)?;
149 let size = size as usize;
150 if buf_after_size.len() < size {
151 return Err($crate::TpmErrorKind::ParseUnderflow);
152 }
153 let (mut params_cursor, final_tail) = buf_after_size.split_at(size);
154
155 $(
156 let ($param_field, tail) = <$param_type>::parse(params_cursor)?;
157 params_cursor = tail;
158 )*
159
160 if !params_cursor.is_empty() {
161 return Err($crate::TpmErrorKind::TrailingData);
162 }
163
164 Ok((
165 Self {
166 $($handle_field,)*
167 $($param_field,)*
168 },
169 final_tail,
170 ))
171 } else {
172 let mut params_cursor = cursor;
173 $(
174 let ($param_field, tail) = <$param_type>::parse(params_cursor)?;
175 params_cursor = tail;
176 )*
177
178 Ok((
179 Self {
180 $($handle_field,)*
181 $($param_field,)*
182 },
183 params_cursor,
184 ))
185 }
186 }
187 }
188
189 impl $crate::message::TpmHeader for $name {
190 const COMMAND: $crate::data::TpmCc = $cc;
191 const NO_SESSIONS: bool = $no_sessions;
192 const WITH_SESSIONS: bool = $with_sessions;
193 const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*;
194 }
195 };
196
197 (
198 $(#[$meta:meta])*
199 $vis:vis struct $name:ident {
200 $(pub $field_name:ident: $field_type:ty),*
201 $(,)?
202 }
203 ) => {
204 $(#[$meta])*
205 $vis struct $name {
206 $(pub $field_name: $field_type,)*
207 }
208
209 impl $crate::TpmSized for $name {
210 const SIZE: usize = 0 $(+ <$field_type>::SIZE)*;
211 fn len(&self) -> usize {
212 0 $(+ $crate::TpmSized::len(&self.$field_name))*
213 }
214 }
215
216 impl $crate::TpmBuild for $name {
217 #[allow(unused_variables)]
218 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
219 $( $crate::TpmBuild::build(&self.$field_name, writer)?; )*
220 Ok(())
221 }
222 }
223
224 impl $crate::TpmParse for $name {
225 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
226 $(let ($field_name, buf) = <$field_type>::parse(buf)?;)*
227 Ok((
228 Self {
229 $($field_name,)*
230 },
231 buf,
232 ))
233 }
234 }
235 };
236}
237
238#[macro_export]
239macro_rules! tpm_tagged_struct {
240 (
241 $(#[$outer:meta])*
242 $vis:vis struct $name:ident {
243 pub $tag_field:ident: $tag_ty:ty,
244 pub $value_field:ident: $value_ty:ty,
245 }
246 ) => {
247 $(#[$outer])*
248 $vis struct $name {
249 pub $tag_field: $tag_ty,
250 pub $value_field: $value_ty,
251 }
252
253 impl $crate::TpmTagged for $name {
254 type Tag = $tag_ty;
255 type Value = $value_ty;
256 }
257
258 impl $crate::TpmSized for $name {
259 const SIZE: usize = <$tag_ty>::SIZE + <$value_ty>::SIZE;
260 fn len(&self) -> usize {
261 $crate::TpmSized::len(&self.$tag_field) + $crate::TpmSized::len(&self.$value_field)
262 }
263 }
264
265 impl $crate::TpmBuild for $name {
266 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
267 $crate::TpmBuild::build(&self.$tag_field, writer)?;
268 $crate::TpmBuild::build(&self.$value_field, writer)
269 }
270 }
271
272 impl $crate::TpmParse for $name {
273 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
274 let ($tag_field, buf) = <$tag_ty>::parse(buf)?;
275 let ($value_field, buf) =
276 <$value_ty as $crate::TpmParseTagged>::parse_tagged($tag_field, buf)?;
277 Ok((
278 Self {
279 $tag_field,
280 $value_field,
281 },
282 buf,
283 ))
284 }
285 }
286 };
287}