1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Module that implements [`MonotonicClock`] trait.
18 use kmr_common::crypto::{MillisecondsSinceEpoch, MonotonicClock};
19 use log::error;
20 
21 /// Monotonic clock implementation for Trusty.
22 pub struct TrustyMonotonicClock;
23 
24 impl MonotonicClock for TrustyMonotonicClock {
now(&self) -> MillisecondsSinceEpoch25     fn now(&self) -> MillisecondsSinceEpoch {
26         let mut secure_time_ns = 0;
27         // Safety: external syscall gets valid raw pointer to a `u64`.
28         let rc = unsafe { trusty_sys::gettime(0, 0, &mut secure_time_ns) };
29         let secure_time_ns = if rc < 0 {
30             // Couldn't get time; original behavior is to return here `u64::MAX` scaled to ms and
31             // log an error
32             error!("Error calling trusty_gettime: {:#x}", rc);
33             ((u64::MAX / 1000) / 1000) as i64
34         } else {
35             (secure_time_ns / 1000) / 1000
36         };
37 
38         MillisecondsSinceEpoch(secure_time_ns)
39     }
40 }
41 
42 #[cfg(test)]
43 mod tests {
44     use super::*;
45     use test::{expect, expect_ne};
46 
47     #[test]
get_milliseconds_since_boot_test()48     fn get_milliseconds_since_boot_test() {
49         let trusty_clock = TrustyMonotonicClock;
50         let time1 = trusty_clock.now().0;
51         let time2 = trusty_clock.now().0;
52         // Because we cannot sleep between calls and granularity is in milliseconds,
53         // time1 and 2 might be the same
54         expect!(time1 <= time2, "Time should not decrement.");
55         expect!(time1 > 0, "time1 should be greater than 0");
56         expect_ne!(time1, ((u64::MAX / 1000) / 1000) as i64, "time1 shouldn't indicate an error");
57         expect_ne!(time2, ((u64::MAX / 1000) / 1000) as i64, "time2 shouldn't indicate an error");
58     }
59 }
60