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)]
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
99impl Default for TpmtPublic {
100    fn default() -> Self {
101        Self {
102            object_type: TpmAlgId::Null,
103            name_alg: TpmAlgId::Null,
104            object_attributes: TpmaObject::empty(),
105            auth_policy: Tpm2bDigest::default(),
106            parameters: TpmuPublicParms::Null,
107            unique: TpmuPublicId::Null,
108        }
109    }
110}
111
112/// Borrowed view of a [`TpmtPublic`] wire structure.
113pub struct TpmtPublicView<'a> {
114    pub object_type: TpmAlgId,
115    pub name_alg: TpmAlgId,
116    pub object_attributes: TpmaObject,
117    pub auth_policy: <Tpm2bDigest as crate::TpmField<'a>>::View,
118    pub parameters: <TpmuPublicParms as crate::TpmTaggedField<'a, TpmAlgId>>::View,
119    pub unique: <TpmuPublicId as crate::TpmTaggedField<'a, TpmAlgId>>::View,
120}
121
122impl<'a> crate::TpmField<'a> for TpmtPublic {
123    type View = TpmtPublicView<'a>;
124
125    fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
126        let (object_type, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
127        let (name_alg, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
128        let (object_attributes, buf) = <TpmaObject as crate::TpmField>::cast_prefix_field(buf)?;
129        let (auth_policy, buf) = <Tpm2bDigest as crate::TpmField>::cast_prefix_field(buf)?;
130        let (parameters, buf) =
131            <TpmuPublicParms as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
132                object_type,
133                buf,
134            )?;
135        let (unique, buf) =
136            <TpmuPublicId as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
137                object_type,
138                buf,
139            )?;
140
141        Ok((
142            TpmtPublicView {
143                object_type,
144                name_alg,
145                object_attributes,
146                auth_policy,
147                parameters,
148                unique,
149            },
150            buf,
151        ))
152    }
153}
154
155tpm_struct_tagged! {
156    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
157    pub struct TpmtPublicParms {
158        pub object_type: TpmAlgId,
159        pub parameters: TpmuPublicParms,
160    }
161}
162
163tpm_struct_tagged! {
164    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
165    pub struct TpmtKdfScheme {
166        pub scheme: TpmAlgId,
167        pub details: TpmuKdfScheme,
168    }
169}
170
171impl Default for TpmtKdfScheme {
172    fn default() -> Self {
173        Self {
174            scheme: TpmAlgId::Null,
175            details: TpmuKdfScheme::Null,
176        }
177    }
178}
179
180tpm_struct_tagged! {
181    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
182    pub struct TpmtRsaDecrypt {
183        pub scheme: TpmAlgId,
184        pub details: crate::data::tpmu::TpmuAsymScheme,
185    }
186}
187
188impl Default for TpmtRsaDecrypt {
189    fn default() -> Self {
190        Self {
191            scheme: TpmAlgId::Null,
192            details: crate::data::tpmu::TpmuAsymScheme::default(),
193        }
194    }
195}
196
197#[derive(Debug, PartialEq, Eq, Clone, Default)]
198pub struct TpmtSensitive {
199    pub sensitive_type: TpmAlgId,
200    pub auth_value: Tpm2bAuth,
201    pub seed_value: Tpm2bDigest,
202    pub sensitive: TpmuSensitiveComposite,
203}
204
205impl TpmSized for TpmtSensitive {
206    const SIZE: usize =
207        TpmAlgId::SIZE + Tpm2bAuth::SIZE + Tpm2bDigest::SIZE + TpmuSensitiveComposite::SIZE;
208    fn len(&self) -> usize {
209        self.sensitive_type.len()
210            + self.auth_value.len()
211            + self.seed_value.len()
212            + self.sensitive.len()
213    }
214}
215
216impl TpmMarshal for TpmtSensitive {
217    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
218        self.sensitive_type.marshal(writer)?;
219        self.auth_value.marshal(writer)?;
220        self.seed_value.marshal(writer)?;
221        self.sensitive.marshal(writer)
222    }
223}
224
225#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
226pub struct TpmtSymDef {
227    pub algorithm: TpmAlgId,
228    pub key_bits: TpmuSymKeyBits,
229    pub mode: TpmuSymMode,
230}
231
232impl TpmSized for TpmtSymDef {
233    const SIZE: usize = TpmAlgId::SIZE + TpmuSymKeyBits::SIZE + TpmAlgId::SIZE;
234    fn len(&self) -> usize {
235        if self.algorithm == TpmAlgId::Null {
236            self.algorithm.len()
237        } else {
238            self.algorithm.len() + self.key_bits.len() + self.mode.len()
239        }
240    }
241}
242
243impl TpmMarshal for TpmtSymDef {
244    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
245        self.algorithm.marshal(writer)?;
246        if self.algorithm != TpmAlgId::Null {
247            self.key_bits.marshal(writer)?;
248            self.mode.marshal(writer)?;
249        }
250        Ok(())
251    }
252}
253
254pub enum TpmtSymDefView<'a> {
255    Null,
256    Value {
257        algorithm: TpmAlgId,
258        key_bits: <TpmuSymKeyBits as crate::TpmTaggedField<'a, TpmAlgId>>::View,
259        mode: <TpmuSymMode as crate::TpmTaggedField<'a, TpmAlgId>>::View,
260    },
261}
262
263impl<'a> crate::TpmField<'a> for TpmtSymDef {
264    type View = TpmtSymDefView<'a>;
265
266    fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
267        let (algorithm, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
268
269        if algorithm == TpmAlgId::Null {
270            return Ok((TpmtSymDefView::Null, buf));
271        }
272
273        let (key_bits, buf) =
274            <TpmuSymKeyBits as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
275                algorithm, buf,
276            )?;
277        let (mode, buf) =
278            <TpmuSymMode as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(
279                algorithm, buf,
280            )?;
281
282        Ok((
283            TpmtSymDefView::Value {
284                algorithm,
285                key_bits,
286                mode,
287            },
288            buf,
289        ))
290    }
291}
292
293pub type TpmtSymDefObject = TpmtSymDef;
294
295tpm_struct_tagged! {
296    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
297    pub struct TpmtNvPublic2 {
298        pub handle_type: TpmHt,
299        pub public_area: TpmuNvPublic2,
300    }
301}
302
303tpm_struct! {
304    #[derive(Debug, PartialEq, Eq, Clone, Default)]
305    wire: TpmtTkCreationWire,
306    pub struct TpmtTkCreation {
307        pub tag: TpmSt,
308        pub hierarchy: TpmRh,
309        pub digest: Tpm2bDigest,
310    }
311}
312
313tpm_struct! {
314    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
315    wire: TpmtTkVerifiedWire,
316    pub struct TpmtTkVerified {
317        pub tag: TpmSt,
318        pub hierarchy: TpmRh,
319        pub digest: Tpm2bDigest,
320    }
321}
322
323tpm_struct! {
324    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
325    wire: TpmtTkAuthWire,
326    pub struct TpmtTkAuth {
327        pub tag: TpmSt,
328        pub hierarchy: TpmRh,
329        pub digest: Tpm2bDigest,
330    }
331}
332
333tpm_struct! {
334    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
335    wire: TpmtTkHashcheckWire,
336    pub struct TpmtTkHashcheck {
337        pub tag: TpmSt,
338        pub hierarchy: TpmRh,
339        pub digest: Tpm2bDigest,
340    }
341}
342
343tpm_struct_tagged! {
344    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
345    pub struct TpmtHa {
346        pub hash_alg: TpmAlgId,
347        pub digest: TpmuHa,
348    }
349}
350
351impl Default for TpmtHa {
352    fn default() -> Self {
353        Self {
354            hash_alg: TpmAlgId::Null,
355            digest: TpmuHa::default(),
356        }
357    }
358}
359
360tpm_struct_tagged! {
361    #[derive(Debug, PartialEq, Eq, Clone)]
362    pub struct TpmtSignature {
363        pub sig_alg: TpmAlgId,
364        pub signature: crate::data::tpmu::TpmuSignature,
365    }
366}
367
368tpm_struct_tagged! {
369    #[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
370    pub struct TpmtKeyedhashScheme {
371        pub scheme: TpmAlgId,
372        pub details: TpmuKeyedhashScheme,
373    }
374}
375
376tpm_struct_tagged! {
377    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
378    pub struct TpmtSigScheme {
379        pub scheme: TpmAlgId,
380        pub details: TpmuSigScheme,
381    }
382}
383
384impl Default for TpmtSigScheme {
385    fn default() -> Self {
386        Self {
387            scheme: TpmAlgId::Null,
388            details: TpmuSigScheme::default(),
389        }
390    }
391}
392
393tpm_struct_tagged! {
394    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
395    pub struct TpmtRsaScheme {
396        pub scheme: TpmAlgId,
397        pub details: crate::data::tpmu::TpmuAsymScheme,
398    }
399}
400
401impl Default for TpmtRsaScheme {
402    fn default() -> Self {
403        Self {
404            scheme: TpmAlgId::Null,
405            details: crate::data::tpmu::TpmuAsymScheme::default(),
406        }
407    }
408}
409
410tpm_struct_tagged! {
411    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
412    pub struct TpmtEccScheme {
413        pub scheme: TpmAlgId,
414        pub details: crate::data::tpmu::TpmuAsymScheme,
415    }
416}
417
418impl Default for TpmtEccScheme {
419    fn default() -> Self {
420        Self {
421            scheme: TpmAlgId::Null,
422            details: crate::data::tpmu::TpmuAsymScheme::default(),
423        }
424    }
425}