1use crate::{
6 basic::{TpmHandle, TpmUint16, TpmUint32, TpmUint64, TpmUint8},
7 constant::{TPM_GENERATED_VALUE, 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, 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: 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 = 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::IntegerTooLarge)?;
66 pcr_select.size = TpmUint8::from(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::<TpmUint8>() + TPM_PCR_SELECT_MAX as usize;
84
85 fn len(&self) -> usize {
86 size_of::<TpmUint8>() + u8::from(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) = TpmUint8::unmarshal(buf)?;
100 let raw = u8::from(size);
101
102 if raw > TPM_PCR_SELECT_MAX {
103 return Err(TpmProtocolError::TooManyItems);
104 }
105 if remainder.len() < raw as usize {
106 return Err(TpmProtocolError::UnexpectedEnd);
107 }
108
109 let (pcr_bytes, final_remainder) = remainder.split_at(raw as 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: TpmUint32,
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::<TpmUint32>() + 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: TpmUint64,
182 pub reset_count: TpmUint32,
183 pub restart_count: TpmUint32,
184 pub safe: TpmiYesNo,
185 }
186}
187
188tpm_struct! {
189 #[derive(Debug, PartialEq, Eq, Clone)]
190 pub struct TpmsContext {
191 pub sequence: TpmUint64,
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: TpmUint16,
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: TpmUint16,
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: TpmUint32,
310 }
311}
312
313tpm_struct! {
314 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
315 pub struct TpmsTimeInfo {
316 pub time: TpmUint64,
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: TpmUint64,
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: TpmUint64,
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: TpmUint16,
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: TpmUint16,
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 attest_type: TpmSt,
425 pub qualified_signer: Tpm2bName,
426 pub extra_data: Tpm2bData,
427 pub clock_info: TpmsClockInfo,
428 pub firmware_version: TpmUint64,
429 pub attested: TpmuAttest,
430}
431
432impl TpmSized for TpmsAttest {
433 const SIZE: usize = size_of::<TpmUint32>()
434 + TpmSt::SIZE
435 + Tpm2bName::SIZE
436 + Tpm2bData::SIZE
437 + TpmsClockInfo::SIZE
438 + size_of::<TpmUint64>()
439 + TpmuAttest::SIZE;
440 fn len(&self) -> usize {
441 size_of::<TpmUint32>()
442 + self.attest_type.len()
443 + self.qualified_signer.len()
444 + self.extra_data.len()
445 + self.clock_info.len()
446 + size_of::<TpmUint64>()
447 + self.attested.len()
448 }
449}
450
451impl TpmMarshal for TpmsAttest {
452 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
453 crate::basic::TpmUint32::from(TPM_GENERATED_VALUE).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) = crate::basic::TpmUint32::unmarshal(buf)?;
466 if u32::from(magic) != TPM_GENERATED_VALUE {
467 return Err(TpmProtocolError::InvalidMagicNumber);
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) = TpmUint64::unmarshal(buf)?;
474 let (attested, buf) = TpmuAttest::unmarshal_tagged(attest_type, buf)?;
475
476 Ok((
477 Self {
478 attest_type,
479 qualified_signer,
480 extra_data,
481 clock_info,
482 firmware_version,
483 attested,
484 },
485 buf,
486 ))
487 }
488}
489
490tpm_struct! {
491 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
492 pub struct TpmsSchemeHash {
493 pub hash_alg: TpmiAlgHash,
494 }
495}
496
497pub type TpmsSchemeHmac = TpmsSchemeHash;
498
499tpm_struct! {
500 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
501 pub struct TpmsSchemeXor {
502 pub hash_alg: TpmiAlgHash,
503 pub kdf: TpmtKdfScheme,
504 }
505}
506
507tpm_struct! {
508 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
509 pub struct TpmsRsaParms {
510 pub symmetric: TpmtSymDefObject,
511 pub scheme: TpmtRsaScheme,
512 pub key_bits: TpmUint16,
513 pub exponent: TpmUint32,
514 }
515}
516
517tpm_struct! {
518 #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
519 pub struct TpmsEccParms {
520 pub symmetric: TpmtSymDefObject,
521 pub scheme: TpmtEccScheme,
522 pub curve_id: TpmEccCurve,
523 pub kdf: TpmtKdfScheme,
524 }
525}