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