1pub mod r#enum;
6pub mod integer;
7pub mod r#struct;
8
9#[macro_export]
10macro_rules! tpm_bitflags {
11 (
12 $(#[$outer:meta])*
13 $vis:vis struct $name:ident($repr:ty) {
14 $(
15 $(#[$inner:meta])*
16 const $field:ident = $value:expr, $string_name:literal;
17 )*
18 }
19 ) => {
20 $(#[$outer])*
21 $vis struct $name($repr);
22
23 impl $name {
24 $(
25 $(#[$inner])*
26 pub const $field: Self = Self($value);
27 )*
28
29 #[must_use]
30 pub const fn bits(&self) -> $repr {
31 self.0
32 }
33
34 #[must_use]
35 pub const fn from_bits_truncate(bits: $repr) -> Self {
36 Self(bits)
37 }
38
39 #[must_use]
40 pub const fn empty() -> Self {
41 Self(0)
42 }
43
44 #[must_use]
45 pub const fn contains(&self, other: Self) -> bool {
46 (self.0 & other.0) == other.0
47 }
48
49 pub fn flag_names(&self) -> impl Iterator<Item = &'static str> + '_ {
50 [
51 $(
52 (Self::$field, $string_name),
53 )*
54 ]
55 .into_iter()
56 .filter(move |(flag, _)| self.contains(*flag))
57 .map(|(_, name)| name)
58 }
59 }
60
61 impl core::ops::BitOr for $name {
62 type Output = Self;
63 fn bitor(self, rhs: Self) -> Self::Output {
64 Self(self.0 | rhs.0)
65 }
66 }
67
68 impl core::ops::BitOrAssign for $name {
69 fn bitor_assign(&mut self, rhs: Self) {
70 self.0 |= rhs.0;
71 }
72 }
73
74 impl $crate::TpmMarshal for $name {
75 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
76 $crate::TpmMarshal::marshal(&self.0, writer)
77 }
78 }
79
80 impl $crate::TpmUnmarshal for $name {
81 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
82 let (val, buf) = <$repr>::unmarshal(buf)?;
83 Ok((Self(val), buf))
84 }
85 }
86
87 impl $crate::TpmSized for $name {
88 const SIZE: usize = core::mem::size_of::<$repr>();
89 fn len(&self) -> usize {
90 Self::SIZE
91 }
92 }
93 };
94}
95
96#[macro_export]
97macro_rules! tpm_bool {
98 (
99 $(#[$outer:meta])*
100 $vis:vis struct $name:ident(bool);
101 ) => {
102 $(#[$outer])*
103 $vis struct $name(pub bool);
104
105 impl From<bool> for $name {
106 fn from(val: bool) -> Self {
107 Self(val)
108 }
109 }
110
111 impl From<$name> for bool {
112 fn from(val: $name) -> Self {
113 val.0
114 }
115 }
116
117 impl $crate::TpmMarshal for $name {
118 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
119 $crate::TpmMarshal::marshal(&u8::from(self.0), writer)
120 }
121 }
122
123 impl $crate::TpmUnmarshal for $name {
124 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
125 let (val, buf) = u8::unmarshal(buf)?;
126 match val {
127 0 => Ok((Self(false), buf)),
128 1 => Ok((Self(true), buf)),
129 _ => Err($crate::TpmProtocolError::InvalidValue),
130 }
131 }
132 }
133
134 impl $crate::TpmSized for $name {
135 const SIZE: usize = core::mem::size_of::<u8>();
136 fn len(&self) -> usize {
137 Self::SIZE
138 }
139 }
140 };
141}
142
143#[macro_export]
144macro_rules! tpm_dispatch {
145 (@const_check_sorted) => {};
146 (@const_check_sorted $prev_cmd:ident, $( $rest_cmd:ident, )*) => {
147 $crate::tpm_dispatch!(@const_check_sorted_impl $prev_cmd, $( $rest_cmd, )*);
148 };
149 (@const_check_sorted_impl $prev_cmd:ident,) => {};
150 (@const_check_sorted_impl $prev_cmd:ident, $current_cmd:ident, $( $rest_cmd:ident, )* ) => {
151 const _: () = assert!(
152 <$crate::frame::data::$prev_cmd as $crate::frame::TpmHeader>::CC as u32 <= <$crate::frame::data::$current_cmd as $crate::frame::TpmHeader>::CC as u32,
153 "TPM_DISPATCH_TABLE must be sorted by TpmCc."
154 );
155 $crate::tpm_dispatch!(@const_check_sorted_impl $current_cmd, $( $rest_cmd, )*);
156 };
157
158 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
159 #[allow(clippy::large_enum_variant)]
161 #[derive(Debug, PartialEq, Eq, Clone)]
162 pub enum TpmCommand {
163 $( $variant($crate::frame::data::$cmd), )*
164 }
165
166 impl $crate::TpmSized for TpmCommand {
167 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE as usize;
168 fn len(&self) -> usize {
169 match self {
170 $( Self::$variant(c) => $crate::TpmSized::len(c), )*
171 }
172 }
173 }
174
175 impl $crate::frame::TpmMarshalBody for TpmCommand {
176 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
177 match self {
178 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_handles(c, writer), )*
179 }
180 }
181 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
182 match self {
183 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_parameters(c, writer), )*
184 }
185 }
186 }
187
188 impl $crate::TpmMarshal for TpmCommand {
189 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
190 match self {
191 $( Self::$variant(c) => $crate::TpmMarshal::marshal(c, writer), )*
192 }
193 }
194 }
195
196 impl $crate::frame::TpmFrame for TpmCommand {
197 fn cc(&self) -> $crate::data::TpmCc {
198 match self {
199 $( Self::$variant(c) => $crate::frame::TpmFrame::cc(c), )*
200 }
201 }
202 fn handles(&self) -> usize {
203 match self {
204 $( Self::$variant(c) => $crate::frame::TpmFrame::handles(c), )*
205 }
206 }
207 }
208
209 impl TpmCommand {
210 pub fn marshal_frame(
216 &self,
217 tag: $crate::data::TpmSt,
218 sessions: &$crate::frame::TpmAuthCommands,
219 writer: &mut $crate::TpmWriter,
220 ) -> $crate::TpmResult<()> {
221 match self {
222 $( Self::$variant(c) => $crate::frame::tpm_marshal_command(c, tag, sessions, writer), )*
223 }
224 }
225 }
226
227 #[allow(clippy::large_enum_variant)]
229 #[derive(Debug, PartialEq, Eq, Clone)]
230 pub enum TpmResponse {
231 $( $variant($crate::frame::data::$resp), )*
232 }
233
234 impl $crate::TpmSized for TpmResponse {
235 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE as usize;
236 fn len(&self) -> usize {
237 match self {
238 $( Self::$variant(r) => $crate::TpmSized::len(r), )*
239 }
240 }
241 }
242
243 impl $crate::frame::TpmMarshalBody for TpmResponse {
244 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
245 match self {
246 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_handles(r, writer), )*
247 }
248 }
249 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
250 match self {
251 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_parameters(r, writer), )*
252 }
253 }
254 }
255
256 impl $crate::TpmMarshal for TpmResponse {
257 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
258 match self {
259 $( Self::$variant(r) => $crate::TpmMarshal::marshal(r, writer), )*
260 }
261 }
262 }
263
264 impl $crate::frame::TpmFrame for TpmResponse {
265 fn cc(&self) -> $crate::data::TpmCc {
266 match self {
267 $( Self::$variant(r) => $crate::frame::TpmFrame::cc(r), )*
268 }
269 }
270 fn handles(&self) -> usize {
271 match self {
272 $( Self::$variant(r) => $crate::frame::TpmFrame::handles(r), )*
273 }
274 }
275 }
276
277 impl TpmResponse {
278 $(
279 #[allow(non_snake_case, clippy::result_large_err)]
285 pub fn $variant(self) -> Result<$crate::frame::data::$resp, Self> {
286 if let Self::$variant(r) = self {
287 Ok(r)
288 } else {
289 Err(self)
290 }
291 }
292 )*
293
294 pub fn marshal_frame(
300 &self,
301 rc: $crate::data::TpmRc,
302 sessions: &$crate::frame::TpmAuthResponses,
303 writer: &mut $crate::TpmWriter,
304 ) -> $crate::TpmResult<()> {
305 match self {
306 $( Self::$variant(r) => $crate::frame::tpm_marshal_response(r, sessions, rc, writer), )*
307 }
308 }
309 }
310
311 pub(crate) static TPM_DISPATCH_TABLE: &[$crate::frame::TpmDispatch] = &[
312 $(
313 $crate::frame::TpmDispatch {
314 cc: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC,
315 handles: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::HANDLES,
316 command_unmarshaler: |handles, params| {
317 <$crate::frame::data::$cmd as $crate::frame::TpmUnmarshalCommand>::unmarshal_body(handles, params)
318 .map(|(c, r)| (TpmCommand::$variant(c), r))
319 },
320 response_unmarshaler: |tag, buf| {
321 <$crate::frame::data::$resp as $crate::frame::TpmUnmarshalResponse>::unmarshal_body(tag, buf)
322 .map(|(r, rest)| (TpmResponse::$variant(r), rest))
323 },
324 },
325 )*
326 ];
327
328 $crate::tpm_dispatch!(@const_check_sorted $( $cmd, )*);
329 };
330}
331
332#[macro_export]
333macro_rules! tpm2b {
334 ($name:ident, $capacity:expr) => {
335 pub type $name = $crate::basic::TpmBuffer<$capacity>;
336 };
337}
338
339#[macro_export]
340macro_rules! tpm2b_struct {
341 (
342 $(#[$meta:meta])*
343 $wrapper_ty:ident, $inner_ty:ty) => {
344 $(#[$meta])*
345 pub struct $wrapper_ty {
346 pub inner: $inner_ty,
347 }
348
349 impl $crate::TpmSized for $wrapper_ty {
350 const SIZE: usize = core::mem::size_of::<u16>() + <$inner_ty>::SIZE;
351 fn len(&self) -> usize {
352 core::mem::size_of::<u16>() + $crate::TpmSized::len(&self.inner)
353 }
354 }
355
356 impl $crate::TpmMarshal for $wrapper_ty {
357 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
358 let inner_len = $crate::TpmSized::len(&self.inner);
359 u16::try_from(inner_len)
360 .map_err(|_| $crate::TpmProtocolError::OperationFailed)?
361 .marshal(writer)?;
362 $crate::TpmMarshal::marshal(&self.inner, writer)
363 }
364 }
365
366 impl $crate::TpmUnmarshal for $wrapper_ty {
367 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
368 let (size, buf_after_size) = u16::unmarshal(buf)?;
369 let size = size as usize;
370
371 if buf_after_size.len() < size {
372 return Err($crate::TpmProtocolError::UnexpectedEnd);
373 }
374 let (inner_bytes, rest) = buf_after_size.split_at(size);
375
376 let (inner_val, tail) = <$inner_ty>::unmarshal(inner_bytes)?;
377
378 if !tail.is_empty() {
379 return Err($crate::TpmProtocolError::TrailingData);
380 }
381
382 Ok((Self { inner: inner_val }, rest))
383 }
384 }
385
386 impl From<$inner_ty> for $wrapper_ty {
387 fn from(inner: $inner_ty) -> Self {
388 Self { inner }
389 }
390 }
391
392 impl core::ops::Deref for $wrapper_ty {
393 type Target = $inner_ty;
394 fn deref(&self) -> &Self::Target {
395 &self.inner
396 }
397 }
398
399 impl core::ops::DerefMut for $wrapper_ty {
400 fn deref_mut(&mut self) -> &mut Self::Target {
401 &mut self.inner
402 }
403 }
404 };
405}
406
407#[macro_export]
408macro_rules! tpml {
409 ($name:ident, $inner_ty:ty, $capacity:expr) => {
410 pub type $name = $crate::basic::TpmList<$inner_ty, $capacity>;
411 };
412}