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