tpm2_protocol/message/
build.rs1use crate::{
6 constant::TPM_HEADER_SIZE,
7 data::{TpmRc, TpmRcBase, TpmSt, TpmsAuthCommand, TpmsAuthResponse},
8 message::{TpmBodyBuild, TpmHeader},
9 TpmBuild, TpmError, TpmResult, TpmSized,
10};
11use core::{convert::TryFrom, mem::size_of};
12
13pub fn tpm_build_command<C>(
19 command: &C,
20 tag: TpmSt,
21 sessions: &[TpmsAuthCommand],
22 writer: &mut crate::TpmWriter,
23) -> TpmResult<()>
24where
25 C: TpmHeader + TpmBodyBuild,
26{
27 if tag != TpmSt::NoSessions && tag != TpmSt::Sessions {
28 return Err(TpmError::MalformedData);
29 }
30
31 let handle_area_size = C::HANDLES * size_of::<u32>();
32 let param_area_size = command.len() - handle_area_size;
33 let auth_area_size = if tag == TpmSt::Sessions {
34 let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
35 size_of::<u32>() + sessions_len
36 } else {
37 0
38 };
39
40 let total_body_len = handle_area_size + auth_area_size + param_area_size;
41 let command_size =
42 u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmError::CapacityExceeded)?;
43
44 (tag as u16).build(writer)?;
45 command_size.build(writer)?;
46 (C::CC as u32).build(writer)?;
47
48 command.build_handles(writer)?;
49
50 if tag == TpmSt::Sessions {
51 let sessions_len = u32::try_from(auth_area_size - size_of::<u32>())
52 .map_err(|_| TpmError::CapacityExceeded)?;
53 sessions_len.build(writer)?;
54 for s in sessions {
55 s.build(writer)?;
56 }
57 }
58
59 command.build_parameters(writer)
60}
61
62pub fn tpm_build_response<R>(
68 response: &R,
69 sessions: &[TpmsAuthResponse],
70 rc: TpmRc,
71 writer: &mut crate::TpmWriter,
72) -> TpmResult<()>
73where
74 R: TpmHeader + TpmBodyBuild,
75{
76 if !matches!(rc, TpmRc::Fmt0(TpmRcBase::Success)) {
77 (TpmSt::NoSessions as u16).build(writer)?;
78 u32::try_from(TPM_HEADER_SIZE)?.build(writer)?;
79 rc.value().build(writer)?;
80 return Ok(());
81 }
82
83 let tag = if sessions.is_empty() {
84 TpmSt::NoSessions
85 } else {
86 TpmSt::Sessions
87 };
88
89 let handle_area_size = R::HANDLES * size_of::<u32>();
90 let param_area_size = response.len() - handle_area_size;
91 let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
92
93 let parameter_area_size_field_len = if tag == TpmSt::Sessions {
94 size_of::<u32>()
95 } else {
96 0
97 };
98
99 let total_body_len =
100 handle_area_size + parameter_area_size_field_len + param_area_size + sessions_len;
101
102 let response_size =
103 u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmError::CapacityExceeded)?;
104
105 (tag as u16).build(writer)?;
106 response_size.build(writer)?;
107 rc.value().build(writer)?;
108
109 response.build_handles(writer)?;
110
111 if tag == TpmSt::Sessions {
112 let params_len = u32::try_from(param_area_size).map_err(|_| TpmError::CapacityExceeded)?;
113 params_len.build(writer)?;
114 }
115
116 response.build_parameters(writer)?;
117
118 if tag == TpmSt::Sessions {
119 for s in sessions {
120 s.build(writer)?;
121 }
122 }
123 Ok(())
124}