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