1use crate::{
6 TpmError, TpmMarshal, TpmResult, TpmSized, 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
133tpm_struct! {
134 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
135 wire: TpmsAcOutputWire,
136 pub struct TpmsAcOutput {
137 pub tag: TpmAt,
138 pub data: TpmUint32,
139 }
140}
141
142tpm_struct! {
143 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
144 wire: TpmsActDataWire,
145 pub struct TpmsActData {
146 pub handle: TpmHandle,
147 pub timeout: TpmUint32,
148 pub attributes: TpmaAct,
149 }
150}
151
152tpm_struct! {
153 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
154 wire: TpmsAlgPropertyWire,
155 pub struct TpmsAlgProperty {
156 pub alg: TpmAlgId,
157 pub alg_properties: TpmaAlgorithm,
158 }
159}
160
161tpm_struct! {
162 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
163 wire: TpmsAuthCommandWire,
164 pub struct TpmsAuthCommand {
165 pub session_handle: TpmHandle,
166 pub nonce: Tpm2bNonce,
167 pub session_attributes: TpmaSession,
168 pub hmac: Tpm2bAuth,
169 }
170}
171
172tpm_struct! {
173 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
174 wire: TpmsAuthResponseWire,
175 pub struct TpmsAuthResponse {
176 pub nonce: Tpm2bNonce,
177 pub session_attributes: TpmaSession,
178 pub hmac: Tpm2bAuth,
179 }
180}
181
182#[derive(Debug, PartialEq, Eq, Clone)]
183pub struct TpmsCapabilityData {
184 pub capability: TpmCap,
185 pub data: TpmuCapabilities,
186}
187
188impl TpmSized for TpmsCapabilityData {
189 const SIZE: usize = size_of::<TpmUint32>() + TpmuCapabilities::SIZE;
190 fn len(&self) -> usize {
191 self.capability.len() + self.data.len()
192 }
193}
194
195impl TpmMarshal for TpmsCapabilityData {
196 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
197 self.capability.marshal(writer)?;
198 self.data.marshal(writer)
199 }
200}
201
202tpm_struct! {
203 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
204 wire: TpmsClockInfoWire,
205 pub struct TpmsClockInfo {
206 pub clock: TpmUint64,
207 pub reset_count: TpmUint32,
208 pub restart_count: TpmUint32,
209 pub safe: TpmiYesNo,
210 }
211}
212
213tpm_struct! {
214 #[derive(Debug, PartialEq, Eq, Clone)]
215 wire: TpmsContextWire,
216 pub struct TpmsContext {
217 pub sequence: TpmUint64,
218 pub saved_handle: TpmHandle,
219 pub hierarchy: TpmRh,
220 pub context_blob: Tpm2b,
221 }
222}
223
224tpm_struct! {
225 #[derive(Debug, PartialEq, Eq, Clone, Default)]
226 wire: TpmsCreationDataWire,
227 pub struct TpmsCreationData {
228 pub pcr_select: TpmlPcrSelection,
229 pub pcr_digest: Tpm2bDigest,
230 pub locality: TpmaLocality,
231 pub parent_name_alg: TpmAlgId,
232 pub parent_name: Tpm2bName,
233 pub parent_qualified_name: Tpm2bName,
234 pub outside_info: Tpm2bData,
235 }
236}
237
238tpm_struct! {
239 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
240 wire: TpmsEccPointWire,
241 pub struct TpmsEccPoint {
242 pub x: Tpm2bEccParameter,
243 pub y: Tpm2bEccParameter,
244 }
245}
246
247tpm_struct! {
248 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
249 wire: TpmsEmptyWire,
250 pub struct TpmsEmpty {}
251}
252
253tpm_struct! {
254 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
255 wire: TpmsKeyedhashParmsWire,
256 pub struct TpmsKeyedhashParms {
257 pub scheme: TpmtKeyedhashScheme,
258 }
259}
260
261tpm_struct! {
262 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
263 wire: TpmsNvPublicWire,
264 pub struct TpmsNvPublic {
265 pub nv_index: TpmHandle,
266 pub name_alg: TpmAlgId,
267 pub attributes: TpmaNv,
268 pub auth_policy: Tpm2bDigest,
269 pub data_size: TpmUint16,
270 }
271}
272
273tpm_struct! {
274 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
275 wire: TpmsNvPublicExpAttrWire,
276 pub struct TpmsNvPublicExpAttr {
277 pub nv_index: TpmiRhNvExpIndex,
278 pub name_alg: TpmAlgId,
279 pub attributes: TpmaNvExp,
280 pub auth_policy: Tpm2bDigest,
281 pub data_size: TpmUint16,
282 }
283}
284
285#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
286pub struct TpmsPcrSelection {
287 pub hash: TpmAlgId,
288 pub pcr_select: TpmsPcrSelect,
289}
290
291impl TpmSized for TpmsPcrSelection {
292 const SIZE: usize = TpmAlgId::SIZE + 1 + TPM_PCR_SELECT_MAX as usize;
293
294 fn len(&self) -> usize {
295 self.hash.len() + self.pcr_select.len()
296 }
297}
298
299impl TpmMarshal for TpmsPcrSelection {
300 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
301 self.hash.marshal(writer)?;
302 self.pcr_select.marshal(writer)
303 }
304}
305
306impl<'a> crate::TpmField<'a> for TpmsPcrSelection {
307 type View = (TpmAlgId, &'a [u8]);
308
309 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
310 let (hash, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
311 let (pcr_select, buf) = <TpmsPcrSelect as crate::TpmField>::cast_prefix_field(buf)?;
312
313 Ok(((hash, pcr_select), buf))
314 }
315}
316
317tpm_struct! {
318 #[derive(Debug, Default, PartialEq, Eq, Clone)]
319 wire: TpmsSensitiveCreateWire,
320 pub struct TpmsSensitiveCreate {
321 pub user_auth: Tpm2bAuth,
322 pub data: Tpm2bSensitiveData,
323 }
324}
325
326tpm_struct! {
327 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
328 wire: TpmsIdObjectWire,
329 pub struct TpmsIdObject {
330 pub integrity_hmac: Tpm2bDigest,
331 pub enc_identity: Tpm2bDigest,
332 }
333}
334
335tpm_struct! {
336 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
337 wire: TpmsSymcipherParmsWire,
338 pub struct TpmsSymcipherParms {
339 pub sym: TpmtSymDefObject,
340 }
341}
342
343tpm_struct! {
344 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
345 wire: TpmsTaggedPropertyWire,
346 pub struct TpmsTaggedProperty {
347 pub property: TpmPt,
348 pub value: TpmUint32,
349 }
350}
351
352tpm_struct! {
353 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
354 wire: TpmsTaggedPolicyWire,
355 pub struct TpmsTaggedPolicy {
356 pub handle: TpmHandle,
357 pub policy_hash: TpmtHa,
358 }
359}
360
361tpm_struct! {
362 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
363 wire: TpmsTimeInfoWire,
364 pub struct TpmsTimeInfo {
365 pub time: TpmUint64,
366 pub clock_info: TpmsClockInfo,
367 }
368}
369
370tpm_struct! {
371 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
372 wire: TpmsSignatureRsaWire,
373 pub struct TpmsSignatureRsa {
374 pub hash: TpmAlgId,
375 pub sig: crate::data::Tpm2bPublicKeyRsa,
376 }
377}
378
379tpm_struct! {
380 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
381 wire: TpmsSignatureEccWire,
382 pub struct TpmsSignatureEcc {
383 pub hash: TpmAlgId,
384 pub signature_r: Tpm2bEccParameter,
385 pub signature_s: Tpm2bEccParameter,
386 }
387}
388
389tpm_struct! {
390 #[derive(Debug, PartialEq, Eq, Clone, Default)]
391 wire: TpmsTimeAttestInfoWire,
392 pub struct TpmsTimeAttestInfo {
393 pub time: TpmsTimeInfo,
394 pub firmware_version: TpmUint64,
395 }
396}
397
398tpm_struct! {
399 #[derive(Debug, PartialEq, Eq, Clone, Default)]
400 wire: TpmsCertifyInfoWire,
401 pub struct TpmsCertifyInfo {
402 pub name: Tpm2bName,
403 pub qualified_name: Tpm2bName,
404 }
405}
406
407tpm_struct! {
408 #[derive(Debug, PartialEq, Eq, Clone, Default)]
409 wire: TpmsQuoteInfoWire,
410 pub struct TpmsQuoteInfo {
411 pub pcr_select: TpmlPcrSelection,
412 pub pcr_digest: Tpm2bDigest,
413 }
414}
415
416tpm_struct! {
417 #[derive(Debug, PartialEq, Eq, Clone, Default)]
418 wire: TpmsCommandAuditInfoWire,
419 pub struct TpmsCommandAuditInfo {
420 pub audit_counter: TpmUint64,
421 pub digest_alg: TpmAlgId,
422 pub audit_digest: Tpm2bDigest,
423 pub command_digest: Tpm2bDigest,
424 }
425}
426
427tpm_struct! {
428 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
429 wire: TpmsSessionAuditInfoWire,
430 pub struct TpmsSessionAuditInfo {
431 pub exclusive_session: TpmiYesNo,
432 pub session_digest: Tpm2bDigest,
433 }
434}
435
436tpm_struct! {
437 #[derive(Debug, PartialEq, Eq, Clone, Default)]
438 wire: TpmsCreationInfoWire,
439 pub struct TpmsCreationInfo {
440 pub object_name: Tpm2bName,
441 pub creation_hash: Tpm2bDigest,
442 }
443}
444
445tpm_struct! {
446 #[derive(Debug, PartialEq, Eq, Clone, Default)]
447 wire: TpmsNvCertifyInfoWire,
448 pub struct TpmsNvCertifyInfo {
449 pub index_name: Tpm2bName,
450 pub offset: TpmUint16,
451 pub nv_contents: Tpm2bMaxNvBuffer,
452 }
453}
454
455tpm_struct! {
456 #[derive(Debug, PartialEq, Eq, Clone, Default)]
457 wire: TpmsNvDigestCertifyInfoWire,
458 pub struct TpmsNvDigestCertifyInfo {
459 pub index_name: Tpm2bName,
460 pub nv_digest: Tpm2bDigest,
461 }
462}
463
464tpm_struct! {
465 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
466 wire: TpmsAlgorithmDetailEccWire,
467 pub struct TpmsAlgorithmDetailEcc {
468 pub curve_id: TpmEccCurve,
469 pub key_size: TpmUint16,
470 pub kdf: TpmtKdfScheme,
471 pub sign: TpmtEccScheme,
472 pub p: Tpm2bEccParameter,
473 pub a: Tpm2bEccParameter,
474 pub b: Tpm2bEccParameter,
475 pub gx: Tpm2bEccParameter,
476 pub gy: Tpm2bEccParameter,
477 pub n: Tpm2bEccParameter,
478 pub h: Tpm2bEccParameter,
479 }
480}
481
482#[derive(Debug, PartialEq, Eq, Clone)]
483pub struct TpmsAttest {
484 pub attest_type: TpmSt,
485 pub qualified_signer: Tpm2bName,
486 pub extra_data: Tpm2bData,
487 pub clock_info: TpmsClockInfo,
488 pub firmware_version: TpmUint64,
489 pub attested: TpmuAttest,
490}
491
492impl TpmSized for TpmsAttest {
493 const SIZE: usize = size_of::<TpmUint32>()
494 + TpmSt::SIZE
495 + Tpm2bName::SIZE
496 + Tpm2bData::SIZE
497 + TpmsClockInfo::SIZE
498 + size_of::<TpmUint64>()
499 + TpmuAttest::SIZE;
500 fn len(&self) -> usize {
501 size_of::<TpmUint32>()
502 + self.attest_type.len()
503 + self.qualified_signer.len()
504 + self.extra_data.len()
505 + self.clock_info.len()
506 + size_of::<TpmUint64>()
507 + self.attested.len()
508 }
509}
510
511impl TpmMarshal for TpmsAttest {
512 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
513 crate::basic::TpmUint32::from(TPM_GENERATED_VALUE).marshal(writer)?;
514 self.attest_type.marshal(writer)?;
515 self.qualified_signer.marshal(writer)?;
516 self.extra_data.marshal(writer)?;
517 self.clock_info.marshal(writer)?;
518 self.firmware_version.marshal(writer)?;
519 self.attested.marshal(writer)
520 }
521}
522
523pub struct TpmsAttestView<'a> {
529 pub attest_type: TpmSt,
531 pub qualified_signer: <Tpm2bName as crate::TpmField<'a>>::View,
533 pub extra_data: <Tpm2bData as crate::TpmField<'a>>::View,
535 pub clock_info: <TpmsClockInfo as crate::TpmField<'a>>::View,
537 pub firmware_version: u64,
539 pub attested: TpmuAttestView<'a>,
541}
542
543impl<'a> crate::TpmField<'a> for TpmsAttest {
544 type View = TpmsAttestView<'a>;
545
546 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
547 let (magic, buf) = <TpmUint32 as crate::TpmField>::cast_prefix_field(buf)?;
548 if magic.value() != TPM_GENERATED_VALUE {
549 return Err(TpmError::InvalidMagicNumber {
550 offset: 0,
551 value: u64::from(magic.value()),
552 });
553 }
554
555 let (attest_type, buf) = <TpmSt as crate::TpmField>::cast_prefix_field(buf)?;
556 let (qualified_signer, buf) = <Tpm2bName as crate::TpmField>::cast_prefix_field(buf)?;
557 let (extra_data, buf) = <Tpm2bData as crate::TpmField>::cast_prefix_field(buf)?;
558 let (clock_info, buf) = <TpmsClockInfo as crate::TpmField>::cast_prefix_field(buf)?;
559 let (firmware_version, buf) = <TpmUint64 as crate::TpmField>::cast_prefix_field(buf)?;
560 let (attested, buf) = TpmuAttest::cast_tagged(attest_type, buf)?;
561
562 Ok((
563 TpmsAttestView {
564 attest_type,
565 qualified_signer,
566 extra_data,
567 clock_info,
568 firmware_version: firmware_version.value(),
569 attested,
570 },
571 buf,
572 ))
573 }
574}
575
576tpm_struct! {
577 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
578 wire: TpmsSchemeHashWire,
579 pub struct TpmsSchemeHash {
580 pub hash_alg: TpmiAlgHash,
581 }
582}
583
584pub type TpmsSchemeHmac = TpmsSchemeHash;
585
586tpm_struct! {
587 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
588 wire: TpmsSchemeXorWire,
589 pub struct TpmsSchemeXor {
590 pub hash_alg: TpmiAlgHash,
591 pub kdf: TpmtKdfScheme,
592 }
593}
594
595tpm_struct! {
596 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
597 wire: TpmsRsaParmsWire,
598 pub struct TpmsRsaParms {
599 pub symmetric: TpmtSymDefObject,
600 pub scheme: TpmtRsaScheme,
601 pub key_bits: TpmUint16,
602 pub exponent: TpmUint32,
603 }
604}
605
606tpm_struct! {
607 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
608 wire: TpmsEccParmsWire,
609 pub struct TpmsEccParms {
610 pub symmetric: TpmtSymDefObject,
611 pub scheme: TpmtEccScheme,
612 pub curve_id: TpmEccCurve,
613 pub kdf: TpmtKdfScheme,
614 }
615}