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