tpm2_protocol/data/
tpmt.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 super::{
6    tpmu::{
7        TpmuHa, TpmuKeyedhashScheme, TpmuNvPublic2, TpmuPublicId, TpmuPublicParms,
8        TpmuSensitiveComposite, TpmuSigScheme, TpmuSymKeyBits, TpmuSymMode,
9    },
10    Tpm2bAuth, Tpm2bDigest, TpmAlgId, TpmHt, TpmRh, TpmSt, TpmaObject,
11};
12use crate::{
13    tpm_struct, tpm_tagged_struct, TpmBuild, TpmErrorKind, TpmParse, TpmParseTagged, TpmResult,
14    TpmSized, TpmTagged, TpmWriter, TPM_MAX_COMMAND_SIZE,
15};
16#[derive(Debug, PartialEq, Eq, Clone)]
17pub struct TpmtPublic {
18    pub object_type: TpmAlgId,
19    pub name_alg: TpmAlgId,
20    pub object_attributes: TpmaObject,
21    pub auth_policy: Tpm2bDigest,
22    pub parameters: TpmuPublicParms,
23    pub unique: TpmuPublicId,
24}
25
26impl TpmTagged for TpmtPublic {
27    type Tag = TpmAlgId;
28    type Value = TpmuPublicParms;
29}
30
31impl TpmSized for TpmtPublic {
32    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
33    fn len(&self) -> usize {
34        self.object_type.len()
35            + self.name_alg.len()
36            + self.object_attributes.len()
37            + self.auth_policy.len()
38            + self.parameters.len()
39            + self.unique.len()
40    }
41}
42
43impl TpmBuild for TpmtPublic {
44    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
45        self.object_type.build(writer)?;
46        self.name_alg.build(writer)?;
47        self.object_attributes.build(writer)?;
48        self.auth_policy.build(writer)?;
49        self.parameters.build(writer)?;
50        self.unique.build(writer)
51    }
52}
53
54impl TpmParse for TpmtPublic {
55    fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
56        let (object_type, buf) = TpmAlgId::parse(buf)?;
57        let (name_alg, buf) = TpmAlgId::parse(buf)?;
58        let (object_attributes, buf) = TpmaObject::parse(buf)?;
59        let (auth_policy, buf) = Tpm2bDigest::parse(buf)?;
60        let (parameters, buf) = TpmuPublicParms::parse_tagged(object_type, buf)?;
61        let (unique, buf) = TpmuPublicId::parse_tagged(object_type, buf)?;
62        let public_area = Self {
63            object_type,
64            name_alg,
65            object_attributes,
66            auth_policy,
67            parameters,
68            unique,
69        };
70        Ok((public_area, buf))
71    }
72}
73
74impl Default for TpmtPublic {
75    fn default() -> Self {
76        Self {
77            object_type: TpmAlgId::Null,
78            name_alg: TpmAlgId::Null,
79            object_attributes: TpmaObject::empty(),
80            auth_policy: Tpm2bDigest::default(),
81            parameters: TpmuPublicParms::Null,
82            unique: TpmuPublicId::Null,
83        }
84    }
85}
86
87tpm_tagged_struct! {
88    #[derive(Debug, PartialEq, Eq, Clone)]
89    pub struct TpmtPublicParms {
90        pub object_type: TpmAlgId,
91        pub parameters: TpmuPublicParms,
92    }
93}
94
95tpm_struct! {
96    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
97    pub struct TpmtScheme {
98        pub scheme: TpmAlgId,
99    }
100}
101
102tpm_struct! {
103    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
104    pub struct TpmtKdfScheme {
105        pub scheme: TpmAlgId,
106    }
107}
108
109tpm_tagged_struct! {
110    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
111    pub struct TpmtRsaDecrypt {
112        pub scheme: TpmAlgId,
113        pub details: crate::data::tpmu::TpmuAsymScheme,
114    }
115}
116
117impl Default for TpmtRsaDecrypt {
118    fn default() -> Self {
119        Self {
120            scheme: TpmAlgId::Null,
121            details: crate::data::tpmu::TpmuAsymScheme::Null,
122        }
123    }
124}
125
126#[derive(Debug, PartialEq, Eq, Clone, Default)]
127pub struct TpmtSensitive {
128    pub sensitive_type: TpmAlgId,
129    pub auth_value: Tpm2bAuth,
130    pub seed_value: Tpm2bDigest,
131    pub sensitive: TpmuSensitiveComposite,
132}
133
134impl TpmtSensitive {
135    /// Constructs a `TpmtSensitive` from a given key algorithm and raw private key bytes.
136    ///
137    /// # Errors
138    ///
139    /// Returns a `TpmErrorKind::InvalidValue` if the key algorithm is not supported for this operation.
140    pub fn from_private_bytes(
141        key_alg: TpmAlgId,
142        private_bytes: &[u8],
143    ) -> Result<Self, TpmErrorKind> {
144        let sensitive = match key_alg {
145            TpmAlgId::Rsa => TpmuSensitiveComposite::Rsa(
146                crate::data::Tpm2bPrivateKeyRsa::try_from(private_bytes)?,
147            ),
148            TpmAlgId::Ecc => TpmuSensitiveComposite::Ecc(crate::data::Tpm2bEccParameter::try_from(
149                private_bytes,
150            )?),
151            TpmAlgId::KeyedHash => TpmuSensitiveComposite::Bits(
152                crate::data::Tpm2bSensitiveData::try_from(private_bytes)?,
153            ),
154            TpmAlgId::SymCipher => {
155                TpmuSensitiveComposite::Sym(crate::data::Tpm2bSymKey::try_from(private_bytes)?)
156            }
157            _ => return Err(TpmErrorKind::InvalidValue),
158        };
159        Ok(Self {
160            sensitive_type: key_alg,
161            auth_value: Tpm2bAuth::default(),
162            seed_value: Tpm2bDigest::default(),
163            sensitive,
164        })
165    }
166}
167
168impl TpmTagged for TpmtSensitive {
169    type Tag = TpmAlgId;
170    type Value = TpmuSensitiveComposite;
171}
172
173impl TpmSized for TpmtSensitive {
174    const SIZE: usize =
175        TpmAlgId::SIZE + Tpm2bAuth::SIZE + Tpm2bDigest::SIZE + TpmuSensitiveComposite::SIZE;
176    fn len(&self) -> usize {
177        self.sensitive_type.len()
178            + self.auth_value.len()
179            + self.seed_value.len()
180            + self.sensitive.len()
181    }
182}
183
184impl TpmBuild for TpmtSensitive {
185    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
186        self.sensitive_type.build(writer)?;
187        self.auth_value.build(writer)?;
188        self.seed_value.build(writer)?;
189        self.sensitive.build(writer)
190    }
191}
192
193impl TpmParse for TpmtSensitive {
194    fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
195        let (sensitive_type, buf) = TpmAlgId::parse(buf)?;
196        let (auth_value, buf) = Tpm2bAuth::parse(buf)?;
197        let (seed_value, buf) = Tpm2bDigest::parse(buf)?;
198        let (sensitive, buf) = TpmuSensitiveComposite::parse_tagged(sensitive_type, buf)?;
199        Ok((
200            Self {
201                sensitive_type,
202                auth_value,
203                seed_value,
204                sensitive,
205            },
206            buf,
207        ))
208    }
209}
210
211#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
212pub struct TpmtSymDef {
213    pub algorithm: TpmAlgId,
214    pub key_bits: TpmuSymKeyBits,
215    pub mode: TpmuSymMode,
216}
217
218impl TpmTagged for TpmtSymDef {
219    type Tag = TpmAlgId;
220    type Value = TpmuSymKeyBits;
221}
222
223impl TpmSized for TpmtSymDef {
224    const SIZE: usize = TpmAlgId::SIZE + TpmuSymKeyBits::SIZE + TpmAlgId::SIZE;
225    fn len(&self) -> usize {
226        if self.algorithm == TpmAlgId::Null {
227            self.algorithm.len()
228        } else {
229            self.algorithm.len() + self.key_bits.len() + self.mode.len()
230        }
231    }
232}
233
234impl TpmBuild for TpmtSymDef {
235    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
236        self.algorithm.build(writer)?;
237        if self.algorithm != TpmAlgId::Null {
238            self.key_bits.build(writer)?;
239            self.mode.build(writer)?;
240        }
241        Ok(())
242    }
243}
244
245impl TpmParse for TpmtSymDef {
246    fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
247        let (algorithm, buf) = TpmAlgId::parse(buf)?;
248        if algorithm == TpmAlgId::Null {
249            return Ok((
250                Self {
251                    algorithm,
252                    key_bits: TpmuSymKeyBits::Null,
253                    mode: TpmuSymMode::Null,
254                },
255                buf,
256            ));
257        }
258
259        let (key_bits, buf) = TpmuSymKeyBits::parse_tagged(algorithm, buf)?;
260        let (mode, buf) = TpmuSymMode::parse_tagged(algorithm, buf)?;
261        Ok((
262            Self {
263                algorithm,
264                key_bits,
265                mode,
266            },
267            buf,
268        ))
269    }
270}
271
272pub type TpmtSymDefObject = TpmtSymDef;
273
274tpm_tagged_struct! {
275    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
276    pub struct TpmtNvPublic2 {
277        pub handle_type: TpmHt,
278        pub public_area: TpmuNvPublic2,
279    }
280}
281
282tpm_struct! {
283    #[derive(Debug, PartialEq, Eq, Clone, Default)]
284    pub struct TpmtTkCreation {
285        pub tag: TpmSt,
286        pub hierarchy: TpmRh,
287        pub digest: Tpm2bDigest,
288    }
289}
290
291tpm_struct! {
292    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
293    pub struct TpmtTkVerified {
294        pub tag: TpmSt,
295        pub hierarchy: TpmRh,
296        pub digest: Tpm2bDigest,
297    }
298}
299
300tpm_struct! {
301    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
302    pub struct TpmtTkAuth {
303        pub tag: TpmSt,
304        pub hierarchy: TpmRh,
305        pub digest: Tpm2bDigest,
306    }
307}
308
309tpm_struct! {
310    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
311    pub struct TpmtTkHashcheck {
312        pub tag: TpmSt,
313        pub hierarchy: TpmRh,
314        pub digest: Tpm2bDigest,
315    }
316}
317
318tpm_tagged_struct! {
319    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
320    pub struct TpmtHa {
321        pub hash_alg: TpmAlgId,
322        pub digest: TpmuHa,
323    }
324}
325
326impl Default for TpmtHa {
327    fn default() -> Self {
328        Self {
329            hash_alg: TpmAlgId::Null,
330            digest: TpmuHa::default(),
331        }
332    }
333}
334
335tpm_tagged_struct! {
336    #[derive(Debug, PartialEq, Eq, Clone)]
337    pub struct TpmtSignature {
338        pub sig_alg: TpmAlgId,
339        pub signature: crate::data::tpmu::TpmuSignature,
340    }
341}
342
343tpm_tagged_struct! {
344    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
345    pub struct TpmtKeyedhashScheme {
346        pub scheme: TpmAlgId,
347        pub details: TpmuKeyedhashScheme,
348    }
349}
350
351tpm_tagged_struct! {
352    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
353    pub struct TpmtSigScheme {
354        pub scheme: TpmAlgId,
355        pub details: TpmuSigScheme,
356    }
357}