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