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