/*
 * Copyright (C) 2022 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.
 */
//! Trusty implementation of RetrieveKeyMaterial.

use alloc::vec::Vec;
use core::ffi::CStr;
use core::mem::size_of;
use hwkey::{Hwkey, KdfVersion, OsRollbackVersion, RollbackVersionSource};
use kmr_common::{crypto, km_err, vec_try_with_capacity, Error};
use kmr_wire::secureclock::{TimeStampToken, TIME_STAMP_MAC_LABEL};

pub(crate) mod legacy;

/// Size of a key agreement key in bytes.
const TRUSTY_KM_KAK_SIZE: usize = 32;

/// Size of a key wrapping key in bytes.
const TRUSTY_KM_WRAPPING_KEY_SIZE: usize = 16;

/// Key slot identification; matches the value used in
/// `OpenSSLKeymasterEnforcement::GetKeyAgreementKey` in `openssl_keymaster_enforcement.cpp` for
/// back-compatibility.
const KM_KAK_SLOT_ID: &'static [u8] = b"com.android.trusty.keymint.kak\0";

/// Key derivation input data; matches `kMasterKeyDerivationData` in `trusty_keymaster_context.cpp`
/// for back-compatibility.
const KM_KEY_DERIVATION_DATA: &'static [u8] = b"KeymasterMaster\0";

/// Size of a `u32` value in bytes.
const U32_SIZE: usize = core::mem::size_of::<u32>();

/// Extract a (little-endian) serialized `u32`.
fn deserialize_u32(bytes: &[u8], error_message: &str) -> Result<u32, Error> {
    let u32_bytes: [u8; U32_SIZE] = match bytes.try_into() {
        Ok(byte_array) => byte_array,
        Err(_) => return Err(km_err!(InvalidArgument, "{}", error_message)),
    };
    Ok(u32::from_le_bytes(u32_bytes))
}

/// Convert an [`OsRollbackVersion`] to an integer value, expanding `Current` along the way.
fn os_rollback_version_to_u32(os_rollback_version: OsRollbackVersion) -> Result<u32, Error> {
    match os_rollback_version {
        // If we get a `Current` version, we want to convert it to the specific version, so the
        // context remains accurate if it is saved and used at a later time.
        OsRollbackVersion::Current => {
            let hwkey_session = match Hwkey::open() {
                Ok(connection) => connection,
                Err(_) => {
                    return Err(km_err!(SecureHwCommunicationFailed, "hwkey connection error"))
                }
            };
            match hwkey_session.query_current_os_version(RollbackVersionSource::CommittedVersion) {
                Ok(OsRollbackVersion::Version(n)) => Ok(n),
                _ => Err(km_err!(
                    SecureHwCommunicationFailed,
                    "couldn't get current os rollback version"
                )),
            }
        }
        OsRollbackVersion::Version(n) => Ok(n),
    }
}

/// Context information required for key derivation with versioned information.
#[derive(Clone, Debug, PartialEq, Eq)]
struct NonLegacyKeyContext {
    kdf_version: KdfVersion,
    os_rollback_version: OsRollbackVersion,
}

/// KEK context that provides information to derive the same Key Encryption Key used to encrypt a
/// given key. To be able to do that we need to know if the key is a legacy one or not; and if it is
/// not a legacy key; we need to know the KDF method used (although currently there is only 1
/// method) and the Os Rollback version (more info on this parameters can be found on the trusty
/// hwkey crate).
#[derive(Clone, Debug, PartialEq, Eq)]
enum TrustyKekContext {
    LegacyKey,
    NonLegacyKey(NonLegacyKeyContext),
}

impl TrustyKekContext {
    /// Current version of the serialized format of [`TrustyKekContext`] data.  If the structure is
    /// changed this number needs to be bumped and the serialize/deserialize functions updated.
    const CONTEXT_VERSION: u32 = 1;

