/*
 * 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 })
    }
}
