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