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, TpmTagged, TpmUnmarshal, TpmUnmarshalTagged,
7    TpmWriter,
8    basic::{TpmBuffer, TpmUint16},
9    constant::{MAX_DIGEST_SIZE, TPM_MAX_COMMAND_SIZE},
10    data::{
11        Tpm2bDigest, Tpm2bEccParameter, Tpm2bPublicKeyRsa, Tpm2bSensitiveData, Tpm2bSymKey,
12        TpmAlgId, TpmCap, TpmHt, TpmSt, TpmlAlgProperty, TpmlCca, TpmlEccCurve, TpmlHandle,
13        TpmlPcrSelection, TpmlTaggedTpmProperty, TpmsCertifyInfo, TpmsCommandAuditInfo,
14        TpmsCreationInfo, TpmsEccParms, TpmsEccPoint, TpmsKeyedhashParms, TpmsNvCertifyInfo,
15        TpmsNvDigestCertifyInfo, TpmsNvPublic, TpmsNvPublicExpAttr, TpmsQuoteInfo, TpmsRsaParms,
16        TpmsSchemeHash, TpmsSchemeHmac, TpmsSchemeXor, TpmsSessionAuditInfo, TpmsSignatureEcc,
17        TpmsSignatureRsa, TpmsSymcipherParms, TpmsTimeAttestInfo, TpmtHa,
18    },
19};
20use core::ops::Deref;
21
22#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
23pub enum TpmuAsymScheme {
24    Hash(TpmsSchemeHash),
25    #[default]
26    Null,
27}
28
29impl TpmTagged for TpmuAsymScheme {
30    type Tag = TpmAlgId;
31    type Value = ();
32}
33
34impl TpmSized for TpmuAsymScheme {
35    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
36    fn len(&self) -> usize {
37        match self {
38            Self::Hash(s) => s.len(),
39            Self::Null => 0,
40        }
41    }
42}
43
44impl TpmMarshal for TpmuAsymScheme {
45    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
46        match self {
47            Self::Hash(s) => s.marshal(writer),
48            Self::Null => Ok(()),
49        }
50    }
51}
52
53impl TpmUnmarshalTagged for TpmuAsymScheme {
54    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
55        match tag {
56            TpmAlgId::Rsassa
57            | TpmAlgId::Rsapss
58            | TpmAlgId::Ecdsa
59            | TpmAlgId::Ecdaa
60            | TpmAlgId::Sm2
61            | TpmAlgId::Ecschnorr
62            | TpmAlgId::Oaep
63            | TpmAlgId::Ecdh
64            | TpmAlgId::Ecmqv => {
65                let (val, buf) = TpmsSchemeHash::unmarshal(buf)?;
66                Ok((Self::Hash(val), buf))
67            }
68            TpmAlgId::Rsaes | TpmAlgId::Null => Ok((Self::Null, buf)),
69            _ => Err(TpmError::VariantNotAvailable(
70                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
71            )),
72        }
73    }
74}
75
76#[derive(Debug, PartialEq, Eq, Clone)]
77#[allow(clippy::large_enum_variant)]
78pub enum TpmuCapabilities {
79    Algs(TpmlAlgProperty),
80    Handles(TpmlHandle),
81    Pcrs(TpmlPcrSelection),
82    Commands(TpmlCca),
83    TpmProperties(TpmlTaggedTpmProperty),
84    EccCurves(TpmlEccCurve),
85}
86
87impl TpmTagged for TpmuCapabilities {
88    type Tag = TpmCap;
89    type Value = ();
90}
91
92impl TpmSized for TpmuCapabilities {
93    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
94    fn len(&self) -> usize {
95        match self {
96            Self::Algs(algs) => algs.len(),
97            Self::Handles(handles) => handles.len(),
98            Self::Pcrs(pcrs) => pcrs.len(),
99            Self::Commands(cmds) => cmds.len(),
100            Self::TpmProperties(props) => props.len(),
101            Self::EccCurves(curves) => curves.len(),
102        }
103    }
104}
105
106impl TpmMarshal for TpmuCapabilities {
107    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
108        match self {
109            Self::Algs(algs) => algs.marshal(writer),
110            Self::Handles(handles) => handles.marshal(writer),
111            Self::Pcrs(pcrs) => pcrs.marshal(writer),
112            Self::Commands(cmds) => cmds.marshal(writer),
113            Self::TpmProperties(props) => props.marshal(writer),
114            Self::EccCurves(curves) => curves.marshal(writer),
115        }
116    }
117}
118
119impl TpmUnmarshalTagged for TpmuCapabilities {
120    fn unmarshal_tagged(tag: TpmCap, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
121        match tag {
122            TpmCap::Algs => {
123                let (algs, buf) = TpmlAlgProperty::unmarshal(buf)?;
124                Ok((TpmuCapabilities::Algs(algs), buf))
125            }
126            TpmCap::Handles => {
127                let (handles, buf) = TpmlHandle::unmarshal(buf)?;
128                Ok((TpmuCapabilities::Handles(handles), buf))
129            }
130            TpmCap::Pcrs => {
131                let (pcrs, buf) = TpmlPcrSelection::unmarshal(buf)?;
132                Ok((TpmuCapabilities::Pcrs(pcrs), buf))
133            }
134            TpmCap::Commands => {
135                let (cmds, buf) = TpmlCca::unmarshal(buf)?;
136                Ok((TpmuCapabilities::Commands(cmds), buf))
137            }
138            TpmCap::TpmProperties => {
139                let (props, buf) = TpmlTaggedTpmProperty::unmarshal(buf)?;
140                Ok((TpmuCapabilities::TpmProperties(props), buf))
141            }
142            TpmCap::EccCurves => {
143                let (curves, buf) = TpmlEccCurve::unmarshal(buf)?;
144                Ok((TpmuCapabilities::EccCurves(curves), buf))
145            }
146        }
147    }
148}
149
150#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
151pub enum TpmuHa {
152    #[default]
153    Null,
154    Digest(TpmBuffer<MAX_DIGEST_SIZE>),
155}
156
157impl TpmTagged for TpmuHa {
158    type Tag = TpmAlgId;
159    type Value = ();
160}
161
162impl TpmMarshal for TpmuHa {
163    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
164        match self {
165            Self::Null => Ok(()),
166            Self::Digest(d) => writer.write_bytes(d),
167        }
168    }
169}
170
171impl TpmUnmarshalTagged for TpmuHa {
172    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
173        let digest_size = match tag {
174            TpmAlgId::Null => return Ok((Self::Null, buf)),
175            TpmAlgId::Sha1 => 20,
176            TpmAlgId::Shake256_192 => 24,
177            TpmAlgId::Sha256 | TpmAlgId::Sm3_256 | TpmAlgId::Sha3_256 | TpmAlgId::Shake256_256 => {
178                32
179            }
180            TpmAlgId::Sha384 | TpmAlgId::Sha3_384 => 48,
181            TpmAlgId::Sha512 | TpmAlgId::Sha3_512 | TpmAlgId::Shake256_512 => 64,
182            _ => {
183                return Err(TpmError::VariantNotAvailable(
184                    crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
185                ));
186            }
187        };
188
189        if buf.len() < digest_size {
190            return Err(TpmError::UnexpectedEnd(
191                crate::TpmErrorValue::new(0).size(digest_size, buf.len()),
192            ));
193        }
194
195        let (digest_bytes, buf) = buf.split_at(digest_size);
196
197        let digest = Self::Digest(TpmBuffer::try_from(digest_bytes).map_err(|_| {
198            TpmError::IntegerTooLarge(crate::TpmErrorValue::new(0).value_usize(digest_size))
199        })?);
200
201        Ok((digest, buf))
202    }
203}
204
205impl TpmSized for TpmuHa {
206    const SIZE: usize = MAX_DIGEST_SIZE;
207    fn len(&self) -> usize {
208        match self {
209            Self::Null => 0,
210            Self::Digest(d) => d.deref().len(),
211        }
212    }
213}
214
215impl Deref for TpmuHa {
216    type Target = [u8];
217
218    fn deref(&self) -> &Self::Target {
219        match self {
220            Self::Null => &[],
221            Self::Digest(d) => d,
222        }
223    }
224}
225
226#[allow(clippy::large_enum_variant)]
227#[derive(Debug, PartialEq, Eq, Clone, Default)]
228pub enum TpmuPublicId {
229    KeyedHash(Tpm2bDigest),
230    SymCipher(Tpm2bSymKey),
231    Rsa(Tpm2bPublicKeyRsa),
232    Ecc(TpmsEccPoint),
233    #[default]
234    Null,
235}
236
237impl TpmTagged for TpmuPublicId {
238    type Tag = TpmAlgId;
239    type Value = ();
240}
241
242impl TpmSized for TpmuPublicId {
243    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
244    fn len(&self) -> usize {
245        match self {
246            Self::KeyedHash(data) => data.len(),
247            Self::SymCipher(data) => data.len(),
248            Self::Rsa(data) => data.len(),
249            Self::Ecc(point) => point.len(),
250            Self::Null => 0,
251        }
252    }
253}
254
255impl TpmMarshal for TpmuPublicId {
256    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
257        match self {
258            Self::KeyedHash(data) => data.marshal(writer),
259            Self::SymCipher(data) => data.marshal(writer),
260            Self::Rsa(data) => data.marshal(writer),
261            Self::Ecc(point) => point.marshal(writer),
262            Self::Null => Ok(()),
263        }
264    }
265}
266
267impl TpmUnmarshalTagged for TpmuPublicId {
268    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
269        match tag {
270            TpmAlgId::KeyedHash => {
271                let (val, rest) = Tpm2bDigest::unmarshal(buf)?;
272                Ok((TpmuPublicId::KeyedHash(val), rest))
273            }
274            TpmAlgId::SymCipher => {
275                let (val, rest) = Tpm2bSymKey::unmarshal(buf)?;
276                Ok((TpmuPublicId::SymCipher(val), rest))
277            }
278            TpmAlgId::Rsa => {
279                let (val, rest) = Tpm2bPublicKeyRsa::unmarshal(buf)?;
280                Ok((TpmuPublicId::Rsa(val), rest))
281            }
282            TpmAlgId::Ecc => {
283                let (point, rest) = TpmsEccPoint::unmarshal(buf)?;
284                Ok((TpmuPublicId::Ecc(point), rest))
285            }
286            TpmAlgId::Null => Ok((TpmuPublicId::Null, buf)),
287            _ => Err(TpmError::VariantNotAvailable(
288                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
289            )),
290        }
291    }
292}
293
294#[derive(Debug, PartialEq, Eq, Clone, Copy)]
295pub enum TpmuPublicParms {
296    KeyedHash(TpmsKeyedhashParms),
297    SymCipher(TpmsSymcipherParms),
298    Rsa(TpmsRsaParms),
299    Ecc(TpmsEccParms),
300    Null,
301}
302
303impl TpmTagged for TpmuPublicParms {
304    type Tag = TpmAlgId;
305    type Value = ();
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
333impl TpmUnmarshalTagged for TpmuPublicParms {
334    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
335        match tag {
336            TpmAlgId::KeyedHash => {
337                let (details, buf) = TpmsKeyedhashParms::unmarshal(buf)?;
338                Ok((Self::KeyedHash(details), buf))
339            }
340            TpmAlgId::SymCipher => {
341                let (details, buf) = TpmsSymcipherParms::unmarshal(buf)?;
342                Ok((Self::SymCipher(details), buf))
343            }
344            TpmAlgId::Rsa => {
345                let (details, buf) = TpmsRsaParms::unmarshal(buf)?;
346                Ok((Self::Rsa(details), buf))
347            }
348            TpmAlgId::Ecc => {
349                let (details, buf) = TpmsEccParms::unmarshal(buf)?;
350                Ok((Self::Ecc(details), buf))
351            }
352            TpmAlgId::Null => Ok((Self::Null, buf)),
353            _ => Err(TpmError::VariantNotAvailable(
354                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
355            )),
356        }
357    }
358}
359
360#[allow(clippy::large_enum_variant)]
361#[derive(Debug, PartialEq, Eq, Clone)]
362pub enum TpmuSensitiveComposite {
363    Rsa(crate::data::Tpm2bPrivateKeyRsa),
364    Ecc(Tpm2bEccParameter),
365    Bits(Tpm2bSensitiveData),
366    Sym(Tpm2bSymKey),
367}
368
369impl TpmTagged for TpmuSensitiveComposite {
370    type Tag = TpmAlgId;
371    type Value = ();
372}
373
374impl Default for TpmuSensitiveComposite {
375    fn default() -> Self {
376        Self::Rsa(crate::data::Tpm2bPrivateKeyRsa::default())
377    }
378}
379
380impl TpmSized for TpmuSensitiveComposite {
381    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
382    fn len(&self) -> usize {
383        match self {
384            Self::Ecc(val) => val.len(),
385            Self::Sym(val) => val.len(),
386            Self::Rsa(val) | Self::Bits(val) => val.len(),
387        }
388    }
389}
390
391impl TpmMarshal for TpmuSensitiveComposite {
392    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
393        match self {
394            Self::Ecc(val) => val.marshal(writer),
395            Self::Sym(val) => val.marshal(writer),
396            Self::Rsa(val) | Self::Bits(val) => val.marshal(writer),
397        }
398    }
399}
400
401impl TpmUnmarshalTagged for TpmuSensitiveComposite {
402    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
403        match tag {
404            TpmAlgId::Rsa => {
405                let (val, buf) = crate::data::Tpm2bPrivateKeyRsa::unmarshal(buf)?;
406                Ok((TpmuSensitiveComposite::Rsa(val), buf))
407            }
408            TpmAlgId::Ecc => {
409                let (val, buf) = Tpm2bEccParameter::unmarshal(buf)?;
410                Ok((TpmuSensitiveComposite::Ecc(val), buf))
411            }
412            TpmAlgId::KeyedHash => {
413                let (val, buf) = Tpm2bSensitiveData::unmarshal(buf)?;
414                Ok((TpmuSensitiveComposite::Bits(val), buf))
415            }
416            TpmAlgId::SymCipher => {
417                let (val, buf) = Tpm2bSymKey::unmarshal(buf)?;
418                Ok((TpmuSensitiveComposite::Sym(val), buf))
419            }
420            _ => Err(TpmError::VariantNotAvailable(
421                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
422            )),
423        }
424    }
425}
426
427#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
428pub enum TpmuSymKeyBits {
429    Aes(TpmUint16),
430    Sm4(TpmUint16),
431    Camellia(TpmUint16),
432    Xor(TpmAlgId),
433    #[default]
434    Null,
435}
436
437impl TpmTagged for TpmuSymKeyBits {
438    type Tag = TpmAlgId;
439    type Value = ();
440}
441
442impl TpmSized for TpmuSymKeyBits {
443    const SIZE: usize = core::mem::size_of::<TpmUint16>();
444    fn len(&self) -> usize {
445        match self {
446            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.len(),
447            Self::Xor(val) => val.len(),
448            Self::Null => 0,
449        }
450    }
451}
452
453impl TpmMarshal for TpmuSymKeyBits {
454    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
455        match self {
456            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.marshal(writer),
457            Self::Xor(val) => val.marshal(writer),
458            Self::Null => Ok(()),
459        }
460    }
461}
462
463impl TpmUnmarshalTagged for TpmuSymKeyBits {
464    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
465        match tag {
466            TpmAlgId::Aes => {
467                let (val, buf) = TpmUint16::unmarshal(buf)?;
468                Ok((TpmuSymKeyBits::Aes(val), buf))
469            }
470            TpmAlgId::Sm4 => {
471                let (val, buf) = TpmUint16::unmarshal(buf)?;
472                Ok((TpmuSymKeyBits::Sm4(val), buf))
473            }
474            TpmAlgId::Camellia => {
475                let (val, buf) = TpmUint16::unmarshal(buf)?;
476                Ok((TpmuSymKeyBits::Camellia(val), buf))
477            }
478            TpmAlgId::Xor => {
479                let (val, buf) = TpmAlgId::unmarshal(buf)?;
480                Ok((TpmuSymKeyBits::Xor(val), buf))
481            }
482            TpmAlgId::Null => Ok((TpmuSymKeyBits::Null, buf)),
483            _ => Err(TpmError::VariantNotAvailable(
484                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
485            )),
486        }
487    }
488}
489
490#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
491pub enum TpmuSymMode {
492    Aes(TpmAlgId),
493    Sm4(TpmAlgId),
494    Camellia(TpmAlgId),
495    Xor(TpmAlgId),
496    #[default]
497    Null,
498}
499
500impl TpmTagged for TpmuSymMode {
501    type Tag = TpmAlgId;
502    type Value = ();
503}
504
505impl TpmSized for TpmuSymMode {
506    const SIZE: usize = core::mem::size_of::<TpmUint16>();
507    fn len(&self) -> usize {
508        match self {
509            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) | Self::Xor(val) => val.len(),
510            Self::Null => 0,
511        }
512    }
513}
514
515impl TpmMarshal for TpmuSymMode {
516    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
517        match self {
518            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) | Self::Xor(val) => {
519                val.marshal(writer)
520            }
521            Self::Null => Ok(()),
522        }
523    }
524}
525
526impl TpmUnmarshalTagged for TpmuSymMode {
527    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
528        match tag {
529            TpmAlgId::Aes => {
530                let (val, buf) = TpmAlgId::unmarshal(buf)?;
531                Ok((TpmuSymMode::Aes(val), buf))
532            }
533            TpmAlgId::Sm4 => {
534                let (val, buf) = TpmAlgId::unmarshal(buf)?;
535                Ok((TpmuSymMode::Sm4(val), buf))
536            }
537            TpmAlgId::Camellia => {
538                let (val, buf) = TpmAlgId::unmarshal(buf)?;
539                Ok((TpmuSymMode::Camellia(val), buf))
540            }
541            TpmAlgId::Xor => {
542                let (val, buf) = TpmAlgId::unmarshal(buf)?;
543                Ok((TpmuSymMode::Xor(val), buf))
544            }
545            TpmAlgId::Null => Ok((TpmuSymMode::Null, buf)),
546            _ => Err(TpmError::VariantNotAvailable(
547                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
548            )),
549        }
550    }
551}
552
553#[derive(Debug, PartialEq, Eq, Clone)]
554pub enum TpmuSignature {
555    Rsassa(TpmsSignatureRsa),
556    Rsapss(TpmsSignatureRsa),
557    Ecdsa(TpmsSignatureEcc),
558    Ecdaa(TpmsSignatureEcc),
559    Sm2(TpmsSignatureEcc),
560    Ecschnorr(TpmsSignatureEcc),
561    Hmac(TpmtHa),
562    Null,
563}
564
565impl TpmTagged for TpmuSignature {
566    type Tag = TpmAlgId;
567    type Value = ();
568}
569
570impl TpmSized for TpmuSignature {
571    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
572    fn len(&self) -> usize {
573        match self {
574            Self::Rsassa(s) | Self::Rsapss(s) => s.len(),
575            Self::Ecdsa(s) | Self::Ecdaa(s) | Self::Sm2(s) | Self::Ecschnorr(s) => s.len(),
576            Self::Hmac(s) => s.len(),
577            Self::Null => 0,
578        }
579    }
580}
581
582impl TpmMarshal for TpmuSignature {
583    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
584        match self {
585            Self::Rsassa(s) | Self::Rsapss(s) => s.marshal(writer),
586            Self::Ecdsa(s) | Self::Ecdaa(s) | Self::Sm2(s) | Self::Ecschnorr(s) => {
587                s.marshal(writer)
588            }
589            Self::Hmac(s) => s.marshal(writer),
590            Self::Null => Ok(()),
591        }
592    }
593}
594
595impl TpmUnmarshalTagged for TpmuSignature {
596    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
597        match tag {
598            TpmAlgId::Rsassa => {
599                let (val, buf) = TpmsSignatureRsa::unmarshal(buf)?;
600                Ok((Self::Rsassa(val), buf))
601            }
602            TpmAlgId::Rsapss => {
603                let (val, buf) = TpmsSignatureRsa::unmarshal(buf)?;
604                Ok((Self::Rsapss(val), buf))
605            }
606            TpmAlgId::Ecdsa => {
607                let (val, buf) = TpmsSignatureEcc::unmarshal(buf)?;
608                Ok((Self::Ecdsa(val), buf))
609            }
610            TpmAlgId::Ecdaa => {
611                let (val, buf) = TpmsSignatureEcc::unmarshal(buf)?;
612                Ok((Self::Ecdaa(val), buf))
613            }
614            TpmAlgId::Sm2 => {
615                let (val, buf) = TpmsSignatureEcc::unmarshal(buf)?;
616                Ok((Self::Sm2(val), buf))
617            }
618            TpmAlgId::Ecschnorr => {
619                let (val, buf) = TpmsSignatureEcc::unmarshal(buf)?;
620                Ok((Self::Ecschnorr(val), buf))
621            }
622            TpmAlgId::Hmac => {
623                let (val, buf) = TpmtHa::unmarshal(buf)?;
624                Ok((Self::Hmac(val), buf))
625            }
626            TpmAlgId::Null => Ok((Self::Null, buf)),
627            _ => Err(TpmError::VariantNotAvailable(
628                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
629            )),
630        }
631    }
632}
633
634#[allow(clippy::large_enum_variant)]
635#[derive(Debug, PartialEq, Eq, Clone)]
636pub enum TpmuAttest {
637    Certify(TpmsCertifyInfo),
638    Creation(TpmsCreationInfo),
639    Quote(TpmsQuoteInfo),
640    CommandAudit(TpmsCommandAuditInfo),
641    SessionAudit(TpmsSessionAuditInfo),
642    Time(TpmsTimeAttestInfo),
643    Nv(TpmsNvCertifyInfo),
644    NvDigest(TpmsNvDigestCertifyInfo),
645}
646
647impl TpmTagged for TpmuAttest {
648    type Tag = TpmSt;
649    type Value = ();
650}
651
652impl TpmSized for TpmuAttest {
653    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
654    fn len(&self) -> usize {
655        match self {
656            Self::Certify(i) => i.len(),
657            Self::Creation(i) => i.len(),
658            Self::Quote(i) => i.len(),
659            Self::CommandAudit(i) => i.len(),
660            Self::SessionAudit(i) => i.len(),
661            Self::Time(i) => i.len(),
662            Self::Nv(i) => i.len(),
663            Self::NvDigest(i) => i.len(),
664        }
665    }
666}
667
668impl TpmMarshal for TpmuAttest {
669    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
670        match self {
671            Self::Certify(i) => i.marshal(writer),
672            Self::Creation(i) => i.marshal(writer),
673            Self::Quote(i) => i.marshal(writer),
674            Self::CommandAudit(i) => i.marshal(writer),
675            Self::SessionAudit(i) => i.marshal(writer),
676            Self::Time(i) => i.marshal(writer),
677            Self::Nv(i) => i.marshal(writer),
678            Self::NvDigest(i) => i.marshal(writer),
679        }
680    }
681}
682
683impl TpmUnmarshalTagged for TpmuAttest {
684    fn unmarshal_tagged(tag: TpmSt, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
685        match tag {
686            TpmSt::AttestCertify => {
687                let (val, buf) = TpmsCertifyInfo::unmarshal(buf)?;
688                Ok((TpmuAttest::Certify(val), buf))
689            }
690            TpmSt::AttestCreation => {
691                let (val, buf) = TpmsCreationInfo::unmarshal(buf)?;
692                Ok((TpmuAttest::Creation(val), buf))
693            }
694            TpmSt::AttestQuote => {
695                let (val, buf) = TpmsQuoteInfo::unmarshal(buf)?;
696                Ok((TpmuAttest::Quote(val), buf))
697            }
698            TpmSt::AttestCommandAudit => {
699                let (val, buf) = TpmsCommandAuditInfo::unmarshal(buf)?;
700                Ok((TpmuAttest::CommandAudit(val), buf))
701            }
702            TpmSt::AttestSessionAudit => {
703                let (val, buf) = TpmsSessionAuditInfo::unmarshal(buf)?;
704                Ok((TpmuAttest::SessionAudit(val), buf))
705            }
706            TpmSt::AttestTime => {
707                let (val, buf) = TpmsTimeAttestInfo::unmarshal(buf)?;
708                Ok((TpmuAttest::Time(val), buf))
709            }
710            TpmSt::AttestNv => {
711                let (val, buf) = TpmsNvCertifyInfo::unmarshal(buf)?;
712                Ok((TpmuAttest::Nv(val), buf))
713            }
714            TpmSt::AttestNvDigest => {
715                let (val, buf) = TpmsNvDigestCertifyInfo::unmarshal(buf)?;
716                Ok((TpmuAttest::NvDigest(val), buf))
717            }
718            _ => Err(TpmError::VariantNotAvailable(
719                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
720            )),
721        }
722    }
723}
724
725#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
726pub enum TpmuKeyedhashScheme {
727    Hmac(TpmsSchemeHash),
728    Xor(TpmsSchemeXor),
729    #[default]
730    Null,
731}
732
733impl TpmTagged for TpmuKeyedhashScheme {
734    type Tag = TpmAlgId;
735    type Value = ();
736}
737
738impl TpmSized for TpmuKeyedhashScheme {
739    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
740    fn len(&self) -> usize {
741        match self {
742            Self::Hmac(s) => s.len(),
743            Self::Xor(s) => s.len(),
744            Self::Null => 0,
745        }
746    }
747}
748
749impl TpmMarshal for TpmuKeyedhashScheme {
750    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
751        match self {
752            Self::Hmac(s) => s.marshal(writer),
753            Self::Xor(s) => s.marshal(writer),
754            Self::Null => Ok(()),
755        }
756    }
757}
758
759impl TpmUnmarshalTagged for TpmuKeyedhashScheme {
760    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
761        match tag {
762            TpmAlgId::Hmac => {
763                let (val, buf) = TpmsSchemeHash::unmarshal(buf)?;
764                Ok((Self::Hmac(val), buf))
765            }
766            TpmAlgId::Xor => {
767                let (val, buf) = TpmsSchemeXor::unmarshal(buf)?;
768                Ok((Self::Xor(val), buf))
769            }
770            TpmAlgId::Null => Ok((Self::Null, buf)),
771            _ => Err(TpmError::VariantNotAvailable(
772                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
773            )),
774        }
775    }
776}
777
778#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
779pub enum TpmuSigScheme {
780    Hash(TpmsSchemeHash),
781    Hmac(TpmsSchemeHmac),
782    #[default]
783    Null,
784}
785
786impl TpmTagged for TpmuSigScheme {
787    type Tag = TpmAlgId;
788    type Value = ();
789}
790
791impl TpmSized for TpmuSigScheme {
792    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
793    fn len(&self) -> usize {
794        match self {
795            Self::Hash(s) | Self::Hmac(s) => s.len(),
796            Self::Null => 0,
797        }
798    }
799}
800
801impl TpmMarshal for TpmuSigScheme {
802    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
803        match self {
804            Self::Hash(s) | Self::Hmac(s) => s.marshal(writer),
805            Self::Null => Ok(()),
806        }
807    }
808}
809
810impl TpmUnmarshalTagged for TpmuSigScheme {
811    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
812        match tag {
813            TpmAlgId::Hmac => {
814                let (val, buf) = TpmsSchemeHmac::unmarshal(buf)?;
815                Ok((Self::Hmac(val), buf))
816            }
817            TpmAlgId::Rsassa
818            | TpmAlgId::Rsapss
819            | TpmAlgId::Ecdsa
820            | TpmAlgId::Ecdaa
821            | TpmAlgId::Sm2
822            | TpmAlgId::Ecschnorr => {
823                let (val, buf) = TpmsSchemeHash::unmarshal(buf)?;
824                Ok((Self::Hash(val), buf))
825            }
826            TpmAlgId::Null => Ok((Self::Null, buf)),
827            _ => Err(TpmError::VariantNotAvailable(
828                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
829            )),
830        }
831    }
832}
833
834#[derive(Debug, PartialEq, Eq, Clone, Copy)]
835pub enum TpmuNvPublic2 {
836    NvIndex(TpmsNvPublic),
837    ExternalNv(TpmsNvPublicExpAttr),
838    PermanentNv(TpmsNvPublic),
839}
840
841impl TpmTagged for TpmuNvPublic2 {
842    type Tag = TpmHt;
843    type Value = ();
844}
845
846#[allow(clippy::match_same_arms)]
847impl TpmSized for TpmuNvPublic2 {
848    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
849    fn len(&self) -> usize {
850        match self {
851            Self::NvIndex(s) => s.len(),
852            Self::ExternalNv(s) => s.len(),
853            Self::PermanentNv(s) => s.len(),
854        }
855    }
856}
857
858impl TpmMarshal for TpmuNvPublic2 {
859    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
860        match self {
861            Self::ExternalNv(s) => s.marshal(writer),
862            Self::NvIndex(s) | Self::PermanentNv(s) => s.marshal(writer),
863        }
864    }
865}
866
867impl TpmUnmarshalTagged for TpmuNvPublic2 {
868    fn unmarshal_tagged(tag: TpmHt, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
869        match tag {
870            TpmHt::NvIndex => {
871                let (val, buf) = TpmsNvPublic::unmarshal(buf)?;
872                Ok((Self::NvIndex(val), buf))
873            }
874            TpmHt::ExternalNv => {
875                let (val, buf) = TpmsNvPublicExpAttr::unmarshal(buf)?;
876                Ok((Self::ExternalNv(val), buf))
877            }
878            TpmHt::PermanentNv => {
879                let (val, buf) = TpmsNvPublic::unmarshal(buf)?;
880                Ok((Self::PermanentNv(val), buf))
881            }
882            _ => Err(TpmError::VariantNotAvailable(
883                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
884            )),
885        }
886    }
887}
888
889#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
890pub enum TpmuKdfScheme {
891    Mgf1(TpmsSchemeHash),
892    Kdf1Sp800_56a(TpmsSchemeHash),
893    Kdf2(TpmsSchemeHash),
894    Kdf1Sp800_108(TpmsSchemeHash),
895    #[default]
896    Null,
897}
898
899impl TpmTagged for TpmuKdfScheme {
900    type Tag = TpmAlgId;
901    type Value = ();
902}
903
904impl TpmSized for TpmuKdfScheme {
905    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
906    fn len(&self) -> usize {
907        match self {
908            Self::Mgf1(s) | Self::Kdf1Sp800_56a(s) | Self::Kdf2(s) | Self::Kdf1Sp800_108(s) => {
909                s.len()
910            }
911            Self::Null => 0,
912        }
913    }
914}
915
916impl TpmMarshal for TpmuKdfScheme {
917    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
918        match self {
919            Self::Mgf1(s) | Self::Kdf1Sp800_56a(s) | Self::Kdf2(s) | Self::Kdf1Sp800_108(s) => {
920                s.marshal(writer)
921            }
922            Self::Null => Ok(()),
923        }
924    }
925}
926
927impl TpmUnmarshalTagged for TpmuKdfScheme {
928    fn unmarshal_tagged(tag: TpmAlgId, buf: &[u8]) -> TpmResult<(Self, &[u8])> {
929        match tag {
930            TpmAlgId::Mgf1 => {
931                let (val, buf) = TpmsSchemeHash::unmarshal(buf)?;
932                Ok((Self::Mgf1(val), buf))
933            }
934            TpmAlgId::Kdf1Sp800_56A => {
935                let (val, buf) = TpmsSchemeHash::unmarshal(buf)?;
936                Ok((Self::Kdf1Sp800_56a(val), buf))
937            }
938            TpmAlgId::Kdf2 => {
939                let (val, buf) = TpmsSchemeHash::unmarshal(buf)?;
940                Ok((Self::Kdf2(val), buf))
941            }
942            TpmAlgId::Kdf1Sp800_108 => {
943                let (val, buf) = TpmsSchemeHash::unmarshal(buf)?;
944                Ok((Self::Kdf1Sp800_108(val), buf))
945            }
946            TpmAlgId::Null => Ok((Self::Null, buf)),
947            _ => Err(TpmError::VariantNotAvailable(
948                crate::TpmErrorValue::new(0).value(u64::from(tag.value())),
949            )),
950        }
951    }
952}