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