//! Functionality for converting legacy keyblob formats.

use alloc::vec::Vec;
use kmr_common::keyblob::{
    legacy, SecureDeletionData, SecureDeletionSecretManager, SecureDeletionSlot,
};
use kmr_common::{
    crypto,
    crypto::{aes, OpaqueKeyMaterial, OpaqueOr},
    explicit, get_bool_tag_value, get_opt_tag_value, get_tag_value, keyblob, km_err, tag,
    try_to_vec, vec_try, Error, FallibleAllocExt,
};
use kmr_ta::device;
use kmr_wire::{
    keymint,
    keymint::{Algorithm, BootInfo, EcCurve, ErrorCode, KeyParam, KeyPurpose, SecurityLevel},
    KeySizeInBits,
};
use log::error;

/// Prefix for KEK derivation input when secure deletion not supported.
const AES_GCM_DESCRIPTOR_V1: &[u8] = b"AES-256-GCM-HKDF-SHA-256, version 1\0";
/// Prefix for KEK derivation input when secure deletion supported.
const AES_GCM_DESCRIPTOR_V2: &[u8] = b"AES-256-GCM-HKDF-SHA-256, version 2\0";

/// Slot number used to indicate that a key has no per-key secure deletion data.
const NO_SDD_SLOT_IDX: u32 = 0;

/// Legacy key handler that detects and converts `EncryptedKeyBlob` instances from
/// the previous Trusty implementation of KeyMint/Keymaster.
pub struct TrustyLegacyKeyBlobHandler<'a> {
    pub aes: &'a dyn crypto::Aes,
    pub hkdf: &'a dyn crypto::Hkdf,
    pub sdd_mgr: Option<&'a mut dyn SecureDeletionSecretManager>,
    pub keys: &'a dyn device::RetrieveKeyMaterial,
}

impl<'a> TrustyLegacyKeyBlobHandler<'a> {
    /// Build the derivation information needed for KEK derivation that is compatible with the
    /// previous C++ implementation.
    fn build_derivation_info(
        &self,
        encrypted_keyblob: &legacy::EncryptedKeyBlob,
        hidden: &[KeyParam],
        sdd_info: Option<(SecureDeletionData, u32)>,
    ) -> Result<Vec<u8>, Error> {
        let mut info = if sdd_info.is_some() {
            try_to_vec(AES_GCM_DESCRIPTOR_V2)?
        } else {
            try_to_vec(AES_GCM_DESCRIPTOR_V1)?
        };
        info.try_extend_from_slice(&tag::legacy::serialize(hidden)?)?;
        info.try_extend_from_slice(&tag::legacy::serialize(&encrypted_keyblob.hw_enforced)?)?;
        info.try_extend_from_slice(&tag::legacy::serialize(&encrypted_keyblob.sw_enforced)?)?;
        if let Some((sdd_data, slot)) = sdd_info {
            info.try_extend_from_slice(
                &(sdd_data.factory_reset_secret.len() as u32).to_ne_bytes(),
            )?;
            info.try_extend_from_slice(&sdd_data.factory_reset_secret)?;

            // If the slot is zero, the per-key secret is empty.
            let secret: &[u8] = if slot == 0 { &[] } else { &sdd_data.secure_deletion_secret };
            info.try_extend_from_slice(&(secret.len() as u32).to_ne_bytes())?;
            info.try_extend_from_slice(&secret)?;

            info.try_extend_from_slice(&slot.to_ne_bytes())?;
        }
        Ok(info)
    }

