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, TpmlPcrSelection, TpmtEccScheme, TpmtKdfScheme, TpmtKeyedhashScheme,
13 TpmtRsaScheme, TpmtSymDefObject, TpmuAttest, TpmuCapabilities,
14 },
15 tpm_struct, TpmHandle, TpmMarshal, TpmProtocolError, TpmResult, TpmSized, TpmUnmarshal,
16 TpmUnmarshalTagged, 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 = TpmProtocolError;
59
60 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
61 if slice.len() > TPM_PCR_SELECT_MAX as usize {
62 return Err(TpmProtocolError::TooManyItems);
63 }
64 let mut pcr_select = Self::new();
65 let len_u8 = u8::try_from(slice.len()).map_err(|_| TpmProtocolError::OperationFailed)?;
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(TpmProtocolError::TooManyItems);
103 }
104 if remainder.len() < size as usize {
105 return Err(TpmProtocolError::UnexpectedEnd);
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) = TpmuCapabilities::unmarshal_tagged(capability, buf)?;
173 Ok((Self { capability, data }, buf))
174 }
175}
176
177tpm_struct! {
178 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
179 pub struct TpmsClockInfo {
180 pub clock: u64,
181 pub reset_count: u32,
182 pub restart_count: u32,
183 pub safe: TpmiYesNo,
184 }
185}
186
187tpm_struct! {
188 #[derive(Debug, PartialEq, Eq, Clone)]
189 pub struct TpmsContext {
190 pub sequence: u64,
191 pub saved_handle: TpmHandle,
192 pub hierarchy: TpmRh,
193 pub context_blob: Tpm2b,
194 }
195}
196
197tpm_struct! {
198 #[derive(Debug, PartialEq, Eq, Clone, Default)]
199 pub struct TpmsCreationData {
200 pub pcr_select: TpmlPcrSelection,
201 pub pcr_digest: Tpm2bDigest,
202 pub locality: TpmaLocality,
203 pub parent_name_alg: TpmAlgId,
204 pub parent_name: Tpm2bName,
205 pub parent_qualified_name: Tpm2bName,
206 pub outside_info: Tpm2bData,
207 }
208}
209
210tpm_struct! {
211 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
212 pub struct TpmsEccPoint {
213 pub x: Tpm2bEccParameter,
214 pub y: Tpm2bEccParameter,
215 }
216}
217
218tpm_struct! {
219 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
220 pub struct TpmsEmpty {}
221}
222
223tpm_struct! {
224 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
225 pub struct TpmsKeyedhashParms {
226 pub scheme: TpmtKeyedhashScheme,
227 }
228}
229
230tpm_struct! {
231 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
232 pub struct TpmsNvPublic {
233 pub nv_index: TpmHandle,
234 pub name_alg: TpmAlgId,
235 pub attributes: TpmaNv,
236 pub auth_policy: Tpm2bDigest,
237 pub data_size: u16,
238 }
239}
240
241tpm_struct! {
242 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
243 pub struct TpmsNvPublicExpAttr {
244 pub nv_index: TpmiRhNvExpIndex,
245 pub name_alg: TpmAlgId,
246 pub attributes: TpmaNvExp,
247 pub auth_policy: Tpm2bDigest,
248 pub data_size: u16,
249 }
250}
251
252#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
253pub struct TpmsPcrSelection {
254 pub hash: TpmAlgId,
255 pub pcr_select: TpmsPcrSelect,
256}
257
258impl TpmSized for TpmsPcrSelection {
259 const SIZE: usize = TpmAlgId::SIZE + 1 + TPM_PCR_SELECT_MAX as usize;
260
261 fn len(&self) -> usize {
262 self.hash.len() + self.pcr_select.len()
263 }
264}
265
266impl TpmMarshal for TpmsPcrSelection {
267 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
268 self.hash.marshal(writer)?;
269 self.pcr_select.marshal(writer)
270 }
271}
272
273impl TpmUnmarshal for TpmsPcrSelection {
274 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
275 let (hash, buf) = TpmAlgId::unmarshal(buf)?;
276 let (pcr_select, buf) = TpmsPcrSelect::unmarshal(buf)?;
277 Ok((Self { hash, pcr_select }, buf))
278 }
279}
280
281tpm_struct! {
282 #[derive(Debug, Default, PartialEq, Eq, Clone)]
283 pub struct TpmsSensitiveCreate {
284 pub user_auth: Tpm2bAuth,
285 pub data: Tpm2bSensitiveData,
286 }
287}
288
289tpm_struct! {
290 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
291 pub struct TpmsIdObject {
292 pub integrity_hmac: Tpm2bDigest,
293 pub enc_identity: Tpm2bDigest,
294 }
295}
296
297tpm_struct! {
298 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
299 pub struct TpmsSymcipherParms {
300 pub sym: TpmtSymDefObject,
301 }
302}
303
304tpm_struct! {
305 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
306 pub struct TpmsTaggedProperty {
307 pub property: TpmPt,
308 pub value: u32,
309 }
310}
311
312tpm_struct! {
313 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
314 pub struct TpmsTimeInfo {
315 pub time: u64,
316 pub clock_info: TpmsClockInfo,
317 }
318}
319
320tpm_struct! {
321 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
322 pub struct TpmsSignatureRsa {
323 pub hash: TpmAlgId,
324 pub sig: crate::data::Tpm2bPublicKeyRsa,
325 }
326}
327
328tpm_struct! {
329 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
330 pub struct TpmsSignatureEcc {
331 pub hash: TpmAlgId,
332 pub signature_r: Tpm2bEccParameter,
333 pub signature_s: Tpm2bEccParameter,
334 }
335}
336
337tpm_struct! {
338 #[derive(Debug, PartialEq, Eq, Clone, Default)]
339 pub struct TpmsTimeAttestInfo {
340 pub time: TpmsTimeInfo,
341 pub firmware_version: u64,
342 }
343}
344
345tpm_struct! {
346 #[derive(Debug, PartialEq, Eq, Clone, Default)]
347 pub struct TpmsCertifyInfo {
348 pub name: Tpm2bName,
349 pub qualified_name: Tpm2bName,
350 }
351}
352
353tpm_struct! {
354 #[derive(Debug, PartialEq, Eq, Clone, Default)]
355 pub struct TpmsQuoteInfo {
356 pub pcr_select: TpmlPcrSelection,
357 pub pcr_digest: Tpm2bDigest,
358 }
359}
360
361tpm_struct! {
362 #[derive(Debug, PartialEq, Eq, Clone, Default)]
363 pub struct TpmsCommandAuditInfo {
364 pub audit_counter: u64,
365 pub digest_alg: TpmAlgId,
366 pub audit_digest: Tpm2bDigest,
367 pub command_digest: Tpm2bDigest,
368 }
369}
370
371tpm_struct! {
372 #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
373 pub struct TpmsSessionAuditInfo {
374 pub exclusive_session: TpmiYesNo,
375 pub session_digest: Tpm2bDigest,
376 }
377}
378
379tpm_struct! {
380 #[derive(Debug, PartialEq, Eq, Clone, Default)]
381 pub struct TpmsCreationInfo {
382 pub object_name: Tpm2bName,
383 pub creation_hash: Tpm2bDigest,
384 }
385}
386
387tpm_struct! {
388 #[derive(Debug, PartialEq, Eq, Clone, Default)]
389 pub struct TpmsNvCertifyInfo {
390 pub index_name: Tpm2bName,
391 pub offset: u16,
392 pub nv_contents: Tpm2bMaxNvBuffer,
393 }
394}
395
396tpm_struct! {
397 #[derive(Debug, PartialEq, Eq, Clone, Default)]
398 pub struct TpmsNvDigestCertifyInfo {
399 pub index_name: Tpm2bName,
400 pub nv_digest: Tpm2bDigest,
401 }
402}
403
404tpm_struct! {
405 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
406 pub struct TpmsAlgorithmDetailEcc {
407 pub curve_id: TpmEccCurve,
408 pub key_size: u16,
409 pub kdf: TpmtKdfScheme,
410 pub sign: TpmtEccScheme,
411 pub p: Tpm2bEccParameter,
412 pub a: Tpm2bEccParameter,
413 pub b: Tpm2bEccParameter,
414 pub gx: Tpm2bEccParameter,
415 pub gy: Tpm2bEccParameter,
416 pub n: Tpm2bEccParameter,
417 pub h: Tpm2bEccParameter,
418 }
419}
420
421#[derive(Debug, PartialEq, Eq, Clone)]
422pub struct TpmsAttest {
423 pub magic: u32,
424 pub attest_type: TpmSt,
425 pub qualified_signer: Tpm2bName,
426 pub extra_data: Tpm2bData,
427 pub clock_info: TpmsClockInfo,
428 pub firmware_version: u64,
429 pub attested: TpmuAttest,
430}
431
432impl TpmSized for TpmsAttest {
433 const SIZE: usize = size_of::<u32>()
434 + TpmSt::SIZE
435 + Tpm2bName::SIZE
436 + Tpm2bData::SIZE
437 + TpmsClockInfo::SIZE
438 + size_of::<u64>()
439 + TpmuAttest::SIZE;
440 fn len(&self) -> usize {
441 size_of::<u32>()
442 + self.attest_type.len()
443 + self.qualified_signer.len()
444 + self.extra_data.len()
445 + self.clock_info.len()
446 + size_of::<u64>()
447 + self.attested.len()
448 }
449}
450
451impl TpmMarshal for TpmsAttest {
452 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
453 0xff54_4347_u32.marshal(writer)?;
454 self.attest_type.marshal(writer)?;
455 self.qualified_signer.marshal(writer)?;
456 self.extra_data.marshal(writer)?;
457 self.clock_info.marshal(writer)?;
458 self.firmware_version.marshal(writer)?;
459 self.attested.marshal(writer)
460 }
461}
462
463impl TpmUnmarshal for TpmsAttest {
464 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
465 let (magic, buf) = u32::unmarshal(buf)?;
466 if magic != TPM_GENERATED_VALUE {
467 return Err(TpmProtocolError::InvalidAttestMagic);
468 }
469 let (attest_type, buf) = TpmSt::unmarshal(buf)?;
470 let (qualified_signer, buf) = Tpm2bName::unmarshal(buf)?;
471 let (extra_data, buf) = Tpm2bData::unmarshal(buf)?;
472 let (clock_info, buf) = TpmsClockInfo::unmarshal(buf)?;
473 let (firmware_version, buf) = u64::unmarshal(buf)?;
474 let (attested, buf) = TpmuAttest::unmarshal_tagged(attest_type, buf)?;
475
476 Ok((
477 Self {
478 magic,
479 attest_type,
480 qualified_signer,
481 extra_data,
482 clock_info,
483 firmware_version,
484 attested,
485 },
486 buf,
487 ))
488 }
489}
490
491tpm_struct! {
492 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
493 pub struct TpmsSchemeHash {
494 pub hash_alg: TpmiAlgHash,
495 }
496}
497
498pub type TpmsSchemeHmac = TpmsSchemeHash;
499
500tpm_struct! {
501 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
502 pub struct TpmsSchemeXor {
503 pub hash_alg: TpmiAlgHash,
504 pub kdf: TpmtKdfScheme,
505 }
506}
507
508tpm_struct! {
509 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
510 pub struct TpmsRsaParms {
511 pub symmetric: TpmtSymDefObject,
512 pub scheme: TpmtRsaScheme,
513 pub key_bits: u16,
514 pub exponent: u32,
515 }
516}
517
518tpm_struct! {
519 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
520 pub struct TpmsEccParms {
521 pub symmetric: TpmtSymDefObject,
522 pub scheme: TpmtEccScheme,
523 pub curve_id: TpmEccCurve,
524 pub kdf: TpmtKdfScheme,
525 }
526}