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 //! Wrapper around autogenerated ffi bindings.
17
18 // Get the bindgen definitions
19 #[allow(non_upper_case_globals)]
20 #[allow(non_camel_case_types)]
21 #[allow(unused)]
22 #[allow(deref_nullptr)] // https://github.com/rust-lang/rust-bindgen/issues/1651
23 mod sys {
24 include!(env!("BINDGEN_INC_FILE"));
25 }
26
27 use core::mem;
28 use kmr_common::try_to_vec;
29 use kmr_wire::legacy::InnerSerialize;
30 use log::{error, warn};
31 use tipc::{Deserialize, Handle, Serialize, Serializer, TipcError};
32
33 /// Add entropy to Trusty's RNG.
trusty_rng_add_entropy(data: &[u8])34 pub fn trusty_rng_add_entropy(data: &[u8]) {
35 let rc = unsafe {
36 // Safety: `data` is a valid slice
37 sys::trusty_rng_add_entropy(data.as_ptr(), data.len())
38 };
39 if rc != 0 {
40 warn!("trusty_rng_add_entropy() failed, {}", rc)
41 }
42 }
43
44 pub(crate) const KEYBOX_PORT: &[u8; 28] = sys::KEYBOX_PORT;
45
46 type KeyboxReqHdr = sys::keybox_req;
47 type KeyboxUnwrapReqPayloadHdr = sys::keybox_unwrap_req;
48
49 pub(crate) const KEYBOX_RESP_HDR_SIZE: usize =
50 mem::size_of::<sys::keybox_resp>() + mem::size_of::<sys::keybox_unwrap_resp>();
51
52 const KEYBOX_RESP_MAX_SIZE: usize = KEYBOX_RESP_HDR_SIZE + (sys::KEYBOX_MAX_SIZE as usize);
53
54 // Because KeyboxUnwrapResp deserialization doesn't use the ffi types, we add this check in case the
55 // c definitions change.
56 const _: () = assert!(
57 KEYBOX_RESP_HDR_SIZE == (mem::size_of::<u32>() + mem::size_of::<u32>() + mem::size_of::<u64>()),
58 "KEYBOX_RESP_HDR_SIZE do not match KeyboxUnwrapResp deserialization assumptions"
59 );
60
61 // KeyboxUnwrapReq is a type created to be processed by Trusty IPC Rust serialization. This means
62 // that any data that needs to be serialized when implementing the `Serialize` trait needs to
63 // outlive its `serialize` function. A consequence of that is that the serialized values might need
64 // some memory backup space until they have been transmitted.
65 // We do not have this restriction on types we are deserializing (like `KeyboxUnwrapResp`); on which
66 // this implementation prefers to use a type that can be directly used by the Rust code. This ends
67 // up creating an asymmetry between requests and responses.
68 pub(crate) struct KeyboxUnwrapReq<'a> {
69 req_header: KeyboxReqHdr,
70 unwrap_req_header: KeyboxUnwrapReqPayloadHdr,
71 wrapped_keybox: &'a [u8],
72 }
73
74 impl<'a> KeyboxUnwrapReq<'a> {
new(wrapped_keybox: &'a [u8]) -> Self75 pub(crate) fn new(wrapped_keybox: &'a [u8]) -> Self {
76 let req_header = KeyboxReqHdr { cmd: sys::keybox_cmd_KEYBOX_CMD_UNWRAP, reserved: 0 };
77 let unwrap_req_header =
78 KeyboxUnwrapReqPayloadHdr { wrapped_keybox_len: wrapped_keybox.len() as u64 };
79 KeyboxUnwrapReq { req_header, unwrap_req_header, wrapped_keybox }
80 }
81 }
82
83 impl<'s> Serialize<'s> for KeyboxUnwrapReq<'s> {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>84 fn serialize<'a: 's, S: Serializer<'s>>(
85 &'a self,
86 serializer: &mut S,
87 ) -> Result<S::Ok, S::Error> {
88 // SAFETY:
89 // - self.req_header.cmd and self.req_header.reserved are u32 and live long enough
90 // - self.unwrap_req_header.wrapped_keybox_len is a u64 and live long enough
91 unsafe {
92 serializer.serialize_as_bytes(&self.req_header.cmd)?;
93 serializer.serialize_as_bytes(&self.req_header.reserved)?;
94 serializer.serialize_as_bytes(&self.unwrap_req_header.wrapped_keybox_len)?;
95 }
96 serializer.serialize_bytes(self.wrapped_keybox)
97 }
98 }
99
100 pub(crate) struct KeyboxUnwrapResp {
101 unwrapped_keybox: Vec<u8>,
102 }
103
104 impl KeyboxUnwrapResp {
get_unwrapped_keybox(self) -> Vec<u8>105 pub(crate) fn get_unwrapped_keybox(self) -> Vec<u8> {
106 self.unwrapped_keybox
107 }
108 }
109
110 impl Deserialize for KeyboxUnwrapResp {
111 type Error = TipcError;
112 const MAX_SERIALIZED_SIZE: usize = KEYBOX_RESP_MAX_SIZE;
deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>113 fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
114 let (cmd, bytes) = <u32>::deserialize(bytes).map_err(|e| {
115 error!("received error when deserializing cmd: {:?}", e);
116 TipcError::UnknownError
117 })?;
118 if cmd != (sys::keybox_cmd_KEYBOX_CMD_UNWRAP | sys::keybox_cmd_KEYBOX_CMD_RSP_BIT) {
119 error!("Keybox unwrap deserialization received wrong cmd: {:?}", cmd);
120 return Err(TipcError::UnknownError);
121 }
122
123 let (status, bytes) = <u32>::deserialize(bytes).map_err(|e| {
124 error!("received error when deserializing status: {:?}", e);
125 TipcError::UnknownError
126 })?;
127 if status != sys::keybox_status_KEYBOX_STATUS_SUCCESS {
128 error!(" Keybox unwrap cmd failed: {:?}", status);
129 return Err(TipcError::UnknownError);
130 }
131
132 let (unwrapped_keybox_len, bytes) = <u64>::deserialize(bytes).map_err(|e| {
133 error!("received error when deserializing status: {:?}", e);
134 TipcError::UnknownError
135 })?;
136 if unwrapped_keybox_len as usize != bytes.len() {
137 error!(
138 "unwrapped keybox had wrong size. Expected: {:?}, Received: {:?}",
139 unwrapped_keybox_len,
140 bytes.len()
141 );
142 return Err(TipcError::UnknownError);
143 }
144
145 let unwrapped_keybox = try_to_vec(bytes).map_err(|e| {
146 error!("received error when trying to copy unwrapped keybox into vector: {:?}", e);
147 TipcError::AllocError
148 })?;
149
150 Ok(Self { unwrapped_keybox })
151 }
152 }
153