    /// Offset of version marker for serialized data.
    const CONTEXT_VER_OFFSET: usize = 0;
    /// Offset of non-legacy key indicator in serialized data.  Reserves 4 bytes in case we want to
    /// replace it with the enum that represents the specific key format.  For kek derivation we
    /// don't really use it; it is either a legacy key or not.
    const NON_LEGACY_KEY_OFFSET: usize = Self::CONTEXT_VER_OFFSET + U32_SIZE;
    /// Offset of KDF version in serialized data.
    const KDF_VER_OFFSET: usize = Self::NON_LEGACY_KEY_OFFSET + U32_SIZE;
    /// Offset of OS rollback version in serialized data.
    const OS_ROLLBACK_VER_OFFSET: usize = Self::KDF_VER_OFFSET + U32_SIZE;

    /// Overall size of serialized form in bytes.
    const SERIALIZED_SIZE: usize = Self::OS_ROLLBACK_VER_OFFSET + U32_SIZE;

    /// Build a new `TrustyKekContext` from constituent values.
    fn new(
        non_legacy_key: bool,
        kdf_version: Option<KdfVersion>,
        os_rollback_version: Option<OsRollbackVersion>,
    ) -> Result<Self, Error> {
        if non_legacy_key {
            if kdf_version.is_none() {
                return Err(km_err!(InvalidArgument, "non-legacy keys require a KDF version"));
            }
            if os_rollback_version.is_none() {
                return Err(km_err!(
                    InvalidArgument,
                    "non-legacy keys require an OS Rollback version"
                ));
            }
            // Directly unwrapping values because we checked that they were not None
            let kdf_version = kdf_version.unwrap();
            let os_rollback_version = os_rollback_version.unwrap();
            Ok(TrustyKekContext::NonLegacyKey(NonLegacyKeyContext {
                kdf_version,
                os_rollback_version,
            }))
        } else {
            if kdf_version.is_some() {
                return Err(km_err!(InvalidArgument, "legacy keys do not use a KDF version"));
            }
            if os_rollback_version.is_some() {
                return Err(km_err!(
                    InvalidArgument,
                    "legacy keys do not use a OS Rollback version"
                ));
            }
            Ok(TrustyKekContext::LegacyKey)
        }
    }

    /// Build a [`TrustyKekContext`] from its serialized form.
    fn from_raw(raw_context: &[u8]) -> Result<Self, Error> {
        if raw_context.len() != Self::SERIALIZED_SIZE {
            return Err(km_err!(
                InvalidArgument,
                "provided kek context had wrong size ({} not {} bytes)",
                raw_context.len(),
                Self::SERIALIZED_SIZE
            ));
        }
        let context_version = deserialize_u32(
            &raw_context[..Self::NON_LEGACY_KEY_OFFSET],
            "couldn't deserialize context version",
        )?;
        if context_version != Self::CONTEXT_VERSION {
            return Err(km_err!(InvalidArgument, "invalid context version {}", context_version));
        }
        let non_legacy_key = deserialize_u32(
            &raw_context[Self::NON_LEGACY_KEY_OFFSET..Self::KDF_VER_OFFSET],
            "couldn't deserialize kdf version",
        )?;
        match non_legacy_key {
            0 => Ok(TrustyKekContext::LegacyKey),
            1 => {
                let kdf_version = deserialize_u32(
                    &raw_context[Self::KDF_VER_OFFSET..Self::OS_ROLLBACK_VER_OFFSET],
                    "couldn't deserialize kdf version",
                )?;
                let kdf_version = KdfVersion::from(kdf_version);
                let os_rollback_version = deserialize_u32(
                    &raw_context[Self::OS_ROLLBACK_VER_OFFSET..],
                    "Couldn't deserialize os rolback version",
                )?;
                let os_rollback_version = OsRollbackVersion::Version(os_rollback_version);
                Ok(TrustyKekContext::NonLegacyKey(NonLegacyKeyContext {
                    kdf_version,
                    os_rollback_version,
                }))
            }
            v => Err(km_err!(InvalidArgument, "invalid non legacy key value {}", v)),
        }
    }