    /// Derive the key encryption key for a keyblob.
    fn derive_kek(
        &self,
        root_kek: &OpaqueOr<kmr_common::crypto::hmac::Key>,
        encrypted_keyblob: &legacy::EncryptedKeyBlob,
        hidden: &[KeyParam],
        sdd_data: Option<(SecureDeletionData, u32)>,
    ) -> Result<crypto::aes::Key, Error> {
        let info = self.build_derivation_info(encrypted_keyblob, hidden, sdd_data)?;
        // Trusty uses explicit keys for legacy keyblobs.
        let raw_key = self.hkdf.hkdf(&[], &explicit!(root_kek)?.0, &info, 256 / 8)?;
        let aes_key = crypto::aes::Key::Aes256(
            raw_key.try_into().map_err(|_e| km_err!(UnknownError, "unexpected HKDF output len"))?,
        );
        Ok(aes_key)
    }

    /// Convert a keyblob from the legacy C++ format to the current format.
    fn convert_key(
        &self,
        keyblob: &[u8],
        params: &[KeyParam],
        root_of_trust: &BootInfo,
        sec_level: SecurityLevel,
    ) -> Result<keyblob::PlaintextKeyBlob, Error> {
        let encrypted_keyblob = legacy::EncryptedKeyBlob::deserialize(keyblob)?;

        // Find the secure deletion data (if any) for the key.
        let sdd_info = match (
            encrypted_keyblob.format.requires_secure_deletion(),
            &self.sdd_mgr,
            encrypted_keyblob.key_slot,
        ) {
            (true, Some(sdd_mgr), None) | (true, Some(sdd_mgr), Some(NO_SDD_SLOT_IDX)) => {
                // Zero slot index implies that just the factory reset secret is populated.
                let sdd_data = sdd_mgr.get_factory_reset_secret()?;
                Some((sdd_data, NO_SDD_SLOT_IDX))
            }
            (true, Some(sdd_mgr), Some(slot_idx)) => {
                let slot = SecureDeletionSlot(slot_idx);
                let sdd_data = sdd_mgr.get_secret(slot)?;

                Some((sdd_data, slot_idx as u32))
            }
            (true, None, _) => {
                return Err(km_err!(
                    InvalidKeyBlob,
                    "keyblob requires secure deletion but no implementation available",
                ))
            }
            (false, _, Some(slot)) => {
                return Err(km_err!(
                    InvalidKeyBlob,
                    "unexpected SDD slot {} for format {:?}",
                    slot,
                    encrypted_keyblob.format
                ))
            }
            (false, _, None) => None,
        };

        // Convert the key characteristics to current form.
        let mut characteristics = vec_try![keymint::KeyCharacteristics {
            security_level: sec_level,
            authorizations: try_to_vec(&encrypted_keyblob.hw_enforced)?,
        }]?;
        if !encrypted_keyblob.sw_enforced.is_empty() {
            characteristics.try_push(keymint::KeyCharacteristics {
                security_level: keymint::SecurityLevel::Keystore,
                authorizations: try_to_vec(&encrypted_keyblob.sw_enforced)?,
            })?;
        }

        // Derive the KEK, using hidden inputs from params and root-of-trust.
        let rots = &[
            &root_of_trust.verified_boot_key[..],
            &(root_of_trust.verified_boot_state as u32).to_ne_bytes(),
            &[if root_of_trust.device_boot_locked { 0x01u8 } else { 0x00u8 }],
        ];
        let hidden_params = legacy::hidden(params, rots)?;

        let rollback_version = match encrypted_keyblob.addl_info {
            Some(v) => Some(
                hwkey::OsRollbackVersion::try_from(v as i32)
                    .map_err(|e| km_err!(InvalidKeyBlob, "unexpected addl_info={} : {:?}", v, e))?,
            ),
            None => None,
        };
        let kek_context = super::TrustyKekContext::new(
            encrypted_keyblob.format.is_versioned(),
            encrypted_keyblob.kdf_version.map(|v| hwkey::KdfVersion::from(v)),
            rollback_version,
        )?
        .to_raw()?;

        let root_kek = self.keys.root_kek(&kek_context)?;
        let aes_key = self.derive_kek(&root_kek, &encrypted_keyblob, &hidden_params, sdd_info)?;

        // Key material is encrypted with AES-GCM; decrypt it.
        let nonce: [u8; aes::GCM_NONCE_SIZE] = encrypted_keyblob
            .nonce
            .try_into()
            .map_err(|_e| km_err!(InvalidKeyBlob, "unexpected nonce len",))?;
        let mode = match encrypted_keyblob.tag.len() {
            12 => crypto::aes::GcmMode::GcmTag12 { nonce },
            13 => crypto::aes::GcmMode::GcmTag13 { nonce },
            14 => crypto::aes::GcmMode::GcmTag14 { nonce },
            15 => crypto::aes::GcmMode::GcmTag15 { nonce },
            16 => crypto::aes::GcmMode::GcmTag16 { nonce },
            l => return Err(km_err!(InvalidKeyBlob, "unexpected AES-GCM tag length {}", l)),
        };
        let mut op =
            self.aes.begin_aead(aes_key.into(), mode, crypto::SymmetricOperation::Decrypt)?;
        let mut raw_key_material = op.update(&encrypted_keyblob.ciphertext)?;
        raw_key_material.try_extend_from_slice(&op.update(&encrypted_keyblob.tag)?)?;
        raw_key_material.try_extend_from_slice(&op.finish()?)?;
        if raw_key_material.len() != encrypted_keyblob.ciphertext.len() {
            return Err(km_err!(
                UnknownError,
                "deciphered len {} != encrypted len {}",
                raw_key_material.len(),
                encrypted_keyblob.ciphertext.len()
            ));
        }

        // Convert the key material into current form.
        let chars = &encrypted_keyblob.hw_enforced;
        let key_material = match get_tag_value!(chars, Algorithm, ErrorCode::InvalidKeyBlob)? {
            // Symmetric keys have the key material stored as raw bytes.
            Algorithm::Aes => {
                // Special case: an AES key might be a storage key.
                if get_bool_tag_value!(chars, StorageKey)? {
                    // Storage key is opaque data.
                    crypto::KeyMaterial::Aes(OpaqueOr::Opaque(OpaqueKeyMaterial(raw_key_material)))
                } else {
                    // Normal case: expect explicit AES key material.
                    crypto::KeyMaterial::Aes(crypto::aes::Key::new(raw_key_material)?.into())
                }
            }
            Algorithm::TripleDes => {
                crypto::KeyMaterial::TripleDes(crypto::des::Key::new(raw_key_material)?.into())
            }
            Algorithm::Hmac => {
                crypto::KeyMaterial::Hmac(crypto::hmac::Key::new(raw_key_material).into())
            }

            // RSA keys have key material stored as a PKCS#1 `RSAPrivateKey` structure, DER-encoded,
            // as decoded by the BoringSSL `RSA_parse_private_key()` function. This matches the
            // internal form of a [`crypto::rsa::Key`].
            Algorithm::Rsa => crypto::KeyMaterial::Rsa(crypto::rsa::Key(raw_key_material).into()),

            Algorithm::Ec => {
                // Determine the EC curve, allowing for old keys that don't include `EC_CURVE` tag.
                let ec_curve = match get_opt_tag_value!(chars, EcCurve)? {
                    Some(c) => *c,
                    None => match get_tag_value!(chars, KeySize, ErrorCode::InvalidKeyBlob)? {
                        KeySizeInBits(224) => EcCurve::P224,
                        KeySizeInBits(384) => EcCurve::P384,
                        KeySizeInBits(256) => {
                            return Err(km_err!(InvalidKeyBlob, "key size 256 ambiguous for EC"))
                        }
                        KeySizeInBits(521) => EcCurve::P521,
                        sz => return Err(km_err!(InvalidKeyBlob, "key size {:?} invalid", sz)),
                    },
                };
                match ec_curve {
                    // NIST curve EC keys are stored as an `ECPrivateKey` structure, DER-encoded, as
                    // decoded by the BoringSSL `EC_KEY_parse_private_key()` function. This matches
                    // the internal form of a [`crypto::ec::NistKey`].
                    EcCurve::P224 => crypto::KeyMaterial::Ec(
                        ec_curve,
                        crypto::CurveType::Nist,
                        crypto::ec::Key::P224(crypto::ec::NistKey(raw_key_material)).into(),
                    ),
                    EcCurve::P256 => crypto::KeyMaterial::Ec(
                        ec_curve,
                        crypto::CurveType::Nist,
                        crypto::ec::Key::P256(crypto::ec::NistKey(raw_key_material)).into(),
                    ),
                    EcCurve::P384 => crypto::KeyMaterial::Ec(
                        ec_curve,
                        crypto::CurveType::Nist,
                        crypto::ec::Key::P384(crypto::ec::NistKey(raw_key_material)).into(),
                    ),
                    EcCurve::P521 => crypto::KeyMaterial::Ec(
                        ec_curve,
                        crypto::CurveType::Nist,
                        crypto::ec::Key::P521(crypto::ec::NistKey(raw_key_material)).into(),
                    ),
                    EcCurve::Curve25519 => {
                        let key = crypto::ec::import_pkcs8_key(&raw_key_material)?;
                        if let crypto::KeyMaterial::Ec(EcCurve::Curve25519, curve_type, _ec_key) =
                            &key
                        {
                            match curve_type {
                                crypto::CurveType::Nist => {
                                    return Err(km_err!(
                                        InvalidKeyBlob,
                                        "unexpected NIST key with curve25519"
                                    ))
                                }
                                crypto::CurveType::Xdh => {
                                    if tag::primary_purpose(chars)? != KeyPurpose::AgreeKey {
                                        return Err(km_err!(
                                            InvalidKeyBlob,
                                            "purpose not AGREE_KEY for X25519 key"
                                        ));
                                    }
                                }
                                crypto::CurveType::EdDsa => {
                                    if tag::primary_purpose(chars)? == KeyPurpose::AgreeKey {
                                        return Err(km_err!(
                                            InvalidKeyBlob,
                                            "AGREE_KEY purpose for non-XDH 25519 key"
                                        ));
                                    }
                                }
                            }
                        } else {
                            return Err(km_err!(
                                InvalidKeyBlob,
                                "curve25519 key with wrong contents"
                            ));
                        }
                        key
                    }
                }
            }
        };

        Ok(keyblob::PlaintextKeyBlob { characteristics, key_material })
    }
}

