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 #[must_use]
37 pub const fn empty() -> Self {
38 Self(0)
39 }
40
41 #[must_use]
42 pub const fn contains(&self, other: Self) -> bool {
43 (self.0 & other.0) == other.0
44 }
45 }
46
47 impl core::ops::BitOr for $name {
48 type Output = Self;
49 fn bitor(self, rhs: Self) -> Self::Output {
50 Self(self.0 | rhs.0)
51 }
52 }
53
54 impl core::ops::BitOrAssign for $name {
55 fn bitor_assign(&mut self, rhs: Self) {
56 self.0 |= rhs.0;
57 }
58 }
59
60 impl core::ops::BitAnd for $name {
61 type Output = Self;
62 fn bitand(self, rhs: Self) -> Self::Output {
63 Self(self.0 & rhs.0)
64 }
65 }
66
67 impl core::ops::BitAndAssign for $name {
68 fn bitand_assign(&mut self, rhs: Self) {
69 self.0 &= rhs.0;
70 }
71 }
72
73 impl core::ops::BitXor for $name {
74 type Output = Self;
75 fn bitxor(self, rhs: Self) -> Self::Output {
76 Self(self.0 ^ rhs.0)
77 }
78 }
79
80 impl core::ops::BitXorAssign for $name {
81 fn bitxor_assign(&mut self, rhs: Self) {
82 self.0 ^= rhs.0;
83 }
84 }
85
86 impl core::ops::Not for $name {
87 type Output = Self;
88 fn not(self) -> Self::Output {
89 Self(!self.0)
90 }
91 }
92
93 impl $crate::TpmMarshal for $name {
94 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
95 let value = <$wrapper>::from(self.0);
96 $crate::TpmMarshal::marshal(&value, writer)
97 }
98 }
99
100 impl $crate::TpmUnmarshal for $name {
101 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
102 let (val, buf) = <$wrapper as $crate::TpmUnmarshal>::unmarshal(buf)?;
103 Ok((Self(val.into()), buf))
104 }
105 }
106
107 impl $crate::TpmSized for $name {
108 const SIZE: usize = core::mem::size_of::<$repr>();
109 fn len(&self) -> usize {
110 Self::SIZE
111 }
112 }
113 };
114
115 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint8) { $($rest:tt)* }) => {
116 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint8, u8) { $($rest)* });
117 };
118 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint16) { $($rest:tt)* }) => {
119 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint16, u16) { $($rest)* });
120 };
121 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint32) { $($rest:tt)* }) => {
122 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint32, u32) { $($rest)* });
123 };
124 ($(#[$meta:meta])* $vis:vis struct $name:ident(TpmUint64) { $($rest:tt)* }) => {
125 tpm_bitflags!(@impl $(#[$meta])* $vis struct $name($crate::basic::TpmUint64, u64) { $($rest)* });
126 };
127}
128
129#[macro_export]
130macro_rules! tpm_bool {
131 (
132 $(#[$outer:meta])*
133 $vis:vis struct $name:ident(bool);
134 ) => {
135 $(#[$outer])*
136 $vis struct $name(pub bool);
137
138 impl From<bool> for $name {
139 fn from(val: bool) -> Self {
140 Self(val)
141 }
142 }
143
144 impl From<$name> for bool {
145 fn from(val: $name) -> Self {
146 val.0
147 }
148 }
149
150 impl $crate::TpmMarshal for $name {
151 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
152 let value = if self.0 { 1 } else { 0 };
153 $crate::basic::TpmUint8::from(value).marshal(writer)
154 }
155 }
156
157 impl $crate::TpmUnmarshal for $name {
158 fn unmarshal(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
159 let (val, buf) = $crate::basic::TpmUint8::unmarshal(buf)?;
160 match u8::from(val) {
161 0 => Ok((Self(false), buf)),
162 1 => Ok((Self(true), buf)),
163 _ => Err($crate::TpmProtocolError::InvalidBoolean),
164 }
165 }
166 }
167
168 impl $crate::TpmSized for $name {
169 const SIZE: usize = core::mem::size_of::<$crate::basic::TpmUint8>();
170 fn len(&self) -> usize {
171 Self::SIZE
172 }
173 }
174 };
175}
176
177#[macro_export]
178macro_rules! tpm_dispatch {
179 (@const_check_sorted) => {};
180 (@const_check_sorted $prev_cmd:ident, $( $rest_cmd:ident, )*) => {
181 $crate::tpm_dispatch!(@const_check_sorted_impl $prev_cmd, $( $rest_cmd, )*);
182 };
183 (@const_check_sorted_impl $prev_cmd:ident,) => {};
184 (@const_check_sorted_impl $prev_cmd:ident, $current_cmd:ident, $( $rest_cmd:ident, )* ) => {
185 const _: () = assert!(
186 <$crate::frame::data::$prev_cmd as $crate::frame::TpmHeader>::CC as u32 <= <$crate::frame::data::$current_cmd as $crate::frame::TpmHeader>::CC as u32,
187 "TPM_DISPATCH_TABLE must be sorted by TpmCc."
188 );
189 $crate::tpm_dispatch!(@const_check_sorted_impl $current_cmd, $( $rest_cmd, )*);
190 };
191
192 ( $( ($cmd:ident, $resp:ident, $variant:ident) ),* $(,)? ) => {
193 #[allow(clippy::large_enum_variant)]
195 #[derive(Debug, PartialEq, Eq, Clone)]
196 pub enum TpmCommand {
197 $( $variant($crate::frame::data::$cmd), )*
198 }
199
200 impl $crate::TpmSized for TpmCommand {
201 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
202 fn len(&self) -> usize {
203 match self {
204 $( Self::$variant(c) => $crate::TpmSized::len(c), )*
205 }
206 }
207 }
208
209 impl $crate::frame::TpmMarshalBody for TpmCommand {
210 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
211 match self {
212 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_handles(c, writer), )*
213 }
214 }
215 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
216 match self {
217 $( Self::$variant(c) => $crate::frame::TpmMarshalBody::marshal_parameters(c, writer), )*
218 }
219 }
220 }
221
222 impl $crate::TpmMarshal for TpmCommand {
223 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
224 match self {
225 $( Self::$variant(c) => $crate::TpmMarshal::marshal(c, writer), )*
226 }
227 }
228 }
229
230 impl $crate::frame::TpmFrame for TpmCommand {
231 fn cc(&self) -> $crate::data::TpmCc {
232 match self {
233 $( Self::$variant(c) => $crate::frame::TpmFrame::cc(c), )*
234 }
235 }
236 fn handles(&self) -> usize {
237 match self {
238 $( Self::$variant(c) => $crate::frame::TpmFrame::handles(c), )*
239 }
240 }
241 }
242
243 impl TpmCommand {
244 pub fn marshal_frame(
250 &self,
251 tag: $crate::data::TpmSt,
252 sessions: &$crate::frame::TpmAuthCommands,
253 writer: &mut $crate::TpmWriter,
254 ) -> $crate::TpmResult<()> {
255 match self {
256 $( Self::$variant(c) => $crate::frame::tpm_marshal_command(c, tag, sessions, writer), )*
257 }
258 }
259 }
260
261 #[allow(clippy::large_enum_variant)]
263 #[derive(Debug, PartialEq, Eq, Clone)]
264 pub enum TpmResponse {
265 $( $variant($crate::frame::data::$resp), )*
266 }
267
268 impl $crate::TpmSized for TpmResponse {
269 const SIZE: usize = $crate::constant::TPM_MAX_COMMAND_SIZE;
270 fn len(&self) -> usize {
271 match self {
272 $( Self::$variant(r) => $crate::TpmSized::len(r), )*
273 }
274 }
275 }
276
277 impl $crate::frame::TpmMarshalBody for TpmResponse {
278 fn marshal_handles(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
279 match self {
280 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_handles(r, writer), )*
281 }
282 }
283 fn marshal_parameters(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
284 match self {
285 $( Self::$variant(r) => $crate::frame::TpmMarshalBody::marshal_parameters(r, writer), )*
286 }
287 }
288 }
289
290 impl $crate::TpmMarshal for TpmResponse {
291 fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
292 match self {
293 $( Self::$variant(r) => $crate::TpmMarshal::marshal(r, writer), )*
294 }
295 }
296 }
297
298 impl $crate::frame::TpmFrame for TpmResponse {
299 fn cc(&self) -> $crate::data::TpmCc {
300 match self {
301 $( Self::$variant(r) => $crate::frame::TpmFrame::cc(r), )*
302 }
303 }
304 fn handles(&self) -> usize {
305 match self {
306 $( Self::$variant(r) => $crate::frame::TpmFrame::handles(r), )*
307 }
308 }
309 }
310
311 impl TpmResponse {
312 $(
313 #[allow(non_snake_case, clippy::result_large_err)]
319 pub fn $variant(self) -> Result<$crate::frame::data::$resp, Self> {
320 if let Self::$variant(r) = self {
321 Ok(r)
322 } else {
323 Err(self)
324 }
325 }
326 )*
327
328 pub fn marshal_frame(
334 &self,
335 rc: $crate::data::TpmRc,
336 sessions: &$crate::frame::TpmAuthResponses,
337 writer: &mut $crate::TpmWriter,
338 ) -> $crate::TpmResult<()> {
339 match self {
340 $( Self::$variant(r) => $crate::frame::tpm_marshal_response(r, sessions, rc, writer), )*
341 }
342 }
343 }
344
345 pub(crate) static TPM_DISPATCH_TABLE: &[$crate::frame::TpmDispatch] = &[
346 $(
347 $crate::frame::TpmDispatch {
348 cc: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::CC,
349 handles: <$crate::frame::data::$cmd as $crate::frame::TpmHeader>::HANDLES,
350 command_unmarshaler: |handles, params| {
351 <$crate::frame::data::$cmd as $crate::frame::TpmUnmarshalCommand>::unmarshal_body(handles, params)
352 .map(|(c, r)| (TpmCommand::$variant(c), r))
353 },
354 response_unmarshaler: |tag, buf| {
355 <$crate::frame::data::$resp as $crate::frame::TpmUnmarshalResponse>::unmarshal_body(tag, buf)
356 .map(|(r, rest)| (TpmResponse::$variant(r), rest))
357 },
358 },
359 )*
360 ];
361
362 $crate::tpm_dispatch!(@const_check_sorted $( $cmd, )*);
363 };
364}