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, Result, ReturnCode,
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 ReturnCode::ensure_success(
92 unsafe {
93 Esys_PCR_Extend(
94 self.mut_context(),
95 pcr_handle.into(),
96 self.optional_session_1(),
97 self.optional_session_2(),
98 self.optional_session_3(),
99 &digests.try_into()?,
100 )
101 },
102 |ret| {
103 error!("Error when extending PCR: {:#010X}", ret);
104 },
105 )
106 }
107
108 // Missing function: PCR_Event
109
110 /// Reads the values of a PCR.
111 ///
112 /// # Arguments
113 /// * `pcr_selection_list` - A [PcrSelectionList] that contains pcr slots in
114 /// different banks that is going to be read.
115 ///
116 /// # Details
117 /// The provided [PcrSelectionList] contains the pcr slots in the different
118 /// banks that is going to be read. It is possible to select more pcr slots
119 /// then what will fit in the returned result so the method returns a [PcrSelectionList]
120 /// that indicates what values were read. The values that were read are returned
121 /// in a [DigestList].
122 ///
123 /// # Errors
124 /// * Several different errors can occur if conversion of return
125 /// data fails.
126 ///
127 /// # Example
128 ///
129 /// ```rust
130 /// # use tss_esapi::{Context, TctiNameConf};
131 /// # use std::{env, str::FromStr};
132 /// # // Create context
133 /// # let mut context =
134 /// # Context::new(
135 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
136 /// # ).expect("Failed to create Context");
137 /// use tss_esapi::{
138 /// interface_types::algorithm::HashingAlgorithm,
139 /// structures::{PcrSelectionListBuilder, PcrSlot},
140 /// };
141 /// // Create PCR selection list with slots in a bank
142 /// // that is going to be read.
143 /// let pcr_selection_list = PcrSelectionListBuilder::new()
144 /// .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1])
145 /// .build()
146 /// .expect("Failed to build PcrSelectionList");
147 ///
148 /// let (update_counter, read_pcr_list, digest_list) = context.pcr_read(pcr_selection_list)
149 /// .expect("Call to pcr_read failed");
150 /// ```
151 pub fn pcr_read(
152 &mut self,
153 pcr_selection_list: PcrSelectionList,
154 ) -> Result<(u32, PcrSelectionList, DigestList)> {
155 let mut pcr_update_counter: u32 = 0;
156 let mut pcr_selection_out_ptr = null_mut();
157 let mut pcr_values_ptr = null_mut();
158 ReturnCode::ensure_success(
159 unsafe {
160 Esys_PCR_Read(
161 self.mut_context(),
162 self.optional_session_1(),
163 self.optional_session_2(),
164 self.optional_session_3(),
165 &pcr_selection_list.into(),
166 &mut pcr_update_counter,
167 &mut pcr_selection_out_ptr,
168 &mut pcr_values_ptr,
169 )
170 },
171 |ret| {
172 error!("Error when reading PCR: {:#010X}", ret);
173 },
174 )?;
175
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 }
182
183 // Missing function: PCR_Allocate
184 // Missing function: PCR_SetAuthPolicy
185 // Missing function: PCR_SetAuthValue
186
187 /// Resets the value in a PCR.
188 ///
189 /// # Arguments
190 /// * `pcr_handle` - A [PcrHandle] to the PCR slot that is to be reset.
191 ///
192 /// # Details
193 /// If the attributes of the PCR indicates that it is allowed
194 /// to reset them and the proper authorization is provided then
195 /// this method can be used to set the the specified PCR in all
196 /// banks to 0.
197 ///
198 /// # Example
199 ///
200 /// ```rust
201 /// # use tss_esapi::{
202 /// # Context, TctiNameConf,
203 /// # constants::SessionType,
204 /// # attributes::SessionAttributesBuilder,
205 /// # structures::SymmetricDefinition,
206 /// # interface_types::algorithm::HashingAlgorithm,
207 /// # };
208 /// # use std::{env, str::FromStr};
209 /// # // Create context
210 /// # let mut context =
211 /// # Context::new(
212 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
213 /// # ).expect("Failed to create Context");
214 /// # // Create session for a pcr
215 /// # let pcr_session = context
216 /// # .start_auth_session(
217 /// # None,
218 /// # None,
219 /// # None,
220 /// # SessionType::Hmac,
221 /// # SymmetricDefinition::AES_256_CFB,
222 /// # HashingAlgorithm::Sha256,
223 /// # )
224 /// # .expect("Failed to create session")
225 /// # .expect("Received invalid handle");
226 /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
227 /// # .with_decrypt(true)
228 /// # .with_encrypt(true)
229 /// # .build();
230 /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask)
231 /// # .expect("Failed to set attributes on session");
232 ///
233 /// use tss_esapi::{
234 /// handles::PcrHandle
235 /// };
236 /// context.execute_with_session(Some(pcr_session), |ctx| {
237 /// ctx.pcr_reset(PcrHandle::Pcr16).expect("Call to pcr_reset failed");
238 /// });
239 /// ```
240 pub fn pcr_reset(&mut self, pcr_handle: PcrHandle) -> Result<()> {
241 ReturnCode::ensure_success(
242 unsafe {
243 Esys_PCR_Reset(
244 self.mut_context(),
245 pcr_handle.into(),
246 self.optional_session_1(),
247 self.optional_session_2(),
248 self.optional_session_3(),
249 )
250 },
251 |ret| {
252 error!("Error when resetting PCR: {:#010X}", ret);
253 },
254 )
255 }
256
257 // Missing function: _TPM_Hash_Start
258 // Missing function: _TPM_Hash_Data
259 // Missing function: _TPM_Hash_End
260}