• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 //! Client used to connect to the keybox service.
17 use crate::ffi_bindings::{KeyboxUnwrapReq, KeyboxUnwrapResp, KEYBOX_PORT, KEYBOX_RESP_HDR_SIZE};
18 use core::ffi::CStr;
19 use kmr_common::{km_err, vec_try, Error};
20 use tipc::{Handle, TipcError};
21 
22 /// A `KeyboxSession` is a `Handle`.
23 type KeyboxSession = Handle;
24 /// Connection to the keybox service.
25 #[derive(Debug, Eq, PartialEq)]
26 struct Keybox(KeyboxSession);
27 
28 impl Keybox {
29     /// Attempt to open a keybox session.
30     ///
31     /// # Examples
32     ///
33     /// ```
34     /// let keybox = keybox::open().expect("could not open hwkey session");
35     /// ```
36     ///
new() -> Result<Self, TipcError>37     fn new() -> Result<Self, TipcError> {
38         let port =
39             CStr::from_bytes_with_nul(KEYBOX_PORT).expect("KEYBOX_PORT was not null terminated");
40         KeyboxSession::connect(port).map(Self)
41     }
42 
keybox_unwrap(&self, wrapped_keybox: &[u8]) -> Result<Vec<u8>, Error>43     pub(crate) fn keybox_unwrap(&self, wrapped_keybox: &[u8]) -> Result<Vec<u8>, Error> {
44         let req = KeyboxUnwrapReq::new(wrapped_keybox);
45         self.0
46             .send(&req)
47             .map_err(|e| km_err!(SecureHwCommunicationFailed, "send unwrap cmd failed: {:?}", e))?;
48         // This uses the same assumption as SetWrappedAttestationKey on the c++ code; which is that
49         // the size of the unwrapped key won't be bigger than the size of the wrapped one.
50         let mut buffer = vec_try![0; wrapped_keybox.len() + KEYBOX_RESP_HDR_SIZE]?;
51         let response: KeyboxUnwrapResp = self
52             .0
53             .recv(&mut buffer)
54             .map_err(|e| km_err!(SecureHwCommunicationFailed, "unwrap response error: {:?}", e))?;
55         Ok(response.get_unwrapped_keybox())
56     }
57 }
58 
keybox_unwrap(wrapped_keybox: &[u8]) -> Result<Vec<u8>, Error>59 pub(crate) fn keybox_unwrap(wrapped_keybox: &[u8]) -> Result<Vec<u8>, Error> {
60     let keybox = Keybox::new().map_err(|e| {
61         km_err!(SecureHwCommunicationFailed, "error opening keybox service: {:?}", e)
62     })?;
63     keybox.keybox_unwrap(wrapped_keybox)
64 }
65 
66 #[cfg(test)]
67 mod tests {
68     use super::*;
69     use test::{expect, expect_eq, skip};
70 
71     // AOSP keybox test server just XORs data with a constant and checksum it, it is not intended to
72     // be secure; just to be used to check the IPC commands.
create_fake_wrapped_data(data: &[u8]) -> Vec<u8>73     fn create_fake_wrapped_data(data: &[u8]) -> Vec<u8> {
74         let mut wrapped_data = Vec::<u8>::new();
75         let mut checksum: u8 = 0;
76         for &element in data {
77             let wrapped_element = element ^ 0x42;
78             wrapped_data.push(wrapped_element);
79             checksum ^= wrapped_element;
80         }
81         wrapped_data.push(checksum);
82         wrapped_data
83     }
84 
85     #[test]
unwrap_fake_keybox_data()86     fn unwrap_fake_keybox_data() {
87         if true {
88             skip!("TODO: reinstate test");
89         }
90         let original_data = b"test_data_to_wrap".as_slice();
91         let wrapped_data = create_fake_wrapped_data(original_data);
92         let result = keybox_unwrap(&wrapped_data);
93         expect!(result.is_ok(), "Failed to unwrap data: {:?}", result);
94         let unwrapped_data = result.expect("Couldn't unwrap data");
95         expect_eq!(original_data, unwrapped_data, "Unwrapped data do not match original one");
96     }
97 }
98