1pub mod r#enum;
6pub mod integer;
7pub mod r#struct;
8
9#[doc(hidden)]
16#[macro_export]
17macro_rules! tpm_byte_view {
18 ($name:ident) => {
19 $crate::tpm_byte_view!(@emit { } { $name });
20 };
21 ($name:ident<const $param:ident: usize>) => {
22 $crate::tpm_byte_view!(@emit { <const $param: usize> } { $name<$param> });
23 };
24 (array $name:ident) => {
25 $crate::tpm_byte_view!(@emit_array { } { $name });
26 };
27 (array $name:ident<const $param:ident: usize>) => {
28 $crate::tpm_byte_view!(@emit_array { <const $param: usize> } { $name<$param> });
29 };
30 (@emit_array { $($generics:tt)* } { $($ty:tt)* }) => {
31 impl $($generics)* $($ty)* {
32 #[must_use]
39 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
40 let ptr = buf.as_ptr().cast::<Self>();
41
42 unsafe { &*ptr }
46 }
47
48 #[must_use]
56 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
57 let ptr = buf.as_mut_ptr().cast::<Self>();
58
59 unsafe { &mut *ptr }
63 }
64 }
65 };
66 (@emit { $($generics:tt)* } { $($ty:tt)* }) => {
67 impl $($generics)* $($ty)* {
68 #[must_use]
75 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
76 let ptr = core::ptr::from_ref(buf) as *const Self;
77
78 unsafe { &*ptr }
81 }
82
83 #[must_use]
91 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
92 let ptr = core::ptr::from_mut(buf) as *mut Self;
93
94 unsafe { &mut *ptr }
97 }
98 }
99
100 impl $($generics)* AsRef<[u8]> for $($ty)* {
101 fn as_ref(&self) -> &[u8] {
102 self.as_bytes()
103 }
104 }
105
106 impl $($generics)* AsMut<[u8]> for $($ty)* {
107 fn as_mut(&mut self) -> &mut [u8] {
108 self.as_bytes_mut()
109 }
110 }
111 };
112}
113
114#[doc(hidden)]
115#[macro_export]
116macro_rules! tpm_bitflags {
117 (@impl $(#[$outer:meta])* $vis:vis struct $name:ident($wrapper:ty, $repr:ty) {
118 $(
119 $(#[$inner:meta])*
120 const $field:ident = $value:expr, $string_name:literal;
121 )*
122 }) => {
123 $(#[$outer])*
124 $vis struct $name($repr);
125
126 impl $name {
127 $(
128 $(#[$inner])*
129 pub const $field: Self = Self($value);
130 )*
131
132 #[must_use]
133 pub const fn bits(&self) -> $repr {
134 self.0
135 }
136
137 #[must_use]
138 pub const fn from_bits_truncate(bits: $repr) -> Self {
139 Self(bits)
140 }
141
142 pub const fn set_bits(&mut self, bits: $repr) {
143 self.0 = bits;
144 }
145
146 #[must_use]
147 pub const fn empty() -> Self {
148 Self(0)
149 }
150
151 #[must_use]
152 pub const fn contains(&self, other: Self) -> bool {
153 (self.0 & other.0) == other.0
154 }
155 }
156
157 impl core::ops::BitOr for $name {
158 type Output = Self;
159 fn bitor(self, rhs: Self) -> Self::Output {
160 Self(self.0 | rhs.0)
161 }
162 }
163
164 impl core::ops::BitOrAssign for $name {
165 fn bitor_assign(&mut self, rhs: Self) {
166 self.0 |= rhs.0;
167 }
168 }
169
170 impl core::ops::BitAnd for $name {
171 type Output = Self;
172 fn bitand(self, rhs: Self) -> Self::Output {
173 Self(self.0 & rhs.0)
174 }
175 }
176
177 impl core::ops::BitAndAssign for $name {
178 fn bitand_assign(&mut self, rhs: Self) {
179 self.0 &= rhs.0;
180 }
181 }
182
183 impl core::ops::BitXor for $name {
184 type Output = Self;
185 fn bitxor(self, rhs: Self) -> Self::Output {
186 Self(self.0 ^ rhs.0)
187 }
188 }
189
190 impl core::ops::BitXorAssign for $name {
191 fn bitxor_assign(&mut self, rhs: Self) {
192 self.0 ^= rhs.0;
193 }
194 }
195
196 impl core::ops::Not for $name {
197 type Output = Self;
198 fn not(self) -> Self::Output {
199 Self(!self.0)
200 }
201 }
202
203 impl $crate::TpmMarshal for $name {
204 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
205 let value = <$wrapper>::from(self.0);
206 $crate::TpmMarshal::marshal(&value, writer)
207 }
208 }
209
210 impl<'a> $crate::TpmField<'a> for $name {
211 type View = Self;
212
213 fn cast_prefix_field(buf: &'a [u8]) -> $crate::TpmResult<(Self::View, &'a [u8])> {
214 let (value, buf) = <$wrapper as $crate::TpmCast>::cast_prefix(buf)?;
215
216 Ok((Self(value.value()), buf))
217 }
218 }
219
220 impl $crate::TpmSized for $name {
221 const SIZE: usize = core::mem::size_of::<$repr>();
222 fn len(&self) -> usize {
223 Self::SIZE
224 }
225 }
226 };
227
228 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint8) { $($rest:tt)* }) => {
229 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint8, u8) { $($rest)* });
230 };
231 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint16) { $($rest:tt)* }) => {
232 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint16, u16) { $($rest)* });
233 };
234 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint32) { $($rest:tt)* }) => {
235 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint32, u32) { $($rest)* });
236 };
237 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint64) { $($rest:tt)* }) => {
238 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint64, u64) { $($rest)* });
239 };
240}
241
242#[doc(hidden)]
243#[macro_export]
244macro_rules! tpm_bool {
245 (
246 $(#[$outer:meta])*
247 $vis:vis struct $name:ident(bool);
248 ) => {
249 $(#[$outer])*
250 $vis struct $name(pub bool);
251
252 impl From<bool> for $name {
253 fn from(val: bool) -> Self {
254 Self(val)
255 }
256 }
257
258 impl From<$name> for bool {
259 fn from(val: $name) -> Self {
260 val.0
261 }
262 }
263
264 impl $crate::TpmMarshal for $name {
265 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
266 let value = if self.0 { 1 } else { 0 };
267 $crate::basic::TpmUint8::from(value).marshal(writer)
268 }
269 }
270
271 impl<'a> $crate::TpmField<'a> for $name {
272 type View = Self;
273
274 fn cast_prefix_field(buf: &'a [u8]) -> $crate::TpmResult<(Self::View, &'a [u8])> {
275 let (value, buf) = <$crate::basic::TpmUint8 as $crate::TpmCast>::cast_prefix(buf)?;
276 match value.value() {
277 0 => Ok((Self(false), buf)),
278 1 => Ok((Self(true), buf)),
279 raw => Err($crate::TpmError::InvalidBoolean { offset: 0, value: u64::from(raw) }),
280 }
281 }
282 }
283
284 impl $crate::TpmSized for $name {
285 const SIZE: usize = core::mem::size_of::<$crate::basic::TpmUint8>();
286 fn len(&self) -> usize {
287 Self::SIZE
288 }
289 }
290 };
291}
292
293#[doc(hidden)]
294#[macro_export]
295macro_rules! tpm_dispatch {
296 (@const_check_sorted) => {};
297 (@const_check_sorted $prev_cmd:ident, $( $rest_cmd:ident, )*) => {
298 $crate::tpm_dispatch!(@const_check_sorted_impl $prev_cmd, $( $rest_cmd, )*);
299 };
300 (@const_check_sorted_impl $prev_cmd:ident,) => {};
301 (@const_check_sorted_impl $prev_cmd:ident, $current_cmd:ident, $( $rest_cmd:ident, )* ) => {
302 const _: () = assert!(
303 <$crate::frame::data::$prev_cmd as $crate::frame::TpmHeader>::CC as u32 <= <$crate::frame::data::$current_cmd as $crate::frame::TpmHeader>::CC as u32,
304 "TPM_DISPATCH_TABLE must be sorted by TpmCc."
305 );
306 $crate::tpm_dispatch!(@const_check_sorted_impl $current_cmd, $( $rest_cmd, )*);
307 };
308
309 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
310 #[allow(clippy::large_enum_variant)]
312 #[derive(Debug, PartialEq, Eq, Clone)]
313 pub enum TpmCommandValue {
314 $( $variant($crate::frame::data::$cmd), )*
315 }
316
317 impl $crate::TpmSized for TpmCommandValue {
318 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
319 fn len(&self) -> usize {
320 match self {
321 $( Self::$variant(c) => $crate::TpmSized::len(c), )*
322 }
323 }
324 }
325
326 impl $crate::frame::TpmMarshalBody for TpmCommandValue {
327 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
328 match self {
329 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_handles(c, writer), )*
330 }
331 }
332 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
333 match self {
334 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_parameters(c, writer), )*
335 }
336 }
337 }
338
339 impl $crate::TpmMarshal for TpmCommandValue {
340 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
341 match self {
342 $( Self::$variant(c) => $crate::TpmMarshal::marshal(c, writer), )*
343 }
344 }
345 }
346
347 impl $crate::frame::TpmFrame for TpmCommandValue {
348 fn cc(&self) -> $crate::data::TpmCc {
349 match self {
350 $( Self::$variant(c) => $crate::frame::TpmFrame::cc(c), )*
351 }
352 }
353 fn handles(&self) -> usize {
354 match self {
355 $( Self::$variant(c) => $crate::frame::TpmFrame::handles(c), )*
356 }
357 }
358 }
359
360 impl TpmCommandValue {
361 pub fn marshal_frame(
367 &self,
368 tag: $crate::data::TpmSt,
369 sessions: &$crate::frame::TpmAuthCommands,
370 writer: &mut $crate::TpmWriter,
371 ) -> $crate::TpmResult<()> {
372 match self {
373 $( Self::$variant(c) => $crate::frame::tpm_marshal_command(c, tag, sessions, writer), )*
374 }
375 }
376 }
377
378 pub enum TpmCommandView<'a> {
380 $( $variant(&'a $crate::frame::TpmCommand), )*
381 }
382
383 impl<'a> TpmCommandView<'a> {
384 pub fn cast_frame(buf: &'a [u8]) -> $crate::TpmResult<Self> {
391 let command = <$crate::frame::TpmCommand>::cast(buf)?;
392
393 Self::cast(command)
394 }
395
396 pub fn cast(command: &'a $crate::frame::TpmCommand) -> $crate::TpmResult<Self> {
403 command.validate()?;
404
405 let cc = command.cc()?;
406 match cc {
407 $( <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC => Ok(Self::$variant(command)), )*
408 #[allow(unreachable_patterns)]
409 _ => Err($crate::TpmError::InvalidCc { offset: 6, value: u64::from(cc.value()) }),
410 }
411 }
412
413 #[must_use]
415 pub fn command(&self) -> &'a $crate::frame::TpmCommand {
416 match self {
417 $( Self::$variant(command) => command, )*
418 }
419 }
420
421 #[must_use]
423 pub fn cc(&self) -> $crate::data::TpmCc {
424 match self {
425 $( Self::$variant(_) => <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC, )*
426 }
427 }
428 }
429
430 #[allow(clippy::large_enum_variant)]
432 #[derive(Debug, PartialEq, Eq, Clone)]
433 pub enum TpmResponseValue {
434 $( $variant($crate::frame::data::$resp), )*
435 }
436
437 impl $crate::TpmSized for TpmResponseValue {
438 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
439 fn len(&self) -> usize {
440 match self {
441 $( Self::$variant(r) => $crate::TpmSized::len(r), )*
442 }
443 }
444 }
445
446 impl $crate::frame::TpmMarshalBody for TpmResponseValue {
447 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
448 match self {
449 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_handles(r, writer), )*
450 }
451 }
452 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
453 match self {
454 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_parameters(r, writer), )*
455 }
456 }
457 }
458
459 impl $crate::TpmMarshal for TpmResponseValue {
460 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
461 match self {
462 $( Self::$variant(r) => $crate::TpmMarshal::marshal(r, writer), )*
463 }
464 }
465 }
466
467 impl $crate::frame::TpmFrame for TpmResponseValue {
468 fn cc(&self) -> $crate::data::TpmCc {
469 match self {
470 $( Self::$variant(r) => $crate::frame::TpmFrame::cc(r), )*
471 }
472 }
473 fn handles(&self) -> usize {
474 match self {
475 $( Self::$variant(r) => $crate::frame::TpmFrame::handles(r), )*
476 }
477 }
478 }
479
480 impl TpmResponseValue {
481 pub fn marshal_frame(
487 &self,
488 rc: $crate::data::TpmRc,
489 sessions: &$crate::frame::TpmAuthResponses,
490 writer: &mut $crate::TpmWriter,
491 ) -> $crate::TpmResult<()> {
492 match self {
493 $( Self::$variant(r) => $crate::frame::tpm_marshal_response(r, rc, sessions, writer), )*
494 }
495 }
496 }
497
498 $(
499 impl TryFrom<TpmResponseValue> for $crate::frame::data::$resp {
500 type Error = TpmResponseValue;
501
502 #[allow(clippy::result_large_err)]
503 fn try_from(value: TpmResponseValue) -> Result<Self, Self::Error> {
504 if let TpmResponseValue::$variant(response) = value {
505 Ok(response)
506 } else {
507 Err(value)
508 }
509 }
510 }
511 )*
512
513 pub enum TpmResponseView<'a> {
515 $( $variant(&'a $crate::frame::TpmResponse), )*
516 }
517
518 pub enum TpmResponseOutcome<'a> {
520 Dispatched(TpmResponseView<'a>),
522 Rejected($crate::data::TpmRc),
524 }
525
526 impl<'a> TpmResponseView<'a> {
527 pub fn cast_frame(
534 cc: $crate::data::TpmCc,
535 buf: &'a [u8],
536 ) -> $crate::TpmResult<TpmResponseOutcome<'a>> {
537 let response = <$crate::frame::TpmResponse>::cast(buf)?;
538
539 Self::cast(cc, response)
540 }
541
542 pub fn cast(
549 cc: $crate::data::TpmCc,
550 response: &'a $crate::frame::TpmResponse,
551 ) -> $crate::TpmResult<TpmResponseOutcome<'a>> {
552 let rc = response.rc()?;
553 if !matches!(rc, $crate::data::TpmRc::Fmt0($crate::data::TpmRcBase::Success)) {
554 return Ok(TpmResponseOutcome::Rejected(rc));
555 }
556
557 response.validate(cc)?;
558
559 match cc {
560 $( <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC => Ok(TpmResponseOutcome::Dispatched(Self::$variant(response))), )*
561 #[allow(unreachable_patterns)]
562 _ => Err($crate::TpmError::InvalidCc { offset: 0, value: u64::from(cc.value()) }),
563 }
564 }
565
566 #[must_use]
568 pub fn response(&self) -> &'a $crate::frame::TpmResponse {
569 match self {
570 $( Self::$variant(response) => response, )*
571 }
572 }
573
574 #[must_use]
576 pub fn cc(&self) -> $crate::data::TpmCc {
577 match self {
578 $( Self::$variant(_) => <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC, )*
579 }
580 }
581 }
582
583 pub(crate) static TPM_DISPATCH_TABLE: &[$crate::frame::TpmDispatch] = &[
584 $(
585 $crate::frame::TpmDispatch {
586 cc: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC,
587 handles: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::HANDLES,
588 response_handles: <$crate::frame::data::$resp as $crate::frame::TpmHeader>::HANDLES,
589 },
590 )*
591 ];
592
593 $crate::tpm_dispatch!(@const_check_sorted $( $cmd, )*);
594 };
595}