impl<'a> keyblob::LegacyKeyHandler for TrustyLegacyKeyBlobHandler<'a> {
    fn convert_legacy_key(
        &self,
        keyblob: &[u8],
        params: &[KeyParam],
        root_of_trust: &BootInfo,
        sec_level: SecurityLevel,
    ) -> Result<keyblob::PlaintextKeyBlob, Error> {
        self.convert_key(keyblob, params, root_of_trust, sec_level)
    }

    fn delete_legacy_key(&mut self, keyblob: &[u8]) -> Result<(), Error> {
        let encrypted_keyblob = legacy::EncryptedKeyBlob::deserialize(keyblob)?;
        if let Some(slot) = encrypted_keyblob.key_slot {
            if slot != NO_SDD_SLOT_IDX {
                if !encrypted_keyblob.format.requires_secure_deletion() {
                    return Err(km_err!(
                        UnknownError,
                        "legacy keyblob of non-SDD format {:?} has non-empty SDD slot {:?}!",
                        encrypted_keyblob.format,
                        slot
                    ));
                }
                if let Some(sdd_mgr) = self.sdd_mgr.as_mut() {
                    if let Err(e) = sdd_mgr.delete_secret(SecureDeletionSlot(slot)) {
                        error!("failed to delete SDD slot {:?} for legacy key: {:?}", slot, e);
                    }
                } else {
                    error!("legacy key has SDD slot {:?} but no SDD mgr available!", slot);
                }
            }
        }
        Ok(())
    }
}
