1use crate::{
6 TpmError, TpmMarshal, TpmResult, TpmSized, TpmUnmarshal, TpmUnmarshalTagged, TpmWriter,
7 basic::{TpmHandle, TpmUint8, TpmUint16, TpmUint32, TpmUint64},
8 constant::{TPM_GENERATED_VALUE, TPM_PCR_SELECT_MAX},
9 data::{
10 Tpm2b, Tpm2bAuth, Tpm2bData, Tpm2bDigest, Tpm2bEccParameter, Tpm2bMaxNvBuffer, Tpm2bName,
11 Tpm2bNonce, Tpm2bSensitiveData, TpmAlgId, TpmAt, TpmCap, TpmEccCurve, TpmPt, TpmRh, TpmSt,
12 TpmaAct, TpmaAlgorithm, TpmaLocality, TpmaNv, TpmaNvExp, TpmaSession, TpmiAlgHash,
13 TpmiRhNvExpIndex, TpmiYesNo, TpmlPcrSelection, TpmtEccScheme, TpmtHa, TpmtKdfScheme,
14 TpmtKeyedhashScheme, TpmtRsaScheme, TpmtSymDefObject, TpmuAttest, TpmuAttestView,
15 TpmuCapabilities,
16 },
17 tpm_struct,
18};
19use core::{
20 convert::TryFrom,
21 fmt::{Debug, Formatter},
22 mem::size_of,
23 ops::Deref,
24};
25
26#[derive(Clone, Copy, PartialEq, Eq)]
28pub struct TpmsPcrSelect {
29 size: TpmUint8,
30 data: [u8; TPM_PCR_SELECT_MAX as usize],
31}
32
33impl TpmsPcrSelect {
34 #[must_use]
36 pub const fn new() -> Self {
37 Self {
38 size: TpmUint8::new(0),
39 data: [0; TPM_PCR_SELECT_MAX as usize],
40 }
41 }
42}
43
44impl Default for TpmsPcrSelect {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl Deref for TpmsPcrSelect {
51 type Target = [u8];
52
53 fn deref(&self) -> &Self::Target {
54 &self.data[..u8::from(self.size) as usize]
55 }
56}
57
58impl TryFrom<&[u8]> for TpmsPcrSelect {
59 type Error = TpmError;
60
61 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
62 if slice.len() > TPM_PCR_SELECT_MAX as usize {
63 return Err(TpmError::TooManyItems {
64 offset: 0,
65 limit: TPM_PCR_SELECT_MAX as usize,
66 actual: slice.len(),
67 });
68 }
69 let mut pcr_select = Self::new();
70 let len_u8 = u8::try_from(slice.len()).map_err(|_| TpmError::IntegerTooLarge {
71 offset: 0,
72 value: crate::tpm_value(slice.len()),
73 })?;
74 pcr_select.size = TpmUint8::from(len_u8);
75 pcr_select.data[..slice.len()].copy_from_slice(slice);
76 Ok(pcr_select)
77 }
78}
79
80impl Debug for TpmsPcrSelect {
81 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
82 write!(f, "TpmsPcrSelect(")?;
83 for byte in self.iter() {
84 write!(f, "{byte:02X}")?;
85 }
86 write!(f, ")")
87 }
88}
89
90impl TpmSized for TpmsPcrSelect {
91 const SIZE: usize = size_of::<TpmUint8>() + TPM_PCR_SELECT_MAX as usize;
92
93 fn len(&self) -> usize {
94 size_of::<TpmUint8>() + u8::from(self.size) as usize
95 }
96}
97
98impl TpmMarshal for TpmsPcrSelect {
99 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
100 self.size.marshal(writer)?;
101 writer.write_bytes(self)
102 }
103}
104
105impl<'a> crate::TpmField<'a> for TpmsPcrSelect {
106 type View = &'a [u8];
107
108 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
109 let (size, remainder) = <TpmUint8 as crate::TpmCast>::cast_prefix(buf)?;
110 let size = size.value() as usize;
111
112 if size > TPM_PCR_SELECT_MAX as usize {
113 return Err(TpmError::TooManyItems {
114 offset: 0,
115 limit: TPM_PCR_SELECT_MAX as usize,
116 actual: size,
117 });
118 }
119
120 if remainder.len() < size {
121 return Err(TpmError::UnexpectedEnd {
122 offset: size_of::<TpmUint8>(),
123 needed: size,
124 available: remainder.len(),
125 });
126 }
127
128 let (pcr_select, remainder) = remainder.split_at(size);
129 Ok((pcr_select, remainder))
130 }
131}
132
133impl TpmUnmarshal for TpmsPcrSelect {
134 fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
135 let (value, remainder) = <Self as crate::TpmField>::cast_prefix_field(buffer)?;
136 Ok((Self::try_from(value)?, remainder))
137 }
138}
139
140tpm_struct! {
141 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
142 wire: TpmsAcOutputWire,
143 pub struct TpmsAcOutput {
144 pub tag: TpmAt,
145 pub data: TpmUint32,
146 }
147}
148
149tpm_struct! {
150 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
151 wire: TpmsActDataWire,
152 pub struct TpmsActData {
153 pub handle: TpmHandle,
154 pub timeout: TpmUint32,
155 pub attributes: TpmaAct,
156 }
157}
158
159tpm_struct! {
160 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
161 wire: TpmsAlgPropertyWire,
162 pub struct TpmsAlgProperty {
163 pub alg: TpmAlgId,
164 pub alg_properties: TpmaAlgorithm,
165 }
166}
167
168tpm_struct! {
169 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
170 wire: TpmsAuthCommandWire,
171 pub struct TpmsAuthCommand {
172 pub session_handle: TpmHandle,
173 pub nonce: Tpm2bNonce,
174 pub session_attributes: TpmaSession,
175 pub hmac: Tpm2bAuth,
176 }
177}
178
179tpm_struct! {
180 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
181 wire: TpmsAuthResponseWire,
182 pub struct TpmsAuthResponse {
183 pub nonce: Tpm2bNonce,
184 pub session_attributes: TpmaSession,
185 pub hmac: Tpm2bAuth,
186 }
187}
188
189#[derive(Debug, PartialEq, Eq, Clone)]
190pub struct TpmsCapabilityData {
191 pub capability: TpmCap,
192 pub data: TpmuCapabilities,
193}
194
195impl TpmSized for TpmsCapabilityData {
196 const SIZE: usize = size_of::<TpmUint32>() + TpmuCapabilities::SIZE;
197 fn len(&self) -> usize {
198 self.capability.len() + self.data.len()
199 }
200}
201
202impl TpmMarshal for TpmsCapabilityData {
203 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
204 self.capability.marshal(writer)?;
205 self.data.marshal(writer)
206 }
207}
208
209impl TpmUnmarshal for TpmsCapabilityData {
210 fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
211 let (capability, buffer) = TpmCap::unmarshal(buffer)?;
212 let (data, buffer) = TpmuCapabilities::unmarshal_tagged(capability, buffer)?;
213 Ok((Self { capability, data }, buffer))
214 }
215}
216
217tpm_struct! {
218 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
219 wire: TpmsClockInfoWire,
220 pub struct TpmsClockInfo {
221 pub clock: TpmUint64,
222 pub reset_count: TpmUint32,
223 pub restart_count: TpmUint32,
224 pub safe: TpmiYesNo,
225 }
226}
227
228tpm_struct! {
229 #[derive(Debug, PartialEq, Eq, Clone)]
230 wire: TpmsContextWire,
231 pub struct TpmsContext {
232 pub sequence: TpmUint64,
233 pub saved_handle: TpmHandle,
234 pub hierarchy: TpmRh,
235 pub context_blob: Tpm2b,
236 }
237}
238
239tpm_struct! {
240 #[derive(Debug, PartialEq, Eq, Clone, Default)]
241 wire: TpmsCreationDataWire,
242 pub struct TpmsCreationData {
243 pub pcr_select: TpmlPcrSelection,
244 pub pcr_digest: Tpm2bDigest,
245 pub locality: TpmaLocality,
246 pub parent_name_alg: TpmAlgId,
247 pub parent_name: Tpm2bName,
248 pub parent_qualified_name: Tpm2bName,
249 pub outside_info: Tpm2bData,
250 }
251}
252
253tpm_struct! {
254 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
255 wire: TpmsEccPointWire,
256 pub struct TpmsEccPoint {
257 pub x: Tpm2bEccParameter,
258 pub y: Tpm2bEccParameter,
259 }
260}
261
262tpm_struct! {
263 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
264 wire: TpmsEmptyWire,
265 pub struct TpmsEmpty {}
266}
267
268tpm_struct! {
269 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
270 wire: TpmsKeyedhashParmsWire,
271 pub struct TpmsKeyedhashParms {
272 pub scheme: TpmtKeyedhashScheme,
273 }
274}
275
276tpm_struct! {
277 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
278 wire: TpmsNvPublicWire,
279 pub struct TpmsNvPublic {
280 pub nv_index: TpmHandle,
281 pub name_alg: TpmAlgId,
282 pub attributes: TpmaNv,
283 pub auth_policy: Tpm2bDigest,
284 pub data_size: TpmUint16,
285 }
286}
287
288tpm_struct! {
289 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
290 wire: TpmsNvPublicExpAttrWire,
291 pub struct TpmsNvPublicExpAttr {
292 pub nv_index: TpmiRhNvExpIndex,
293 pub name_alg: TpmAlgId,
294 pub attributes: TpmaNvExp,
295 pub auth_policy: Tpm2bDigest,
296 pub data_size: TpmUint16,
297 }
298}
299
300#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
301pub struct TpmsPcrSelection {
302 pub hash: TpmAlgId,
303 pub pcr_select: TpmsPcrSelect,
304}
305
306impl TpmSized for TpmsPcrSelection {
307 const SIZE: usize = TpmAlgId::SIZE + 1 + TPM_PCR_SELECT_MAX as usize;
308
309 fn len(&self) -> usize {
310 self.hash.len() + self.pcr_select.len()
311 }
312}
313
314impl TpmMarshal for TpmsPcrSelection {
315 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
316 self.hash.marshal(writer)?;
317 self.pcr_select.marshal(writer)
318 }
319}
320
321impl<'a> crate::TpmField<'a> for TpmsPcrSelection {
322 type View = (TpmAlgId, &'a [u8]);
323
324 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
325 let (hash, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
326 let (pcr_select, buf) = <TpmsPcrSelect as crate::TpmField>::cast_prefix_field(buf)?;
327
328 Ok(((hash, pcr_select), buf))
329 }
330}
331
332impl TpmUnmarshal for TpmsPcrSelection {
333 fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
334 let (hash, buffer) = TpmAlgId::unmarshal(buffer)?;
335 let (pcr_select, buffer) = TpmsPcrSelect::unmarshal(buffer)?;
336 Ok((Self { hash, pcr_select }, buffer))
337 }
338}
339
340tpm_struct! {
341 #[derive(Debug, Default, PartialEq, Eq, Clone)]
342 wire: TpmsSensitiveCreateWire,
343 pub struct TpmsSensitiveCreate {
344 pub user_auth: Tpm2bAuth,
345 pub data: Tpm2bSensitiveData,
346 }
347}
348
349tpm_struct! {
350 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
351 wire: TpmsIdObjectWire,
352 pub struct TpmsIdObject {
353 pub integrity_hmac: Tpm2bDigest,
354 pub enc_identity: Tpm2bDigest,
355 }
356}
357
358tpm_struct! {
359 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
360 wire: TpmsSymcipherParmsWire,
361 pub struct TpmsSymcipherParms {
362 pub sym: TpmtSymDefObject,
363 }
364}
365
366tpm_struct! {
367 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
368 wire: TpmsTaggedPropertyWire,
369 pub struct TpmsTaggedProperty {
370 pub property: TpmPt,
371 pub value: TpmUint32,
372 }
373}
374
375tpm_struct! {
376 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
377 wire: TpmsTaggedPolicyWire,
378 pub struct TpmsTaggedPolicy {
379 pub handle: TpmHandle,
380 pub policy_hash: TpmtHa,
381 }
382}
383
384tpm_struct! {
385 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
386 wire: TpmsTimeInfoWire,
387 pub struct TpmsTimeInfo {
388 pub time: TpmUint64,
389 pub clock_info: TpmsClockInfo,
390 }
391}
392
393tpm_struct! {
394 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
395 wire: TpmsSignatureRsaWire,
396 pub struct TpmsSignatureRsa {
397 pub hash: TpmAlgId,
398 pub sig: crate::data::Tpm2bPublicKeyRsa,
399 }
400}
401
402tpm_struct! {
403 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
404 wire: TpmsSignatureEccWire,
405 pub struct TpmsSignatureEcc {
406 pub hash: TpmAlgId,
407 pub signature_r: Tpm2bEccParameter,
408 pub signature_s: Tpm2bEccParameter,
409 }
410}
411
412tpm_struct! {
413 #[derive(Debug, PartialEq, Eq, Clone, Default)]
414 wire: TpmsTimeAttestInfoWire,
415 pub struct TpmsTimeAttestInfo {
416 pub time: TpmsTimeInfo,
417 pub firmware_version: TpmUint64,
418 }
419}
420
421tpm_struct! {
422 #[derive(Debug, PartialEq, Eq, Clone, Default)]
423 wire: TpmsCertifyInfoWire,
424 pub struct TpmsCertifyInfo {
425 pub name: Tpm2bName,
426 pub qualified_name: Tpm2bName,
427 }
428}
429
430tpm_struct! {
431 #[derive(Debug, PartialEq, Eq, Clone, Default)]
432 wire: TpmsQuoteInfoWire,
433 pub struct TpmsQuoteInfo {
434 pub pcr_select: TpmlPcrSelection,
435 pub pcr_digest: Tpm2bDigest,
436 }
437}
438
439tpm_struct! {
440 #[derive(Debug, PartialEq, Eq, Clone, Default)]
441 wire: TpmsCommandAuditInfoWire,
442 pub struct TpmsCommandAuditInfo {
443 pub audit_counter: TpmUint64,
444 pub digest_alg: TpmAlgId,
445 pub audit_digest: Tpm2bDigest,
446 pub command_digest: Tpm2bDigest,
447 }
448}
449
450tpm_struct! {
451 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
452 wire: TpmsSessionAuditInfoWire,
453 pub struct TpmsSessionAuditInfo {
454 pub exclusive_session: TpmiYesNo,
455 pub session_digest: Tpm2bDigest,
456 }
457}
458
459tpm_struct! {
460 #[derive(Debug, PartialEq, Eq, Clone, Default)]
461 wire: TpmsCreationInfoWire,
462 pub struct TpmsCreationInfo {
463 pub object_name: Tpm2bName,
464 pub creation_hash: Tpm2bDigest,
465 }
466}
467
468tpm_struct! {
469 #[derive(Debug, PartialEq, Eq, Clone, Default)]
470 wire: TpmsNvCertifyInfoWire,
471 pub struct TpmsNvCertifyInfo {
472 pub index_name: Tpm2bName,
473 pub offset: TpmUint16,
474 pub nv_contents: Tpm2bMaxNvBuffer,
475 }
476}
477
478tpm_struct! {
479 #[derive(Debug, PartialEq, Eq, Clone, Default)]
480 wire: TpmsNvDigestCertifyInfoWire,
481 pub struct TpmsNvDigestCertifyInfo {
482 pub index_name: Tpm2bName,
483 pub nv_digest: Tpm2bDigest,
484 }
485}
486
487tpm_struct! {
488 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
489 wire: TpmsAlgorithmDetailEccWire,
490 pub struct TpmsAlgorithmDetailEcc {
491 pub curve_id: TpmEccCurve,
492 pub key_size: TpmUint16,
493 pub kdf: TpmtKdfScheme,
494 pub sign: TpmtEccScheme,
495 pub p: Tpm2bEccParameter,
496 pub a: Tpm2bEccParameter,
497 pub b: Tpm2bEccParameter,
498 pub gx: Tpm2bEccParameter,
499 pub gy: Tpm2bEccParameter,
500 pub n: Tpm2bEccParameter,
501 pub h: Tpm2bEccParameter,
502 }
503}
504
505#[derive(Debug, PartialEq, Eq, Clone)]
506pub struct TpmsAttest {
507 pub attest_type: TpmSt,
508 pub qualified_signer: Tpm2bName,
509 pub extra_data: Tpm2bData,
510 pub clock_info: TpmsClockInfo,
511 pub firmware_version: TpmUint64,
512 pub attested: TpmuAttest,
513}
514
515impl TpmSized for TpmsAttest {
516 const SIZE: usize = size_of::<TpmUint32>()
517 + TpmSt::SIZE
518 + Tpm2bName::SIZE
519 + Tpm2bData::SIZE
520 + TpmsClockInfo::SIZE
521 + size_of::<TpmUint64>()
522 + TpmuAttest::SIZE;
523 fn len(&self) -> usize {
524 size_of::<TpmUint32>()
525 + self.attest_type.len()
526 + self.qualified_signer.len()
527 + self.extra_data.len()
528 + self.clock_info.len()
529 + size_of::<TpmUint64>()
530 + self.attested.len()
531 }
532}
533
534impl TpmMarshal for TpmsAttest {
535 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
536 crate::basic::TpmUint32::from(TPM_GENERATED_VALUE).marshal(writer)?;
537 self.attest_type.marshal(writer)?;
538 self.qualified_signer.marshal(writer)?;
539 self.extra_data.marshal(writer)?;
540 self.clock_info.marshal(writer)?;
541 self.firmware_version.marshal(writer)?;
542 self.attested.marshal(writer)
543 }
544}
545
546impl TpmUnmarshal for TpmsAttest {
547 fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
548 let (magic, buffer) = TpmUint32::unmarshal(buffer)?;
549 if magic.value() != TPM_GENERATED_VALUE {
550 return Err(TpmError::InvalidMagicNumber {
551 offset: 0,
552 value: u64::from(magic.value()),
553 });
554 }
555
556 let (attest_type, buffer) = TpmSt::unmarshal(buffer)?;
557 let (qualified_signer, buffer) = Tpm2bName::unmarshal(buffer)?;
558 let (extra_data, buffer) = Tpm2bData::unmarshal(buffer)?;
559 let (clock_info, buffer) = TpmsClockInfo::unmarshal(buffer)?;
560 let (firmware_version, buffer) = TpmUint64::unmarshal(buffer)?;
561 let (attested, buffer) = TpmuAttest::unmarshal_tagged(attest_type, buffer)?;
562
563 Ok((
564 Self {
565 attest_type,
566 qualified_signer,
567 extra_data,
568 clock_info,
569 firmware_version,
570 attested,
571 },
572 buffer,
573 ))
574 }
575}
576
577pub struct TpmsAttestView<'a> {
583 pub attest_type: TpmSt,
585 pub qualified_signer: <Tpm2bName as crate::TpmField<'a>>::View,
587 pub extra_data: <Tpm2bData as crate::TpmField<'a>>::View,
589 pub clock_info: <TpmsClockInfo as crate::TpmField<'a>>::View,
591 pub firmware_version: u64,
593 pub attested: TpmuAttestView<'a>,
595}
596
597impl<'a> crate::TpmField<'a> for TpmsAttest {
598 type View = TpmsAttestView<'a>;
599
600 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
601 let (magic, buf) = <TpmUint32 as crate::TpmField>::cast_prefix_field(buf)?;
602 if magic.value() != TPM_GENERATED_VALUE {
603 return Err(TpmError::InvalidMagicNumber {
604 offset: 0,
605 value: u64::from(magic.value()),
606 });
607 }
608
609 let (attest_type, buf) = <TpmSt as crate::TpmField>::cast_prefix_field(buf)?;
610 let (qualified_signer, buf) = <Tpm2bName as crate::TpmField>::cast_prefix_field(buf)?;
611 let (extra_data, buf) = <Tpm2bData as crate::TpmField>::cast_prefix_field(buf)?;
612 let (clock_info, buf) = <TpmsClockInfo as crate::TpmField>::cast_prefix_field(buf)?;
613 let (firmware_version, buf) = <TpmUint64 as crate::TpmField>::cast_prefix_field(buf)?;
614 let (attested, buf) = TpmuAttest::cast_tagged(attest_type, buf)?;
615
616 Ok((
617 TpmsAttestView {
618 attest_type,
619 qualified_signer,
620 extra_data,
621 clock_info,
622 firmware_version: firmware_version.value(),
623 attested,
624 },
625 buf,
626 ))
627 }
628}
629
630tpm_struct! {
631 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
632 wire: TpmsSchemeHashWire,
633 pub struct TpmsSchemeHash {
634 pub hash_alg: TpmiAlgHash,
635 }
636}
637
638pub type TpmsSchemeHmac = TpmsSchemeHash;
639
640tpm_struct! {
641 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
642 wire: TpmsSchemeXorWire,
643 pub struct TpmsSchemeXor {
644 pub hash_alg: TpmiAlgHash,
645 pub kdf: TpmtKdfScheme,
646 }
647}
648
649tpm_struct! {
650 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
651 wire: TpmsRsaParmsWire,
652 pub struct TpmsRsaParms {
653 pub symmetric: TpmtSymDefObject,
654 pub scheme: TpmtRsaScheme,
655 pub key_bits: TpmUint16,
656 pub exponent: TpmUint32,
657 }
658}
659
660tpm_struct! {
661 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
662 wire: TpmsEccParmsWire,
663 pub struct TpmsEccParms {
664 pub symmetric: TpmtSymDefObject,
665 pub scheme: TpmtEccScheme,
666 pub curve_id: TpmEccCurve,
667 pub kdf: TpmtKdfScheme,
668 }
669}