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