Skip to main content

tpm2_protocol/data/
tpmt.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2025 Opinsys Oy
3// Copyright (c) 2024-2025 Jarkko Sakkinen
4
5use super::{
6    Tpm2bAuth, Tpm2bDigest, TpmAlgId, TpmHt, TpmRh, TpmSt, TpmaObject, TpmuHa, TpmuKdfScheme,
7    TpmuKeyedhashScheme, TpmuNvPublic2, TpmuPublicId, TpmuPublicParms, TpmuSensitiveComposite,
8    TpmuSigScheme, TpmuSymKeyBits, TpmuSymMode,
9};
10use crate::{
11    TpmMarshal, TpmResult, TpmSized, TpmWriter, constant::TPM_MAX_COMMAND_SIZE, tpm_struct,
12};
13
14macro_rules! tpm_struct_tagged {
15    (
16        $(#[$outer:meta])*
17        $vis:vis struct $name:ident {
18            pub $tag_field:ident: $tag_ty:ty,
19            pub $value_field:ident: $value_ty:ty,
20        }
21    ) => {
22        $(#[$outer])*
23        $vis struct $name {
24            pub $tag_field: $tag_ty,
25            pub $value_field: $value_ty,
26        }
27
28        impl $crate::TpmSized for $name {
29            const SIZE: usize = <$tag_ty>::SIZE + <$value_ty>::SIZE;
30            fn len(&self) -> usize {
31                $crate::TpmSized::len(&self.$tag_field) + $crate::TpmSized::len(&self.$value_field)
32            }
33        }
34
35        impl $crate::TpmMarshal for $name {
36            fn marshal(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
37                $crate::TpmMarshal::marshal(&self.$tag_field, writer)?;
38                $crate::TpmMarshal::marshal(&self.$value_field, writer)
39            }
40        }
41
42        impl<'a> $crate::TpmField<'a> for $name
43        where
44            $tag_ty: $crate::TpmField<'a, View = $tag_ty>,
45            $value_ty: $crate::TpmTaggedField<'a, $tag_ty>,
46        {
47            type View = (
48                $tag_ty,
49                <$value_ty as $crate::TpmTaggedField<'a, $tag_ty>>::View,
50            );
51
52            fn cast_prefix_field(buf: &'a [u8]) -> $crate::TpmResult<(Self::View, &'a [u8])> {
53                let ($tag_field, buf) = <$tag_ty as $crate::TpmField>::cast_prefix_field(buf)?;
54                let ($value_field, buf) =
55                    <$value_ty as $crate::TpmTaggedField<'a, $tag_ty>>::cast_tagged_prefix_field(
56                        $tag_field,
57                        buf,
58                    )?;
59
60                Ok((($tag_field, $value_field), buf))
61            }
62        }
63    };
64}
65
66#[derive(Debug, PartialEq, Eq, Clone, Default)]
67pub struct TpmtPublic {
68    pub object_type: TpmAlgId,
69    pub name_alg: TpmAlgId,
70    pub object_attributes: TpmaObject,
71    pub auth_policy: Tpm2bDigest,
72    pub parameters: TpmuPublicParms,
73    pub unique: TpmuPublicId,
74}
75
76impl TpmSized for TpmtPublic {
77    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
78    fn len(&self) -> usize {
79        self.object_type.len()
80            + self.name_alg.len()
81            + self.object_attributes.len()
82            + self.auth_policy.len()
83            + self.parameters.len()
84            + self.unique.len()
85    }
86}
87
88impl TpmMarshal for TpmtPublic {
89    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
90        self.object_type.marshal(writer)?;
91        self.name_alg.marshal(writer)?;
92        self.object_attributes.marshal(writer)?;
93        self.auth_policy.marshal(writer)?;
94        self.parameters.marshal(writer)?;
95        self.unique.marshal(writer)
96    }
97}
98
99/// Borrowed view of a [`TpmtPublic`] wire structure.
100pub struct TpmtPublicView<'a> {
101    pub object_type: TpmAlgId,
102    pub name_alg: TpmAlgId,
103    pub object_attributes: TpmaObject,
104    pub auth_policy: <Tpm2bDigest as crate::TpmField<'a>>::View,
105    pub parameters: <TpmuPublicParms as crate::TpmTaggedField<'a, TpmAlgId>>::View,
106    pub unique: <TpmuPublicId as crate::TpmTaggedField<'a, TpmAlgId>>::View,
107}
108
109impl<'a> crate::TpmField<'a> for TpmtPublic {
110    type View = TpmtPublicView<'a>;
111
112    fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
113        let (object_type, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
114        let (name_alg, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
115        let (object_attributes, buf) = <TpmaObject as crate::TpmField>::cast_prefix_field(buf)?;
116        let (auth_policy, buf) = <Tpm2bDigest as crate::TpmField>::cast_prefix_field(buf)?;
117        let (parameters, buf) =
118            <TpmuPublicParms as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
119                object_type,
120                buf,
121            )?;
122        let (unique, buf) =
123            <TpmuPublicId as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
124                object_type,
125                buf,
126            )?;
127
128        Ok((
129            TpmtPublicView {
130                object_type,
131                name_alg,
132                object_attributes,
133                auth_policy,
134                parameters,
135                unique,
136            },
137            buf,
138        ))
139    }
140}
141
142tpm_struct_tagged! {
143    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
144    pub struct TpmtPublicParms {
145        pub object_type: TpmAlgId,
146        pub parameters: TpmuPublicParms,
147    }
148}
149
150tpm_struct_tagged! {
151    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
152    pub struct TpmtKdfScheme {
153        pub scheme: TpmAlgId,
154        pub details: TpmuKdfScheme,
155    }
156}
157
158impl Default for TpmtKdfScheme {
159    fn default() -> Self {
160        Self {
161            scheme: TpmAlgId::Null,
162            details: TpmuKdfScheme::Null,
163        }
164    }
165}
166
167tpm_struct_tagged! {
168    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
169    pub struct TpmtRsaDecrypt {
170        pub scheme: TpmAlgId,
171        pub details: crate::data::tpmu::TpmuAsymScheme,
172    }
173}
174
175impl Default for TpmtRsaDecrypt {
176    fn default() -> Self {
177        Self {
178            scheme: TpmAlgId::Null,
179            details: crate::data::tpmu::TpmuAsymScheme::default(),
180        }
181    }
182}
183
184#[derive(Debug, PartialEq, Eq, Clone, Default)]
185pub struct TpmtSensitive {
186    pub sensitive_type: TpmAlgId,
187    pub auth_value: Tpm2bAuth,
188    pub seed_value: Tpm2bDigest,
189    pub sensitive: TpmuSensitiveComposite,
190}
191
192impl TpmSized for TpmtSensitive {
193    const SIZE: usize =
194        TpmAlgId::SIZE + Tpm2bAuth::SIZE + Tpm2bDigest::SIZE + TpmuSensitiveComposite::SIZE;
195    fn len(&self) -> usize {
196        self.sensitive_type.len()
197            + self.auth_value.len()
198            + self.seed_value.len()
199            + self.sensitive.len()
200    }
201}
202
203impl TpmMarshal for TpmtSensitive {
204    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
205        self.sensitive_type.marshal(writer)?;
206        self.auth_value.marshal(writer)?;
207        self.seed_value.marshal(writer)?;
208        self.sensitive.marshal(writer)
209    }
210}
211
212#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
213pub struct TpmtSymDef {
214    pub algorithm: TpmAlgId,
215    pub key_bits: TpmuSymKeyBits,
216    pub mode: TpmuSymMode,
217}
218
219impl TpmSized for TpmtSymDef {
220    const SIZE: usize = TpmAlgId::SIZE + TpmuSymKeyBits::SIZE + TpmAlgId::SIZE;
221    fn len(&self) -> usize {
222        if self.algorithm == TpmAlgId::Null {
223            self.algorithm.len()
224        } else {
225            self.algorithm.len() + self.key_bits.len() + self.mode.len()
226        }
227    }
228}
229
230impl TpmMarshal for TpmtSymDef {
231    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
232        self.algorithm.marshal(writer)?;
233        if self.algorithm != TpmAlgId::Null {
234            self.key_bits.marshal(writer)?;
235            self.mode.marshal(writer)?;
236        }
237        Ok(())
238    }
239}
240
241pub enum TpmtSymDefView<'a> {
242    Null,
243    Value {
244        algorithm: TpmAlgId,
245        key_bits: <TpmuSymKeyBits as crate::TpmTaggedField<'a, TpmAlgId>>::View,
246        mode: <TpmuSymMode as crate::TpmTaggedField<'a, TpmAlgId>>::View,
247    },
248}
249
250impl<'a> crate::TpmField<'a> for TpmtSymDef {
251    type View = TpmtSymDefView<'a>;
252
253    fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
254        let (algorithm, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
255
256        if algorithm == TpmAlgId::Null {
257            return Ok((TpmtSymDefView::Null, buf));
258        }
259
260        let (key_bits, buf) =
261            <TpmuSymKeyBits as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
262                algorithm, buf,
263            )?;
264        let (mode, buf) =
265            <TpmuSymMode as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
266                algorithm, buf,
267            )?;
268
269        Ok((
270            TpmtSymDefView::Value {
271                algorithm,
272                key_bits,
273                mode,
274            },
275            buf,
276        ))
277    }
278}
279
280pub type TpmtSymDefObject = TpmtSymDef;
281
282tpm_struct_tagged! {
283    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
284    pub struct TpmtNvPublic2 {
285        pub handle_type: TpmHt,
286        pub public_area: TpmuNvPublic2,
287    }
288}
289
290tpm_struct! {
291    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
292    wire: TpmtTkCreationWire,
293    pub struct TpmtTkCreation {
294        pub tag: TpmSt,
295        pub hierarchy: TpmRh,
296        pub digest: Tpm2bDigest,
297    }
298}
299
300tpm_struct! {
301    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
302    wire: TpmtTkVerifiedWire,
303    pub struct TpmtTkVerified {
304        pub tag: TpmSt,
305        pub hierarchy: TpmRh,
306        pub digest: Tpm2bDigest,
307    }
308}
309
310tpm_struct! {
311    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
312    wire: TpmtTkAuthWire,
313    pub struct TpmtTkAuth {
314        pub tag: TpmSt,
315        pub hierarchy: TpmRh,
316        pub digest: Tpm2bDigest,
317    }
318}
319
320tpm_struct! {
321    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
322    wire: TpmtTkHashcheckWire,
323    pub struct TpmtTkHashcheck {
324        pub tag: TpmSt,
325        pub hierarchy: TpmRh,
326        pub digest: Tpm2bDigest,
327    }
328}
329
330tpm_struct_tagged! {
331    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
332    pub struct TpmtHa {
333        pub hash_alg: TpmAlgId,
334        pub digest: TpmuHa,
335    }
336}
337
338impl Default for TpmtHa {
339    fn default() -> Self {
340        Self {
341            hash_alg: TpmAlgId::Null,
342            digest: TpmuHa::default(),
343        }
344    }
345}
346
347tpm_struct_tagged! {
348    #[derive(Debug, PartialEq, Eq, Clone)]
349    pub struct TpmtSignature {
350        pub sig_alg: TpmAlgId,
351        pub signature: crate::data::tpmu::TpmuSignature,
352    }
353}
354
355tpm_struct_tagged! {
356    #[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
357    pub struct TpmtKeyedhashScheme {
358        pub scheme: TpmAlgId,
359        pub details: TpmuKeyedhashScheme,
360    }
361}
362
363tpm_struct_tagged! {
364    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
365    pub struct TpmtSigScheme {
366        pub scheme: TpmAlgId,
367        pub details: TpmuSigScheme,
368    }
369}
370
371impl Default for TpmtSigScheme {
372    fn default() -> Self {
373        Self {
374            scheme: TpmAlgId::Null,
375            details: TpmuSigScheme::default(),
376        }
377    }
378}
379
380tpm_struct_tagged! {
381    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
382    pub struct TpmtRsaScheme {
383        pub scheme: TpmAlgId,
384        pub details: crate::data::tpmu::TpmuAsymScheme,
385    }
386}
387
388impl Default for TpmtRsaScheme {
389    fn default() -> Self {
390        Self {
391            scheme: TpmAlgId::Null,
392            details: crate::data::tpmu::TpmuAsymScheme::default(),
393        }
394    }
395}
396
397tpm_struct_tagged! {
398    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
399    pub struct TpmtEccScheme {
400        pub scheme: TpmAlgId,
401        pub details: crate::data::tpmu::TpmuAsymScheme,
402    }
403}
404
405impl Default for TpmtEccScheme {
406    fn default() -> Self {
407        Self {
408            scheme: TpmAlgId::Null,
409            details: crate::data::tpmu::TpmuAsymScheme::default(),
410        }
411    }
412}