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