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