tpm2_protocol/data/
tpms.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2025 Opinsys Oy
3// Copyright (c) 2024-2025 Jarkko Sakkinen
4
5use 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}