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