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