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