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