Skip to main content

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}