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