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