    /// Convert a [`TrustyKekContext`] into its serialized form, as 4 consecutive little-endian U32
    /// values:
    /// - context version
    /// - non-legacy key indicator
    /// - KDF version
    /// - OS rollback version.
    fn to_raw(&self) -> Result<Vec<u8>, Error> {
        // For legacy keys giving 0 values for OS and KDF version. These values will be ignored on
        // deserialization.
        let (os_version, kdf_version, non_legacy_key) = match self {
            TrustyKekContext::LegacyKey => (0, 0, 0u32),
            TrustyKekContext::NonLegacyKey(ctx) => {
                let os_version = os_rollback_version_to_u32(ctx.os_rollback_version)?;
                let kdf_version: u32 = ctx.kdf_version.into();
                (os_version, kdf_version, 1u32)
            }
        };
        let mut raw_vec = vec_try_with_capacity!(Self::SERIALIZED_SIZE)?;
        raw_vec.extend_from_slice(&Self::CONTEXT_VERSION.to_le_bytes());
        raw_vec.extend_from_slice(&non_legacy_key.to_le_bytes());
        raw_vec.extend_from_slice(&kdf_version.to_le_bytes());
        raw_vec.extend_from_slice(&os_version.to_le_bytes());
        Ok(raw_vec)
    }
}

/// Key material retrieval implementation for Trusty.
pub struct TrustyKeys;

// TODO: Change traits definitions to support kek and kak keys stored on hardware if needed.
//       RawKeyMaterial assume that the key will be passed in the clear, which won't be the case
//       if the IP block never releases the key. KeyMaterial type fixes that issue by including
//       Opaque keys, but RawKeys are not included in KeyMaterial.
impl kmr_ta::device::RetrieveKeyMaterial for TrustyKeys {
    fn root_kek(&self, context: &[u8]) -> Result<crypto::OpaqueOr<crypto::hmac::Key>, Error> {
        let context = TrustyKekContext::from_raw(context)?;
        let hwkey_session = Hwkey::open().map_err(|e| {
            km_err!(SecureHwCommunicationFailed, "failed to connect to hwkey: {:?}", e)
        })?;

        let mut key_buffer = [0; TRUSTY_KM_WRAPPING_KEY_SIZE];

        match context {
            TrustyKekContext::NonLegacyKey(context) => {
                let _ = hwkey_session
                    .derive_key_req()
                    .unique_key()
                    .kdf(context.kdf_version)
                    .os_rollback_version(context.os_rollback_version)
                    .rollback_version_source(RollbackVersionSource::CommittedVersion)
                    .derive(KM_KEY_DERIVATION_DATA, &mut key_buffer)
                    .map_err(|e| {
                        km_err!(SecureHwCommunicationFailed, "failed to derive key: {:?}", e)
                    })?;
            }
            TrustyKekContext::LegacyKey => {
                let _ = hwkey_session
                    .derive_key_req()
                    .kdf(KdfVersion::Version(1))
                    .derive(KM_KEY_DERIVATION_DATA, &mut key_buffer)
                    .map_err(|e| {
                        km_err!(SecureHwCommunicationFailed, "failed to derive legacy key: {:?}", e)
                    })?;
            }
        }
        Ok(crypto::hmac::Key::new(key_buffer.to_vec()).into())
    }

