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::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::TpmSized for $name {
121 const SIZE: usize = 0 $(+ <$handle_type>::SIZE)* $(+ <$param_type>::SIZE)*;
122 fn len(&self) -> usize {
123 let params_len: usize = 0 $(+ $crate::TpmSized::len(&self.$param_field))*;
124 let handles_len: usize = 0 $(+ $crate::TpmSized::len(&self.$handle_field))*;
125 let parameter_area_size_field_len: usize = if $with_sessions {
126 core::mem::size_of::<u32>()
127 } else {
128 0
129 };
130 handles_len + parameter_area_size_field_len + params_len
131 }
132 }
133
134 impl $crate::TpmBuild for $name {
135 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
136 let params_len: usize = 0 $(+ $crate::TpmSized::len(&self.$param_field))*;
137 $($crate::TpmBuild::build(&self.$handle_field, writer)?;)*
138 if $with_sessions {
139 let params_len_u32 = u32::try_from(params_len)
140 .map_err(|_| $crate::TpmErrorKind::BuildCapacity)?;
141 $crate::TpmBuild::build(¶ms_len_u32, writer)?;
142 }
143 $($crate::TpmBuild::build(&self.$param_field, writer)?;)*
144 Ok(())
145 }
146 }
147
148 impl $crate::TpmParse for $name {
149 #[allow(unused_mut)]
150 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
151 let mut cursor = buf;
152 $(
153 let ($handle_field, tail) = <$handle_type>::parse(cursor)?;
154 cursor = tail;
155 )*
156
157 if $with_sessions {
158 let (size, buf_after_size) = u32::parse(cursor)?;
159 let size = size as usize;
160 if buf_after_size.len() < size {
161 return Err($crate::TpmErrorKind::ParseUnderflow);
162 }
163 let (mut params_cursor, final_tail) = buf_after_size.split_at(size);
164
165 $(
166 let ($param_field, tail) = <$param_type>::parse(params_cursor)?;
167 params_cursor = tail;
168 )*
169
170 if !params_cursor.is_empty() {
171 return Err($crate::TpmErrorKind::TrailingData);
172 }
173
174 Ok((
175 Self {
176 $($handle_field,)*
177 $($param_field,)*
178 },
179 final_tail,
180 ))
181 } else {
182 let mut params_cursor = cursor;
183 $(
184 let ($param_field, tail) = <$param_type>::parse(params_cursor)?;
185 params_cursor = tail;
186 )*
187
188 Ok((
189 Self {
190 $($handle_field,)*
191 $($param_field,)*
192 },
193 params_cursor,
194 ))
195 }
196 }
197 }
198
199 impl $crate::message::TpmHeader for $name {
200 const COMMAND: $crate::data::TpmCc = $cc;
201 const NO_SESSIONS: bool = $no_sessions;
202 const WITH_SESSIONS: bool = $with_sessions;
203 const HANDLES: usize = 0 $(+ {let _ = stringify!($handle_field); 1})*;
204 }
205 };
206
207 (
208 $(#[$meta:meta])*
209 $vis:vis struct $name:ident {
210 $(pub $field_name:ident: $field_type:ty),*
211 $(,)?
212 }
213 ) => {
214 $(#[$meta])*
215 $vis struct $name {
216 $(pub $field_name: $field_type,)*
217 }
218
219 impl $crate::TpmSized for $name {
220 const SIZE: usize = 0 $(+ <$field_type>::SIZE)*;
221 fn len(&self) -> usize {
222 0 $(+ $crate::TpmSized::len(&self.$field_name))*
223 }
224 }
225
226 impl $crate::TpmBuild for $name {
227 #[allow(unused_variables)]
228 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
229 $( $crate::TpmBuild::build(&self.$field_name, writer)?; )*
230 Ok(())
231 }
232 }
233
234 impl $crate::TpmParse for $name {
235 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
236 $(let ($field_name, buf) = <$field_type>::parse(buf)?;)*
237 Ok((
238 Self {
239 $($field_name,)*
240 },
241 buf,
242 ))
243 }
244 }
245 };
246}
247
248#[macro_export]
249macro_rules! tpm_tagged_struct {
250 (
251 $(#[$outer:meta])*
252 $vis:vis struct $name:ident {
253 pub $tag_field:ident: $tag_ty:ty,
254 pub $value_field:ident: $value_ty:ty,
255 }
256 ) => {
257 $(#[$outer])*
258 $vis struct $name {
259 pub $tag_field: $tag_ty,
260 pub $value_field: $value_ty,
261 }
262
263 impl $crate::TpmTagged for $name {
264 type Tag = $tag_ty;
265 type Value = $value_ty;
266 }
267
268 impl $crate::TpmSized for $name {
269 const SIZE: usize = <$tag_ty>::SIZE + <$value_ty>::SIZE;
270 fn len(&self) -> usize {
271 $crate::TpmSized::len(&self.$tag_field) + $crate::TpmSized::len(&self.$value_field)
272 }
273 }
274
275 impl $crate::TpmBuild for $name {
276 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
277 $crate::TpmBuild::build(&self.$tag_field, writer)?;
278 $crate::TpmBuild::build(&self.$value_field, writer)
279 }
280 }
281
282 impl $crate::TpmParse for $name {
283 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
284 let ($tag_field, buf) = <$tag_ty>::parse(buf)?;
285 let ($value_field, buf) =
286 <$value_ty as $crate::TpmParseTagged>::parse_tagged($tag_field, buf)?;
287 Ok((
288 Self {
289 $tag_field,
290 $value_field,
291 },
292 buf,
293 ))
294 }
295 }
296 };
297}