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