/*
 * 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;
use tipc::{Deserialize, Handle, Serialize, Serializer, TipcError};

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