/* * 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::() + mem::size_of::(); 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::() + mem::size_of::() + mem::size_of::()), "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 { // 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, } impl KeyboxUnwrapResp { pub(crate) fn get_unwrapped_keybox(self) -> Vec { 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]) -> Result { let (cmd, bytes) = ::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) = ::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) = ::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 }) } }