//! 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 {
    pub aes: Box<dyn crypto::Aes>,
    pub hkdf: Box<dyn crypto::Hkdf>,
    pub sdd_mgr: Option<Box<dyn SecureDeletionSecretManager>>,
    pub keys: Box<dyn device::RetrieveKeyMaterial>,
}

impl TrustyLegacyKeyBlobHandler {
    /// 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))
            }
            (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)
                    .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(hwkey::KdfVersion::from),
            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 keyblob::LegacyKeyHandler for TrustyLegacyKeyBlobHandler {
    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(())
    }
}
