tpm2_protocol/message/
build.rs1use crate::{
6 data::{TpmRc, TpmSt, TpmsAuthCommand, TpmsAuthResponse},
7 message::{TpmHeader, TpmHeaderCommand, 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 sessions: &[TpmsAuthCommand],
21 writer: &mut crate::TpmWriter,
22) -> TpmResult<()>
23where
24 C: TpmHeaderCommand,
25{
26 match tag {
27 TpmSt::NoSessions => {
28 if !C::NO_SESSIONS {
29 return Err(TpmErrorKind::InvalidTag {
30 type_name: "TpmSt",
31 expected: TpmSt::Sessions as u16,
32 got: tag as u16,
33 });
34 }
35 }
36 TpmSt::Sessions => {
37 if !C::WITH_SESSIONS {
38 return Err(TpmErrorKind::InvalidTag {
39 type_name: "TpmSt",
40 expected: TpmSt::NoSessions as u16,
41 got: tag as u16,
42 });
43 }
44 }
45 _ => {
46 return Err(TpmErrorKind::InvalidValue);
47 }
48 }
49
50 let handle_area_size = C::HANDLES * size_of::<u32>();
51 let param_area_size = command.len() - handle_area_size;
52 let auth_area_size = if tag == TpmSt::Sessions {
53 let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
54 size_of::<u32>() + sessions_len
55 } else {
56 0
57 };
58
59 let total_body_len = handle_area_size + auth_area_size + param_area_size;
60 let command_size =
61 u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmErrorKind::ValueTooLarge)?;
62
63 (tag as u16).build(writer)?;
64 command_size.build(writer)?;
65 (C::COMMAND as u32).build(writer)?;
66
67 command.build_handles(writer)?;
68
69 if tag == TpmSt::Sessions {
70 let sessions_len_u32 = u32::try_from(auth_area_size - size_of::<u32>())
71 .map_err(|_| TpmErrorKind::ValueTooLarge)?;
72 sessions_len_u32.build(writer)?;
73 for s in sessions {
74 s.build(writer)?;
75 }
76 }
77
78 command.build_parameters(writer)
79}
80
81pub fn tpm_build_response<R>(
87 response: &R,
88 sessions: &[TpmsAuthResponse],
89 rc: TpmRc,
90 writer: &mut crate::TpmWriter,
91) -> TpmResult<()>
92where
93 R: TpmHeader,
94{
95 let tag = if !rc.is_error() && R::WITH_SESSIONS && !sessions.is_empty() {
96 TpmSt::Sessions
97 } else {
98 TpmSt::NoSessions
99 };
100
101 if rc.is_error() {
102 (TpmSt::NoSessions as u16).build(writer)?;
103 u32::try_from(TPM_HEADER_SIZE)?.build(writer)?;
104 rc.value().build(writer)?;
105 return Ok(());
106 }
107
108 let body_len = response.len();
109 let sessions_len: usize = sessions.iter().map(TpmSized::len).sum();
110 let total_body_len = body_len + sessions_len;
111 let response_size =
112 u32::try_from(TPM_HEADER_SIZE + total_body_len).map_err(|_| TpmErrorKind::ValueTooLarge)?;
113
114 (tag as u16).build(writer)?;
115 response_size.build(writer)?;
116 rc.value().build(writer)?;
117
118 response.build(writer)?;
119
120 if tag == TpmSt::Sessions {
121 for s in sessions {
122 s.build(writer)?;
123 }
124 }
125 Ok(())
126}