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