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