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    Context, Result, ReturnCode,
5    handles::{AuthHandle, PcrHandle},
6    interface_types::algorithm::HashingAlgorithm,
7    structures::{
8        Auth, Digest, DigestList, DigestValues, Event, PcrAllocateResult, PcrSelectionList,
9    },
10    tss2_esys::{
11        Esys_PCR_Allocate, Esys_PCR_Event, Esys_PCR_Extend, Esys_PCR_Read, Esys_PCR_Reset,
12        Esys_PCR_SetAuthPolicy, Esys_PCR_SetAuthValue,
13    },
14};
15use log::error;
16use std::convert::{TryFrom, TryInto};
17use std::ptr::null_mut;
18
19impl Context {
20    /// Extends a PCR with the specified digests.
21    ///
22    /// # Arguments
23    /// * `pcr_handle`- A [PcrHandle] to the PCR slot that is to be extended.
24    /// * `digests` - The [DigestValues] with which the slot shall be extended.
25    ///
26    /// # Details
27    /// This method is used to cause an update to the indicated PCR. The digests param
28    /// contains the digests for specific algorithms that are to be used.
29    ///
30    /// # Example
31    ///
32    /// ```rust
33    /// # use tss_esapi::{
34    /// #     Context, TctiNameConf,
35    /// #     constants::SessionType,
36    /// #     attributes::SessionAttributesBuilder,
37    /// #     handles::PcrHandle,
38    /// #     structures::{Digest, SymmetricDefinition},
39    /// # };
40    /// # use std::{env, str::FromStr};
41    /// # // Create context
42    /// # let mut context =
43    /// #     Context::new(
44    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
45    /// #     ).expect("Failed to create Context");
46    /// # // Create session for a pcr
47    /// # let pcr_session = context
48    /// #     .start_auth_session(
49    /// #         None,
50    /// #         None,
51    /// #         None,
52    /// #         SessionType::Hmac,
53    /// #         SymmetricDefinition::AES_256_CFB,
54    /// #         tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
55    /// #     )
56    /// #     .expect("Failed to create session")
57    /// #     .expect("Received invalid handle");
58    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
59    /// #     .with_decrypt(true)
60    /// #     .with_encrypt(true)
61    /// #     .build();
62    /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask)
63    /// #     .expect("Failed to set attributes on session");
64    /// #
65    /// # let digest_sha1 = Digest::try_from(vec![
66    /// #       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
67    /// #   ])
68    /// #   .expect("Failed to create sha1 Digest from data");
69    /// #
70    /// # let digest_sha256 = Digest::try_from(vec![
71    /// #        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
72    /// #        24, 25, 26, 27, 28, 29, 30, 31, 32,
73    /// #    ]).expect("Failed to create Sha256 Digest from data");
74    /// use std::convert::TryFrom;
75    /// use tss_esapi::{
76    ///     structures::{DigestValues},
77    ///     interface_types::algorithm::HashingAlgorithm,
78    /// };
79    /// // Extend both sha256 and sha1
80    /// let mut vals = DigestValues::new();
81    /// vals.set(
82    ///     HashingAlgorithm::Sha1,
83    ///     digest_sha1,
84    /// );
85    /// vals.set(
86    ///     HashingAlgorithm::Sha256,
87    ///     digest_sha256,
88    /// );
89    /// // Use pcr_session for authorization when extending
90    /// // PCR 16 with the values for the banks specified in
91    /// // vals.
92    /// context.execute_with_session(Some(pcr_session), |ctx| {
93    ///     ctx.pcr_extend(PcrHandle::Pcr16, vals).expect("Call to pcr_extend failed");
94    /// });
95    /// ```
96    pub fn pcr_extend(&mut self, pcr_handle: PcrHandle, digests: DigestValues) -> Result<()> {
97        ReturnCode::ensure_success(
98            unsafe {
99                Esys_PCR_Extend(
100                    self.mut_context(),
101                    pcr_handle.into(),
102                    self.required_session_1()?,
103                    self.optional_session_2(),
104                    self.optional_session_3(),
105                    &digests.try_into()?,
106                )
107            },
108            |ret| {
109                error!("Error when extending PCR: {:#010X}", ret);
110            },
111        )
112    }
113
114    /// Cause an event to be recorded in a PCR.
115    ///
116    /// # Arguments
117    ///
118    /// * `pcr_handle` - A [PcrHandle] of the PCR slot to extend.
119    /// * `event_data` - An [Event] data to be extended.
120    ///
121    /// # Details
122    ///
123    /// *From the specification*
124    /// > This command is used to cause an update to the indicated PCR.
125    /// > The data in eventData is hashed using each of the implemented hash algorithms.
126    /// > For each PCR bank, pcrHandle is extended with the hash of eventData
127    /// > for that bank's algorithm.
128    ///
129    /// # Returns
130    ///
131    /// A [DigestValues] containing the digest of the event data for each implemented algorithm.
132    ///
133    /// # Example
134    ///
135    /// ```rust
136    /// # use tss_esapi::{
137    /// #     Context, TctiNameConf,
138    /// #     constants::SessionType,
139    /// #     attributes::SessionAttributesBuilder,
140    /// #     interface_types::algorithm::HashingAlgorithm,
141    /// #     structures::{Event, SymmetricDefinition},
142    /// # };
143    /// # // Create context
144    /// # let mut context =
145    /// #     Context::new(
146    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
147    /// #     ).expect("Failed to create Context");
148    /// # // Create session for a pcr
149    /// # let pcr_session = context
150    /// #     .start_auth_session(
151    /// #         None,
152    /// #         None,
153    /// #         None,
154    /// #         SessionType::Hmac,
155    /// #         SymmetricDefinition::AES_256_CFB,
156    /// #         HashingAlgorithm::Sha256,
157    /// #     )
158    /// #     .expect("Failed to create session")
159    /// #     .expect("Received invalid handle");
160    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
161    /// #     .with_decrypt(true)
162    /// #     .with_encrypt(true)
163    /// #     .build();
164    /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask)
165    /// #     .expect("Failed to set attributes on session");
166    /// use tss_esapi::{handles::PcrHandle, structures::MaxBuffer};
167    /// let event_data = Event::try_from(vec![1, 2, 3, 4])
168    ///     .expect("Failed to create event data");
169    /// // Use pcr_session for authorization when recording the event in PCR 16.
170    /// let digests = context.execute_with_session(Some(pcr_session), |ctx| {
171    ///     ctx.pcr_event(PcrHandle::Pcr16, event_data)
172    ///         .expect("Call to pcr_event failed")
173    /// });
174    /// ```
175    pub fn pcr_event(&mut self, pcr_handle: PcrHandle, event_data: Event) -> Result<DigestValues> {
176        let mut digests_ptr = null_mut();
177        ReturnCode::ensure_success(
178            unsafe {
179                Esys_PCR_Event(
180                    self.mut_context(),
181                    pcr_handle.into(),
182                    self.required_session_1()?,
183                    self.optional_session_2(),
184                    self.optional_session_3(),
185                    &event_data.into(),
186                    &mut digests_ptr,
187                )
188            },
189            |ret| {
190                error!("Error when performing PCR event: {:#010X}", ret);
191            },
192        )?;
193        let digests = Context::ffi_data_to_owned(digests_ptr)?;
194        let mut digest_values = DigestValues::new();
195        for i in 0..digests.count as usize {
196            let tpmt_ha = digests.digests[i];
197            let algorithm = HashingAlgorithm::try_from(tpmt_ha.hashAlg)?;
198            let digest = match algorithm {
199                HashingAlgorithm::Sha1 => Digest::from(unsafe { tpmt_ha.digest.sha1 }),
200                HashingAlgorithm::Sha256 => Digest::from(unsafe { tpmt_ha.digest.sha256 }),
201                HashingAlgorithm::Sha384 => Digest::from(unsafe { tpmt_ha.digest.sha384 }),
202                HashingAlgorithm::Sha512 => Digest::from(unsafe { tpmt_ha.digest.sha512 }),
203                HashingAlgorithm::Sm3_256 => Digest::from(unsafe { tpmt_ha.digest.sm3_256 }),
204                _ => {
205                    return Err(crate::Error::local_error(
206                        crate::WrapperErrorKind::WrongValueFromTpm,
207                    ));
208                }
209            };
210            digest_values.set(algorithm, digest);
211        }
212        Ok(digest_values)
213    }
214
215    /// Reads the values of a PCR.
216    ///
217    /// # Arguments
218    /// * `pcr_selection_list` - A [PcrSelectionList] that contains pcr slots in
219    ///   different banks that is going to be read.
220    ///
221    /// # Details
222    /// The provided [PcrSelectionList] contains the pcr slots in the different
223    /// banks that is going to be read. It is possible to select more pcr slots
224    /// then what will fit in the returned result so the method returns a [PcrSelectionList]
225    /// that indicates what values were read. The values that were read are returned
226    /// in a [DigestList].
227    ///
228    /// # Errors
229    /// * Several different errors can occur if conversion of return
230    ///   data fails.
231    ///
232    /// # Example
233    ///
234    /// ```rust
235    /// # use tss_esapi::{Context, TctiNameConf};
236    /// # use std::{env, str::FromStr};
237    /// # // Create context
238    /// # let mut context =
239    /// #     Context::new(
240    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
241    /// #     ).expect("Failed to create Context");
242    /// use tss_esapi::{
243    ///     interface_types::algorithm::HashingAlgorithm,
244    ///     structures::{PcrSelectionListBuilder, PcrSlot},
245    /// };
246    /// // Create PCR selection list with slots in a bank
247    /// // that is going to be read.
248    /// let pcr_selection_list = PcrSelectionListBuilder::new()
249    ///     .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1])
250    ///     .build()
251    ///     .expect("Failed to build PcrSelectionList");
252    ///
253    /// let (update_counter, read_pcr_list, digest_list) = context.pcr_read(pcr_selection_list)
254    ///     .expect("Call to pcr_read failed");
255    /// ```
256    pub fn pcr_read(
257        &mut self,
258        pcr_selection_list: PcrSelectionList,
259    ) -> Result<(u32, PcrSelectionList, DigestList)> {
260        let mut pcr_update_counter: u32 = 0;
261        let mut pcr_selection_out_ptr = null_mut();
262        let mut pcr_values_ptr = null_mut();
263        ReturnCode::ensure_success(
264            unsafe {
265                Esys_PCR_Read(
266                    self.mut_context(),
267                    self.optional_session_1(),
268                    self.optional_session_2(),
269                    self.optional_session_3(),
270                    &pcr_selection_list.into(),
271                    &mut pcr_update_counter,
272                    &mut pcr_selection_out_ptr,
273                    &mut pcr_values_ptr,
274                )
275            },
276            |ret| {
277                error!("Error when reading PCR: {:#010X}", ret);
278            },
279        )?;
280
281        Ok((
282            pcr_update_counter,
283            PcrSelectionList::try_from(Context::ffi_data_to_owned(pcr_selection_out_ptr)?)?,
284            DigestList::try_from(Context::ffi_data_to_owned(pcr_values_ptr)?)?,
285        ))
286    }
287
288    /// Allocate PCR banks.
289    ///
290    /// # Arguments
291    ///
292    /// * `auth_handle` - An [AuthHandle] for the platform hierarchy.
293    /// * `pcr_allocation` - A [PcrSelectionList] specifying the requested PCR allocation.
294    ///
295    /// # Details
296    ///
297    /// *From the specification*
298    /// > This command is used to set the desired PCR allocation of PCR and algorithms.
299    ///
300    /// # Returns
301    ///
302    /// A [PcrAllocateResult] consisting of:
303    /// * `allocation_success` - Whether the allocation was successful.
304    /// * `max_pcr` - Maximum number of PCR that may be in a bank.
305    /// * `size_needed` - Number of octets required to satisfy the request.
306    /// * `size_available` - Number of octets available (maximum size of NV).
307    ///
308    /// # Example
309    ///
310    /// ```rust
311    /// # use tss_esapi::{
312    /// #     Context, TctiNameConf,
313    /// #     constants::SessionType,
314    /// #     attributes::SessionAttributesBuilder,
315    /// #     interface_types::algorithm::HashingAlgorithm,
316    /// #     structures::SymmetricDefinition,
317    /// # };
318    /// # // Create context
319    /// # let mut context =
320    /// #     Context::new(
321    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
322    /// #     ).expect("Failed to create Context");
323    /// # // Create session for the platform hierarchy
324    /// # let session = context
325    /// #     .start_auth_session(
326    /// #         None,
327    /// #         None,
328    /// #         None,
329    /// #         SessionType::Hmac,
330    /// #         SymmetricDefinition::AES_256_CFB,
331    /// #         HashingAlgorithm::Sha256,
332    /// #     )
333    /// #     .expect("Failed to create session")
334    /// #     .expect("Received invalid handle");
335    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
336    /// #     .with_decrypt(true)
337    /// #     .with_encrypt(true)
338    /// #     .build();
339    /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
340    /// #     .expect("Failed to set attributes on session");
341    /// use tss_esapi::{
342    ///     handles::AuthHandle,
343    ///     structures::{PcrSelectionListBuilder, PcrSlot},
344    /// };
345    /// let pcr_allocation = PcrSelectionListBuilder::new()
346    ///     .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot0, PcrSlot::Slot1])
347    ///     .build()
348    ///     .expect("Failed to build PcrSelectionList");
349    /// // The platform hierarchy must authorize the allocation.
350    /// let result = context
351    ///     .execute_with_session(Some(session), |ctx| {
352    ///         ctx.pcr_allocate(AuthHandle::Platform, pcr_allocation)
353    ///             .expect("Call to pcr_allocate failed")
354    ///     });
355    /// ```
356    pub fn pcr_allocate(
357        &mut self,
358        auth_handle: AuthHandle,
359        pcr_allocation: PcrSelectionList,
360    ) -> Result<PcrAllocateResult> {
361        let mut allocation_success: u8 = 0;
362        let mut max_pcr: u32 = 0;
363        let mut size_needed: u32 = 0;
364        let mut size_available: u32 = 0;
365        ReturnCode::ensure_success(
366            unsafe {
367                Esys_PCR_Allocate(
368                    self.mut_context(),
369                    auth_handle.into(),
370                    self.required_session_1()?,
371                    self.optional_session_2(),
372                    self.optional_session_3(),
373                    &pcr_allocation.into(),
374                    &mut allocation_success,
375                    &mut max_pcr,
376                    &mut size_needed,
377                    &mut size_available,
378                )
379            },
380            |ret| {
381                error!("Error when allocating PCR: {:#010X}", ret);
382            },
383        )?;
384        Ok(PcrAllocateResult {
385            allocation_success: (allocation_success != 0).into(),
386            max_pcr,
387            size_needed,
388            size_available,
389        })
390    }
391
392    /// Set the authorization policy for a PCR.
393    ///
394    /// # Arguments
395    ///
396    /// * `auth_handle` - An [AuthHandle] for the platform hierarchy.
397    /// * `auth_policy` - A [Digest] representing the authorization policy.
398    /// * `hash_algorithm` - The [HashingAlgorithm] of the policy.
399    /// * `pcr_handle` - A [PcrHandle] of the PCR to set the policy for.
400    ///
401    /// # Details
402    ///
403    /// *From the specification*
404    /// > This command is used to associate a policy with a PCR or group of PCR.
405    ///
406    /// # Example
407    ///
408    /// <!--
409    /// This example is marked `no_run` because `PCR_SetAuthPolicy` succeeds only
410    /// for PCRs that the TPM platform configuration assigns to a PolicyAuth group.
411    /// swtpm/libtpms assigns no PCRs to such a group.
412    /// Reference: https://github.com/stefanberger/libtpms/blob/521c51073fe6f7c56023db78e56961fcaf7906e8/src/tpm2/TPMCmd/Platform/src/PlatformPcr.c
413    /// -->
414    ///
415    /// ```rust, no_run
416    /// # use tss_esapi::{
417    /// #     Context, TctiNameConf,
418    /// #     constants::SessionType,
419    /// #     attributes::SessionAttributesBuilder,
420    /// #     interface_types::algorithm::HashingAlgorithm,
421    /// #     structures::SymmetricDefinition,
422    /// # };
423    /// # // Create context
424    /// # let mut context =
425    /// #     Context::new(
426    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
427    /// #     ).expect("Failed to create Context");
428    /// # // Create session for the platform hierarchy
429    /// # let session = context
430    /// #     .start_auth_session(
431    /// #         None,
432    /// #         None,
433    /// #         None,
434    /// #         SessionType::Hmac,
435    /// #         SymmetricDefinition::AES_256_CFB,
436    /// #         HashingAlgorithm::Sha256,
437    /// #     )
438    /// #     .expect("Failed to create session")
439    /// #     .expect("Received invalid handle");
440    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
441    /// #     .with_decrypt(true)
442    /// #     .with_encrypt(true)
443    /// #     .build();
444    /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
445    /// #     .expect("Failed to set attributes on session");
446    /// use tss_esapi::{
447    ///     handles::{AuthHandle, PcrHandle},
448    ///     structures::Digest,
449    /// };
450    /// context.execute_with_session(Some(session), |ctx| {
451    ///     ctx.pcr_set_auth_policy(
452    ///         AuthHandle::Platform,
453    ///         Digest::default(),
454    ///         HashingAlgorithm::Null,
455    ///         PcrHandle::Pcr16,
456    ///     )
457    ///     .expect("Call to pcr_set_auth_policy failed")
458    /// });
459    /// ```
460    pub fn pcr_set_auth_policy(
461        &mut self,
462        auth_handle: AuthHandle,
463        auth_policy: Digest,
464        hash_algorithm: HashingAlgorithm,
465        pcr_handle: PcrHandle,
466    ) -> Result<()> {
467        ReturnCode::ensure_success(
468            unsafe {
469                Esys_PCR_SetAuthPolicy(
470                    self.mut_context(),
471                    auth_handle.into(),
472                    self.required_session_1()?,
473                    self.optional_session_2(),
474                    self.optional_session_3(),
475                    &auth_policy.into(),
476                    hash_algorithm.into(),
477                    pcr_handle.into(),
478                )
479            },
480            |ret| {
481                error!("Error when setting PCR auth policy: {:#010X}", ret);
482            },
483        )
484    }
485
486    /// Set the authorization value for a PCR.
487    ///
488    /// # Arguments
489    ///
490    /// * `pcr_handle` - A [PcrHandle] of the PCR to set the auth value for.
491    /// * `auth` - An [Auth] value for the PCR.
492    ///
493    /// # Details
494    ///
495    /// *From the specification*
496    /// > This command changes the authValue of a PCR or group of PCR.
497    ///
498    /// # Example
499    ///
500    /// <!--
501    /// This example is marked `no_run` because `PCR_SetAuthValue` succeeds only
502    /// for PCRs that the TPM platform configuration assigns to an AuthValue group.
503    /// swtpm/libtpms assigns no PCRs to such a group.
504    /// Reference: https://github.com/stefanberger/libtpms/blob/521c51073fe6f7c56023db78e56961fcaf7906e8/src/tpm2/TPMCmd/Platform/src/PlatformPcr.c
505    /// -->
506    ///
507    /// ```rust, no_run
508    /// # use tss_esapi::{
509    /// #     Context, TctiNameConf,
510    /// #     constants::SessionType,
511    /// #     attributes::SessionAttributesBuilder,
512    /// #     interface_types::algorithm::HashingAlgorithm,
513    /// #     structures::SymmetricDefinition,
514    /// # };
515    /// # // Create context
516    /// # let mut context =
517    /// #     Context::new(
518    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
519    /// #     ).expect("Failed to create Context");
520    /// # // Create session for a pcr
521    /// # let session = context
522    /// #     .start_auth_session(
523    /// #         None,
524    /// #         None,
525    /// #         None,
526    /// #         SessionType::Hmac,
527    /// #         SymmetricDefinition::AES_256_CFB,
528    /// #         HashingAlgorithm::Sha256,
529    /// #     )
530    /// #     .expect("Failed to create session")
531    /// #     .expect("Received invalid handle");
532    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
533    /// #     .with_decrypt(true)
534    /// #     .with_encrypt(true)
535    /// #     .build();
536    /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
537    /// #     .expect("Failed to set attributes on session");
538    /// use tss_esapi::{handles::PcrHandle, structures::Auth};
539    /// let auth = Auth::from_bytes(&[1, 2, 3, 4]).expect("Failed to create Auth");
540    /// context.execute_with_session(Some(session), |ctx| {
541    ///     ctx.pcr_set_auth_value(PcrHandle::Pcr16, auth)
542    ///         .expect("Call to pcr_set_auth_value failed")
543    /// });
544    /// ```
545    pub fn pcr_set_auth_value(&mut self, pcr_handle: PcrHandle, auth: Auth) -> Result<()> {
546        ReturnCode::ensure_success(
547            unsafe {
548                Esys_PCR_SetAuthValue(
549                    self.mut_context(),
550                    pcr_handle.into(),
551                    self.required_session_1()?,
552                    self.optional_session_2(),
553                    self.optional_session_3(),
554                    &auth.into(),
555                )
556            },
557            |ret| {
558                error!("Error when setting PCR auth value: {:#010X}", ret);
559            },
560        )
561    }
562
563    /// Resets the value in a PCR.
564    ///
565    /// # Arguments
566    /// * `pcr_handle` -  A [PcrHandle] to the PCR slot that is to be reset.
567    ///
568    /// # Details
569    /// If the attributes of the PCR indicates that it is allowed
570    /// to reset them and the proper authorization is provided then
571    /// this method can be used to set the the specified PCR in all
572    /// banks to 0.
573    ///
574    /// # Example
575    ///
576    /// ```rust
577    /// # use tss_esapi::{
578    /// #     Context, TctiNameConf,
579    /// #     constants::SessionType,
580    /// #     attributes::SessionAttributesBuilder,
581    /// #     structures::SymmetricDefinition,
582    /// #     interface_types::algorithm::HashingAlgorithm,
583    /// # };
584    /// # use std::{env, str::FromStr};
585    /// # // Create context
586    /// # let mut context =
587    /// #     Context::new(
588    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
589    /// #     ).expect("Failed to create Context");
590    /// # // Create session for a pcr
591    /// # let pcr_session = context
592    /// #     .start_auth_session(
593    /// #         None,
594    /// #         None,
595    /// #         None,
596    /// #         SessionType::Hmac,
597    /// #         SymmetricDefinition::AES_256_CFB,
598    /// #         HashingAlgorithm::Sha256,
599    /// #     )
600    /// #     .expect("Failed to create session")
601    /// #     .expect("Received invalid handle");
602    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
603    /// #     .with_decrypt(true)
604    /// #     .with_encrypt(true)
605    /// #     .build();
606    /// # context.tr_sess_set_attributes(pcr_session, session_attributes, session_attributes_mask)
607    /// #     .expect("Failed to set attributes on session");
608    ///
609    /// use tss_esapi::{
610    ///      handles::PcrHandle
611    /// };
612    /// context.execute_with_session(Some(pcr_session), |ctx| {
613    ///     ctx.pcr_reset(PcrHandle::Pcr16).expect("Call to pcr_reset failed");
614    /// });
615    /// ```
616    pub fn pcr_reset(&mut self, pcr_handle: PcrHandle) -> Result<()> {
617        ReturnCode::ensure_success(
618            unsafe {
619                Esys_PCR_Reset(
620                    self.mut_context(),
621                    pcr_handle.into(),
622                    self.required_session_1()?,
623                    self.optional_session_2(),
624                    self.optional_session_3(),
625                )
626            },
627            |ret| {
628                error!("Error when resetting PCR: {:#010X}", ret);
629            },
630        )
631    }
632}