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
50 impl core::ops::BitOr for $name {
51 type Output = Self;
52 fn bitor(self, rhs: Self) -> Self::Output {
53 Self(self.0 | rhs.0)
54 }
55 }
56
57 impl core::ops::BitOrAssign for $name {
58 fn bitor_assign(&mut self, rhs: Self) {
59 self.0 |= rhs.0;
60 }
61 }
62
63 impl core::ops::BitAnd for $name {
64 type Output = Self;
65 fn bitand(self, rhs: Self) -> Self::Output {
66 Self(self.0 & rhs.0)
67 }
68 }
69
70 impl core::ops::BitAndAssign for $name {
71 fn bitand_assign(&mut self, rhs: Self) {
72 self.0 &= rhs.0;
73 }
74 }
75
76 impl core::ops::BitXor for $name {
77 type Output = Self;
78 fn bitxor(self, rhs: Self) -> Self::Output {
79 Self(self.0 ^ rhs.0)
80 }
81 }
82
83 impl core::ops::BitXorAssign for $name {
84 fn bitxor_assign(&mut self, rhs: Self) {
85 self.0 ^= rhs.0;
86 }
87 }
88
89 impl core::ops::Not for $name {
90 type Output = Self;
91 fn not(self) -> Self::Output {
92 Self(!self.0)
93 }
94 }
95
96 impl $crate::TpmMarshal for $name {
97 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
98 $crate::TpmMarshal::marshal(&self.0, writer)
99 }
100 }
101
102 impl $crate::TpmUnmarshal for $name {
103 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
104 let (val, buf) = <$repr as $crate::TpmUnmarshal>::unmarshal(buf)?;
105 Ok((Self(val), buf))
106 }
107 }
108
109 impl $crate::TpmSized for $name {
110 const SIZE: usize = core::mem::size_of::<$repr>();
111 fn len(&self) -> usize {
112 Self::SIZE
113 }
114 }
115 };
116}
117
118#[macro_export]
119macro_rules! tpm_bool {
120 (
121 $(#[$outer:meta])*
122 $vis:vis struct $name:ident(bool);
123 ) => {
124 $(#[$outer])*
125 $vis struct $name(pub bool);
126
127 impl From<bool> for $name {
128 fn from(val: bool) -> Self {
129 Self(val)
130 }
131 }
132
133 impl From<$name> for bool {
134 fn from(val: $name) -> Self {
135 val.0
136 }
137 }
138
139 impl $crate::TpmMarshal for $name {
140 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
141 let value = if self.0 { 1 } else { 0 };
142 $crate::basic::Uint8::from(value).marshal(writer)
143 }
144 }
145
146 impl $crate::TpmUnmarshal for $name {
147 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
148 let (val, buf) = $crate::basic::Uint8::unmarshal(buf)?;
149 match u8::from(val) {
150 0 => Ok((Self(false), buf)),
151 1 => Ok((Self(true), buf)),
152 _ => Err($crate::TpmProtocolError::InvalidBoolean),
153 }
154 }
155 }
156
157 impl $crate::TpmSized for $name {
158 const SIZE: usize = core::mem::size_of::<$crate::basic::Uint8>();
159 fn len(&self) -> usize {
160 Self::SIZE
161 }
162 }
163 };
164}
165
166#[macro_export]
167macro_rules! tpm_dispatch {
168 (@const_check_sorted) => {};
169 (@const_check_sorted $prev_cmd:ident, $( $rest_cmd:ident, )*) => {
170 $crate::tpm_dispatch!(@const_check_sorted_impl $prev_cmd, $( $rest_cmd, )*);
171 };
172 (@const_check_sorted_impl $prev_cmd:ident,) => {};
173 (@const_check_sorted_impl $prev_cmd:ident, $current_cmd:ident, $( $rest_cmd:ident, )* ) => {
174 const _: () = assert!(
175 <$crate::frame::data::$prev_cmd as $crate::frame::TpmHeader>::CC as u32 <= <$crate::frame::data::$current_cmd as $crate::frame::TpmHeader>::CC as u32,
176 "TPM_DISPATCH_TABLE must be sorted by TpmCc."
177 );
178 $crate::tpm_dispatch!(@const_check_sorted_impl $current_cmd, $( $rest_cmd, )*);
179 };
180
181 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
182 #[allow(clippy::large_enum_variant)]
184 #[derive(Debug, PartialEq, Eq, Clone)]
185 pub enum TpmCommand {
186 $( $variant($crate::frame::data::$cmd), )*
187 }
188
189 impl $crate::TpmSized for TpmCommand {
190 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
191 fn len(&self) -> usize {
192 match self {
193 $( Self::$variant(c) => $crate::TpmSized::len(c), )*
194 }
195 }
196 }
197
198 impl $crate::frame::TpmMarshalBody for TpmCommand {
199 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
200 match self {
201 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_handles(c, writer), )*
202 }
203 }
204 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
205 match self {
206 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_parameters(c, writer), )*
207 }
208 }
209 }
210
211 impl $crate::TpmMarshal for TpmCommand {
212 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
213 match self {
214 $( Self::$variant(c) => $crate::TpmMarshal::marshal(c, writer), )*
215 }
216 }
217 }
218
219 impl $crate::frame::TpmFrame for TpmCommand {
220 fn cc(&self) -> $crate::data::TpmCc {
221 match self {
222 $( Self::$variant(c) => $crate::frame::TpmFrame::cc(c), )*
223 }
224 }
225 fn handles(&self) -> usize {
226 match self {
227 $( Self::$variant(c) => $crate::frame::TpmFrame::handles(c), )*
228 }
229 }
230 }
231
232 impl TpmCommand {
233 pub fn marshal_frame(
239 &self,
240 tag: $crate::data::TpmSt,
241 sessions: &$crate::frame::TpmAuthCommands,
242 writer: &mut $crate::TpmWriter,
243 ) -> $crate::TpmResult<()> {
244 match self {
245 $( Self::$variant(c) => $crate::frame::tpm_marshal_command(c, tag, sessions, writer), )*
246 }
247 }
248 }
249
250 #[allow(clippy::large_enum_variant)]
252 #[derive(Debug, PartialEq, Eq, Clone)]
253 pub enum TpmResponse {
254 $( $variant($crate::frame::data::$resp), )*
255 }
256
257 impl $crate::TpmSized for TpmResponse {
258 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
259 fn len(&self) -> usize {
260 match self {
261 $( Self::$variant(r) => $crate::TpmSized::len(r), )*
262 }
263 }
264 }
265
266 impl $crate::frame::TpmMarshalBody for TpmResponse {
267 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
268 match self {
269 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_handles(r, writer), )*
270 }
271 }
272 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
273 match self {
274 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_parameters(r, writer), )*
275 }
276 }
277 }
278
279 impl $crate::TpmMarshal for TpmResponse {
280 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
281 match self {
282 $( Self::$variant(r) => $crate::TpmMarshal::marshal(r, writer), )*
283 }
284 }
285 }
286
287 impl $crate::frame::TpmFrame for TpmResponse {
288 fn cc(&self) -> $crate::data::TpmCc {
289 match self {
290 $( Self::$variant(r) => $crate::frame::TpmFrame::cc(r), )*
291 }
292 }
293 fn handles(&self) -> usize {
294 match self {
295 $( Self::$variant(r) => $crate::frame::TpmFrame::handles(r), )*
296 }
297 }
298 }
299
300 impl TpmResponse {
301 $(
302 #[allow(non_snake_case, clippy::result_large_err)]
308 pub fn $variant(self) -> Result<$crate::frame::data::$resp, Self> {
309 if let Self::$variant(r) = self {
310 Ok(r)
311 } else {
312 Err(self)
313 }
314 }
315 )*
316
317 pub fn marshal_frame(
323 &self,
324 rc: $crate::data::TpmRc,
325 sessions: &$crate::frame::TpmAuthResponses,
326 writer: &mut $crate::TpmWriter,
327 ) -> $crate::TpmResult<()> {
328 match self {
329 $( Self::$variant(r) => $crate::frame::tpm_marshal_response(r, sessions, rc, writer), )*
330 }
331 }
332 }
333
334 pub(crate) static TPM_DISPATCH_TABLE: &[$crate::frame::TpmDispatch] = &[
335 $(
336 $crate::frame::TpmDispatch {
337 cc: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC,
338 handles: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::HANDLES,
339 command_unmarshaler: |handles, params| {
340 <$crate::frame::data::$cmd as $crate::frame::TpmUnmarshalCommand>::unmarshal_body(handles, params)
341 .map(|(c, r)| (TpmCommand::$variant(c), r))
342 },
343 response_unmarshaler: |tag, buf| {
344 <$crate::frame::data::$resp as $crate::frame::TpmUnmarshalResponse>::unmarshal_body(tag, buf)
345 .map(|(r, rest)| (TpmResponse::$variant(r), rest))
346 },
347 },
348 )*
349 ];
350
351 $crate::tpm_dispatch!(@const_check_sorted $( $cmd, )*);
352 };
353}
354
355#[macro_export]
356macro_rules! tpm2b {
357 ($name:ident, $capacity:expr) => {
358 pub type $name = $crate::basic::TpmBuffer<$capacity>;
359 };
360}
361
362#[macro_export]
363macro_rules! tpm2b_struct {
364 (
365 $(#[$meta:meta])*
366 $wrapper_ty:ident, $inner_ty:ty) => {
367 $(#[$meta])*
368 pub struct $wrapper_ty {
369 pub inner: $inner_ty,
370 }
371
372 impl $crate::TpmSized for $wrapper_ty {
373 const SIZE: usize = core::mem::size_of::<$crate::basic::Uint16>() + <$inner_ty>::SIZE;
374 fn len(&self) -> usize {
375 core::mem::size_of::<$crate::basic::Uint16>() + $crate::TpmSized::len(&self.inner)
376 }
377 }
378
379 impl $crate::TpmMarshal for $wrapper_ty
380 where
381 $inner_ty: $crate::TpmSized,
382 {
383 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
384 let inner_len = $crate::TpmSized::len(&self.inner);
385 let len_field = <$crate::basic::Uint16>::try_from(inner_len)
386 .map_err(|_| $crate::TpmProtocolError::IntegerTooLarge)?;
387 len_field.marshal(writer)?;
388 $crate::TpmMarshal::marshal(&self.inner, writer)
389 }
390 }
391
392 impl $crate::TpmUnmarshal for $wrapper_ty {
393 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
394 let (size, buf_after_size) = <$crate::basic::Uint16 as $crate::TpmUnmarshal>::unmarshal(buf)?;
395 let size = u16::from(size) as usize;
396
397 if buf_after_size.len() < size {
398 return Err($crate::TpmProtocolError::UnexpectedEnd);
399 }
400 let (inner_bytes, rest) = buf_after_size.split_at(size);
401
402 let (inner_val, tail) = <$inner_ty>::unmarshal(inner_bytes)?;
403
404 if !tail.is_empty() {
405 return Err($crate::TpmProtocolError::TrailingData);
406 }
407
408 Ok((Self { inner: inner_val }, rest))
409 }
410 }
411
412 impl From<$inner_ty> for $wrapper_ty {
413 fn from(inner: $inner_ty) -> Self {
414 Self { inner }
415 }
416 }
417
418 impl core::ops::Deref for $wrapper_ty {
419 type Target = $inner_ty;
420 fn deref(&self) -> &Self::Target {
421 &self.inner
422 }
423 }
424
425 impl core::ops::DerefMut for $wrapper_ty {
426 fn deref_mut(&mut self) -> &mut Self::Target {
427 &mut self.inner
428 }
429 }
430 };
431}
432
433#[macro_export]
434macro_rules! tpml {
435 ($name:ident, $inner_ty:ty, $capacity:expr) => {
436 pub type $name = $crate::basic::TpmList<$inner_ty, $capacity>;
437 };
438}