tss_esapi/context/tpm_commands/integrity_collection_pcr.rs
1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4 handles::PcrHandle,
5 structures::{DigestList, DigestValues, PcrSelectionList},
6 tss2_esys::{Esys_PCR_Extend, Esys_PCR_Read, Esys_PCR_Reset},
7 Context, Error, Result,
8};
9use log::error;
10use std::convert::{TryFrom, TryInto};
11use std::ptr::null_mut;
12
13impl Context {
14 /// Extends a PCR with the specified digests.
15 ///
16 /// # Arguments
17 /// * `pcr_handle`- A [PcrHandle] to the PCR slot that is to be extended.
18 /// * `digests` - The [DigestValues] with which the slot shall be extended.
19 ///
20 /// # Details
21 /// This method is used to cause an update to the indicated PCR. The digests param
22 /// contains the digests for specific algorithms that are to be used.
23 ///
24 /// # Example
25 ///
26 /// ```rust
27 /// # use tss_esapi::{
28 /// # Context, TctiNameConf,
29 /// # constants::SessionType,
30 /// # attributes::SessionAttributesBuilder,
31 /// # handles::PcrHandle,
32 /// # structures::{Digest, SymmetricDefinition},
33 /// # };
34 /// # use std::{env, str::FromStr};
35 /// # // Create context
36 /// # let mut context =
37 /// # Context::new(
38 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
39 /// # ).expect("Failed to create Context");
40 /// # // Create session for a pcr
41 /// # let pcr_session = context
42 /// # .start_auth_session(
43 /// # None,
44 /// # None,
45 /// # None,
46 /// # SessionType::Hmac,
47 /// # SymmetricDefinition::AES_256_CFB,
48 /// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
49 /// # )
50 /// # .expect("Failed to create session")
51 /// # .expect("Received invalid handle");
52 /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
53 /// # .with_decrypt(true)
54 /// # .with_encrypt(true)
55 /// # .build();
56 /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask)
57 /// # .expect("Failed to set attributes on session");
58 /// #
59 /// # let digest_sha1 = Digest::try_from(vec![
60 /// # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
61 /// # ])
62 /// # .expect("Failed to create sha1 Digest from data");
63 /// #
64 /// # let digest_sha256 = Digest::try_from(vec![
65 /// # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
66 /// # 24, 25, 26, 27, 28, 29, 30, 31, 32,
67 /// # ]).expect("Failed to create Sha256 Digest from data");
68 /// use std::convert::TryFrom;
69 /// use tss_esapi::{
70 /// structures::{DigestValues},
71 /// interface_types::algorithm::HashingAlgorithm,
72 /// };
73 /// // Extend both sha256 and sha1
74 /// let mut vals = DigestValues::new();
75 /// vals.set(
76 /// HashingAlgorithm::Sha1,
77 /// digest_sha1,
78 /// );
79 /// vals.set(
80 /// HashingAlgorithm::Sha256,
81 /// digest_sha256,
82 /// );
83 /// // Use pcr_session for authorization when extending
84 /// // PCR 16 with the values for the banks specified in
85 /// // vals.
86 /// context.execute_with_session(Some(pcr_session), |ctx| {
87 /// ctx.pcr_extend(PcrHandle::Pcr16, vals).expect("Call to pcr_extend failed");
88 /// });
89 /// ```
90 pub fn pcr_extend(&mut self, pcr_handle: PcrHandle, digests: DigestValues) -> Result<()> {
91 let ret = unsafe {
92 Esys_PCR_Extend(
93 self.mut_context(),
94 pcr_handle.into(),
95 self.optional_session_1(),
96 self.optional_session_2(),
97 self.optional_session_3(),
98 &digests.try_into()?,
99 )
100 };
101 let ret = Error::from_tss_rc(ret);
102
103 if ret.is_success() {
104 Ok(())
105 } else {
106 error!("Error when extending PCR: {}", ret);
107 Err(ret)
108 }
109 }
110
111 // Missing function: PCR_Event
112
113 /// Reads the values of a PCR.
114 ///
115 /// # Arguments
116 /// * `pcr_selection_list` - A [PcrSelectionList] that contains pcr slots in
117 /// different banks that is going to be read.
118 ///
119 /// # Details
120 /// The provided [PcrSelectionList] contains the pcr slots in the different
121 /// banks that is going to be read. It is possible to select more pcr slots
122 /// then what will fit in the returned result so the method returns a [PcrSelectionList]
123 /// that indicates what values were read. The values that were read are returned
124 /// in a [DigestList].
125 ///
126 /// # Errors
127 /// * Several different errors can occur if conversion of return
128 /// data fails.
129 ///
130 /// # Example
131 ///
132 /// ```rust
133 /// # use tss_esapi::{Context, TctiNameConf};
134 /// # use std::{env, str::FromStr};
135 /// # // Create context
136 /// # let mut context =
137 /// # Context::new(
138 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
139 /// # ).expect("Failed to create Context");
140 /// use tss_esapi::{
141 /// interface_types::algorithm::HashingAlgorithm,
142 /// structures::{PcrSelectionListBuilder, PcrSlot},
143 /// };
144 /// // Create PCR selection list with slots in a bank
145 /// // that is going to be read.
146 /// let pcr_selection_list = PcrSelectionListBuilder::new()
147 /// .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1])
148 /// .build()
149 /// .expect("Failed to build PcrSelectionList");
150 ///
151 /// let (update_counter, read_pcr_list, digest_list) = context.pcr_read(pcr_selection_list)
152 /// .expect("Call to pcr_read failed");
153 /// ```
154 pub fn pcr_read(
155 &mut self,
156 pcr_selection_list: PcrSelectionList,
157 ) -> Result<(u32, PcrSelectionList, DigestList)> {
158 let mut pcr_update_counter: u32 = 0;
159 let mut pcr_selection_out_ptr = null_mut();
160 let mut pcr_values_ptr = null_mut();
161 let ret = unsafe {
162 Esys_PCR_Read(
163 self.mut_context(),
164 self.optional_session_1(),
165 self.optional_session_2(),
166 self.optional_session_3(),
167 &pcr_selection_list.into(),
168 &mut pcr_update_counter,
169 &mut pcr_selection_out_ptr,
170 &mut pcr_values_ptr,
171 )
172 };
173 let ret = Error::from_tss_rc(ret);
174
175 if ret.is_success() {
176 Ok((
177 pcr_update_counter,
178 PcrSelectionList::try_from(Context::ffi_data_to_owned(pcr_selection_out_ptr))?,
179 DigestList::try_from(Context::ffi_data_to_owned(pcr_values_ptr))?,
180 ))
181 } else {
182 error!("Error when reading PCR: {}", ret);
183 Err(ret)
184 }
185 }
186
187 // Missing function: PCR_Allocate
188 // Missing function: PCR_SetAuthPolicy
189 // Missing function: PCR_SetAuthValue
190
191 /// Resets the value in a PCR.
192 ///
193 /// # Arguments
194 /// * `pcr_handle` - A [PcrHandle] to the PCR slot that is to be reset.
195 ///
196 /// # Details
197 /// If the attributes of the PCR indicates that it is allowed
198 /// to reset them and the proper authorization is provided then
199 /// this method can be used to set the the specified PCR in all
200 /// banks to 0.
201 ///
202 /// # Example
203 ///
204 /// ```rust
205 /// # use tss_esapi::{
206 /// # Context, TctiNameConf,
207 /// # constants::SessionType,
208 /// # attributes::SessionAttributesBuilder,
209 /// # structures::SymmetricDefinition,
210 /// # interface_types::algorithm::HashingAlgorithm,
211 /// # };
212 /// # use std::{env, str::FromStr};
213 /// # // Create context
214 /// # let mut context =
215 /// # Context::new(
216 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
217 /// # ).expect("Failed to create Context");
218 /// # // Create session for a pcr
219 /// # let pcr_session = context
220 /// # .start_auth_session(
221 /// # None,
222 /// # None,
223 /// # None,
224 /// # SessionType::Hmac,
225 /// # SymmetricDefinition::AES_256_CFB,
226 /// # HashingAlgorithm::Sha256,
227 /// # )
228 /// # .expect("Failed to create session")
229 /// # .expect("Received invalid handle");
230 /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
231 /// # .with_decrypt(true)
232 /// # .with_encrypt(true)
233 /// # .build();
234 /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask)
235 /// # .expect("Failed to set attributes on session");
236 ///
237 /// use tss_esapi::{
238 /// handles::PcrHandle
239 /// };
240 /// context.execute_with_session(Some(pcr_session), |ctx| {
241 /// ctx.pcr_reset(PcrHandle::Pcr16).expect("Call to pcr_reset failed");
242 /// });
243 /// ```
244 pub fn pcr_reset(&mut self, pcr_handle: PcrHandle) -> Result<()> {
245 let ret = unsafe {
246 Esys_PCR_Reset(
247 self.mut_context(),
248 pcr_handle.into(),
249 self.optional_session_1(),
250 self.optional_session_2(),
251 self.optional_session_3(),
252 )
253 };
254 let ret = Error::from_tss_rc(ret);
255
256 if ret.is_success() {
257 Ok(())
258 } else {
259 error!("Error when resetting PCR: {}", ret);
260 Err(ret)
261 }
262 }
263
264 // Missing function: _TPM_Hash_Start
265 // Missing function: _TPM_Hash_Data
266 // Missing function: _TPM_Hash_End
267}