1#[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::TpmCommandBuild>::build_handles(self, writer)?;
40 <Self as $crate::message::TpmCommandBuild>::build_parameters(self, writer)
41 }
42 }
43
44 impl $crate::message::TpmCommandBuild 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::message::TpmCommandBodyParse for $name {
59 #[allow(unused_mut)]
60 fn parse_body<'a>(
61 handles: &'a [u8],
62 params: &'a [u8],
63 ) -> $crate::TpmResult<(Self, &'a [u8])> {
64 let mut cursor = handles;
65 $(
66 let ($handle_field, tail) = <$handle_type as $crate::TpmParse>::parse(cursor)?;
67 cursor = tail;
68 )*
69
70 if !cursor.is_empty() {
71 return Err($crate::TpmErrorKind::TrailingData);
72 }
73
74 let mut cursor = params;
75 $(
76 let ($param_field, tail) = <$param_type as $crate::TpmParse>::parse(cursor)?;
77 cursor = tail;
78 )*
79
80 Ok((
81 Self {
82 $($handle_field,)*
83 $($param_field,)*
84 },
85 cursor,
86 ))
87 }
88 }
89
90 impl $crate::message::TpmHeader for $name {
91 const COMMAND: $crate::data::TpmCc = $cc;
92 const NO_SESSIONS: bool = $no_sessions;
93 const WITH_SESSIONS: bool = $with_sessions;
94 const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*;
95 }
96 };
97
98 (
99 $(#[$meta:meta])*
100 kind: Response,
101 name: $name:ident,
102 cc: $cc:expr,
103 no_sessions: $no_sessions:expr,
104 with_sessions: $with_sessions:expr,
105 handles: {
106 $(pub $handle_field:ident: $handle_type:ty),*
107 $(,)?
108 },
109 parameters: {
110 $(pub $param_field:ident: $param_type:ty),*
111 $(,)?
112 }
113 ) => {
114 $(#[$meta])*
115 pub struct $name {
116 $(pub $handle_field: $handle_type,)*
117 $(pub $param_field: $param_type,)*
118 }
119
120 impl $crate::message::TpmResponseBuild for $name {
121 #[allow(unused_variables)]
122 fn build_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
123 $($crate::TpmBuild::build(&self.$handle_field, writer)?;)*
124 Ok(())
125 }
126 #[allow(unused_variables)]
127 fn build_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
128 $($crate::TpmBuild::build(&self.$param_field, writer)?;)*
129 Ok(())
130 }
131 }
132
133 impl $crate::TpmSized for $name {
134 const SIZE: usize = 0 $(+ <$handle_type>::SIZE)* $(+ <$param_type>::SIZE)*;
135 fn len(&self) -> usize {
136 0 $(+ $crate::TpmSized::len(&self.$handle_field))* $(+ $crate::TpmSized::len(&self.$param_field))*
137 }
138 }
139
140 impl $crate::TpmBuild for $name {
141 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
142 <Self as $crate::message::TpmResponseBuild>::build_handles(self, writer)?;
143 <Self as $crate::message::TpmResponseBuild>::build_parameters(self, writer)
144 }
145 }
146
147 impl $crate::message::TpmResponseBodyParse for $name {
148 #[allow(unused_mut)]
149 fn parse_body(
150 tag: $crate::data::TpmSt,
151 buf: &[u8],
152 ) -> $crate::TpmResult<(Self, &[u8])> {
153 let mut cursor = buf;
154 $(
155 let ($handle_field, tail) = <$handle_type as $crate::TpmParse>::parse(cursor)?;
156 cursor = tail;
157 )*
158
159 if $with_sessions && tag == $crate::data::TpmSt::Sessions {
160 let (size, buf_after_size) = <u32 as $crate::TpmParse>::parse(cursor)?;
161 let size = size as usize;
162 if buf_after_size.len() < size {
163 return Err($crate::TpmErrorKind::ParseUnderflow);
164 }
165 let (mut params_cursor, final_tail) = buf_after_size.split_at(size);
166
167 $(
168 let ($param_field, tail) = <$param_type as $crate::TpmParse>::parse(params_cursor)?;
169 params_cursor = tail;
170 )*
171
172 if !params_cursor.is_empty() {
173 return Err($crate::TpmErrorKind::TrailingData);
174 }
175
176 Ok((
177 Self {
178 $($handle_field,)*
179 $($param_field,)*
180 },
181 final_tail,
182 ))
183 } else {
184 let mut params_cursor = cursor;
185 $(
186 let ($param_field, tail) = <$param_type as $crate::TpmParse>::parse(params_cursor)?;
187 params_cursor = tail;
188 )*
189
190 Ok((
191 Self {
192 $($handle_field,)*
193 $($param_field,)*
194 },
195 params_cursor,
196 ))
197 }
198 }
199 }
200
201 impl $crate::message::TpmHeader for $name {
202 const COMMAND: $crate::data::TpmCc = $cc;
203 const NO_SESSIONS: bool = $no_sessions;
204 const WITH_SESSIONS: bool = $with_sessions;
205 const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*;
206 }
207 };
208
209 (
210 $(#[$meta:meta])*
211 $vis:vis struct $name:ident {
212 $(pub $field_name:ident: $field_type:ty),*
213 $(,)?
214 }
215 ) => {
216 $(#[$meta])*
217 $vis struct $name {
218 $(pub $field_name: $field_type,)*
219 }
220
221 impl $crate::TpmSized for $name {
222 const SIZE: usize = 0 $(+ <$field_type>::SIZE)*;
223 fn len(&self) -> usize {
224 0 $(+ $crate::TpmSized::len(&self.$field_name))*
225 }
226 }
227
228 impl $crate::TpmBuild for $name {
229 #[allow(unused_variables)]
230 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
231 $( $crate::TpmBuild::build(&self.$field_name, writer)?; )*
232 Ok(())
233 }
234 }
235
236 impl $crate::TpmParse for $name {
237 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
238 $(let ($field_name, buf) = <$field_type>::parse(buf)?;)*
239 Ok((
240 Self {
241 $($field_name,)*
242 },
243 buf,
244 ))
245 }
246 }
247 };
248}
249
250#[macro_export]
251macro_rules! tpm_tagged_struct {
252 (
253 $(#[$outer:meta])*
254 $vis:vis struct $name:ident {
255 pub $tag_field:ident: $tag_ty:ty,
256 pub $value_field:ident: $value_ty:ty,
257 }
258 ) => {
259 $(#[$outer])*
260 $vis struct $name {
261 pub $tag_field: $tag_ty,
262 pub $value_field: $value_ty,
263 }
264
265 impl $crate::TpmTagged for $name {
266 type Tag = $tag_ty;
267 type Value = $value_ty;
268 }
269
270 impl $crate::TpmSized for $name {
271 const SIZE: usize = <$tag_ty>::SIZE + <$value_ty>::SIZE;
272 fn len(&self) -> usize {
273 $crate::TpmSized::len(&self.$tag_field) + $crate::TpmSized::len(&self.$value_field)
274 }
275 }
276
277 impl $crate::TpmBuild for $name {
278 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
279 $crate::TpmBuild::build(&self.$tag_field, writer)?;
280 $crate::TpmBuild::build(&self.$value_field, writer)
281 }
282 }
283
284 impl $crate::TpmParse for $name {
285 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
286 let ($tag_field, buf) = <$tag_ty>::parse(buf)?;
287 let ($value_field, buf) =
288 <$value_ty as $crate::TpmParseTagged>::parse_tagged($tag_field, buf)?;
289 Ok((
290 Self {
291 $tag_field,
292 $value_field,
293 },
294 buf,
295 ))
296 }
297 }
298 };
299}