    fn kek_context(&self) -> Result<Vec<u8>, Error> {
        TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current))?
            .to_raw()
    }

    fn kak(&self) -> Result<crypto::OpaqueOr<crypto::aes::Key>, Error> {
        let hwkey_session = Hwkey::open().map_err(|e| {
            km_err!(SecureHwCommunicationFailed, "failed to connect to HwKey: {:?}", e)
        })?;
        let mut key_buffer = [0; TRUSTY_KM_KAK_SIZE];
        let keyslot = CStr::from_bytes_with_nul(KM_KAK_SLOT_ID)
            .expect("should never happen, KM_KAK_SLOT_ID follows from_bytes_with_nul rules");
        let _kak = hwkey_session
            .get_keyslot_data(keyslot, &mut key_buffer)
            .map_err(|e| km_err!(SecureHwCommunicationFailed, "failed to retrieve kak: {:?}", e))?;
        // TODO: check whether `key_buffer` needs truncating to size of `_kak`.
        Ok(crypto::aes::Key::Aes256(key_buffer).into())
    }

    fn timestamp_token_mac_input(&self, token: &TimeStampToken) -> Result<Vec<u8>, Error> {
        let mut result = vec_try_with_capacity!(
            TIME_STAMP_MAC_LABEL.len() +
        size_of::<i64>() + // challenge (host-endian)
        size_of::<i64>() + // timestamp (host-endian)
        size_of::<u32>() // 1u32 (host-endian)
        )?;
        // For compatibility with previous implementations, use native byte order for MAC inputs.
        result.extend_from_slice(TIME_STAMP_MAC_LABEL);
        result.extend_from_slice(&token.challenge.to_ne_bytes()[..]);
        result.extend_from_slice(&token.timestamp.milliseconds.to_ne_bytes()[..]);
        result.extend_from_slice(&1u32.to_ne_bytes()[..]);
        Ok(result)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use kmr_ta::device::RetrieveKeyMaterial;
    use test::{expect, expect_eq, expect_ne};

    #[test]
    fn kak_call_returns_key() {
        let trusty_keys = TrustyKeys;
        let kak = trusty_keys.kak().expect("Couldn't retrieve kak");
        let kak = kmr_common::explicit!(kak).expect("kak should be an explicit key");

        expect!(matches!(kak, crypto::aes::Key::Aes256(_)), "Should have received an AES 256 key");

        let key = match kak {
            crypto::aes::Key::Aes256(key) => key,
            _ => panic!("Wrong type of key received"),
        };
        // Getting an all 0 key agreement key by chance is not likely if we got a connection to
        // HWKey
        expect_ne!(key, [0; TRUSTY_KM_KAK_SIZE], "key agreement key should not be 0s");
    }

    #[test]
    fn kak_two_calls_returns_same_key() {
        let trusty_keys = TrustyKeys;

        let kak = trusty_keys.kak().expect("Couldn't retrieve kak");
        let kak1 = match kmr_common::explicit!(kak).expect("kak should be an explicit key") {
            crypto::aes::Key::Aes256(key) => key,
            _ => panic!("Wrong type of key received"),
        };
        let kak = trusty_keys.kak().expect("Couldn't retrieve kak");
        let kak2 = match kmr_common::explicit!(kak).expect("kak should be an explicit key") {
            crypto::aes::Key::Aes256(key) => key,
            _ => panic!("Wrong type of key received"),
        };
        expect_eq!(kak1, kak2, "Calls to kak should return the same key");
    }

    #[test]
    fn kek_call_returns_key() {
        let trusty_keys = TrustyKeys;
        let kek = trusty_keys
            .root_kek(&trusty_keys.kek_context().expect("Couldn't get kek context"))
            .expect("Couldn't get kek");
        let kek = kmr_common::explicit!(kek).expect("kek should be an explicit key");

        // Getting an all 0 key encryption key by chance is not likely if we got a connection to
        // HWKey
        expect_ne!(
            kek.0,
            [0; TRUSTY_KM_WRAPPING_KEY_SIZE].to_vec(),
            "Key encryption key should not be 0s"
        );
    }

    #[test]
    fn kek_two_calls_returns_same_key() {
        let trusty_keys = TrustyKeys;
        let kek1 = kmr_common::explicit!(trusty_keys
            .root_kek(&trusty_keys.kek_context().expect("Couldn't get kek context"))
            .expect("Couldn't get kek"))
        .expect("kek should be an explicit key");
        let kek2 = kmr_common::explicit!(trusty_keys
            .root_kek(&trusty_keys.kek_context().expect("Couldn't get kek context"))
            .expect("Couldn't get kek"))
        .expect("kek should be an explicit key");

        expect_eq!(kek1.0, kek2.0, "Calls to root_kek should return the same key");
    }

    #[test]
    fn kek_with_different_context_return_different_keys() {
        let context1 =
            TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current));
        // Transforming back and forward to raw format to get specific versions
        let context1 = TrustyKekContext::from_raw(&context1.unwrap().to_raw().unwrap()).unwrap();
        let non_legacy_context1 = match context1.clone() {
            TrustyKekContext::NonLegacyKey(context) => context,
            _ => panic!("Didn't get back a non-legacy key"),
        };
        let context1_version = match non_legacy_context1.os_rollback_version {
            OsRollbackVersion::Version(n) => n,
            _ => panic!("Didn't get an specific version"),
        };
        // Specific running/committed versions are greater than 0.
        let context2_version = context1_version - 1;
        let context2 = TrustyKekContext::new(
            true,
            Some(KdfVersion::Best),
            Some(OsRollbackVersion::Version(context2_version)),
        )
        .unwrap();
        let trusty_keys = TrustyKeys;
        let kek1 = kmr_common::explicit!(trusty_keys
            .root_kek(&context1.to_raw().expect("Couldn't serialize kek1 context"))
            .expect("Couldn't get kek"))
        .expect("kek should be an explicit key");
        let kek2 = kmr_common::explicit!(trusty_keys
            .root_kek(&context2.to_raw().expect("Couldn't serialize kek2 context"))
            .expect("Couldn't get kek"))
        .expect("kek should be an explicit key");

        expect_ne!(kek1.0, kek2.0, "kek keys should be different");
    }

    #[test]
    fn legacy_kek_is_different_than_non_legacy() {
        let context1 =
            TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current))
                .unwrap();
        let context2 = TrustyKekContext::new(false, None, None).unwrap();
        let trusty_keys = TrustyKeys;
        let kek1 = kmr_common::explicit!(trusty_keys
            .root_kek(&context1.to_raw().expect("Couldn't serialize kek1 context"))
            .expect("Couldn't get kek"))
        .expect("kek should be an explicit key");
        let kek2 = kmr_common::explicit!(trusty_keys
            .root_kek(&context2.to_raw().expect("Couldn't serialize kek2 context"))
            .expect("Couldn't get kek"))
        .expect("kek should be an explicit key");

        expect_ne!(kek1.0, kek2.0, "kek keys should be different");
    }

    #[test]
    fn deserializing_u32s() {
        let num = deserialize_u32(&[0; 0], "");
        expect!(num.is_err(), "We need an array of exactly 4 bytes for a u32");
        let num = deserialize_u32(&[0; 3], "");
        expect!(num.is_err(), "We need an array of exactly 4 bytes for a u32");
        let num = deserialize_u32(&[0; 5], "");
        expect!(num.is_err(), "We need an array of exactly 4 bytes for a u32");
        let num = deserialize_u32(&[0; 4], "").unwrap();
        expect_eq!(num, 0, "recovered number should be 0");
        let num = deserialize_u32(&[0xff; 4], "").unwrap();
        expect_eq!(num, 0xffffffff, "recovered number should be 0xffffffff");
        let num = deserialize_u32(&[1, 0, 0, 0], "").unwrap();
        expect_eq!(num, 1, "recovered number should be 1");
        let num = deserialize_u32(&[0x78, 0x56, 0x34, 0x12], "").unwrap();
        expect_eq!(num, 0x12345678, "recovered number should be 0x12345678");
    }

    #[test]
    fn os_version_to_u32() {
        for version in 0..20 {
            let u32_version =
                os_rollback_version_to_u32(OsRollbackVersion::Version(version)).unwrap();
            expect_eq!(version, u32_version, "Wriong version received");
        }
        let curr_version = os_rollback_version_to_u32(OsRollbackVersion::Current).unwrap();
        expect_ne!(curr_version, 0, "Current version should not be 0");
    }

    #[test]
    fn deserializing_bad_kek_context_fails() {
        let ctx_1 = TrustyKekContext::from_raw(&[0; 0]);
        expect!(ctx_1.is_err(), "deserializing an empty context should fail");
        let good_ctx =
            TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current))
                .unwrap();
        let mut ctx_raw = good_ctx.to_raw().unwrap();
        ctx_raw.push(0);
        let ctx_2 = TrustyKekContext::from_raw(&ctx_raw);
        expect!(ctx_2.is_err(), "deserializing a bigger than expected context should fail");
        ctx_raw.pop();
        let ctx_3 = TrustyKekContext::from_raw(&ctx_raw);
        expect!(ctx_3.is_ok(), "checking that good context can be deserialized");
        ctx_raw.pop();
        let ctx_4 = TrustyKekContext::from_raw(&ctx_raw);
        expect!(ctx_4.is_err(), "deserializing a smaller than expected context should fail");
        let ctx_5 = TrustyKekContext::from_raw(&[0; TrustyKekContext::SERIALIZED_SIZE]);
        expect!(ctx_5.is_err(), "deserializing a smaller than expected context should fail");
    }

    #[test]
    fn test_kek_context_serialization() {
        let original_ctx = TrustyKekContext::new(
            true,
            Some(KdfVersion::Best),
            Some(OsRollbackVersion::Version(2)),
        )
        .unwrap();
        let recovered_ctx = TrustyKekContext::from_raw(&original_ctx.to_raw().unwrap()).unwrap();
        expect_eq!(original_ctx, recovered_ctx, "Didn't get back same context");
        let original_ctx = TrustyKekContext::new(false, None, None).unwrap();
        let recovered_ctx = TrustyKekContext::from_raw(&original_ctx.to_raw().unwrap()).unwrap();
        expect_eq!(original_ctx, recovered_ctx, "Didn't get back same context");
    }

    #[test]
    fn test_kek_context_creation() {
        // Testing that non legacy context requires all parameters to be present
        let non_legacy_ctx = TrustyKekContext::new(true, None, Some(OsRollbackVersion::Version(2)));
        expect!(
            non_legacy_ctx.is_err(),
            "We should not be able to create a non legacy context without KDF version"
        );
        let non_legacy_ctx = TrustyKekContext::new(true, Some(KdfVersion::Best), None);
        expect!(
            non_legacy_ctx.is_err(),
            "We should not be able to create a non legacy context without OS rollback version"
        );
        let non_legacy_ctx = TrustyKekContext::new(
            true,
            Some(KdfVersion::Best),
            Some(OsRollbackVersion::Version(2)),
        );
        expect!(non_legacy_ctx.is_ok(), "Couldn't create non legacy context");
        // Testing that legacy context requires all optional parameters to be None
        let legacy_ctx = TrustyKekContext::new(
            false,
            Some(KdfVersion::Best),
            Some(OsRollbackVersion::Version(2)),
        );
        expect!(
            legacy_ctx.is_err(),
            "We should not be able to create a non legacy with optional parameters"
        );
        let legacy_ctx = TrustyKekContext::new(false, None, Some(OsRollbackVersion::Version(2)));
        expect!(
            legacy_ctx.is_err(),
            "We should not be able to create a non legacy context with a OS Rollback version"
        );
        let legacy_ctx = TrustyKekContext::new(false, Some(KdfVersion::Best), None);
        expect!(
            legacy_ctx.is_err(),
            "We should not be able to create a non legacy context without OS rollback version"
        );
        let legacy_ctx = TrustyKekContext::new(false, None, None);
        expect!(legacy_ctx.is_ok(), "Couldn't create legacy context");
    }
}
