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}