tpm2_protocol/
message.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, Tpm2bCreationData, Tpm2bData, Tpm2bDigest, Tpm2bEncryptedSecret,
8        Tpm2bMaxBuffer, Tpm2bName, Tpm2bPrivate, Tpm2bPublic, Tpm2bSensitiveCreate, TpmAlgId,
9        TpmCap, TpmCc, TpmRc, TpmRh, TpmSe, TpmSt, TpmiYesNo, TpmlDigest, TpmlDigestValues,
10        TpmlPcrSelection, TpmsAuthCommand, TpmsAuthResponse, TpmsCapabilityData, TpmsContext,
11        TpmtSymDef, TpmtSymDefObject, TpmtTkCreation, TpmtTkHashcheck,
12    },
13    tpm_dispatch, tpm_response, tpm_struct, TpmBuild, TpmErrorKind, TpmList, TpmParse,
14    TpmPersistent, TpmResult, TpmSession, TpmSized, TpmTransient, TpmWriter,
15};
16use core::{convert::TryFrom, fmt::Debug, mem::size_of};
17
18/// The maximum number of handles a command can have.
19pub const MAX_HANDLES: usize = 8;
20/// The maximum number of sessions a command can have.
21pub const MAX_SESSIONS: usize = 8;
22
23/// A fixed-capacity list for TPM handles.
24pub type TpmHandles = TpmList<u32, MAX_HANDLES>;
25/// A fixed-capacity list for command authorization sessions.
26pub type TpmAuthCommands = TpmList<TpmsAuthCommand, MAX_SESSIONS>;
27/// A fixed-capacity list for response authorization sessions.
28pub type TpmAuthResponses = TpmList<TpmsAuthResponse, MAX_SESSIONS>;
29
30/// A trait for TPM commands and responses that provides header information.
31pub trait TpmHeader<'a>: TpmBuild + TpmParse<'a> + Debug + TpmSized {
32    const COMMAND: TpmCc;
33    const NO_SESSIONS: bool;
34    const WITH_SESSIONS: bool;
35    const HANDLES: usize;
36}
37
38/// The result of parsing a TPM response, containing either the successfully parsed
39/// body and auth areas (with a success or warning code) or a fatal error code.
40pub type TpmParseResult<'a> = Result<(TpmRc, TpmResponseBody, TpmAuthResponses), (TpmRc, &'a [u8])>;
41
42pub const TPM_HEADER_SIZE: usize = 10;
43
44/// Builds a TPM command into a writer and returns the total bytes written.
45///
46/// # Errors
47///
48/// * `TpmErrorKind::ValueTooLarge` if the command has unknown state
49pub fn tpm_build_command<'a, C>(
50    command: &C,
51    tag: TpmSt,
52    handles: Option<&[u32]>,
53    sessions: &[TpmsAuthCommand],
54    writer: &mut crate::TpmWriter,
55) -> TpmResult<()>
56where
57    C: TpmHeader<'a>,
58{
59    match tag {
60        TpmSt::NoSessions => {
61            if !C::NO_SESSIONS {
62                return Err(TpmErrorKind::InvalidTag {
63                    type_name: "TpmSt",
64                    expected: TpmSt::Sessions as u16,
65                    got: tag as u16,
66                });
67            }
68        }
69        TpmSt::Sessions => {
70            if !C::WITH_SESSIONS {
71                return Err(TpmErrorKind::InvalidTag {
72                    type_name: "TpmSt",
73                    expected: TpmSt::NoSessions as u16,
74                    got: tag as u16,
75                });
76            }
77        }
78        _ => {
79            return Err(TpmErrorKind::InvalidValue);
80        }
81    }
82
83    let handles = handles.unwrap_or(&[]);
84    if handles.len() != C::HANDLES {
85        return Err(TpmErrorKind::InternalError);
86    }
87
88    let handle_area_len = core::mem::size_of_val(handles);
89    let parameters_len = command.len();
90
91    let auth_area_len = if tag == TpmSt::Sessions {
92        let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
93        size_of::<u32>() + sessions_len
94    } else {
95        0
96    };
97
98    let total_body_len = handle_area_len + auth_area_len + parameters_len;
99    let command_size =
100        u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmErrorKind::ValueTooLarge)?;
101
102    (tag as u16).build(writer)?;
103    command_size.build(writer)?;
104    (C::COMMAND as u32).build(writer)?;
105
106    for handle in handles {
107        handle.build(writer)?;
108    }
109
110    if tag == TpmSt::Sessions {
111        let sessions_len_u32 = u32::try_from(auth_area_len - size_of::<u32>())
112            .map_err(|_| TpmErrorKind::ValueTooLarge)?;
113        sessions_len_u32.build(writer)?;
114        for s in sessions {
115            s.build(writer)?;
116        }
117    }
118
119    command.build(writer)
120}
121
122/// Builds a TPM response.
123///
124/// # Errors
125///
126/// * `TpmErrorKind::ValueTooLarge` if the response has unknown state
127pub fn tpm_build_response<R>(
128    response: &R,
129    sessions: &[TpmsAuthResponse],
130    rc: TpmRc,
131    writer: &mut crate::TpmWriter,
132) -> TpmResult<()>
133where
134    R: for<'a> TpmHeader<'a>,
135{
136    let tag = if !rc.is_error() && R::WITH_SESSIONS && !sessions.is_empty() {
137        TpmSt::Sessions
138    } else {
139        TpmSt::NoSessions
140    };
141
142    if rc.is_error() {
143        (TpmSt::NoSessions as u16).build(writer)?;
144        u32::try_from(TPM_HEADER_SIZE)?.build(writer)?;
145        rc.value().build(writer)?;
146        return Ok(());
147    }
148
149    let body_len = response.len();
150    let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
151    let total_body_len = body_len + sessions_len;
152    let response_size =
153        u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmErrorKind::ValueTooLarge)?;
154
155    (tag as u16).build(writer)?;
156    response_size.build(writer)?;
157    rc.value().build(writer)?;
158
159    response.build(writer)?;
160
161    if tag == TpmSt::Sessions {
162        for s in sessions {
163            s.build(writer)?;
164        }
165    }
166    Ok(())
167}
168
169/// Parses a command from a TPM command buffer.
170///
171/// # Errors
172///
173/// * `TpmErrorKind::Boundary` if the buffer is too small
174/// * `TpmErrorKind::InvalidDiscriminant` if the buffer contains an unsupported command code or unexpected byte
175/// * `TpmErrorKind::TrailingData` if the command has after spurious data left
176pub fn tpm_parse_command(buf: &[u8]) -> TpmResult<(TpmHandles, TpmCommandBody, TpmAuthCommands)> {
177    if buf.len() < TPM_HEADER_SIZE {
178        return Err(TpmErrorKind::Boundary);
179    }
180    let command_len = buf.len();
181
182    let (tag_raw, buf) = u16::parse(buf)?;
183    let tag = TpmSt::try_from(tag_raw).map_err(|()| TpmErrorKind::InvalidDiscriminant {
184        type_name: "TpmSt",
185        value: u64::from(tag_raw),
186    })?;
187    let (size, buf) = u32::parse(buf)?;
188    let (cc_raw, mut buf) = u32::parse(buf)?;
189
190    if command_len != size as usize {
191        return Err(TpmErrorKind::Boundary);
192    }
193
194    let cc = TpmCc::try_from(cc_raw).map_err(|()| TpmErrorKind::InvalidDiscriminant {
195        type_name: "TpmCc",
196        value: u64::from(cc_raw),
197    })?;
198    let dispatch = PARSE_COMMAND_MAP
199        .binary_search_by_key(&cc, |d| d.0)
200        .map(|index| &PARSE_COMMAND_MAP[index])
201        .map_err(|_| TpmErrorKind::InvalidDiscriminant {
202            type_name: "TpmCc",
203            value: u64::from(cc_raw),
204        })?;
205
206    if tag == TpmSt::Sessions && !dispatch.2 {
207        return Err(TpmErrorKind::InvalidTag {
208            type_name: "TpmSt",
209            expected: TpmSt::NoSessions as u16,
210            got: tag_raw,
211        });
212    }
213    if tag == TpmSt::NoSessions && !dispatch.1 {
214        return Err(TpmErrorKind::InvalidTag {
215            type_name: "TpmSt",
216            expected: TpmSt::Sessions as u16,
217            got: tag_raw,
218        });
219    }
220
221    let mut handles = TpmHandles::new();
222    for _ in 0..dispatch.3 {
223        let (handle, rest) = u32::parse(buf)?;
224        handles
225            .try_push(handle)
226            .map_err(|_| TpmErrorKind::ValueTooLarge)?;
227        buf = rest;
228    }
229
230    let mut sessions = TpmAuthCommands::new();
231    let param_buf = if tag == TpmSt::Sessions {
232        let (auth_area_size, auth_buf) = u32::parse(buf)?;
233        let auth_area_size = auth_area_size as usize;
234        if auth_buf.len() < auth_area_size {
235            return Err(TpmErrorKind::Boundary);
236        }
237        let (mut auth_area, param_buf) = auth_buf.split_at(auth_area_size);
238        while !auth_area.is_empty() {
239            let (session, rest) = TpmsAuthCommand::parse(auth_area)?;
240            sessions
241                .try_push(session)
242                .map_err(|_| TpmErrorKind::ValueTooLarge)?;
243            auth_area = rest;
244        }
245        if !auth_area.is_empty() {
246            return Err(TpmErrorKind::TrailingData);
247        }
248        param_buf
249    } else {
250        buf
251    };
252
253    let (command_data, remainder) = (dispatch.4)(param_buf)?;
254
255    if !remainder.is_empty() {
256        return Err(TpmErrorKind::TrailingData);
257    }
258
259    Ok((handles, command_data, sessions))
260}
261
262/// Parses a response from a TPM response buffer.
263///
264/// # Errors
265///
266/// * `TpmErrorKind::Boundary` if the buffer is too small
267/// * `TpmErrorKind::InvalidTag` if the tag in the buffer does not match expected
268/// * `TpmErrorKind::InvalidDiscriminant` if the buffer contains an unsupported command code
269/// * `TpmErrorKind::TrailingData` if the response has after spurious data left
270pub fn tpm_parse_response(cc: TpmCc, buf: &[u8]) -> TpmResult<TpmParseResult> {
271    if buf.len() < TPM_HEADER_SIZE {
272        return Err(TpmErrorKind::Boundary);
273    }
274
275    let (tag_raw, remainder) = u16::parse(buf)?;
276    let (size, remainder) = u32::parse(remainder)?;
277    let (code, body_buf) = u32::parse(remainder)?;
278
279    if buf.len() != size as usize {
280        return Err(TpmErrorKind::Boundary);
281    }
282
283    let rc = TpmRc::try_from(code)?;
284    if rc.is_error() {
285        return Ok(Err((rc, body_buf)));
286    }
287
288    let tag = TpmSt::try_from(tag_raw).map_err(|()| TpmErrorKind::InvalidDiscriminant {
289        type_name: "TpmSt",
290        value: u64::from(tag_raw),
291    })?;
292
293    let dispatch = PARSE_RESPONSE_MAP
294        .binary_search_by_key(&cc, |d| d.0)
295        .map(|index| &PARSE_RESPONSE_MAP[index])
296        .map_err(|_| TpmErrorKind::InvalidDiscriminant {
297            type_name: "TpmCc",
298            value: u64::from(cc as u32),
299        })?;
300
301    let (body, mut session_area) = (dispatch.2)(body_buf)?;
302
303    let mut auth_responses = TpmAuthResponses::new();
304    if tag == TpmSt::Sessions {
305        while !session_area.is_empty() {
306            let (session, rest) = TpmsAuthResponse::parse(session_area)?;
307            auth_responses
308                .try_push(session)
309                .map_err(|_| TpmErrorKind::ValueTooLarge)?;
310            session_area = rest;
311        }
312    }
313
314    if !session_area.is_empty() {
315        return Err(TpmErrorKind::TrailingData);
316    }
317
318    Ok(Ok((rc, body, auth_responses)))
319}
320
321tpm_struct!(
322    #[derive(Debug, PartialEq, Eq, Clone)]
323    TpmContextLoadCommand,
324    TpmCc::ContextLoad,
325    true,
326    false,
327    0,
328    {
329        pub context: TpmsContext,
330    }
331);
332
333tpm_struct!(
334    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
335    TpmContextSaveCommand,
336    TpmCc::ContextSave,
337    true,
338    false,
339    1,
340    {}
341);
342
343tpm_struct!(
344    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
345    TpmDictionaryAttackLockResetCommand,
346    TpmCc::DictionaryAttackLockReset,
347    false,
348    true,
349    1,
350    {}
351);
352
353tpm_struct!(
354    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
355    TpmFlushContextCommand,
356    TpmCc::FlushContext,
357    true,
358    false,
359    0,
360    {
361        pub flush_handle: u32,
362    }
363);
364
365tpm_struct!(
366    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
367    TpmUnsealCommand,
368    TpmCc::Unseal,
369    false,
370    true,
371    1,
372    {}
373);
374
375macro_rules! tpm_create {
376    ($name:ident, $cc:expr) => {
377        tpm_struct!(
378            #[derive(Debug, Default, PartialEq, Eq, Clone)]
379            $name,
380            $cc,
381            false,
382            true,
383            1,
384            {
385                pub in_sensitive: Tpm2bSensitiveCreate,
386                pub in_public: Tpm2bPublic,
387                pub outside_info: Tpm2b,
388                pub creation_pcr: TpmlPcrSelection,
389            }
390        );
391    };
392}
393
394tpm_create!(TpmCreateCommand, TpmCc::Create);
395tpm_create!(TpmCreatePrimaryCommand, TpmCc::CreatePrimary);
396
397tpm_struct!(
398    #[derive(Debug, PartialEq, Eq, Clone)]
399    TpmEvictControlCommand,
400    TpmCc::EvictControl,
401    false,
402    true,
403    2,
404    {
405        pub persistent_handle: TpmPersistent,
406    }
407);
408
409tpm_struct!(
410    #[derive(Debug, PartialEq, Eq, Clone)]
411    TpmGetCapabilityCommand,
412    TpmCc::GetCapability,
413    true,
414    true,
415    0,
416    {
417        pub cap: TpmCap,
418        pub property: u32,
419        pub property_count: u32,
420    }
421);
422
423tpm_struct!(
424    #[derive(Debug, PartialEq, Eq, Clone)]
425    TpmHashCommand,
426    TpmCc::Hash,
427    true,
428    false,
429    0,
430    {
431        pub data: Tpm2bMaxBuffer,
432        pub hash_alg: TpmAlgId,
433        pub hierarchy: TpmRh,
434    }
435);
436
437tpm_struct!(
438    #[derive(Debug, PartialEq, Eq, Clone)]
439    TpmImportCommand,
440    TpmCc::Import,
441    false,
442    true,
443    1,
444    {
445        pub encryption_key: Tpm2b,
446        pub object_public: Tpm2bPublic,
447        pub duplicate: Tpm2bPrivate,
448        pub in_sym_seed: Tpm2bEncryptedSecret,
449        pub symmetric_alg: TpmtSymDef,
450    }
451);
452
453tpm_struct!(
454    #[derive(Debug, Default, PartialEq, Eq, Clone)]
455    TpmLoadCommand,
456    TpmCc::Load,
457    false,
458    true,
459    1,
460    {
461        pub in_private: Tpm2bPrivate,
462        pub in_public: Tpm2bPublic,
463    }
464);
465
466tpm_struct!(
467    #[derive(Debug, Default, PartialEq, Eq, Clone)]
468    TpmObjectChangeAuthCommand,
469    TpmCc::ObjectChangeAuth,
470    false,
471    true,
472    2,
473    {
474        pub new_auth: Tpm2bAuth,
475    }
476);
477
478tpm_struct!(
479    #[derive(Debug, PartialEq, Eq, Clone)]
480    TpmPcrEventCommand,
481    TpmCc::PcrEvent,
482    false,
483    true,
484    1,
485    {
486        pub event_data: Tpm2b,
487    }
488);
489
490tpm_struct!(
491    #[derive(Debug, Default, PartialEq, Eq, Clone)]
492    TpmPcrReadCommand,
493    TpmCc::PcrRead,
494    true,
495    false,
496    0,
497    {
498        pub pcr_selection_in: TpmlPcrSelection,
499    }
500);
501
502tpm_struct!(
503    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
504    TpmPolicyAuthValueCommand,
505    TpmCc::PolicyAuthValue,
506    false,
507    true,
508    1,
509    {}
510);
511
512tpm_struct!(
513    #[derive(Debug, PartialEq, Eq, Clone)]
514    TpmPolicyCommandCodeCommand,
515    TpmCc::PolicyCommandCode,
516    false,
517    true,
518    1,
519    {
520        pub code: TpmCc,
521    }
522);
523
524tpm_struct!(
525    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
526    TpmPolicyGetDigestCommand,
527    TpmCc::PolicyGetDigest,
528    false,
529    true,
530    1,
531    {}
532);
533
534#[derive(Debug, Default, PartialEq, Eq, Clone)]
535pub struct TpmPolicyGetDigestResponse {
536    pub policy_digest: Tpm2bDigest,
537}
538impl TpmHeader<'_> for TpmPolicyGetDigestResponse {
539    const COMMAND: TpmCc = TpmCc::PolicyGetDigest;
540    const NO_SESSIONS: bool = false;
541    const WITH_SESSIONS: bool = true;
542    const HANDLES: usize = 0;
543}
544impl TpmSized for TpmPolicyGetDigestResponse {
545    const SIZE: usize = <Tpm2bDigest>::SIZE;
546    fn len(&self) -> usize {
547        self.policy_digest.len()
548    }
549}
550impl TpmBuild for TpmPolicyGetDigestResponse {
551    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
552        self.policy_digest.build(writer)
553    }
554}
555impl<'a> TpmParse<'a> for TpmPolicyGetDigestResponse {
556    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
557        if buf.is_empty() {
558            return Ok((Self::default(), buf));
559        }
560        let (policy_digest, buf) = Tpm2bDigest::parse(buf)?;
561        Ok((Self { policy_digest }, buf))
562    }
563}
564
565tpm_struct!(
566    #[derive(Debug, Default, PartialEq, Eq, Clone)]
567    TpmPolicyOrCommand,
568    TpmCc::PolicyOR,
569    false,
570    true,
571    1,
572    {
573        pub p_hash_list: TpmlDigest,
574    }
575);
576
577tpm_struct!(
578    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
579    TpmPolicyPasswordCommand,
580    TpmCc::PolicyPassword,
581    false,
582    true,
583    1,
584    {}
585);
586
587tpm_struct!(
588    #[derive(Debug, Default, PartialEq, Eq, Clone)]
589    TpmPolicyPcrCommand,
590    TpmCc::PolicyPcr,
591    false,
592    true,
593    1,
594    {
595        pub pcr_digest: Tpm2bDigest,
596        pub pcrs: TpmlPcrSelection,
597    }
598);
599
600tpm_struct!(
601    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
602    TpmPolicyRestartCommand,
603    TpmCc::PolicyRestart,
604    false,
605    true,
606    0,
607    {}
608);
609
610tpm_struct!(
611    #[derive(Debug, Default, PartialEq, Eq, Clone)]
612    TpmPolicySecretCommand,
613    TpmCc::PolicySecret,
614    false,
615    true,
616    2,
617    {
618        pub nonce_tpm: Tpm2b,
619        pub cp_hash_a: Tpm2bDigest,
620        pub policy_ref: Tpm2b,
621        pub expiration: i32,
622    }
623);
624
625tpm_struct!(
626    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
627    TpmReadPublicCommand,
628    TpmCc::ReadPublic,
629    true,
630    true,
631    1,
632    {}
633);
634
635tpm_struct!(
636    #[derive(Debug, Default, PartialEq, Eq, Clone)]
637    TpmStartAuthSessionCommand,
638    TpmCc::StartAuthSession,
639    true,
640    true,
641    2,
642    {
643        pub nonce_caller: Tpm2b,
644        pub encrypted_salt: Tpm2b,
645        pub session_type: TpmSe,
646        pub symmetric: TpmtSymDefObject,
647        pub auth_hash: TpmAlgId,
648    }
649);
650
651tpm_struct!(
652    #[derive(Debug, PartialEq, Eq, Clone)]
653    TpmVendorTcgTestCommand,
654    TpmCc::VendorTcgTest,
655    true,
656    false,
657    0,
658    {
659        pub input_data: Tpm2bData,
660    }
661);
662
663tpm_struct!(
664    #[derive(Debug, PartialEq, Eq, Clone)]
665    TpmContextLoadResponse,
666    TpmCc::ContextLoad,
667    true,
668    false,
669    0,
670    {
671        pub loaded_handle: TpmTransient,
672    }
673);
674
675tpm_struct!(
676    #[derive(Debug, PartialEq, Eq, Clone)]
677    TpmContextSaveResponse,
678    TpmCc::ContextSave,
679    true,
680    false,
681    0,
682    {
683        pub context: TpmsContext,
684    }
685);
686
687tpm_struct!(
688    #[derive(Debug, PartialEq, Eq, Clone)]
689    TpmHashResponse,
690    TpmCc::Hash,
691    true,
692    false,
693    0,
694    {
695        pub out_hash: Tpm2bDigest,
696        pub validation: TpmtTkHashcheck,
697    }
698);
699
700tpm_struct!(
701    #[derive(Debug, Default, PartialEq, Eq, Clone)]
702    TpmImportResponse,
703    TpmCc::Import,
704    false,
705    true,
706    0,
707    {
708        pub out_private: Tpm2bPrivate,
709    }
710);
711
712tpm_response!(
713    #[derive(Debug, Default, PartialEq, Eq, Clone)]
714    TpmObjectChangeAuthResponse,
715    TpmCc::ObjectChangeAuth,
716    false,
717    true,
718    {
719        pub out_private: Tpm2bPrivate,
720    }
721);
722
723tpm_struct!(
724    #[derive(Debug, Default, PartialEq, Eq, Clone)]
725    TpmPcrReadResponse,
726    TpmCc::PcrRead,
727    true,
728    false,
729    0,
730    {
731        pub pcr_update_counter: u32,
732        pub pcr_selection_out: TpmlPcrSelection,
733        pub pcr_values: TpmlDigest,
734    }
735);
736
737tpm_struct!(
738    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
739    TpmPolicyAuthValueResponse,
740    TpmCc::PolicyAuthValue,
741    false,
742    true,
743    0,
744    {}
745);
746
747tpm_struct!(
748    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
749    TpmPolicyCommandCodeResponse,
750    TpmCc::PolicyCommandCode,
751    false,
752    true,
753    0,
754    {}
755);
756
757tpm_struct!(
758    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
759    TpmPolicyOrResponse,
760    TpmCc::PolicyOR,
761    false,
762    true,
763    0,
764    {}
765);
766
767tpm_struct!(
768    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
769    TpmPolicyPasswordResponse,
770    TpmCc::PolicyPassword,
771    false,
772    true,
773    0,
774    {}
775);
776
777tpm_struct!(
778    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
779    TpmPolicyPcrResponse,
780    TpmCc::PolicyPcr,
781    false,
782    true,
783    0,
784    {}
785);
786
787tpm_struct!(
788    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
789    TpmPolicyRestartResponse,
790    TpmCc::PolicyRestart,
791    false,
792    true,
793    0,
794    {}
795);
796
797tpm_struct!(
798    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
799    TpmPolicySecretResponse,
800    TpmCc::PolicySecret,
801    false,
802    true,
803    0,
804    {}
805);
806
807tpm_response!(
808    #[derive(Debug, Default, PartialEq, Eq, Clone)]
809    TpmReadPublicResponse,
810    TpmCc::ReadPublic,
811    true,
812    false,
813    {
814        pub out_public: Tpm2bPublic,
815        pub name: Tpm2bName,
816        pub qualified_name: Tpm2bName,
817    }
818);
819
820tpm_struct!(
821    #[derive(Debug, Default, PartialEq, Eq, Clone)]
822    TpmStartAuthSessionResponse,
823    TpmCc::StartAuthSession,
824    true,
825    false,
826    0,
827    {
828        pub session_handle: TpmSession,
829        pub nonce_tpm: Tpm2b,
830    }
831);
832
833tpm_struct!(
834    #[derive(Debug, PartialEq, Eq, Clone)]
835    TpmVendorTcgTestResponse,
836    TpmCc::VendorTcgTest,
837    true,
838    false,
839    0,
840    {
841        pub output_data: Tpm2bData,
842    }
843);
844
845tpm_response!(
846    #[derive(Debug, PartialEq, Eq, Clone)]
847    TpmCreatePrimaryResponse,
848    TpmCc::CreatePrimary,
849    false,
850    true,
851    pub object_handle: TpmTransient,
852    {
853        pub out_public: Tpm2bPublic,
854        pub creation_data: Tpm2bCreationData,
855        pub creation_hash: Tpm2bDigest,
856        pub creation_ticket: TpmtTkCreation,
857        pub name: Tpm2bName,
858    }
859);
860
861tpm_response!(
862    #[derive(Debug, PartialEq, Eq, Clone)]
863    TpmCreateResponse,
864    TpmCc::Create,
865    false,
866    true,
867    {
868        pub out_private: Tpm2bPrivate,
869        pub out_public: Tpm2bPublic,
870        pub creation_data: Tpm2bCreationData,
871        pub creation_hash: Tpm2bDigest,
872        pub creation_ticket: TpmtTkCreation,
873    }
874);
875
876tpm_struct!(
877    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
878    TpmDictionaryAttackLockResetResponse,
879    TpmCc::DictionaryAttackLockReset,
880    false,
881    true,
882    0,
883    {}
884);
885
886tpm_struct!(
887    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
888    TpmEvictControlResponse,
889    TpmCc::EvictControl,
890    false,
891    true,
892    0,
893    {}
894);
895
896tpm_struct!(
897    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
898    TpmFlushContextResponse,
899    TpmCc::FlushContext,
900    true,
901    false,
902    0,
903    {}
904);
905
906tpm_struct!(
907    #[derive(Debug, PartialEq, Eq, Clone)]
908    TpmGetCapabilityResponse,
909    TpmCc::GetCapability,
910    true,
911    false,
912    0,
913    {
914        pub more_data: TpmiYesNo,
915        pub capability_data: TpmsCapabilityData,
916    }
917);
918
919tpm_response!(
920    #[derive(Debug, PartialEq, Eq, Clone)]
921    TpmLoadResponse,
922    TpmCc::Load,
923    false,
924    true,
925    pub object_handle: TpmTransient,
926    {
927        pub name: Tpm2bName,
928    }
929);
930
931tpm_response!(
932    #[derive(Debug, Default, PartialEq, Eq, Clone)]
933    TpmPcrEventResponse,
934    TpmCc::PcrEvent,
935    false,
936    true,
937    {
938        pub digests: TpmlDigestValues,
939    }
940);
941
942tpm_response!(
943    #[derive(Debug, Default, PartialEq, Eq, Clone)]
944    TpmUnsealResponse,
945    TpmCc::Unseal,
946    false,
947    true,
948    {
949        pub out_data: Tpm2b,
950    }
951);
952
953tpm_dispatch! {
954    (TpmEvictControlCommand, TpmEvictControlResponse, EvictControl),
955    (TpmCreatePrimaryCommand, TpmCreatePrimaryResponse, CreatePrimary),
956    (TpmDictionaryAttackLockResetCommand, TpmDictionaryAttackLockResetResponse, DictionaryAttackLockReset),
957    (TpmPcrEventCommand, TpmPcrEventResponse, PcrEvent),
958    (TpmObjectChangeAuthCommand, TpmObjectChangeAuthResponse, ObjectChangeAuth),
959    (TpmPolicySecretCommand, TpmPolicySecretResponse, PolicySecret),
960    (TpmCreateCommand, TpmCreateResponse, Create),
961    (TpmImportCommand, TpmImportResponse, Import),
962    (TpmLoadCommand, TpmLoadResponse, Load),
963    (TpmUnsealCommand, TpmUnsealResponse, Unseal),
964    (TpmContextLoadCommand, TpmContextLoadResponse, ContextLoad),
965    (TpmContextSaveCommand, TpmContextSaveResponse, ContextSave),
966    (TpmFlushContextCommand, TpmFlushContextResponse, FlushContext),
967    (TpmPolicyAuthValueCommand, TpmPolicyAuthValueResponse, PolicyAuthValue),
968    (TpmPolicyCommandCodeCommand, TpmPolicyCommandCodeResponse, PolicyCommandCode),
969    (TpmPolicyOrCommand, TpmPolicyOrResponse, PolicyOr),
970    (TpmReadPublicCommand, TpmReadPublicResponse, ReadPublic),
971    (TpmStartAuthSessionCommand, TpmStartAuthSessionResponse, StartAuthSession),
972    (TpmGetCapabilityCommand, TpmGetCapabilityResponse, GetCapability),
973    (TpmHashCommand, TpmHashResponse, Hash),
974    (TpmPcrReadCommand, TpmPcrReadResponse, PcrRead),
975    (TpmPolicyPcrCommand, TpmPolicyPcrResponse, PolicyPcr),
976    (TpmPolicyRestartCommand, TpmPolicyRestartResponse, PolicyRestart),
977    (TpmPolicyGetDigestCommand, TpmPolicyGetDigestResponse, PolicyGetDigest),
978    (TpmPolicyPasswordCommand, TpmPolicyPasswordResponse, PolicyPassword),
979    (TpmVendorTcgTestCommand, TpmVendorTcgTestResponse, VendorTcgTest),
980}