| /* |
| * Copyright (C) 2023 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| //! Wrapper around autogenerated ffi bindings. |
| |
| // Get the bindgen definitions |
| #[allow(non_upper_case_globals)] |
| #[allow(non_camel_case_types)] |
| #[allow(unused)] |
| #[allow(deref_nullptr)] // https://github.com/rust-lang/rust-bindgen/issues/1651 |
| mod sys { |
| include!(env!("BINDGEN_INC_FILE")); |
| } |
| |
| use core::mem; |
| use kmr_common::try_to_vec; |
| use kmr_wire::legacy::InnerSerialize; |
| use log::{error, warn}; |
| use tipc::{Deserialize, Handle, Serialize, Serializer, TipcError}; |
| |
| /// Add entropy to Trusty's RNG. |
| pub fn trusty_rng_add_entropy(data: &[u8]) { |
| let rc = unsafe { |
| // Safety: `data` is a valid slice |
| sys::trusty_rng_add_entropy(data.as_ptr(), data.len()) |
| }; |
| if rc != 0 { |
| warn!("trusty_rng_add_entropy() failed, {}", rc) |
| } |
| } |
| |
| pub(crate) const KEYBOX_PORT: &[u8; 28] = sys::KEYBOX_PORT; |
| |
| type KeyboxReqHdr = sys::keybox_req; |
| type KeyboxUnwrapReqPayloadHdr = sys::keybox_unwrap_req; |
| |
| pub(crate) const KEYBOX_RESP_HDR_SIZE: usize = |
| mem::size_of::<sys::keybox_resp>() + mem::size_of::<sys::keybox_unwrap_resp>(); |
| |
| const KEYBOX_RESP_MAX_SIZE: usize = KEYBOX_RESP_HDR_SIZE + (sys::KEYBOX_MAX_SIZE as usize); |
| |
| // Because KeyboxUnwrapResp deserialization doesn't use the ffi types, we add this check in case the |
| // c definitions change. |
| const _: () = assert!( |
| KEYBOX_RESP_HDR_SIZE == (mem::size_of::<u32>() + mem::size_of::<u32>() + mem::size_of::<u64>()), |
| "KEYBOX_RESP_HDR_SIZE do not match KeyboxUnwrapResp deserialization assumptions" |
| ); |
| |
| // KeyboxUnwrapReq is a type created to be processed by Trusty IPC Rust serialization. This means |
| // that any data that needs to be serialized when implementing the `Serialize` trait needs to |
| // outlive its `serialize` function. A consequence of that is that the serialized values might need |
| // some memory backup space until they have been transmitted. |
| // We do not have this restriction on types we are deserializing (like `KeyboxUnwrapResp`); on which |
| // this implementation prefers to use a type that can be directly used by the Rust code. This ends |
| // up creating an asymmetry between requests and responses. |
| pub(crate) struct KeyboxUnwrapReq<'a> { |
| req_header: KeyboxReqHdr, |
| unwrap_req_header: KeyboxUnwrapReqPayloadHdr, |
| wrapped_keybox: &'a [u8], |
| } |
| |
| impl<'a> KeyboxUnwrapReq<'a> { |
| pub(crate) fn new(wrapped_keybox: &'a [u8]) -> Self { |
| let req_header = KeyboxReqHdr { cmd: sys::keybox_cmd_KEYBOX_CMD_UNWRAP, reserved: 0 }; |
| let unwrap_req_header = |
| KeyboxUnwrapReqPayloadHdr { wrapped_keybox_len: wrapped_keybox.len() as u64 }; |
| KeyboxUnwrapReq { req_header, unwrap_req_header, wrapped_keybox } |
| } |
| } |
| |
| impl<'s> Serialize<'s> for KeyboxUnwrapReq<'s> { |
| fn serialize<'a: 's, S: Serializer<'s>>( |
| &'a self, |
| serializer: &mut S, |
| ) -> Result<S::Ok, S::Error> { |
| // SAFETY: |
| // - self.req_header.cmd and self.req_header.reserved are u32 and live long enough |
| // - self.unwrap_req_header.wrapped_keybox_len is a u64 and live long enough |
| unsafe { |
| serializer.serialize_as_bytes(&self.req_header.cmd)?; |
| serializer.serialize_as_bytes(&self.req_header.reserved)?; |
| serializer.serialize_as_bytes(&self.unwrap_req_header.wrapped_keybox_len)?; |
| } |
| serializer.serialize_bytes(self.wrapped_keybox) |
| } |
| } |
| |
| pub(crate) struct KeyboxUnwrapResp { |
| unwrapped_keybox: Vec<u8>, |
| } |
| |
| impl KeyboxUnwrapResp { |
| pub(crate) fn get_unwrapped_keybox(self) -> Vec<u8> { |
| self.unwrapped_keybox |
| } |
| } |
| |
| impl Deserialize for KeyboxUnwrapResp { |
| type Error = TipcError; |
| const MAX_SERIALIZED_SIZE: usize = KEYBOX_RESP_MAX_SIZE; |
| fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> { |
| let (cmd, bytes) = <u32>::deserialize(bytes).map_err(|e| { |
| error!("received error when deserializing cmd: {:?}", e); |
| TipcError::UnknownError |
| })?; |
| if cmd != (sys::keybox_cmd_KEYBOX_CMD_UNWRAP | sys::keybox_cmd_KEYBOX_CMD_RSP_BIT) { |
| error!("Keybox unwrap deserialization received wrong cmd: {:?}", cmd); |
| return Err(TipcError::UnknownError); |
| } |
| |
| let (status, bytes) = <u32>::deserialize(bytes).map_err(|e| { |
| error!("received error when deserializing status: {:?}", e); |
| TipcError::UnknownError |
| })?; |
| if status != sys::keybox_status_KEYBOX_STATUS_SUCCESS { |
| error!(" Keybox unwrap cmd failed: {:?}", status); |
| return Err(TipcError::UnknownError); |
| } |
| |
| let (unwrapped_keybox_len, bytes) = <u64>::deserialize(bytes).map_err(|e| { |
| error!("received error when deserializing status: {:?}", e); |
| TipcError::UnknownError |
| })?; |
| if unwrapped_keybox_len as usize != bytes.len() { |
| error!( |
| "unwrapped keybox had wrong size. Expected: {:?}, Received: {:?}", |
| unwrapped_keybox_len, |
| bytes.len() |
| ); |
| return Err(TipcError::UnknownError); |
| } |
| |
| let unwrapped_keybox = try_to_vec(bytes).map_err(|e| { |
| error!("received error when trying to copy unwrapped keybox into vector: {:?}", e); |
| TipcError::AllocError |
| })?; |
| |
| Ok(Self { unwrapped_keybox }) |
| } |
| } |