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