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