Skip to main content

tss_esapi/context/tpm_commands/
clocks_and_timers.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    Context, Result, ReturnCode,
5    constants::ClockAdjust,
6    handles::AuthHandle,
7    structures::TimeInfo,
8    tss2_esys::{Esys_ClockRateAdjust, Esys_ClockSet, Esys_ReadClock},
9};
10use log::error;
11use std::{convert::TryFrom, ptr::null_mut};
12
13impl Context {
14    /// Read the current time and clock info.
15    ///
16    /// # Details
17    ///
18    /// *From the specification*
19    /// > This command returns the current values of Time and Clock.
20    ///
21    /// # Returns
22    ///
23    /// A [TimeInfo] structure containing the current time and clock information.
24    ///
25    /// # Example
26    ///
27    /// ```rust
28    /// # use tss_esapi::{Context, TctiNameConf};
29    /// # let mut context =
30    /// #     Context::new(
31    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
32    /// #     ).expect("Failed to create Context");
33    /// let time_info = context.read_clock().unwrap();
34    /// println!("Time: {}", time_info.time());
35    /// ```
36    pub fn read_clock(&mut self) -> Result<TimeInfo> {
37        let mut current_time_ptr = null_mut();
38        ReturnCode::ensure_success(
39            unsafe {
40                Esys_ReadClock(
41                    self.mut_context(),
42                    self.optional_session_1(),
43                    self.optional_session_2(),
44                    self.optional_session_3(),
45                    &mut current_time_ptr,
46                )
47            },
48            |ret| {
49                error!("Error reading clock: {:#010X}", ret);
50            },
51        )?;
52        TimeInfo::try_from(Context::ffi_data_to_owned(current_time_ptr)?)
53    }
54
55    /// Set the clock to a new value.
56    ///
57    /// # Arguments
58    ///
59    /// * `auth_handle` - An [AuthHandle] for the authorization (Owner or Platform).
60    /// * `new_time` - The new clock setting in milliseconds.
61    ///
62    /// # Details
63    ///
64    /// *From the specification*
65    /// > This command is used to advance the value of the TPM's Clock. The
66    /// > command will fail if newTime is less than the current value of Clock
67    /// > or if the new time is greater than 0xFFFF000000000000.
68    ///
69    /// # Example
70    ///
71    /// ```rust
72    /// # use tss_esapi::{Context, TctiNameConf};
73    /// # use tss_esapi::{handles::AuthHandle, interface_types::session_handles::AuthSession};
74    /// # let mut context =
75    /// #     Context::new(
76    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
77    /// #     ).expect("Failed to create Context");
78    /// let time_info = context.read_clock().unwrap();
79    /// let new_time = time_info.clock_info().clock() + 100_000;
80    /// context
81    ///     .execute_with_session(Some(AuthSession::Password), |ctx| {
82    ///         ctx.clock_set(AuthHandle::Owner, new_time)
83    ///     })
84    ///     .unwrap();
85    /// ```
86    pub fn clock_set(&mut self, auth_handle: AuthHandle, new_time: u64) -> Result<()> {
87        ReturnCode::ensure_success(
88            unsafe {
89                Esys_ClockSet(
90                    self.mut_context(),
91                    auth_handle.into(),
92                    self.required_session_1()?,
93                    self.optional_session_2(),
94                    self.optional_session_3(),
95                    new_time,
96                )
97            },
98            |ret| {
99                error!("Error setting clock: {:#010X}", ret);
100            },
101        )
102    }
103
104    /// Adjust the TPM clock update rate.
105    ///
106    /// # Arguments
107    ///
108    /// * `auth_handle` - An [AuthHandle] for the authorization (Owner or Platform).
109    /// * `rate_adjust` - The clock update-rate adjustment to apply.
110    ///
111    /// # Details
112    ///
113    /// *From the specification*
114    /// > This command adjusts the rate of advance of Clock and Time to provide
115    /// > a better approximation to real time.
116    ///
117    /// # Example
118    ///
119    /// ```rust
120    /// # use tss_esapi::{Context, TctiNameConf};
121    /// # use tss_esapi::{
122    /// #     constants::ClockAdjust,
123    /// #     handles::AuthHandle,
124    /// #     interface_types::session_handles::AuthSession,
125    /// # };
126    /// # let mut context =
127    /// #     Context::new(
128    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
129    /// #     ).expect("Failed to create Context");
130    /// context
131    ///     .execute_with_session(Some(AuthSession::Password), |ctx| {
132    ///         ctx.clock_rate_adjust(AuthHandle::Owner, ClockAdjust::NoChange)
133    ///     })
134    ///     .unwrap();
135    /// ```
136    pub fn clock_rate_adjust(
137        &mut self,
138        auth_handle: AuthHandle,
139        rate_adjust: ClockAdjust,
140    ) -> Result<()> {
141        ReturnCode::ensure_success(
142            unsafe {
143                Esys_ClockRateAdjust(
144                    self.mut_context(),
145                    auth_handle.into(),
146                    self.required_session_1()?,
147                    self.optional_session_2(),
148                    self.optional_session_3(),
149                    rate_adjust.into(),
150                )
151            },
152            |ret| {
153                error!("Error adjusting clock rate: {:#010X}", ret);
154            },
155        )
156    }
157}