1pub mod r#enum;
6pub mod integer;
7pub mod r#struct;
8
9#[macro_export]
10macro_rules! tpm_bitflags {
11 (@impl $(#[$outer:meta])* $vis:vis struct $name:ident($wrapper:ty, $repr:ty) {
12 $(
13 $(#[$inner:meta])*
14 const $field:ident = $value:expr, $string_name:literal;
15 )*
16 }) => {
17 $(#[$outer])*
18 $vis struct $name($repr);
19
20 impl $name {
21 $(
22 $(#[$inner])*
23 pub const $field: Self = Self($value);
24 )*
25
26 #[must_use]
27 pub const fn bits(&self) -> $repr {
28 self.0
29 }
30
31 #[must_use]
32 pub const fn from_bits_truncate(bits: $repr) -> Self {
33 Self(bits)
34 }
35
36 pub const fn set_bits(&mut self, bits: $repr) {
37 self.0 = bits;
38 }
39
40 #[must_use]
41 pub const fn empty() -> Self {
42 Self(0)
43 }
44
45 #[must_use]
46 pub const fn contains(&self, other: Self) -> bool {
47 (self.0 & other.0) == other.0
48 }
49 }
50
51 impl core::ops::BitOr for $name {
52 type Output = Self;
53 fn bitor(self, rhs: Self) -> Self::Output {
54 Self(self.0 | rhs.0)
55 }
56 }
57
58 impl core::ops::BitOrAssign for $name {
59 fn bitor_assign(&mut self, rhs: Self) {
60 self.0 |= rhs.0;
61 }
62 }
63
64 impl core::ops::BitAnd for $name {
65 type Output = Self;
66 fn bitand(self, rhs: Self) -> Self::Output {
67 Self(self.0 & rhs.0)
68 }
69 }
70
71 impl core::ops::BitAndAssign for $name {
72 fn bitand_assign(&mut self, rhs: Self) {
73 self.0 &= rhs.0;
74 }
75 }
76
77 impl core::ops::BitXor for $name {
78 type Output = Self;
79 fn bitxor(self, rhs: Self) -> Self::Output {
80 Self(self.0 ^ rhs.0)
81 }
82 }
83
84 impl core::ops::BitXorAssign for $name {
85 fn bitxor_assign(&mut self, rhs: Self) {
86 self.0 ^= rhs.0;
87 }
88 }
89
90 impl core::ops::Not for $name {
91 type Output = Self;
92 fn not(self) -> Self::Output {
93 Self(!self.0)
94 }
95 }
96
97 impl $crate::TpmMarshal for $name {
98 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
99 let value = <$wrapper>::from(self.0);
100 $crate::TpmMarshal::marshal(&value, writer)
101 }
102 }
103
104 impl<'a> $crate::TpmField<'a> for $name {
105 type View = Self;
106
107 fn cast_prefix_field(buf: &'a [u8]) -> $crate::TpmResult<(Self::View, &'a [u8])> {
108 let (value, buf) = <$wrapper as $crate::TpmCast>::cast_prefix(buf)?;
109
110 Ok((Self(value.get()), buf))
111 }
112 }
113
114 impl $crate::TpmSized for $name {
115 const SIZE: usize = core::mem::size_of::<$repr>();
116 fn len(&self) -> usize {
117 Self::SIZE
118 }
119 }
120 };
121
122 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint8) { $($rest:tt)* }) => {
123 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint8, u8) { $($rest)* });
124 };
125 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint16) { $($rest:tt)* }) => {
126 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint16, u16) { $($rest)* });
127 };
128 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint32) { $($rest:tt)* }) => {
129 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint32, u32) { $($rest)* });
130 };
131 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint64) { $($rest:tt)* }) => {
132 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint64, u64) { $($rest)* });
133 };
134}
135
136#[macro_export]
137macro_rules! tpm_bool {
138 (
139 $(#[$outer:meta])*
140 $vis:vis struct $name:ident(bool);
141 ) => {
142 $(#[$outer])*
143 $vis struct $name(pub bool);
144
145 impl From<bool> for $name {
146 fn from(val: bool) -> Self {
147 Self(val)
148 }
149 }
150
151 impl From<$name> for bool {
152 fn from(val: $name) -> Self {
153 val.0
154 }
155 }
156
157 impl $crate::TpmMarshal for $name {
158 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
159 let value = if self.0 { 1 } else { 0 };
160 $crate::basic::TpmUint8::from(value).marshal(writer)
161 }
162 }
163
164 impl<'a> $crate::TpmField<'a> for $name {
165 type View = Self;
166
167 fn cast_prefix_field(buf: &'a [u8]) -> $crate::TpmResult<(Self::View, &'a [u8])> {
168 let (value, buf) = <$crate::basic::TpmUint8 as $crate::TpmCast>::cast_prefix(buf)?;
169 match value.get() {
170 0 => Ok((Self(false), buf)),
171 1 => Ok((Self(true), buf)),
172 raw => Err($crate::TpmError::InvalidBoolean(
173 $crate::TpmErrorValue::new(0).value(u64::from(raw)),
174 )),
175 }
176 }
177 }
178
179 impl $crate::TpmSized for $name {
180 const SIZE: usize = core::mem::size_of::<$crate::basic::TpmUint8>();
181 fn len(&self) -> usize {
182 Self::SIZE
183 }
184 }
185 };
186}
187
188#[macro_export]
189macro_rules! tpm_dispatch {
190 (@const_check_sorted) => {};
191 (@const_check_sorted $prev_cmd:ident, $( $rest_cmd:ident, )*) => {
192 $crate::tpm_dispatch!(@const_check_sorted_impl $prev_cmd, $( $rest_cmd, )*);
193 };
194 (@const_check_sorted_impl $prev_cmd:ident,) => {};
195 (@const_check_sorted_impl $prev_cmd:ident, $current_cmd:ident, $( $rest_cmd:ident, )* ) => {
196 const _: () = assert!(
197 <$crate::frame::data::$prev_cmd as $crate::frame::TpmHeader>::CC as u32 <= <$crate::frame::data::$current_cmd as $crate::frame::TpmHeader>::CC as u32,
198 "TPM_DISPATCH_TABLE must be sorted by TpmCc."
199 );
200 $crate::tpm_dispatch!(@const_check_sorted_impl $current_cmd, $( $rest_cmd, )*);
201 };
202
203 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
204 #[allow(clippy::large_enum_variant)]
206 #[derive(Debug, PartialEq, Eq, Clone)]
207 pub enum TpmCommandValue {
208 $( $variant($crate::frame::data::$cmd), )*
209 }
210
211 impl $crate::TpmSized for TpmCommandValue {
212 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
213 fn len(&self) -> usize {
214 match self {
215 $( Self::$variant(c) => $crate::TpmSized::len(c), )*
216 }
217 }
218 }
219
220 impl $crate::frame::TpmMarshalBody for TpmCommandValue {
221 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
222 match self {
223 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_handles(c, writer), )*
224 }
225 }
226 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
227 match self {
228 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_parameters(c, writer), )*
229 }
230 }
231 }
232
233 impl $crate::TpmMarshal for TpmCommandValue {
234 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
235 match self {
236 $( Self::$variant(c) => $crate::TpmMarshal::marshal(c, writer), )*
237 }
238 }
239 }
240
241 impl $crate::frame::TpmFrame for TpmCommandValue {
242 fn cc(&self) -> $crate::data::TpmCc {
243 match self {
244 $( Self::$variant(c) => $crate::frame::TpmFrame::cc(c), )*
245 }
246 }
247 fn handles(&self) -> usize {
248 match self {
249 $( Self::$variant(c) => $crate::frame::TpmFrame::handles(c), )*
250 }
251 }
252 }
253
254 impl TpmCommandValue {
255 pub fn marshal_frame(
261 &self,
262 tag: $crate::data::TpmSt,
263 sessions: &$crate::frame::TpmAuthCommands,
264 writer: &mut $crate::TpmWriter,
265 ) -> $crate::TpmResult<()> {
266 match self {
267 $( Self::$variant(c) => $crate::frame::tpm_marshal_command(c, tag, sessions, writer), )*
268 }
269 }
270 }
271
272 pub enum TpmCommandView<'a> {
274 $( $variant(&'a $crate::frame::TpmCommand), )*
275 }
276
277 impl<'a> TpmCommandView<'a> {
278 pub fn cast_frame(buf: &'a [u8]) -> $crate::TpmResult<Self> {
285 let command = <$crate::frame::TpmCommand>::cast(buf)?;
286
287 Self::cast(command)
288 }
289
290 pub fn cast(command: &'a $crate::frame::TpmCommand) -> $crate::TpmResult<Self> {
297 command.validate()?;
298
299 let cc = command.cc()?;
300 match cc {
301 $( <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC => Ok(Self::$variant(command)), )*
302 _ => Err($crate::TpmError::InvalidCc(
303 $crate::TpmErrorValue::new(6).value(u64::from(cc.value())),
304 )),
305 }
306 }
307
308 #[must_use]
310 pub fn command(&self) -> &'a $crate::frame::TpmCommand {
311 match self {
312 $( Self::$variant(command) => command, )*
313 }
314 }
315
316 #[must_use]
318 pub fn cc(&self) -> $crate::data::TpmCc {
319 match self {
320 $( Self::$variant(_) => <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC, )*
321 }
322 }
323 }
324
325 #[allow(clippy::large_enum_variant)]
327 #[derive(Debug, PartialEq, Eq, Clone)]
328 pub enum TpmResponseValue {
329 $( $variant($crate::frame::data::$resp), )*
330 }
331
332 impl $crate::TpmSized for TpmResponseValue {
333 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
334 fn len(&self) -> usize {
335 match self {
336 $( Self::$variant(r) => $crate::TpmSized::len(r), )*
337 }
338 }
339 }
340
341 impl $crate::frame::TpmMarshalBody for TpmResponseValue {
342 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
343 match self {
344 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_handles(r, writer), )*
345 }
346 }
347 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
348 match self {
349 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_parameters(r, writer), )*
350 }
351 }
352 }
353
354 impl $crate::TpmMarshal for TpmResponseValue {
355 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
356 match self {
357 $( Self::$variant(r) => $crate::TpmMarshal::marshal(r, writer), )*
358 }
359 }
360 }
361
362 impl $crate::frame::TpmFrame for TpmResponseValue {
363 fn cc(&self) -> $crate::data::TpmCc {
364 match self {
365 $( Self::$variant(r) => $crate::frame::TpmFrame::cc(r), )*
366 }
367 }
368 fn handles(&self) -> usize {
369 match self {
370 $( Self::$variant(r) => $crate::frame::TpmFrame::handles(r), )*
371 }
372 }
373 }
374
375 impl TpmResponseValue {
376 $(
377 #[allow(non_snake_case, clippy::result_large_err)]
383 pub fn $variant(self) -> Result<$crate::frame::data::$resp, Self> {
384 if let Self::$variant(r) = self {
385 Ok(r)
386 } else {
387 Err(self)
388 }
389 }
390 )*
391
392 pub fn marshal_frame(
398 &self,
399 rc: $crate::data::TpmRc,
400 sessions: &$crate::frame::TpmAuthResponses,
401 writer: &mut $crate::TpmWriter,
402 ) -> $crate::TpmResult<()> {
403 match self {
404 $( Self::$variant(r) => $crate::frame::tpm_marshal_response(r, sessions, rc, writer), )*
405 }
406 }
407 }
408
409 pub enum TpmResponseView<'a> {
411 $( $variant(&'a $crate::frame::TpmResponse), )*
412 }
413
414 pub type TpmResponseViewResult<'a> = Result<TpmResponseView<'a>, $crate::data::TpmRc>;
416
417 impl<'a> TpmResponseView<'a> {
418 pub fn cast_frame(
425 cc: $crate::data::TpmCc,
426 buf: &'a [u8],
427 ) -> $crate::TpmResult<TpmResponseViewResult<'a>> {
428 let response = <$crate::frame::TpmResponse>::cast(buf)?;
429
430 Self::cast(cc, response)
431 }
432
433 pub fn cast(
440 cc: $crate::data::TpmCc,
441 response: &'a $crate::frame::TpmResponse,
442 ) -> $crate::TpmResult<TpmResponseViewResult<'a>> {
443 let rc = response.rc()?;
444 if !matches!(rc, $crate::data::TpmRc::Fmt0($crate::data::TpmRcBase::Success)) {
445 return Ok(Err(rc));
446 }
447
448 response.validate(cc)?;
449
450 match cc {
451 $( <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC => Ok(Ok(Self::$variant(response))), )*
452 _ => Err($crate::TpmError::InvalidCc(
453 $crate::TpmErrorValue::new(0).value(u64::from(cc.value())),
454 )),
455 }
456 }
457
458 #[must_use]
460 pub fn response(&self) -> &'a $crate::frame::TpmResponse {
461 match self {
462 $( Self::$variant(response) => response, )*
463 }
464 }
465
466 #[must_use]
468 pub fn cc(&self) -> $crate::data::TpmCc {
469 match self {
470 $( Self::$variant(_) => <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC, )*
471 }
472 }
473 }
474
475 pub(crate) static TPM_DISPATCH_TABLE: &[$crate::frame::TpmDispatch] = &[
476 $(
477 $crate::frame::TpmDispatch {
478 cc: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC,
479 handles: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::HANDLES,
480 response_handles: <$crate::frame::data::$resp as $crate::frame::TpmHeader>::HANDLES,
481 },
482 )*
483 ];
484
485 $crate::tpm_dispatch!(@const_check_sorted $( $cmd, )*);
486 };
487}