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, Default)]
316pub enum TpmuPublicParms {
317    KeyedHash(TpmsKeyedhashParms),
318    SymCipher(TpmsSymcipherParms),
319    Rsa(TpmsRsaParms),
320    Ecc(TpmsEccParms),
321    #[default]
322    Null,
323}
324
325impl TpmSized for TpmuPublicParms {
326    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
327    fn len(&self) -> usize {
328        match self {
329            Self::KeyedHash(d) => d.len(),
330            Self::SymCipher(d) => d.len(),
331            Self::Rsa(d) => d.len(),
332            Self::Ecc(d) => d.len(),
333            Self::Null => 0,
334        }
335    }
336}
337
338impl TpmMarshal for TpmuPublicParms {
339    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
340        match self {
341            Self::KeyedHash(d) => d.marshal(writer),
342            Self::SymCipher(d) => d.marshal(writer),
343            Self::Rsa(d) => d.marshal(writer),
344            Self::Ecc(d) => d.marshal(writer),
345            Self::Null => Ok(()),
346        }
347    }
348}
349
350tpmu_view!(TpmuPublicParmsView, TpmuPublicParms, TpmAlgId {
351    KeyedHash(TpmsKeyedhashParms): TpmAlgId::KeyedHash;
352    SymCipher(TpmsSymcipherParms): TpmAlgId::SymCipher;
353    Rsa(TpmsRsaParms): TpmAlgId::Rsa;
354    Ecc(TpmsEccParms): TpmAlgId::Ecc;
355    @null Null: TpmAlgId::Null;
356});
357
358#[allow(clippy::large_enum_variant)]
359#[derive(Debug, PartialEq, Eq, Clone)]
360pub enum TpmuSensitiveComposite {
361    Rsa(crate::data::Tpm2bPrivateKeyRsa),
362    Ecc(Tpm2bEccParameter),
363    Bits(Tpm2bSensitiveData),
364    Sym(Tpm2bSymKey),
365}
366
367impl Default for TpmuSensitiveComposite {
368    fn default() -> Self {
369        Self::Rsa(crate::data::Tpm2bPrivateKeyRsa::default())
370    }
371}
372
373impl TpmSized for TpmuSensitiveComposite {
374    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
375    fn len(&self) -> usize {
376        match self {
377            Self::Ecc(val) => val.len(),
378            Self::Sym(val) => val.len(),
379            Self::Rsa(val) | Self::Bits(val) => val.len(),
380        }
381    }
382}
383
384impl TpmMarshal for TpmuSensitiveComposite {
385    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
386        match self {
387            Self::Ecc(val) => val.marshal(writer),
388            Self::Sym(val) => val.marshal(writer),
389            Self::Rsa(val) | Self::Bits(val) => val.marshal(writer),
390        }
391    }
392}
393
394tpmu_view!(TpmuSensitiveCompositeView, TpmuSensitiveComposite, TpmAlgId {
395    Rsa(crate::data::Tpm2bPrivateKeyRsa): TpmAlgId::Rsa;
396    Ecc(Tpm2bEccParameter): TpmAlgId::Ecc;
397    Bits(Tpm2bSensitiveData): TpmAlgId::KeyedHash;
398    Sym(Tpm2bSymKey): TpmAlgId::SymCipher;
399});
400
401#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
402pub enum TpmuSymKeyBits {
403    Aes(TpmUint16),
404    Sm4(TpmUint16),
405    Camellia(TpmUint16),
406    Xor(TpmAlgId),
407    #[default]
408    Null,
409}
410
411impl TpmSized for TpmuSymKeyBits {
412    const SIZE: usize = core::mem::size_of::<TpmUint16>();
413    fn len(&self) -> usize {
414        match self {
415            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.len(),
416            Self::Xor(val) => val.len(),
417            Self::Null => 0,
418        }
419    }
420}
421
422impl TpmMarshal for TpmuSymKeyBits {
423    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
424        match self {
425            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.marshal(writer),
426            Self::Xor(val) => val.marshal(writer),
427            Self::Null => Ok(()),
428        }
429    }
430}
431
432tpmu_view!(TpmuSymKeyBitsView, TpmuSymKeyBits, TpmAlgId {
433    Aes(TpmUint16): TpmAlgId::Aes;
434    Sm4(TpmUint16): TpmAlgId::Sm4;
435    Camellia(TpmUint16): TpmAlgId::Camellia;
436    Xor(TpmAlgId): TpmAlgId::Xor;
437    @null Null: TpmAlgId::Null;
438});
439
440#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
441pub enum TpmuSymMode {
442    Aes(TpmAlgId),
443    Sm4(TpmAlgId),
444    Camellia(TpmAlgId),
445    Xor(TpmAlgId),
446    #[default]
447    Null,
448}
449
450impl TpmSized for TpmuSymMode {
451    const SIZE: usize = core::mem::size_of::<TpmUint16>();
452    fn len(&self) -> usize {
453        match self {
454            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) | Self::Xor(val) => val.len(),
455            Self::Null => 0,
456        }
457    }
458}
459
460impl TpmMarshal for TpmuSymMode {
461    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
462        match self {
463            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) | Self::Xor(val) => {
464                val.marshal(writer)
465            }
466            Self::Null => Ok(()),
467        }
468    }
469}
470
471tpmu_view!(TpmuSymModeView, TpmuSymMode, TpmAlgId {
472    Aes(TpmAlgId): TpmAlgId::Aes;
473    Sm4(TpmAlgId): TpmAlgId::Sm4;
474    Camellia(TpmAlgId): TpmAlgId::Camellia;
475    Xor(TpmAlgId): TpmAlgId::Xor;
476    @null Null: TpmAlgId::Null;
477});
478
479#[derive(Debug, PartialEq, Eq, Clone)]
480pub enum TpmuSignature {
481    Rsassa(TpmsSignatureRsa),
482    Rsapss(TpmsSignatureRsa),
483    Ecdsa(TpmsSignatureEcc),
484    Ecdaa(TpmsSignatureEcc),
485    Sm2(TpmsSignatureEcc),
486    Ecschnorr(TpmsSignatureEcc),
487    Hmac(TpmtHa),
488    Null,
489}
490
491impl TpmSized for TpmuSignature {
492    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
493    fn len(&self) -> usize {
494        match self {
495            Self::Rsassa(s) | Self::Rsapss(s) => s.len(),
496            Self::Ecdsa(s) | Self::Ecdaa(s) | Self::Sm2(s) | Self::Ecschnorr(s) => s.len(),
497            Self::Hmac(s) => s.len(),
498            Self::Null => 0,
499        }
500    }
501}
502
503impl TpmMarshal for TpmuSignature {
504    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
505        match self {
506            Self::Rsassa(s) | Self::Rsapss(s) => s.marshal(writer),
507            Self::Ecdsa(s) | Self::Ecdaa(s) | Self::Sm2(s) | Self::Ecschnorr(s) => {
508                s.marshal(writer)
509            }
510            Self::Hmac(s) => s.marshal(writer),
511            Self::Null => Ok(()),
512        }
513    }
514}
515
516tpmu_view!(TpmuSignatureView, TpmuSignature, TpmAlgId {
517    Rsassa(TpmsSignatureRsa): TpmAlgId::Rsassa;
518    Rsapss(TpmsSignatureRsa): TpmAlgId::Rsapss;
519    Ecdsa(TpmsSignatureEcc): TpmAlgId::Ecdsa;
520    Ecdaa(TpmsSignatureEcc): TpmAlgId::Ecdaa;
521    Sm2(TpmsSignatureEcc): TpmAlgId::Sm2;
522    Ecschnorr(TpmsSignatureEcc): TpmAlgId::Ecschnorr;
523    Hmac(TpmtHa): TpmAlgId::Hmac;
524    @null Null: TpmAlgId::Null;
525});
526
527#[allow(clippy::large_enum_variant)]
528#[derive(Debug, PartialEq, Eq, Clone)]
529pub enum TpmuAttest {
530    Certify(TpmsCertifyInfo),
531    Creation(TpmsCreationInfo),
532    Quote(TpmsQuoteInfo),
533    CommandAudit(TpmsCommandAuditInfo),
534    SessionAudit(TpmsSessionAuditInfo),
535    Time(TpmsTimeAttestInfo),
536    Nv(TpmsNvCertifyInfo),
537    NvDigest(TpmsNvDigestCertifyInfo),
538}
539
540impl TpmSized for TpmuAttest {
541    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
542    fn len(&self) -> usize {
543        match self {
544            Self::Certify(i) => i.len(),
545            Self::Creation(i) => i.len(),
546            Self::Quote(i) => i.len(),
547            Self::CommandAudit(i) => i.len(),
548            Self::SessionAudit(i) => i.len(),
549            Self::Time(i) => i.len(),
550            Self::Nv(i) => i.len(),
551            Self::NvDigest(i) => i.len(),
552        }
553    }
554}
555
556impl TpmMarshal for TpmuAttest {
557    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
558        match self {
559            Self::Certify(i) => i.marshal(writer),
560            Self::Creation(i) => i.marshal(writer),
561            Self::Quote(i) => i.marshal(writer),
562            Self::CommandAudit(i) => i.marshal(writer),
563            Self::SessionAudit(i) => i.marshal(writer),
564            Self::Time(i) => i.marshal(writer),
565            Self::Nv(i) => i.marshal(writer),
566            Self::NvDigest(i) => i.marshal(writer),
567        }
568    }
569}
570
571tpmu_view!(TpmuAttestView, TpmuAttest, TpmSt {
572    Certify(TpmsCertifyInfo): TpmSt::AttestCertify;
573    Creation(TpmsCreationInfo): TpmSt::AttestCreation;
574    Quote(TpmsQuoteInfo): TpmSt::AttestQuote;
575    CommandAudit(TpmsCommandAuditInfo): TpmSt::AttestCommandAudit;
576    SessionAudit(TpmsSessionAuditInfo): TpmSt::AttestSessionAudit;
577    Time(TpmsTimeAttestInfo): TpmSt::AttestTime;
578    Nv(TpmsNvCertifyInfo): TpmSt::AttestNv;
579    NvDigest(TpmsNvDigestCertifyInfo): TpmSt::AttestNvDigest;
580});
581
582#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
583pub enum TpmuKeyedhashScheme {
584    Hmac(TpmsSchemeHash),
585    Xor(TpmsSchemeXor),
586    #[default]
587    Null,
588}
589
590impl TpmSized for TpmuKeyedhashScheme {
591    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
592    fn len(&self) -> usize {
593        match self {
594            Self::Hmac(s) => s.len(),
595            Self::Xor(s) => s.len(),
596            Self::Null => 0,
597        }
598    }
599}
600
601impl TpmMarshal for TpmuKeyedhashScheme {
602    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
603        match self {
604            Self::Hmac(s) => s.marshal(writer),
605            Self::Xor(s) => s.marshal(writer),
606            Self::Null => Ok(()),
607        }
608    }
609}
610
611tpmu_view!(TpmuKeyedhashSchemeView, TpmuKeyedhashScheme, TpmAlgId {
612    Hmac(TpmsSchemeHash): TpmAlgId::Hmac;
613    Xor(TpmsSchemeXor): TpmAlgId::Xor;
614    @null Null: TpmAlgId::Null;
615});
616
617#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
618pub enum TpmuSigScheme {
619    Hash(TpmsSchemeHash),
620    Hmac(TpmsSchemeHmac),
621    #[default]
622    Null,
623}
624
625impl TpmSized for TpmuSigScheme {
626    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
627    fn len(&self) -> usize {
628        match self {
629            Self::Hash(s) | Self::Hmac(s) => s.len(),
630            Self::Null => 0,
631        }
632    }
633}
634
635impl TpmMarshal for TpmuSigScheme {
636    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
637        match self {
638            Self::Hash(s) | Self::Hmac(s) => s.marshal(writer),
639            Self::Null => Ok(()),
640        }
641    }
642}
643
644tpmu_view!(TpmuSigSchemeView, TpmuSigScheme, TpmAlgId {
645    Hmac(TpmsSchemeHmac): TpmAlgId::Hmac;
646    Hash(TpmsSchemeHash): TpmAlgId::Rsassa|TpmAlgId::Rsapss|TpmAlgId::Ecdsa|TpmAlgId::Ecdaa|TpmAlgId::Sm2|TpmAlgId::Ecschnorr;
647    @null Null: TpmAlgId::Null;
648});
649
650#[derive(Debug, PartialEq, Eq, Clone, Copy)]
651pub enum TpmuNvPublic2 {
652    NvIndex(TpmsNvPublic),
653    ExternalNv(TpmsNvPublicExpAttr),
654    PermanentNv(TpmsNvPublic),
655}
656
657#[allow(clippy::match_same_arms)]
658impl TpmSized for TpmuNvPublic2 {
659    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
660    fn len(&self) -> usize {
661        match self {
662            Self::NvIndex(s) => s.len(),
663            Self::ExternalNv(s) => s.len(),
664            Self::PermanentNv(s) => s.len(),
665        }
666    }
667}
668
669impl TpmMarshal for TpmuNvPublic2 {
670    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
671        match self {
672            Self::ExternalNv(s) => s.marshal(writer),
673            Self::NvIndex(s) | Self::PermanentNv(s) => s.marshal(writer),
674        }
675    }
676}
677
678tpmu_view!(TpmuNvPublic2View, TpmuNvPublic2, TpmHt {
679    NvIndex(TpmsNvPublic): TpmHt::NvIndex;
680    ExternalNv(TpmsNvPublicExpAttr): TpmHt::ExternalNv;
681    PermanentNv(TpmsNvPublic): TpmHt::PermanentNv;
682});
683
684#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
685pub enum TpmuKdfScheme {
686    Mgf1(TpmsSchemeHash),
687    Kdf1Sp800_56a(TpmsSchemeHash),
688    Kdf2(TpmsSchemeHash),
689    Kdf1Sp800_108(TpmsSchemeHash),
690    #[default]
691    Null,
692}
693
694impl TpmSized for TpmuKdfScheme {
695    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
696    fn len(&self) -> usize {
697        match self {
698            Self::Mgf1(s) | Self::Kdf1Sp800_56a(s) | Self::Kdf2(s) | Self::Kdf1Sp800_108(s) => {
699                s.len()
700            }
701            Self::Null => 0,
702        }
703    }
704}
705
706impl TpmMarshal for TpmuKdfScheme {
707    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
708        match self {
709            Self::Mgf1(s) | Self::Kdf1Sp800_56a(s) | Self::Kdf2(s) | Self::Kdf1Sp800_108(s) => {
710                s.marshal(writer)
711            }
712            Self::Null => Ok(()),
713        }
714    }
715}
716
717tpmu_view!(TpmuKdfSchemeView, TpmuKdfScheme, TpmAlgId {
718    Mgf1(TpmsSchemeHash): TpmAlgId::Mgf1;
719    Kdf1Sp800_56a(TpmsSchemeHash): TpmAlgId::Kdf1Sp800_56A;
720    Kdf2(TpmsSchemeHash): TpmAlgId::Kdf2;
721    Kdf1Sp800_108(TpmsSchemeHash): TpmAlgId::Kdf1Sp800_108;
722    @null Null: TpmAlgId::Null;
723});