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