tpm2_protocol/message/
build.rs1use crate::{
6 data::{TpmRc, TpmSt, TpmsAuthCommand, TpmsAuthResponse},
7 message::{TpmHeader, TPM_HEADER_SIZE},
8 TpmBuild, TpmErrorKind, TpmResult, TpmSized,
9};
10use core::mem::size_of;
11
12pub fn tpm_build_command<C>(
18 command: &C,
19 tag: TpmSt,
20 handles: Option<&[u32]>,
21 sessions: &[TpmsAuthCommand],
22 writer: &mut crate::TpmWriter,
23) -> TpmResult<()>
24where
25 C: TpmHeader,
26{
27 match tag {
28 TpmSt::NoSessions => {
29 if !C::NO_SESSIONS {
30 return Err(TpmErrorKind::InvalidTag {
31 type_name: "TpmSt",
32 expected: TpmSt::Sessions as u16,
33 got: tag as u16,
34 });
35 }
36 }
37 TpmSt::Sessions => {
38 if !C::WITH_SESSIONS {
39 return Err(TpmErrorKind::InvalidTag {
40 type_name: "TpmSt",
41 expected: TpmSt::NoSessions as u16,
42 got: tag as u16,
43 });
44 }
45 }
46 _ => {
47 return Err(TpmErrorKind::InvalidValue);
48 }
49 }
50
51 let handles = handles.unwrap_or(&[]);
52 if handles.len() != C::HANDLES {
53 return Err(TpmErrorKind::InternalError);
54 }
55
56 let handle_area_len = core::mem::size_of_val(handles);
57 let parameters_len = command.len();
58
59 let auth_area_len = if tag == TpmSt::Sessions {
60 let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
61 size_of::<u32>() + sessions_len
62 } else {
63 0
64 };
65
66 let total_body_len = handle_area_len + auth_area_len + parameters_len;
67 let command_size =
68 u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmErrorKind::ValueTooLarge)?;
69
70 (tag as u16).build(writer)?;
71 command_size.build(writer)?;
72 (C::COMMAND as u32).build(writer)?;
73
74 for handle in handles {
75 handle.build(writer)?;
76 }
77
78 if tag == TpmSt::Sessions {
79 let sessions_len_u32 = u32::try_from(auth_area_len - size_of::<u32>())
80 .map_err(|_| TpmErrorKind::ValueTooLarge)?;
81 sessions_len_u32.build(writer)?;
82 for s in sessions {
83 s.build(writer)?;
84 }
85 }
86
87 command.build(writer)
88}
89
90pub fn tpm_build_response<R>(
96 response: &R,
97 sessions: &[TpmsAuthResponse],
98 rc: TpmRc,
99 writer: &mut crate::TpmWriter,
100) -> TpmResult<()>
101where
102 R: TpmHeader,
103{
104 let tag = if !rc.is_error() && R::WITH_SESSIONS && !sessions.is_empty() {
105 TpmSt::Sessions
106 } else {
107 TpmSt::NoSessions
108 };
109
110 if rc.is_error() {
111 (TpmSt::NoSessions as u16).build(writer)?;
112 u32::try_from(TPM_HEADER_SIZE)?.build(writer)?;
113 rc.value().build(writer)?;
114 return Ok(());
115 }
116
117 let body_len = response.len();
118 let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
119 let total_body_len = body_len + sessions_len;
120 let response_size =
121 u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmErrorKind::ValueTooLarge)?;
122
123 (tag as u16).build(writer)?;
124 response_size.build(writer)?;
125 rc.value().build(writer)?;
126
127 response.build(writer)?;
128
129 if tag == TpmSt::Sessions {
130 for s in sessions {
131 s.build(writer)?;
132 }
133 }
134 Ok(())
135}