1use crate::{
6 constant::TPM_GENERATED_VALUE,
7 constant::TPM_PCR_SELECT_MAX,
8 data::{
9 Tpm2b, Tpm2bAuth, Tpm2bData, Tpm2bDigest, Tpm2bEccParameter, Tpm2bMaxNvBuffer, Tpm2bName,
10 Tpm2bNonce, Tpm2bSensitiveData, TpmAlgId, TpmAt, TpmCap, TpmEccCurve, TpmPt, TpmRh, TpmSt,
11 TpmaAlgorithm, TpmaLocality, TpmaNv, TpmaNvExp, TpmaSession, TpmiAlgHash, TpmiRhNvExpIndex,
12 TpmiYesNo, TpmlAlgProperty, TpmlCca, TpmlEccCurve, TpmlHandle, TpmlPcrSelection,
13 TpmlTaggedTpmProperty, TpmtEccScheme, TpmtKdfScheme, TpmtKeyedhashScheme, TpmtRsaScheme,
14 TpmtSymDefObject, TpmuAttest, TpmuCapabilities,
15 },
16 tpm_struct, TpmBuild, TpmError, TpmHandle, TpmParse, TpmResult, TpmSized, TpmWriter,
17};
18use core::{
19 convert::TryFrom,
20 fmt::{Debug, Formatter},
21 mem::size_of,
22 ops::Deref,
23};
24
25#[derive(Clone, Copy, PartialEq, Eq)]
27pub struct TpmsPcrSelect {
28 size: u8,
29 data: [u8; TPM_PCR_SELECT_MAX],
30}
31
32impl TpmsPcrSelect {
33 #[must_use]
35 pub const fn new() -> Self {
36 Self {
37 size: 0,
38 data: [0; TPM_PCR_SELECT_MAX],
39 }
40 }
41}
42
43impl Default for TpmsPcrSelect {
44 fn default() -> Self {
45 Self::new()
46 }
47}
48
49impl Deref for TpmsPcrSelect {
50 type Target = [u8];
51
52 fn deref(&self) -> &Self::Target {
53 &self.data[..self.size as usize]
54 }
55}
56
57impl TryFrom<&[u8]> for TpmsPcrSelect {
58 type Error = TpmError;
59
60 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
61 if slice.len() > TPM_PCR_SELECT_MAX {
62 return Err(TpmError::CapacityExceeded);
63 }
64 let mut pcr_select = Self::new();
65 let len_u8 = u8::try_from(slice.len())?;
66 pcr_select.size = len_u8;
67 pcr_select.data[..slice.len()].copy_from_slice(slice);
68 Ok(pcr_select)
69 }
70}
71
72impl Debug for TpmsPcrSelect {
73 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
74 write!(f, "TpmsPcrSelect(")?;
75 for byte in self.iter() {
76 write!(f, "{byte:02X}")?;
77 }
78 write!(f, ")")
79 }
80}
81
82impl TpmSized for TpmsPcrSelect {
83 const SIZE: usize = size_of::<u8>() + TPM_PCR_SELECT_MAX;
84
85 fn len(&self) -> usize {
86 size_of::<u8>() + self.size as usize
87 }
88}
89
90impl TpmBuild for TpmsPcrSelect {
91 fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
92 self.size.build(writer)?;
93 writer.write_bytes(self)
94 }
95}
96
97impl TpmParse for TpmsPcrSelect {
98 fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
99 let (size, remainder) = u8::parse(buf)?;
100 let size_usize = size as usize;
101
102 if size_usize > TPM_PCR_SELECT_MAX {
103 return Err(TpmError::CapacityExceeded);
104 }
105 if remainder.len() < size_usize {
106 return Err(TpmError::DataTruncated);
107 }
108
109 let (pcr_bytes, final_remainder) = remainder.split_at(size_usize);
110 let pcr_select = Self::try_from(pcr_bytes)?;
111 Ok((pcr_select, final_remainder))
112 }
113}
114
115tpm_struct! {
116 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
117 pub struct TpmsAcOutput {
118 pub tag: TpmAt,
119 pub data: u32,
120 }
121}
122
123tpm_struct! {
124 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
125 pub struct TpmsAlgProperty {
126 pub alg: TpmAlgId,
127 pub alg_properties: TpmaAlgorithm,
128 }
129}
130
131tpm_struct! {
132 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
133 pub struct TpmsAuthCommand {
134 pub session_handle: TpmHandle,
135 pub nonce: Tpm2bNonce,
136 pub session_attributes: TpmaSession,
137 pub hmac: Tpm2bAuth,
138 }
139}
140
141tpm_struct! {
142 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
143 pub struct TpmsAuthResponse {
144 pub nonce: Tpm2bNonce,
145 pub session_attributes: TpmaSession,
146 pub hmac: Tpm2bAuth,
147 }
148}
149
150#[derive(Debug, PartialEq, Eq, Clone)]
151pub struct TpmsCapabilityData {
152 pub capability: TpmCap,
153 pub data: TpmuCapabilities,
154}
155
156impl TpmSized for TpmsCapabilityData {
157 const SIZE: usize = size_of::<u32>() + TpmuCapabilities::SIZE;
158 fn len(&self) -> usize {
159 self.capability.len() + self.data.len()
160 }
161}
162
163impl TpmBuild for TpmsCapabilityData {
164 fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
165 self.capability.build(writer)?;
166 self.data.build(writer)
167 }
168}
169
170impl TpmParse for TpmsCapabilityData {
171 fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
172 let (capability, buf) = TpmCap::parse(buf)?;
173 let (data, buf) = match capability {
174 TpmCap::Algs => {
175 let (algs, buf) = TpmlAlgProperty::parse(buf)?;
176 (TpmuCapabilities::Algs(algs), buf)
177 }
178 TpmCap::Handles => {
179 let (handles, buf) = TpmlHandle::parse(buf)?;
180 (TpmuCapabilities::Handles(handles), buf)
181 }
182 TpmCap::Pcrs => {
183 let (pcrs, buf) = TpmlPcrSelection::parse(buf)?;
184 (TpmuCapabilities::Pcrs(pcrs), buf)
185 }
186 TpmCap::Commands => {
187 let (cmds, buf) = TpmlCca::parse(buf)?;
188 (TpmuCapabilities::Commands(cmds), buf)
189 }
190 TpmCap::TpmProperties => {
191 let (props, buf) = TpmlTaggedTpmProperty::parse(buf)?;
192 (TpmuCapabilities::TpmProperties(props), buf)
193 }
194 TpmCap::EccCurves => {
195 let (curves, buf) = TpmlEccCurve::parse(buf)?;
196 (TpmuCapabilities::EccCurves(curves), buf)
197 }
198 };
199 Ok((Self { capability, data }, buf))
200 }
201}
202
203tpm_struct! {
204 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
205 pub struct TpmsClockInfo {
206 pub clock: u64,
207 pub reset_count: u32,
208 pub restart_count: u32,
209 pub safe: TpmiYesNo,
210 }
211}
212
213tpm_struct! {
214 #[derive(Debug, PartialEq, Eq, Clone)]
215 pub struct TpmsContext {
216 pub sequence: u64,
217 pub saved_handle: TpmHandle,
218 pub hierarchy: TpmRh,
219 pub context_blob: Tpm2b,
220 }
221}
222
223tpm_struct! {
224 #[derive(Debug, PartialEq, Eq, Clone, Default)]
225 pub struct TpmsCreationData {
226 pub pcr_select: TpmlPcrSelection,
227 pub pcr_digest: Tpm2bDigest,
228 pub locality: TpmaLocality,
229 pub parent_name_alg: TpmAlgId,
230 pub parent_name: Tpm2bName,
231 pub parent_qualified_name: Tpm2bName,
232 pub outside_info: Tpm2bData,
233 }
234}
235
236tpm_struct! {
237 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
238 pub struct TpmsEccPoint {
239 pub x: Tpm2bEccParameter,
240 pub y: Tpm2bEccParameter,
241 }
242}
243
244tpm_struct! {
245 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
246 pub struct TpmsEmpty {}
247}
248
249tpm_struct! {
250 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
251 pub struct TpmsKeyedhashParms {
252 pub scheme: TpmtKeyedhashScheme,
253 }
254}
255
256tpm_struct! {
257 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
258 pub struct TpmsNvPublic {
259 pub nv_index: TpmHandle,
260 pub name_alg: TpmAlgId,
261 pub attributes: TpmaNv,
262 pub auth_policy: Tpm2bDigest,
263 pub data_size: u16,
264 }
265}
266
267tpm_struct! {
268 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
269 pub struct TpmsNvPublicExpAttr {
270 pub nv_index: TpmiRhNvExpIndex,
271 pub name_alg: TpmAlgId,
272 pub attributes: TpmaNvExp,
273 pub auth_policy: Tpm2bDigest,
274 pub data_size: u16,
275 }
276}
277
278#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
279pub struct TpmsPcrSelection {
280 pub hash: TpmAlgId,
281 pub pcr_select: TpmsPcrSelect,
282}
283
284impl TpmSized for TpmsPcrSelection {
285 const SIZE: usize = TpmAlgId::SIZE + 1 + TPM_PCR_SELECT_MAX;
286
287 fn len(&self) -> usize {
288 self.hash.len() + self.pcr_select.len()
289 }
290}
291
292impl TpmBuild for TpmsPcrSelection {
293 fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
294 self.hash.build(writer)?;
295 self.pcr_select.build(writer)
296 }
297}
298
299impl TpmParse for TpmsPcrSelection {
300 fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
301 let (hash, buf) = TpmAlgId::parse(buf)?;
302 let (pcr_select, buf) = TpmsPcrSelect::parse(buf)?;
303 Ok((Self { hash, pcr_select }, buf))
304 }
305}
306
307tpm_struct! {
308 #[derive(Debug, Default, PartialEq, Eq, Clone)]
309 pub struct TpmsSensitiveCreate {
310 pub user_auth: Tpm2bAuth,
311 pub data: Tpm2bSensitiveData,
312 }
313}
314
315tpm_struct! {
316 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
317 pub struct TpmsIdObject {
318 pub integrity_hmac: Tpm2bDigest,
319 pub enc_identity: Tpm2bDigest,
320 }
321}
322
323tpm_struct! {
324 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
325 pub struct TpmsSymcipherParms {
326 pub sym: TpmtSymDefObject,
327 }
328}
329
330tpm_struct! {
331 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
332 pub struct TpmsTaggedProperty {
333 pub property: TpmPt,
334 pub value: u32,
335 }
336}
337
338tpm_struct! {
339 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
340 pub struct TpmsTimeInfo {
341 pub time: u64,
342 pub clock_info: TpmsClockInfo,
343 }
344}
345
346tpm_struct! {
347 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
348 pub struct TpmsSignatureRsa {
349 pub hash: TpmAlgId,
350 pub sig: crate::data::Tpm2bPublicKeyRsa,
351 }
352}
353
354tpm_struct! {
355 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
356 pub struct TpmsSignatureEcc {
357 pub hash: TpmAlgId,
358 pub signature_r: Tpm2bEccParameter,
359 pub signature_s: Tpm2bEccParameter,
360 }
361}
362
363tpm_struct! {
364 #[derive(Debug, PartialEq, Eq, Clone, Default)]
365 pub struct TpmsTimeAttestInfo {
366 pub time: TpmsTimeInfo,
367 pub firmware_version: u64,
368 }
369}
370
371tpm_struct! {
372 #[derive(Debug, PartialEq, Eq, Clone, Default)]
373 pub struct TpmsCertifyInfo {
374 pub name: Tpm2bName,
375 pub qualified_name: Tpm2bName,
376 }
377}
378
379tpm_struct! {
380 #[derive(Debug, PartialEq, Eq, Clone, Default)]
381 pub struct TpmsQuoteInfo {
382 pub pcr_select: TpmlPcrSelection,
383 pub pcr_digest: Tpm2bDigest,
384 }
385}
386
387tpm_struct! {
388 #[derive(Debug, PartialEq, Eq, Clone, Default)]
389 pub struct TpmsCommandAuditInfo {
390 pub audit_counter: u64,
391 pub digest_alg: TpmAlgId,
392 pub audit_digest: Tpm2bDigest,
393 pub command_digest: Tpm2bDigest,
394 }
395}
396
397tpm_struct! {
398 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
399 pub struct TpmsSessionAuditInfo {
400 pub exclusive_session: TpmiYesNo,
401 pub session_digest: Tpm2bDigest,
402 }
403}
404
405tpm_struct! {
406 #[derive(Debug, PartialEq, Eq, Clone, Default)]
407 pub struct TpmsCreationInfo {
408 pub object_name: Tpm2bName,
409 pub creation_hash: Tpm2bDigest,
410 }
411}
412
413tpm_struct! {
414 #[derive(Debug, PartialEq, Eq, Clone, Default)]
415 pub struct TpmsNvCertifyInfo {
416 pub index_name: Tpm2bName,
417 pub offset: u16,
418 pub nv_contents: Tpm2bMaxNvBuffer,
419 }
420}
421
422tpm_struct! {
423 #[derive(Debug, PartialEq, Eq, Clone, Default)]
424 pub struct TpmsNvDigestCertifyInfo {
425 pub index_name: Tpm2bName,
426 pub nv_digest: Tpm2bDigest,
427 }
428}
429
430tpm_struct! {
431 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
432 pub struct TpmsAlgorithmDetailEcc {
433 pub curve_id: TpmEccCurve,
434 pub key_size: u16,
435 pub kdf: TpmtKdfScheme,
436 pub sign: TpmtEccScheme,
437 pub p: Tpm2bEccParameter,
438 pub a: Tpm2bEccParameter,
439 pub b: Tpm2bEccParameter,
440 pub gx: Tpm2bEccParameter,
441 pub gy: Tpm2bEccParameter,
442 pub n: Tpm2bEccParameter,
443 pub h: Tpm2bEccParameter,
444 }
445}
446
447#[derive(Debug, PartialEq, Eq, Clone)]
448pub struct TpmsAttest {
449 pub magic: u32,
450 pub attest_type: TpmSt,
451 pub qualified_signer: Tpm2bName,
452 pub extra_data: Tpm2bData,
453 pub clock_info: TpmsClockInfo,
454 pub firmware_version: u64,
455 pub attested: TpmuAttest,
456}
457
458impl TpmSized for TpmsAttest {
459 const SIZE: usize = size_of::<u32>()
460 + TpmSt::SIZE
461 + Tpm2bName::SIZE
462 + Tpm2bData::SIZE
463 + TpmsClockInfo::SIZE
464 + size_of::<u64>()
465 + TpmuAttest::SIZE;
466 fn len(&self) -> usize {
467 size_of::<u32>()
468 + self.attest_type.len()
469 + self.qualified_signer.len()
470 + self.extra_data.len()
471 + self.clock_info.len()
472 + size_of::<u64>()
473 + self.attested.len()
474 }
475}
476
477impl TpmBuild for TpmsAttest {
478 fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
479 0xff54_4347_u32.build(writer)?;
480 self.attest_type.build(writer)?;
481 self.qualified_signer.build(writer)?;
482 self.extra_data.build(writer)?;
483 self.clock_info.build(writer)?;
484 self.firmware_version.build(writer)?;
485 self.attested.build(writer)
486 }
487}
488
489impl TpmParse for TpmsAttest {
490 fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
491 let (magic, buf) = u32::parse(buf)?;
492 if magic != TPM_GENERATED_VALUE {
493 return Err(TpmError::MalformedData);
494 }
495 let (attest_type, buf) = TpmSt::parse(buf)?;
496 let (qualified_signer, buf) = Tpm2bName::parse(buf)?;
497 let (extra_data, buf) = Tpm2bData::parse(buf)?;
498 let (clock_info, buf) = TpmsClockInfo::parse(buf)?;
499 let (firmware_version, buf) = u64::parse(buf)?;
500 let (attested, buf) = match attest_type {
501 TpmSt::AttestCertify => {
502 let (val, buf) = TpmsCertifyInfo::parse(buf)?;
503 (TpmuAttest::Certify(val), buf)
504 }
505 TpmSt::AttestCreation => {
506 let (val, buf) = TpmsCreationInfo::parse(buf)?;
507 (TpmuAttest::Creation(val), buf)
508 }
509 TpmSt::AttestQuote => {
510 let (val, buf) = TpmsQuoteInfo::parse(buf)?;
511 (TpmuAttest::Quote(val), buf)
512 }
513 TpmSt::AttestCommandAudit => {
514 let (val, buf) = TpmsCommandAuditInfo::parse(buf)?;
515 (TpmuAttest::CommandAudit(val), buf)
516 }
517 TpmSt::AttestSessionAudit => {
518 let (val, buf) = TpmsSessionAuditInfo::parse(buf)?;
519 (TpmuAttest::SessionAudit(val), buf)
520 }
521 TpmSt::AttestTime => {
522 let (val, buf) = TpmsTimeAttestInfo::parse(buf)?;
523 (TpmuAttest::Time(val), buf)
524 }
525 TpmSt::AttestNv => {
526 let (val, buf) = TpmsNvCertifyInfo::parse(buf)?;
527 (TpmuAttest::Nv(val), buf)
528 }
529 TpmSt::AttestNvDigest => {
530 let (val, buf) = TpmsNvDigestCertifyInfo::parse(buf)?;
531 (TpmuAttest::NvDigest(val), buf)
532 }
533 _ => return Err(TpmError::MalformedData),
534 };
535
536 Ok((
537 Self {
538 magic,
539 attest_type,
540 qualified_signer,
541 extra_data,
542 clock_info,
543 firmware_version,
544 attested,
545 },
546 buf,
547 ))
548 }
549}
550
551tpm_struct! {
552 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
553 pub struct TpmsSchemeHash {
554 pub hash_alg: TpmiAlgHash,
555 }
556}
557
558pub type TpmsSchemeHmac = TpmsSchemeHash;
559
560tpm_struct! {
561 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
562 pub struct TpmsSchemeXor {
563 pub hash_alg: TpmiAlgHash,
564 pub kdf: TpmtKdfScheme,
565 }
566}
567
568tpm_struct! {
569 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
570 pub struct TpmsRsaParms {
571 pub symmetric: TpmtSymDefObject,
572 pub scheme: TpmtRsaScheme,
573 pub key_bits: u16,
574 pub exponent: u32,
575 }
576}
577
578tpm_struct! {
579 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
580 pub struct TpmsEccParms {
581 pub symmetric: TpmtSymDefObject,
582 pub scheme: TpmtEccScheme,
583 pub curve_id: TpmEccCurve,
584 pub kdf: TpmtKdfScheme,
585 }
586}