1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! TA functionality for secure clocks.
16 
17 use alloc::vec::Vec;
18 use core::mem::size_of;
19 use kmr_common::{km_err, vec_try_with_capacity, Error};
20 use kmr_wire::secureclock::{TimeStampToken, TIME_STAMP_MAC_LABEL};
21 
22 impl crate::KeyMintTa {
generate_timestamp(&self, challenge: i64) -> Result<TimeStampToken, Error>23     pub(crate) fn generate_timestamp(&self, challenge: i64) -> Result<TimeStampToken, Error> {
24         if let Some(clock) = &self.imp.clock {
25             let mut ret =
26                 TimeStampToken { challenge, timestamp: clock.now().into(), mac: Vec::new() };
27             let mac_input = self.dev.keys.timestamp_token_mac_input(&ret)?;
28             ret.mac = self.device_hmac(&mac_input)?;
29             Ok(ret)
30         } else {
31             Err(km_err!(Unimplemented, "no clock available"))
32         }
33     }
34 }
35 
36 /// Build the HMAC input for a [`TimeStampToken`]
timestamp_token_mac_input(token: &TimeStampToken) -> Result<Vec<u8>, Error>37 pub fn timestamp_token_mac_input(token: &TimeStampToken) -> Result<Vec<u8>, Error> {
38     let mut result = vec_try_with_capacity!(
39         TIME_STAMP_MAC_LABEL.len() +
40         size_of::<i64>() + // challenge (BE)
41         size_of::<i64>() + // timestamp (BE)
42         size_of::<u32>() // 1u32 (BE)
43     )?;
44     result.extend_from_slice(TIME_STAMP_MAC_LABEL);
45     result.extend_from_slice(&token.challenge.to_be_bytes()[..]);
46     result.extend_from_slice(&token.timestamp.milliseconds.to_be_bytes()[..]);
47     result.extend_from_slice(&1u32.to_be_bytes()[..]);
48     Ok(result)
49 }
50