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