Skip to main content

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    TpmError, TpmMarshal, TpmResult, TpmSized, TpmUnmarshal, TpmUnmarshalTagged, TpmWriter,
7    basic::{TpmHandle, TpmUint8, TpmUint16, TpmUint32, TpmUint64},
8    constant::{TPM_GENERATED_VALUE, TPM_PCR_SELECT_MAX},
9    data::{
10        Tpm2b, Tpm2bAuth, Tpm2bData, Tpm2bDigest, Tpm2bEccParameter, Tpm2bMaxNvBuffer, Tpm2bName,
11        Tpm2bNonce, Tpm2bSensitiveData, TpmAlgId, TpmAt, TpmCap, TpmEccCurve, TpmPt, TpmRh, TpmSt,
12        TpmaAct, TpmaAlgorithm, TpmaLocality, TpmaNv, TpmaNvExp, TpmaSession, TpmiAlgHash,
13        TpmiRhNvExpIndex, TpmiYesNo, TpmlPcrSelection, TpmtEccScheme, TpmtHa, TpmtKdfScheme,
14        TpmtKeyedhashScheme, TpmtRsaScheme, TpmtSymDefObject, TpmuAttest, TpmuAttestView,
15        TpmuCapabilities,
16    },
17    tpm_struct,
18};
19use core::{
20    convert::TryFrom,
21    fmt::{Debug, Formatter},
22    mem::size_of,
23    ops::Deref,
24};
25
26/// A fixed-capacity list for a PCR selection bitmap.
27#[derive(Clone, Copy, PartialEq, Eq)]
28pub struct TpmsPcrSelect {
29    size: TpmUint8,
30    data: [u8; TPM_PCR_SELECT_MAX as usize],
31}
32
33impl TpmsPcrSelect {
34    /// Creates a new, empty `TpmsPcrSelect`.
35    #[must_use]
36    pub const fn new() -> Self {
37        Self {
38            size: TpmUint8::new(0),
39            data: [0; TPM_PCR_SELECT_MAX as usize],
40        }
41    }
42}
43
44impl Default for TpmsPcrSelect {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl Deref for TpmsPcrSelect {
51    type Target = [u8];
52
53    fn deref(&self) -> &Self::Target {
54        &self.data[..u8::from(self.size) as usize]
55    }
56}
57
58impl TryFrom<&[u8]> for TpmsPcrSelect {
59    type Error = TpmError;
60
61    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
62        if slice.len() > TPM_PCR_SELECT_MAX as usize {
63            return Err(TpmError::TooManyItems {
64                offset: 0,
65                limit: TPM_PCR_SELECT_MAX as usize,
66                actual: slice.len(),
67            });
68        }
69        let mut pcr_select = Self::new();
70        let len_u8 = u8::try_from(slice.len()).map_err(|_| TpmError::IntegerTooLarge {
71            offset: 0,
72            value: crate::tpm_value(slice.len()),
73        })?;
74        pcr_select.size = TpmUint8::from(len_u8);
75        pcr_select.data[..slice.len()].copy_from_slice(slice);
76        Ok(pcr_select)
77    }
78}
79
80impl Debug for TpmsPcrSelect {
81    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
82        write!(f, "TpmsPcrSelect(")?;
83        for byte in self.iter() {
84            write!(f, "{byte:02X}")?;
85        }
86        write!(f, ")")
87    }
88}
89
90impl TpmSized for TpmsPcrSelect {
91    const SIZE: usize = size_of::<TpmUint8>() + TPM_PCR_SELECT_MAX as usize;
92
93    fn len(&self) -> usize {
94        size_of::<TpmUint8>() + u8::from(self.size) as usize
95    }
96}
97
98impl TpmMarshal for TpmsPcrSelect {
99    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
100        self.size.marshal(writer)?;
101        writer.write_bytes(self)
102    }
103}
104
105impl<'a> crate::TpmField<'a> for TpmsPcrSelect {
106    type View = &'a [u8];
107
108    fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
109        let (size, remainder) = <TpmUint8 as crate::TpmCast>::cast_prefix(buf)?;
110        let size = size.value() as usize;
111
112        if size > TPM_PCR_SELECT_MAX as usize {
113            return Err(TpmError::TooManyItems {
114                offset: 0,
115                limit: TPM_PCR_SELECT_MAX as usize,
116                actual: size,
117            });
118        }
119
120        if remainder.len() < size {
121            return Err(TpmError::UnexpectedEnd {
122                offset: size_of::<TpmUint8>(),
123                needed: size,
124                available: remainder.len(),
125            });
126        }
127
128        let (pcr_select, remainder) = remainder.split_at(size);
129        Ok((pcr_select, remainder))
130    }
131}
132
133impl TpmUnmarshal for TpmsPcrSelect {
134    fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
135        let (value, remainder) = <Self as crate::TpmField>::cast_prefix_field(buffer)?;
136        Ok((Self::try_from(value)?, remainder))
137    }
138}
139
140tpm_struct! {
141    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
142    wire: TpmsAcOutputWire,
143    pub struct TpmsAcOutput {
144        pub tag: TpmAt,
145        pub data: TpmUint32,
146    }
147}
148
149tpm_struct! {
150    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
151    wire: TpmsActDataWire,
152    pub struct TpmsActData {
153        pub handle: TpmHandle,
154        pub timeout: TpmUint32,
155        pub attributes: TpmaAct,
156    }
157}
158
159tpm_struct! {
160    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
161    wire: TpmsAlgPropertyWire,
162    pub struct TpmsAlgProperty {
163        pub alg: TpmAlgId,
164        pub alg_properties: TpmaAlgorithm,
165    }
166}
167
168tpm_struct! {
169    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
170    wire: TpmsAuthCommandWire,
171    pub struct TpmsAuthCommand {
172        pub session_handle: TpmHandle,
173        pub nonce: Tpm2bNonce,
174        pub session_attributes: TpmaSession,
175        pub hmac: Tpm2bAuth,
176    }
177}
178
179tpm_struct! {
180    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
181    wire: TpmsAuthResponseWire,
182    pub struct TpmsAuthResponse {
183        pub nonce: Tpm2bNonce,
184        pub session_attributes: TpmaSession,
185        pub hmac: Tpm2bAuth,
186    }
187}
188
189#[derive(Debug, PartialEq, Eq, Clone)]
190pub struct TpmsCapabilityData {
191    pub capability: TpmCap,
192    pub data: TpmuCapabilities,
193}
194
195impl TpmSized for TpmsCapabilityData {
196    const SIZE: usize = size_of::<TpmUint32>() + TpmuCapabilities::SIZE;
197    fn len(&self) -> usize {
198        self.capability.len() + self.data.len()
199    }
200}
201
202impl TpmMarshal for TpmsCapabilityData {
203    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
204        self.capability.marshal(writer)?;
205        self.data.marshal(writer)
206    }
207}
208
209impl TpmUnmarshal for TpmsCapabilityData {
210    fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
211        let (capability, buffer) = TpmCap::unmarshal(buffer)?;
212        let (data, buffer) = TpmuCapabilities::unmarshal_tagged(capability, buffer)?;
213        Ok((Self { capability, data }, buffer))
214    }
215}
216
217tpm_struct! {
218    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
219    wire: TpmsClockInfoWire,
220    pub struct TpmsClockInfo {
221        pub clock: TpmUint64,
222        pub reset_count: TpmUint32,
223        pub restart_count: TpmUint32,
224        pub safe: TpmiYesNo,
225    }
226}
227
228tpm_struct! {
229    #[derive(Debug, PartialEq, Eq, Clone)]
230    wire: TpmsContextWire,
231    pub struct TpmsContext {
232        pub sequence: TpmUint64,
233        pub saved_handle: TpmHandle,
234        pub hierarchy: TpmRh,
235        pub context_blob: Tpm2b,
236    }
237}
238
239tpm_struct! {
240    #[derive(Debug, PartialEq, Eq, Clone, Default)]
241    wire: TpmsCreationDataWire,
242    pub struct TpmsCreationData {
243        pub pcr_select: TpmlPcrSelection,
244        pub pcr_digest: Tpm2bDigest,
245        pub locality: TpmaLocality,
246        pub parent_name_alg: TpmAlgId,
247        pub parent_name: Tpm2bName,
248        pub parent_qualified_name: Tpm2bName,
249        pub outside_info: Tpm2bData,
250    }
251}
252
253tpm_struct! {
254    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
255    wire: TpmsEccPointWire,
256    pub struct TpmsEccPoint {
257        pub x: Tpm2bEccParameter,
258        pub y: Tpm2bEccParameter,
259    }
260}
261
262tpm_struct! {
263    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
264    wire: TpmsEmptyWire,
265    pub struct TpmsEmpty {}
266}
267
268tpm_struct! {
269    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
270    wire: TpmsKeyedhashParmsWire,
271    pub struct TpmsKeyedhashParms {
272        pub scheme: TpmtKeyedhashScheme,
273    }
274}
275
276tpm_struct! {
277    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
278    wire: TpmsNvPublicWire,
279    pub struct TpmsNvPublic {
280        pub nv_index: TpmHandle,
281        pub name_alg: TpmAlgId,
282        pub attributes: TpmaNv,
283        pub auth_policy: Tpm2bDigest,
284        pub data_size: TpmUint16,
285    }
286}
287
288tpm_struct! {
289    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
290    wire: TpmsNvPublicExpAttrWire,
291    pub struct TpmsNvPublicExpAttr {
292        pub nv_index: TpmiRhNvExpIndex,
293        pub name_alg: TpmAlgId,
294        pub attributes: TpmaNvExp,
295        pub auth_policy: Tpm2bDigest,
296        pub data_size: TpmUint16,
297    }
298}
299
300#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
301pub struct TpmsPcrSelection {
302    pub hash: TpmAlgId,
303    pub pcr_select: TpmsPcrSelect,
304}
305
306impl TpmSized for TpmsPcrSelection {
307    const SIZE: usize = TpmAlgId::SIZE + 1 + TPM_PCR_SELECT_MAX as usize;
308
309    fn len(&self) -> usize {
310        self.hash.len() + self.pcr_select.len()
311    }
312}
313
314impl TpmMarshal for TpmsPcrSelection {
315    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
316        self.hash.marshal(writer)?;
317        self.pcr_select.marshal(writer)
318    }
319}
320
321impl<'a> crate::TpmField<'a> for TpmsPcrSelection {
322    type View = (TpmAlgId, &'a [u8]);
323
324    fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
325        let (hash, buf) = <TpmAlgId as crate::TpmField>::cast_prefix_field(buf)?;
326        let (pcr_select, buf) = <TpmsPcrSelect as crate::TpmField>::cast_prefix_field(buf)?;
327
328        Ok(((hash, pcr_select), buf))
329    }
330}
331
332impl TpmUnmarshal for TpmsPcrSelection {
333    fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
334        let (hash, buffer) = TpmAlgId::unmarshal(buffer)?;
335        let (pcr_select, buffer) = TpmsPcrSelect::unmarshal(buffer)?;
336        Ok((Self { hash, pcr_select }, buffer))
337    }
338}
339
340tpm_struct! {
341    #[derive(Debug, Default, PartialEq, Eq, Clone)]
342    wire: TpmsSensitiveCreateWire,
343    pub struct TpmsSensitiveCreate {
344        pub user_auth: Tpm2bAuth,
345        pub data: Tpm2bSensitiveData,
346    }
347}
348
349tpm_struct! {
350    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
351    wire: TpmsIdObjectWire,
352    pub struct TpmsIdObject {
353        pub integrity_hmac: Tpm2bDigest,
354        pub enc_identity: Tpm2bDigest,
355    }
356}
357
358tpm_struct! {
359    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
360    wire: TpmsSymcipherParmsWire,
361    pub struct TpmsSymcipherParms {
362        pub sym: TpmtSymDefObject,
363    }
364}
365
366tpm_struct! {
367    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
368    wire: TpmsTaggedPropertyWire,
369    pub struct TpmsTaggedProperty {
370        pub property: TpmPt,
371        pub value: TpmUint32,
372    }
373}
374
375tpm_struct! {
376    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
377    wire: TpmsTaggedPolicyWire,
378    pub struct TpmsTaggedPolicy {
379        pub handle: TpmHandle,
380        pub policy_hash: TpmtHa,
381    }
382}
383
384tpm_struct! {
385    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
386    wire: TpmsTimeInfoWire,
387    pub struct TpmsTimeInfo {
388        pub time: TpmUint64,
389        pub clock_info: TpmsClockInfo,
390    }
391}
392
393tpm_struct! {
394    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
395    wire: TpmsSignatureRsaWire,
396    pub struct TpmsSignatureRsa {
397        pub hash: TpmAlgId,
398        pub sig: crate::data::Tpm2bPublicKeyRsa,
399    }
400}
401
402tpm_struct! {
403    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
404    wire: TpmsSignatureEccWire,
405    pub struct TpmsSignatureEcc {
406        pub hash: TpmAlgId,
407        pub signature_r: Tpm2bEccParameter,
408        pub signature_s: Tpm2bEccParameter,
409    }
410}
411
412tpm_struct! {
413    #[derive(Debug, PartialEq, Eq, Clone, Default)]
414    wire: TpmsTimeAttestInfoWire,
415    pub struct TpmsTimeAttestInfo {
416        pub time: TpmsTimeInfo,
417        pub firmware_version: TpmUint64,
418    }
419}
420
421tpm_struct! {
422    #[derive(Debug, PartialEq, Eq, Clone, Default)]
423    wire: TpmsCertifyInfoWire,
424    pub struct TpmsCertifyInfo {
425        pub name: Tpm2bName,
426        pub qualified_name: Tpm2bName,
427    }
428}
429
430tpm_struct! {
431    #[derive(Debug, PartialEq, Eq, Clone, Default)]
432    wire: TpmsQuoteInfoWire,
433    pub struct TpmsQuoteInfo {
434        pub pcr_select: TpmlPcrSelection,
435        pub pcr_digest: Tpm2bDigest,
436    }
437}
438
439tpm_struct! {
440    #[derive(Debug, PartialEq, Eq, Clone, Default)]
441    wire: TpmsCommandAuditInfoWire,
442    pub struct TpmsCommandAuditInfo {
443        pub audit_counter: TpmUint64,
444        pub digest_alg: TpmAlgId,
445        pub audit_digest: Tpm2bDigest,
446        pub command_digest: Tpm2bDigest,
447    }
448}
449
450tpm_struct! {
451    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
452    wire: TpmsSessionAuditInfoWire,
453    pub struct TpmsSessionAuditInfo {
454        pub exclusive_session: TpmiYesNo,
455        pub session_digest: Tpm2bDigest,
456    }
457}
458
459tpm_struct! {
460    #[derive(Debug, PartialEq, Eq, Clone, Default)]
461    wire: TpmsCreationInfoWire,
462    pub struct TpmsCreationInfo {
463        pub object_name: Tpm2bName,
464        pub creation_hash: Tpm2bDigest,
465    }
466}
467
468tpm_struct! {
469    #[derive(Debug, PartialEq, Eq, Clone, Default)]
470    wire: TpmsNvCertifyInfoWire,
471    pub struct TpmsNvCertifyInfo {
472        pub index_name: Tpm2bName,
473        pub offset: TpmUint16,
474        pub nv_contents: Tpm2bMaxNvBuffer,
475    }
476}
477
478tpm_struct! {
479    #[derive(Debug, PartialEq, Eq, Clone, Default)]
480    wire: TpmsNvDigestCertifyInfoWire,
481    pub struct TpmsNvDigestCertifyInfo {
482        pub index_name: Tpm2bName,
483        pub nv_digest: Tpm2bDigest,
484    }
485}
486
487tpm_struct! {
488    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
489    wire: TpmsAlgorithmDetailEccWire,
490    pub struct TpmsAlgorithmDetailEcc {
491        pub curve_id: TpmEccCurve,
492        pub key_size: TpmUint16,
493        pub kdf: TpmtKdfScheme,
494        pub sign: TpmtEccScheme,
495        pub p: Tpm2bEccParameter,
496        pub a: Tpm2bEccParameter,
497        pub b: Tpm2bEccParameter,
498        pub gx: Tpm2bEccParameter,
499        pub gy: Tpm2bEccParameter,
500        pub n: Tpm2bEccParameter,
501        pub h: Tpm2bEccParameter,
502    }
503}
504
505#[derive(Debug, PartialEq, Eq, Clone)]
506pub struct TpmsAttest {
507    pub attest_type: TpmSt,
508    pub qualified_signer: Tpm2bName,
509    pub extra_data: Tpm2bData,
510    pub clock_info: TpmsClockInfo,
511    pub firmware_version: TpmUint64,
512    pub attested: TpmuAttest,
513}
514
515impl TpmSized for TpmsAttest {
516    const SIZE: usize = size_of::<TpmUint32>()
517        + TpmSt::SIZE
518        + Tpm2bName::SIZE
519        + Tpm2bData::SIZE
520        + TpmsClockInfo::SIZE
521        + size_of::<TpmUint64>()
522        + TpmuAttest::SIZE;
523    fn len(&self) -> usize {
524        size_of::<TpmUint32>()
525            + self.attest_type.len()
526            + self.qualified_signer.len()
527            + self.extra_data.len()
528            + self.clock_info.len()
529            + size_of::<TpmUint64>()
530            + self.attested.len()
531    }
532}
533
534impl TpmMarshal for TpmsAttest {
535    fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
536        crate::basic::TpmUint32::from(TPM_GENERATED_VALUE).marshal(writer)?;
537        self.attest_type.marshal(writer)?;
538        self.qualified_signer.marshal(writer)?;
539        self.extra_data.marshal(writer)?;
540        self.clock_info.marshal(writer)?;
541        self.firmware_version.marshal(writer)?;
542        self.attested.marshal(writer)
543    }
544}
545
546impl TpmUnmarshal for TpmsAttest {
547    fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
548        let (magic, buffer) = TpmUint32::unmarshal(buffer)?;
549        if magic.value() != TPM_GENERATED_VALUE {
550            return Err(TpmError::InvalidMagicNumber {
551                offset: 0,
552                value: u64::from(magic.value()),
553            });
554        }
555
556        let (attest_type, buffer) = TpmSt::unmarshal(buffer)?;
557        let (qualified_signer, buffer) = Tpm2bName::unmarshal(buffer)?;
558        let (extra_data, buffer) = Tpm2bData::unmarshal(buffer)?;
559        let (clock_info, buffer) = TpmsClockInfo::unmarshal(buffer)?;
560        let (firmware_version, buffer) = TpmUint64::unmarshal(buffer)?;
561        let (attested, buffer) = TpmuAttest::unmarshal_tagged(attest_type, buffer)?;
562
563        Ok((
564            Self {
565                attest_type,
566                qualified_signer,
567                extra_data,
568                clock_info,
569                firmware_version,
570                attested,
571            },
572            buffer,
573        ))
574    }
575}
576
577/// Borrowed view over a marshaled [`TpmsAttest`].
578///
579/// The leading magic word is validated against
580/// [`TPM_GENERATED_VALUE`](crate::constant::TPM_GENERATED_VALUE) during the
581/// cast and is therefore not exposed as a field.
582pub struct TpmsAttestView<'a> {
583    /// The attestation structure tag selecting the [`attested`](Self::attested) body.
584    pub attest_type: TpmSt,
585    /// Borrowed qualified name of the signing key.
586    pub qualified_signer: <Tpm2bName as crate::TpmField<'a>>::View,
587    /// Borrowed caller-provided qualifying data.
588    pub extra_data: <Tpm2bData as crate::TpmField<'a>>::View,
589    /// Borrowed TPM clock information.
590    pub clock_info: <TpmsClockInfo as crate::TpmField<'a>>::View,
591    /// TPM firmware version.
592    pub firmware_version: u64,
593    /// Borrowed attestation body selected by [`attest_type`](Self::attest_type).
594    pub attested: TpmuAttestView<'a>,
595}
596
597impl<'a> crate::TpmField<'a> for TpmsAttest {
598    type View = TpmsAttestView<'a>;
599
600    fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
601        let (magic, buf) = <TpmUint32 as crate::TpmField>::cast_prefix_field(buf)?;
602        if magic.value() != TPM_GENERATED_VALUE {
603            return Err(TpmError::InvalidMagicNumber {
604                offset: 0,
605                value: u64::from(magic.value()),
606            });
607        }
608
609        let (attest_type, buf) = <TpmSt as crate::TpmField>::cast_prefix_field(buf)?;
610        let (qualified_signer, buf) = <Tpm2bName as crate::TpmField>::cast_prefix_field(buf)?;
611        let (extra_data, buf) = <Tpm2bData as crate::TpmField>::cast_prefix_field(buf)?;
612        let (clock_info, buf) = <TpmsClockInfo as crate::TpmField>::cast_prefix_field(buf)?;
613        let (firmware_version, buf) = <TpmUint64 as crate::TpmField>::cast_prefix_field(buf)?;
614        let (attested, buf) = TpmuAttest::cast_tagged(attest_type, buf)?;
615
616        Ok((
617            TpmsAttestView {
618                attest_type,
619                qualified_signer,
620                extra_data,
621                clock_info,
622                firmware_version: firmware_version.value(),
623                attested,
624            },
625            buf,
626        ))
627    }
628}
629
630tpm_struct! {
631    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
632    wire: TpmsSchemeHashWire,
633    pub struct TpmsSchemeHash {
634        pub hash_alg: TpmiAlgHash,
635    }
636}
637
638pub type TpmsSchemeHmac = TpmsSchemeHash;
639
640tpm_struct! {
641    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
642    wire: TpmsSchemeXorWire,
643    pub struct TpmsSchemeXor {
644        pub hash_alg: TpmiAlgHash,
645        pub kdf: TpmtKdfScheme,
646    }
647}
648
649tpm_struct! {
650    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
651    wire: TpmsRsaParmsWire,
652    pub struct TpmsRsaParms {
653        pub symmetric: TpmtSymDefObject,
654        pub scheme: TpmtRsaScheme,
655        pub key_bits: TpmUint16,
656        pub exponent: TpmUint32,
657    }
658}
659
660tpm_struct! {
661    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
662    wire: TpmsEccParmsWire,
663    pub struct TpmsEccParms {
664        pub symmetric: TpmtSymDefObject,
665        pub scheme: TpmtEccScheme,
666        pub curve_id: TpmEccCurve,
667        pub kdf: TpmtKdfScheme,
668    }
669}