Skip to main content

tpm2_protocol/data/
tpmu.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 crate::{
6    TpmError, TpmMarshal, TpmResult, TpmSized, TpmUnmarshalTagged, TpmWriter,
7    basic::{TpmBuffer, TpmUint16},
8    constant::{MAX_DIGEST_SIZE, TPM_MAX_COMMAND_SIZE},
9    data::{
10        Tpm2bDigest, Tpm2bEccParameter, Tpm2bPublicKeyRsa, Tpm2bSensitiveData, Tpm2bSymKey,
11        TpmAlgId, TpmCap, TpmHt, TpmSt, TpmlActData, TpmlAlgProperty, TpmlCc, TpmlCca,
12        TpmlEccCurve, TpmlHandle, TpmlPcrSelection, TpmlTaggedPolicy, TpmlTaggedTpmProperty,
13        TpmsCertifyInfo, TpmsCommandAuditInfo, TpmsCreationInfo, TpmsEccParms, TpmsEccPoint,
14        TpmsKeyedhashParms, TpmsNvCertifyInfo, TpmsNvDigestCertifyInfo, TpmsNvPublic,
15        TpmsNvPublicExpAttr, TpmsQuoteInfo, TpmsRsaParms, TpmsSchemeHash, TpmsSchemeHmac,
16        TpmsSchemeXor, TpmsSessionAuditInfo, TpmsSignatureEcc, TpmsSignatureRsa,
17        TpmsSymcipherParms, TpmsTimeAttestInfo, TpmtHa,
18    },
19};
20use core::ops::Deref;
21
22macro_rules! tpmu_view {
23    (
24        $view:ident, $union:ident, $tag_ty:ty {
25            $(
26                $variant:ident($field_ty:ty): $($tag:path)|+;
27            )*
28            $(
29                @null $null_variant:ident: $($null_tag:path)|+;
30            )?
31        }
32    ) => {
33        pub enum $view<'a>
34        where
35            $($field_ty: crate::TpmField<'a>,)*
36        {
37            $(
38                $variant(<$field_ty as crate::TpmField<'a>>::View),
39            )*
40            $(
41                $null_variant,
42            )?
43        }
44
45        impl $union {
46            /// Casts a tag-selected union payload into a borrowed view.
47            ///
48            /// # Errors
49            ///
50            /// Returns `Err(TpmError)` when `tag` does not select a valid variant or
51            /// `buf` does not start with a valid selected payload.
52            pub fn cast_tagged<'a>(
53                tag: $tag_ty,
54                buf: &'a [u8],
55            ) -> TpmResult<($view<'a>, &'a [u8])>
56            where
57                $($field_ty: crate::TpmField<'a>,)*
58            {
59                <Self as crate::TpmTaggedField<'a, $tag_ty>>::cast_tagged_prefix_field(tag, buf)
60            }
61
62            /// Returns `true` when the union payload is the variant selected
63            /// by `tag`.
64            #[must_use]
65            pub fn matches_tag(&self, tag: $tag_ty) -> bool {
66                #[allow(unreachable_patterns)]
67                match (self, tag) {
68                    $(
69                        (Self::$variant(_), $($tag)|+) => true,
70                    )*
71                    $(
72                        (Self::$null_variant, $($null_tag)|+) => true,
73                    )?
74                    _ => false,
75                }
76            }
77        }
78
79        impl<'a> crate::TpmTaggedField<'a, $tag_ty> for $union
80        where
81            $($field_ty: crate::TpmField<'a>,)*
82        {
83            type View = $view<'a>;
84
85            fn cast_tagged_prefix_field(
86                tag: $tag_ty,
87                buf: &'a [u8],
88            ) -> TpmResult<(Self::View, &'a [u8])> {
89                #[allow(unreachable_patterns)]
90                match tag {
91                    $(
92                        $($tag)|+ => {
93                            let (value, buf) = <$field_ty as crate::TpmField>::cast_prefix_field(buf)?;
94                            Ok(($view::$variant(value), buf))
95                        }
96                    )*
97                    $(
98                        $($null_tag)|+ => Ok(($view::$null_variant, buf)),
99                    )?
100                    _ => Err(TpmError::VariantNotAvailable { offset: 0, value: u64::from(tag.value()) }),
101                }
102            }
103        }
104
105        impl crate::TpmUnmarshalTagged<$tag_ty> for $union
106        where
107            $($field_ty: crate::TpmUnmarshal,)*
108        {
109            fn unmarshal_tagged(tag: $tag_ty, buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
110                #[allow(unreachable_patterns)]
111                match tag {
112                    $(
113                        $($tag)|+ => {
114                            let (value, buffer) = <$field_ty as crate::TpmUnmarshal>::unmarshal(buffer)?;
115                            Ok((Self::$variant(value), buffer))
116                        }
117                    )*
118                    $(
119                        $($null_tag)|+ => Ok((Self::$null_variant, buffer)),
120                    )?
121                    _ => Err(TpmError::VariantNotAvailable { offset: 0, value: u64::from(tag.value()) }),
122                }
123            }
124        }
125    };
126}
127
128#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
129pub enum TpmuAsymScheme {
130    Hash(TpmsSchemeHash),
131    #[default]
132    Null,
133}
134
135impl TpmSized for TpmuAsymScheme {
136    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
137    fn len(&self) -> usize {
138        match self {
139            Self::Hash(s) => s.len(),
140            Self::Null => 0,
141        }
142    }
143}
144
145impl TpmMarshal for TpmuAsymScheme {
146    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
147        match self {
148            Self::Hash(s) => s.marshal(writer),
149            Self::Null => Ok(()),
150        }
151    }
152}
153
154tpmu_view!(TpmuAsymSchemeView, TpmuAsymScheme, TpmAlgId {
155    Hash(TpmsSchemeHash): TpmAlgId::Rsassa|TpmAlgId::Rsapss|TpmAlgId::Ecdsa|TpmAlgId::Ecdaa|TpmAlgId::Sm2|TpmAlgId::Ecschnorr|TpmAlgId::Oaep|TpmAlgId::Ecdh|TpmAlgId::Ecmqv;
156    @null Null: TpmAlgId::Rsaes|TpmAlgId::Null;
157});
158
159#[derive(Debug, PartialEq, Eq, Clone)]
160#[allow(clippy::large_enum_variant)]
161pub enum TpmuCapabilities {
162    Algs(TpmlAlgProperty),
163    Handles(TpmlHandle),
164    Pcrs(TpmlPcrSelection),
165    Commands(TpmlCca),
166    PpCommands(TpmlCc),
167    AuditCommands(TpmlCc),
168    TpmProperties(TpmlTaggedTpmProperty),
169    EccCurves(TpmlEccCurve),
170    AuthPolicies(TpmlTaggedPolicy),
171    Act(TpmlActData),
172}
173
174impl TpmSized for TpmuCapabilities {
175    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
176    fn len(&self) -> usize {
177        match self {
178            Self::Algs(algs) => algs.len(),
179            Self::Handles(handles) => handles.len(),
180            Self::Pcrs(pcrs) => pcrs.len(),
181            Self::Commands(cmds) => cmds.len(),
182            Self::PpCommands(cmds) | Self::AuditCommands(cmds) => cmds.len(),
183            Self::TpmProperties(props) => props.len(),
184            Self::EccCurves(curves) => curves.len(),
185            Self::AuthPolicies(policies) => policies.len(),
186            Self::Act(act) => act.len(),
187        }
188    }
189}
190
191impl TpmMarshal for TpmuCapabilities {
192    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
193        match self {
194            Self::Algs(algs) => algs.marshal(writer),
195            Self::Handles(handles) => handles.marshal(writer),
196            Self::Pcrs(pcrs) => pcrs.marshal(writer),
197            Self::Commands(cmds) => cmds.marshal(writer),
198            Self::PpCommands(cmds) | Self::AuditCommands(cmds) => cmds.marshal(writer),
199            Self::TpmProperties(props) => props.marshal(writer),
200            Self::EccCurves(curves) => curves.marshal(writer),
201            Self::AuthPolicies(policies) => policies.marshal(writer),
202            Self::Act(act) => act.marshal(writer),
203        }
204    }
205}
206
207tpmu_view!(TpmuCapabilitiesView, TpmuCapabilities, TpmCap {
208    Algs(TpmlAlgProperty): TpmCap::Algs;
209    Handles(TpmlHandle): TpmCap::Handles;
210    Pcrs(TpmlPcrSelection): TpmCap::Pcrs;
211    Commands(TpmlCca): TpmCap::Commands;
212    PpCommands(TpmlCc): TpmCap::PpCommands;
213    AuditCommands(TpmlCc): TpmCap::AuditCommands;
214    TpmProperties(TpmlTaggedTpmProperty): TpmCap::TpmProperties;
215    EccCurves(TpmlEccCurve): TpmCap::EccCurves;
216    AuthPolicies(TpmlTaggedPolicy): TpmCap::AuthPolicies;
217    Act(TpmlActData): TpmCap::Act;
218});
219
220#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
221pub enum TpmuHa {
222    #[default]
223    Null,
224    Digest(TpmBuffer<MAX_DIGEST_SIZE>),
225}
226
227impl TpmMarshal for TpmuHa {
228    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
229        match self {
230            Self::Null => Ok(()),
231            Self::Digest(d) => writer.write_bytes(d),
232        }
233    }
234}
235
236impl TpmSized for TpmuHa {
237    const SIZE: usize = MAX_DIGEST_SIZE;
238    fn len(&self) -> usize {
239        match self {
240            Self::Null => 0,
241            Self::Digest(d) => d.deref().len(),
242        }
243    }
244}
245
246pub enum TpmuHaView<'a> {
247    Null,
248    Digest(&'a [u8]),
249}
250
251/// Returns the digest size in bytes for a hash algorithm selector.
252fn digest_size(tag: TpmAlgId) -> Option<usize> {
253    match tag {
254        TpmAlgId::Sha1 => Some(20),
255        TpmAlgId::Shake256_192 => Some(24),
256        TpmAlgId::Sha256 | TpmAlgId::Sm3_256 | TpmAlgId::Sha3_256 | TpmAlgId::Shake256_256 => {
257            Some(32)
258        }
259        TpmAlgId::Sha384 | TpmAlgId::Sha3_384 => Some(48),
260        TpmAlgId::Sha512 | TpmAlgId::Sha3_512 | TpmAlgId::Shake256_512 => Some(64),
261        _ => None,
262    }
263}
264
265impl TpmuHa {
266    /// Returns `true` when the union payload matches the digest algorithm and
267    /// digest size selected by `tag`.
268    #[must_use]
269    pub fn matches_tag(&self, tag: TpmAlgId) -> bool {
270        match (self, tag) {
271            (Self::Null, TpmAlgId::Null) => true,
272            (Self::Digest(digest), tag) => {
273                digest_size(tag).is_some_and(|size| digest.len() == size)
274            }
275            _ => false,
276        }
277    }
278
279    /// Casts a tag-selected digest payload into a borrowed view.
280    ///
281    /// # Errors
282    ///
283    /// Returns `Err(TpmError)` when `tag` is not a digest algorithm or `buf` is
284    /// too short for the selected digest size.
285    pub fn cast_tagged<'a>(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(TpmuHaView<'a>, &'a [u8])> {
286        <Self as crate::TpmTaggedField<'a, TpmAlgId>>::cast_tagged_prefix_field(tag, buf)
287    }
288}
289
290impl<'a> crate::TpmTaggedField<'a, TpmAlgId> for TpmuHa {
291    type View = TpmuHaView<'a>;
292
293    fn cast_tagged_prefix_field(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
294        let Some(digest_size) = digest_size(tag) else {
295            if tag == TpmAlgId::Null {
296                return Ok((TpmuHaView::Null, buf));
297            }
298
299            return Err(TpmError::VariantNotAvailable {
300                offset: 0,
301                value: u64::from(tag.value()),
302            });
303        };
304
305        if buf.len() < digest_size {
306            return Err(TpmError::UnexpectedEnd {
307                offset: 0,
308                needed: digest_size,
309                available: buf.len(),
310            });
311        }
312
313        let (digest, buf) = buf.split_at(digest_size);
314        Ok((TpmuHaView::Digest(digest), buf))
315    }
316}
317
318impl TpmUnmarshalTagged<TpmAlgId> for TpmuHa {
319    fn unmarshal_tagged(tag: TpmAlgId, buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
320        let (view, buffer) = Self::cast_tagged(tag, buffer)?;
321        let value = match view {
322            TpmuHaView::Null => Self::Null,
323            TpmuHaView::Digest(digest) => Self::Digest(TpmBuffer::try_from(digest)?),
324        };
325        Ok((value, buffer))
326    }
327}
328
329impl Deref for TpmuHa {
330    type Target = [u8];
331
332    fn deref(&self) -> &Self::Target {
333        match self {
334            Self::Null => &[],
335            Self::Digest(d) => d,
336        }
337    }
338}
339
340#[allow(clippy::large_enum_variant)]
341#[derive(Debug, PartialEq, Eq, Clone, Default)]
342pub enum TpmuPublicId {
343    KeyedHash(Tpm2bDigest),
344    SymCipher(Tpm2bSymKey),
345    Rsa(Tpm2bPublicKeyRsa),
346    Ecc(TpmsEccPoint),
347    #[default]
348    Null,
349}
350
351impl TpmSized for TpmuPublicId {
352    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
353    fn len(&self) -> usize {
354        match self {
355            Self::KeyedHash(data) => data.len(),
356            Self::SymCipher(data) => data.len(),
357            Self::Rsa(data) => data.len(),
358            Self::Ecc(point) => point.len(),
359            Self::Null => 0,
360        }
361    }
362}
363
364impl TpmMarshal for TpmuPublicId {
365    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
366        match self {
367            Self::KeyedHash(data) => data.marshal(writer),
368            Self::SymCipher(data) => data.marshal(writer),
369            Self::Rsa(data) => data.marshal(writer),
370            Self::Ecc(point) => point.marshal(writer),
371            Self::Null => Ok(()),
372        }
373    }
374}
375
376tpmu_view!(TpmuPublicIdView, TpmuPublicId, TpmAlgId {
377    KeyedHash(Tpm2bDigest): TpmAlgId::KeyedHash;
378    SymCipher(Tpm2bSymKey): TpmAlgId::SymCipher;
379    Rsa(Tpm2bPublicKeyRsa): TpmAlgId::Rsa;
380    Ecc(TpmsEccPoint): TpmAlgId::Ecc;
381    @null Null: TpmAlgId::Null;
382});
383
384#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
385pub enum TpmuPublicParms {
386    KeyedHash(TpmsKeyedhashParms),
387    SymCipher(TpmsSymcipherParms),
388    Rsa(TpmsRsaParms),
389    Ecc(TpmsEccParms),
390    #[default]
391    Null,
392}
393
394impl TpmSized for TpmuPublicParms {
395    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
396    fn len(&self) -> usize {
397        match self {
398            Self::KeyedHash(d) => d.len(),
399            Self::SymCipher(d) => d.len(),
400            Self::Rsa(d) => d.len(),
401            Self::Ecc(d) => d.len(),
402            Self::Null => 0,
403        }
404    }
405}
406
407impl TpmMarshal for TpmuPublicParms {
408    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
409        match self {
410            Self::KeyedHash(d) => d.marshal(writer),
411            Self::SymCipher(d) => d.marshal(writer),
412            Self::Rsa(d) => d.marshal(writer),
413            Self::Ecc(d) => d.marshal(writer),
414            Self::Null => Ok(()),
415        }
416    }
417}
418
419tpmu_view!(TpmuPublicParmsView, TpmuPublicParms, TpmAlgId {
420    KeyedHash(TpmsKeyedhashParms): TpmAlgId::KeyedHash;
421    SymCipher(TpmsSymcipherParms): TpmAlgId::SymCipher;
422    Rsa(TpmsRsaParms): TpmAlgId::Rsa;
423    Ecc(TpmsEccParms): TpmAlgId::Ecc;
424    @null Null: TpmAlgId::Null;
425});
426
427#[allow(clippy::large_enum_variant)]
428#[derive(Debug, PartialEq, Eq, Clone)]
429pub enum TpmuSensitiveComposite {
430    Rsa(crate::data::Tpm2bPrivateKeyRsa),
431    Ecc(Tpm2bEccParameter),
432    Bits(Tpm2bSensitiveData),
433    Sym(Tpm2bSymKey),
434}
435
436impl Default for TpmuSensitiveComposite {
437    fn default() -> Self {
438        Self::Rsa(crate::data::Tpm2bPrivateKeyRsa::default())
439    }
440}
441
442impl TpmSized for TpmuSensitiveComposite {
443    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
444    fn len(&self) -> usize {
445        match self {
446            Self::Ecc(val) => val.len(),
447            Self::Sym(val) => val.len(),
448            Self::Rsa(val) | Self::Bits(val) => val.len(),
449        }
450    }
451}
452
453impl TpmMarshal for TpmuSensitiveComposite {
454    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
455        match self {
456            Self::Ecc(val) => val.marshal(writer),
457            Self::Sym(val) => val.marshal(writer),
458            Self::Rsa(val) | Self::Bits(val) => val.marshal(writer),
459        }
460    }
461}
462
463tpmu_view!(TpmuSensitiveCompositeView, TpmuSensitiveComposite, TpmAlgId {
464    Rsa(crate::data::Tpm2bPrivateKeyRsa): TpmAlgId::Rsa;
465    Ecc(Tpm2bEccParameter): TpmAlgId::Ecc;
466    Bits(Tpm2bSensitiveData): TpmAlgId::KeyedHash;
467    Sym(Tpm2bSymKey): TpmAlgId::SymCipher;
468});
469
470#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
471pub enum TpmuSymKeyBits {
472    Aes(TpmUint16),
473    Sm4(TpmUint16),
474    Camellia(TpmUint16),
475    Xor(TpmAlgId),
476    #[default]
477    Null,
478}
479
480impl TpmSized for TpmuSymKeyBits {
481    const SIZE: usize = core::mem::size_of::<TpmUint16>();
482    fn len(&self) -> usize {
483        match self {
484            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.len(),
485            Self::Xor(val) => val.len(),
486            Self::Null => 0,
487        }
488    }
489}
490
491impl TpmMarshal for TpmuSymKeyBits {
492    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
493        match self {
494            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.marshal(writer),
495            Self::Xor(val) => val.marshal(writer),
496            Self::Null => Ok(()),
497        }
498    }
499}
500
501tpmu_view!(TpmuSymKeyBitsView, TpmuSymKeyBits, TpmAlgId {
502    Aes(TpmUint16): TpmAlgId::Aes;
503    Sm4(TpmUint16): TpmAlgId::Sm4;
504    Camellia(TpmUint16): TpmAlgId::Camellia;
505    Xor(TpmAlgId): TpmAlgId::Xor;
506    @null Null: TpmAlgId::Null;
507});
508
509#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
510pub enum TpmuSymMode {
511    Aes(TpmAlgId),
512    Sm4(TpmAlgId),
513    Camellia(TpmAlgId),
514    Xor(TpmAlgId),
515    #[default]
516    Null,
517}
518
519impl TpmSized for TpmuSymMode {
520    const SIZE: usize = core::mem::size_of::<TpmUint16>();
521    fn len(&self) -> usize {
522        match self {
523            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) | Self::Xor(val) => val.len(),
524            Self::Null => 0,
525        }
526    }
527}
528
529impl TpmMarshal for TpmuSymMode {
530    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
531        match self {
532            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) | Self::Xor(val) => {
533                val.marshal(writer)
534            }
535            Self::Null => Ok(()),
536        }
537    }
538}
539
540tpmu_view!(TpmuSymModeView, TpmuSymMode, TpmAlgId {
541    Aes(TpmAlgId): TpmAlgId::Aes;
542    Sm4(TpmAlgId): TpmAlgId::Sm4;
543    Camellia(TpmAlgId): TpmAlgId::Camellia;
544    Xor(TpmAlgId): TpmAlgId::Xor;
545    @null Null: TpmAlgId::Null;
546});
547
548#[derive(Debug, PartialEq, Eq, Clone)]
549pub enum TpmuSignature {
550    Rsassa(TpmsSignatureRsa),
551    Rsapss(TpmsSignatureRsa),
552    Ecdsa(TpmsSignatureEcc),
553    Ecdaa(TpmsSignatureEcc),
554    Sm2(TpmsSignatureEcc),
555    Ecschnorr(TpmsSignatureEcc),
556    Hmac(TpmtHa),
557    Null,
558}
559
560impl TpmSized for TpmuSignature {
561    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
562    fn len(&self) -> usize {
563        match self {
564            Self::Rsassa(s) | Self::Rsapss(s) => s.len(),
565            Self::Ecdsa(s) | Self::Ecdaa(s) | Self::Sm2(s) | Self::Ecschnorr(s) => s.len(),
566            Self::Hmac(s) => s.len(),
567            Self::Null => 0,
568        }
569    }
570}
571
572impl TpmMarshal for TpmuSignature {
573    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
574        match self {
575            Self::Rsassa(s) | Self::Rsapss(s) => s.marshal(writer),
576            Self::Ecdsa(s) | Self::Ecdaa(s) | Self::Sm2(s) | Self::Ecschnorr(s) => {
577                s.marshal(writer)
578            }
579            Self::Hmac(s) => s.marshal(writer),
580            Self::Null => Ok(()),
581        }
582    }
583}
584
585tpmu_view!(TpmuSignatureView, TpmuSignature, TpmAlgId {
586    Rsassa(TpmsSignatureRsa): TpmAlgId::Rsassa;
587    Rsapss(TpmsSignatureRsa): TpmAlgId::Rsapss;
588    Ecdsa(TpmsSignatureEcc): TpmAlgId::Ecdsa;
589    Ecdaa(TpmsSignatureEcc): TpmAlgId::Ecdaa;
590    Sm2(TpmsSignatureEcc): TpmAlgId::Sm2;
591    Ecschnorr(TpmsSignatureEcc): TpmAlgId::Ecschnorr;
592    Hmac(TpmtHa): TpmAlgId::Hmac;
593    @null Null: TpmAlgId::Null;
594});
595
596#[allow(clippy::large_enum_variant)]
597#[derive(Debug, PartialEq, Eq, Clone)]
598pub enum TpmuAttest {
599    Certify(TpmsCertifyInfo),
600    Creation(TpmsCreationInfo),
601    Quote(TpmsQuoteInfo),
602    CommandAudit(TpmsCommandAuditInfo),
603    SessionAudit(TpmsSessionAuditInfo),
604    Time(TpmsTimeAttestInfo),
605    Nv(TpmsNvCertifyInfo),
606    NvDigest(TpmsNvDigestCertifyInfo),
607}
608
609impl TpmSized for TpmuAttest {
610    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
611    fn len(&self) -> usize {
612        match self {
613            Self::Certify(i) => i.len(),
614            Self::Creation(i) => i.len(),
615            Self::Quote(i) => i.len(),
616            Self::CommandAudit(i) => i.len(),
617            Self::SessionAudit(i) => i.len(),
618            Self::Time(i) => i.len(),
619            Self::Nv(i) => i.len(),
620            Self::NvDigest(i) => i.len(),
621        }
622    }
623}
624
625impl TpmMarshal for TpmuAttest {
626    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
627        match self {
628            Self::Certify(i) => i.marshal(writer),
629            Self::Creation(i) => i.marshal(writer),
630            Self::Quote(i) => i.marshal(writer),
631            Self::CommandAudit(i) => i.marshal(writer),
632            Self::SessionAudit(i) => i.marshal(writer),
633            Self::Time(i) => i.marshal(writer),
634            Self::Nv(i) => i.marshal(writer),
635            Self::NvDigest(i) => i.marshal(writer),
636        }
637    }
638}
639
640tpmu_view!(TpmuAttestView, TpmuAttest, TpmSt {
641    Certify(TpmsCertifyInfo): TpmSt::AttestCertify;
642    Creation(TpmsCreationInfo): TpmSt::AttestCreation;
643    Quote(TpmsQuoteInfo): TpmSt::AttestQuote;
644    CommandAudit(TpmsCommandAuditInfo): TpmSt::AttestCommandAudit;
645    SessionAudit(TpmsSessionAuditInfo): TpmSt::AttestSessionAudit;
646    Time(TpmsTimeAttestInfo): TpmSt::AttestTime;
647    Nv(TpmsNvCertifyInfo): TpmSt::AttestNv;
648    NvDigest(TpmsNvDigestCertifyInfo): TpmSt::AttestNvDigest;
649});
650
651#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
652pub enum TpmuKeyedhashScheme {
653    Hmac(TpmsSchemeHash),
654    Xor(TpmsSchemeXor),
655    #[default]
656    Null,
657}
658
659impl TpmSized for TpmuKeyedhashScheme {
660    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
661    fn len(&self) -> usize {
662        match self {
663            Self::Hmac(s) => s.len(),
664            Self::Xor(s) => s.len(),
665            Self::Null => 0,
666        }
667    }
668}
669
670impl TpmMarshal for TpmuKeyedhashScheme {
671    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
672        match self {
673            Self::Hmac(s) => s.marshal(writer),
674            Self::Xor(s) => s.marshal(writer),
675            Self::Null => Ok(()),
676        }
677    }
678}
679
680tpmu_view!(TpmuKeyedhashSchemeView, TpmuKeyedhashScheme, TpmAlgId {
681    Hmac(TpmsSchemeHash): TpmAlgId::Hmac;
682    Xor(TpmsSchemeXor): TpmAlgId::Xor;
683    @null Null: TpmAlgId::Null;
684});
685
686#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
687pub enum TpmuSigScheme {
688    Hash(TpmsSchemeHash),
689    Hmac(TpmsSchemeHmac),
690    #[default]
691    Null,
692}
693
694impl TpmSized for TpmuSigScheme {
695    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
696    fn len(&self) -> usize {
697        match self {
698            Self::Hash(s) | Self::Hmac(s) => s.len(),
699            Self::Null => 0,
700        }
701    }
702}
703
704impl TpmMarshal for TpmuSigScheme {
705    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
706        match self {
707            Self::Hash(s) | Self::Hmac(s) => s.marshal(writer),
708            Self::Null => Ok(()),
709        }
710    }
711}
712
713tpmu_view!(TpmuSigSchemeView, TpmuSigScheme, TpmAlgId {
714    Hmac(TpmsSchemeHmac): TpmAlgId::Hmac;
715    Hash(TpmsSchemeHash): TpmAlgId::Rsassa|TpmAlgId::Rsapss|TpmAlgId::Ecdsa|TpmAlgId::Ecdaa|TpmAlgId::Sm2|TpmAlgId::Ecschnorr;
716    @null Null: TpmAlgId::Null;
717});
718
719#[derive(Debug, PartialEq, Eq, Clone, Copy)]
720pub enum TpmuNvPublic2 {
721    NvIndex(TpmsNvPublic),
722    ExternalNv(TpmsNvPublicExpAttr),
723    PermanentNv(TpmsNvPublic),
724}
725
726#[allow(clippy::match_same_arms)]
727impl TpmSized for TpmuNvPublic2 {
728    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
729    fn len(&self) -> usize {
730        match self {
731            Self::NvIndex(s) => s.len(),
732            Self::ExternalNv(s) => s.len(),
733            Self::PermanentNv(s) => s.len(),
734        }
735    }
736}
737
738impl TpmMarshal for TpmuNvPublic2 {
739    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
740        match self {
741            Self::ExternalNv(s) => s.marshal(writer),
742            Self::NvIndex(s) | Self::PermanentNv(s) => s.marshal(writer),
743        }
744    }
745}
746
747tpmu_view!(TpmuNvPublic2View, TpmuNvPublic2, TpmHt {
748    NvIndex(TpmsNvPublic): TpmHt::NvIndex;
749    ExternalNv(TpmsNvPublicExpAttr): TpmHt::ExternalNv;
750    PermanentNv(TpmsNvPublic): TpmHt::PermanentNv;
751});
752
753#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
754pub enum TpmuKdfScheme {
755    Mgf1(TpmsSchemeHash),
756    Kdf1Sp800_56a(TpmsSchemeHash),
757    Kdf2(TpmsSchemeHash),
758    Kdf1Sp800_108(TpmsSchemeHash),
759    #[default]
760    Null,
761}
762
763impl TpmSized for TpmuKdfScheme {
764    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
765    fn len(&self) -> usize {
766        match self {
767            Self::Mgf1(s) | Self::Kdf1Sp800_56a(s) | Self::Kdf2(s) | Self::Kdf1Sp800_108(s) => {
768                s.len()
769            }
770            Self::Null => 0,
771        }
772    }
773}
774
775impl TpmMarshal for TpmuKdfScheme {
776    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
777        match self {
778            Self::Mgf1(s) | Self::Kdf1Sp800_56a(s) | Self::Kdf2(s) | Self::Kdf1Sp800_108(s) => {
779                s.marshal(writer)
780            }
781            Self::Null => Ok(()),
782        }
783    }
784}
785
786tpmu_view!(TpmuKdfSchemeView, TpmuKdfScheme, TpmAlgId {
787    Mgf1(TpmsSchemeHash): TpmAlgId::Mgf1;
788    Kdf1Sp800_56a(TpmsSchemeHash): TpmAlgId::Kdf1Sp800_56A;
789    Kdf2(TpmsSchemeHash): TpmAlgId::Kdf2;
790    Kdf1Sp800_108(TpmsSchemeHash): TpmAlgId::Kdf1Sp800_108;
791    @null Null: TpmAlgId::Null;
792});