blob: 75af3333c120fc432ad83e86df9c0fccd297e953 [file] [log] [blame]
/*
* 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
#[allow(unaligned_references)] // https://github.com/rust-lang/rust/issues/82523
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: &'static [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 })
}
}