// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::common::{DataRequest, KeyAttributes, KeyRequestType, KeyType, KmsKey};
use crate::crypto_provider::{
    optee_provider::OpteeProvider, software_provider::SoftwareProvider, CryptoProvider,
};
use crate::kms_asymmetric_key::KmsAsymmetricKey;
use crate::kms_sealing_key::{KmsSealingKey, SEALING_KEY_NAME};
use anyhow::format_err;
use base64;
use fidl::endpoints::ServerEnd;
use fidl_fuchsia_kms::{
    AsymmetricKeyAlgorithm, AsymmetricPrivateKeyMarker, Error, KeyManagerRequest, KeyOrigin,
    KeyProvider, MAX_DATA_SIZE,
};
use fidl_fuchsia_mem::Buffer;
use fuchsia_async as fasync;
use futures::prelude::*;
use log::{error, warn};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::io::{Error as IOError, ErrorKind};
use std::path::{Path, PathBuf};
use std::str;
use std::sync::{Arc, Mutex, RwLock};

const DEFAULT_PROVIDER: KeyProvider = KeyProvider::SoftwareProvider;
const KEY_FOLDER: &str = "/data/kms";
const USER_KEY_SUBFOLDER: &str = "user";
const INTERNAL_KEY_SUBFOLDER: &str = "internal";

#[derive(Serialize, Deserialize)]
struct KeyAttributesJson {
    pub key_algorithm: u32,
    pub key_type: KeyType,
    pub key_origin: u32,
    pub key_provider: u32,
    pub key_data: Vec<u8>,
}

/// Manages a key object map, delegates operation to key object and manages storage for key data.
///
/// KeyManager manages a key_name -> key_object map and delegates operations to key objects. When a
/// key creates, the key manager insert the key into the key map. When getting a key handle, the key
/// manager return the key object from key map. When deleting a key, the key is removed from key map
///, note that the key object itself is still alive as long as the handle is still alive, however,
/// the object would be mark deleted and any following request on that handle should return a
/// failure.
///
/// KeyManager also manages the storage for key data and key attributes.
pub struct KeyManager {
    /// A map of key_name -> key_object to store all the user keys.
    user_key_map: Arc<Mutex<HashMap<String, Arc<Mutex<dyn KmsKey>>>>>,
    /// A map of key_name -> key_object to store all the KMS internally managed keys. These keys are
    /// stored under a different folder than the user keys, thus we need a separate map to manage
    /// them in memory to be consistent.
    internal_key_map: Arc<Mutex<HashMap<String, Arc<Mutex<dyn KmsKey>>>>>,
    /// All the available crypto providers.
    crypto_provider_map: RwLock<HashMap<KeyProvider, Box<dyn CryptoProvider>>>,
    /// The path to the key folder to store key data and attributes.
    key_folder: String,
    provider: KeyProvider,
}

impl KeyManager {
    pub fn new() -> Self {
        let mut key_manager = KeyManager {
            user_key_map: Arc::new(Mutex::new(HashMap::new())),
            internal_key_map: Arc::new(Mutex::new(HashMap::new())),
            crypto_provider_map: RwLock::new(HashMap::new()),
            key_folder: KEY_FOLDER.to_string(),
            provider: DEFAULT_PROVIDER,
        };

        key_manager.add_provider(Box::new(SoftwareProvider::new()));
        key_manager.add_provider(Box::new(OpteeProvider {}));

        key_manager
    }

    pub fn set_provider(&mut self, crypto_provider: KeyProvider) -> Result<(), anyhow::Error> {
        if !self.crypto_provider_map.read().unwrap().contains_key(&crypto_provider) {
            return Err(format_err!("Invalid crypto provider name"));
        }
        self.provider = crypto_provider;
        Ok(())
    }

    #[allow(dead_code)]
    #[cfg(test)]
    pub fn set_key_folder(&mut self, key_folder: &str) {
        self.key_folder = key_folder.to_string();
    }

    pub fn handle_request(&self, req: KeyManagerRequest) -> Result<(), fidl::Error> {
        match req {
            KeyManagerRequest::GenerateAsymmetricKey { key_name, key, responder } => {
                self.with_provider(self.provider, |provider| {
                    // Default algorithm for asymmetric key is ECDSA-SHA512-P521.
                    responder.send(&mut self.generate_asymmetric_key_and_bind(
                        &key_name,
                        key,
                        AsymmetricKeyAlgorithm::EcdsaSha512P521,
                        provider.unwrap(),
                    ))
                })
            }
            KeyManagerRequest::GenerateAsymmetricKeyWithAlgorithm {
                key_name,
                key_algorithm,
                key,
                responder,
            } => self.with_provider(self.provider, |provider| {
                responder.send(&mut self.generate_asymmetric_key_and_bind(
                    &key_name,
                    key,
                    key_algorithm,
                    provider.unwrap(),
                ))
            }),
            KeyManagerRequest::GetAsymmetricPrivateKey { key_name, key, responder } => {
                responder.send(&mut self.get_asymmetric_private_key_and_bind(&key_name, key))
            }
            KeyManagerRequest::ImportAsymmetricPrivateKey {
                data,
                key_name,
                key_algorithm,
                key,
                responder,
            } => self.with_provider(self.provider, |provider| {
                responder.send(&mut self.import_asymmetric_private_key_and_bind(
                    &data,
                    &key_name,
                    key_algorithm,
                    key,
                    provider.unwrap(),
                ))
            }),
            KeyManagerRequest::SealData { plain_text, responder } => self
                .with_provider(self.provider, |provider| {
                    responder.send(&mut self.seal_data(plain_text, provider.unwrap()))
                }),
            KeyManagerRequest::UnsealData { cipher_text, responder } => self
                .with_provider(self.provider, |provider| {
                    responder.send(&mut self.unseal_data(cipher_text, provider.unwrap()))
                }),
            KeyManagerRequest::DeleteKey { key_name, responder } => {
                responder.send(&mut self.delete_key(&key_name))
            }
        }
    }

    /// Bind an in_memory asymmetric key object to a channel initiated by user.
    ///
    /// # Arguments
    ///
    /// * `key_name` - The name for the key to bind.
    /// * `key_to_bind` - The in memory key object to bind.
    /// * `key` - The server end of the user channel to bind the key to.
    fn bind_asymmetric_key_to_server(
        &self,
        key_name: &str,
        key_to_bind: Arc<Mutex<dyn KmsKey>>,
        key: ServerEnd<AsymmetricPrivateKeyMarker>,
    ) -> Result<(), Error> {
        let mut request_stream = key.into_stream().map_err(debug_err_fn!(
            Error::InternalError,
            "Error creating AsymmetricKey request stream {:?}"
        ))?;
        // Need to clone the key_name to be move into the async function.
        let key_name = String::from(key_name);
        // Copy the key map into the async function.
        let key_map_ref = Arc::clone(&self.user_key_map);
        fasync::Task::local(
            // Spawn async job to handle requests.
            async move {
                while let Some(r) = request_stream.try_next().await? {
                    key_to_bind
                        .lock()
                        .unwrap()
                        .handle_request(KeyRequestType::AsymmetricPrivateKeyRequest(r))?;
                }
                Ok(())
            }
            .and_then(|_| async move {
                Self::clean_up(key_map_ref, &key_name);
                Ok(())
            })
            .unwrap_or_else(|e: fidl::Error| error!("Error running AsymmetricKey {:?}", e)),
        )
        .detach();
        Ok(())
    }

    /// Clean up the in memory key object if it no longer required.
    ///
    /// The key is no longer used. If it is only referenced in the key_map, remove it. This would
    // free the cached key data.
    ///
    /// # Arguments
    ///
    /// * `key_map` - The reference to the key object map.
    /// * `key_name` - The name for the key that is no longer required.
    fn clean_up(key_map: Arc<Mutex<HashMap<String, Arc<Mutex<dyn KmsKey>>>>>, key_name: &str) {
        let mut key_map = key_map.lock().unwrap();
        if key_map.contains_key(key_name) {
            let key_only_referenced_in_map = {
                let key = &key_map[key_name];
                Arc::strong_count(key) == 1
            };
            if key_only_referenced_in_map {
                key_map.remove(key_name);
            }
        }
    }

    /// Generate an asymmetric key object and bind the generated key to the user channel.
    ///
    /// # Arguments
    ///
    /// * `key_name` - The name for the key to be generated.
    /// * `key` - The server end of the user channel to bind.
    /// * `key_algorithm` - The algorithm for the key to be generated.
    /// * `provider` - The crypto provider to generate the key with.
    fn generate_asymmetric_key_and_bind(
        &self,
        key_name: &str,
        key: ServerEnd<AsymmetricPrivateKeyMarker>,
        key_algorithm: AsymmetricKeyAlgorithm,
        provider: &dyn CryptoProvider,
    ) -> Result<(), Error> {
        let key_to_bind = self.generate_asymmetric_key(key_name, key_algorithm, provider)?;
        self.bind_asymmetric_key_to_server(key_name, key_to_bind, key)
    }

    /// Generate an asymmetric key object.
    ///
    /// Generate an asymmetric key object, write the key data and key attributes to file. Insert the
    /// in memory key object into key map and return the key object.
    ///
    /// # Arguments
    ///
    /// * `key_name` - The name for the key to be generated.
    /// * `key_algorithm` - The algorithm for the key to be generated.
    /// * `provider` - The crypto provider to generate the key with.
    fn generate_asymmetric_key(
        &self,
        key_name: &str,
        key_algorithm: AsymmetricKeyAlgorithm,
        provider: &dyn CryptoProvider,
    ) -> Result<Arc<Mutex<KmsAsymmetricKey>>, Error> {
        self.generate_or_import_asymmetric_key(key_name, key_algorithm, provider, None)
    }

    /// Import an asymmetric key object and bind the imported key to the user channel.
    ///
    /// # Arguments
    ///
    /// * `data` - The imported key data.
    /// * `key_name` - The name for the key to be imported.
    /// * `key_algorithm` - The algorithm for the key to be imported.
    /// * `key` - The server end of the user channel to bind
    /// * `provider` - The crypto provider to parse the key with.
    fn import_asymmetric_private_key_and_bind(
        &self,
        data: &[u8],
        key_name: &str,
        key_algorithm: AsymmetricKeyAlgorithm,
        key: ServerEnd<AsymmetricPrivateKeyMarker>,
        provider: &dyn CryptoProvider,
    ) -> Result<(), Error> {
        let key_to_bind =
            self.import_asymmetric_private_key(data, &key_name, key_algorithm, provider)?;
        self.bind_asymmetric_key_to_server(&key_name, key_to_bind, key)
    }

    /// Import an asymmetric key object.
    ///
    /// Import an asymmetric key object, write the key data and key attributes to file. Insert the
    /// in memory key object into key map and return the key object.
    ///
    /// # Arguments
    ///
    /// * `data` - The imported key data.
    /// * `key_name` - The name for the key to be imported.
    /// * `key_algorithm` - The algorithm for the key to be imported.
    /// * `provider` - The crypto provider to parse the key with.
    fn import_asymmetric_private_key(
        &self,
        data: &[u8],
        key_name: &str,
        key_algorithm: AsymmetricKeyAlgorithm,
        provider: &dyn CryptoProvider,
    ) -> Result<Arc<Mutex<KmsAsymmetricKey>>, Error> {
        self.generate_or_import_asymmetric_key(key_name, key_algorithm, provider, Some(data))
    }

    /// Generate or import an asymmetric key object depending on whether imported_key_data is None.
    fn generate_or_import_asymmetric_key(
        &self,
        key_name: &str,
        key_algorithm: AsymmetricKeyAlgorithm,
        provider: &dyn CryptoProvider,
        imported_key_data: Option<&[u8]>,
    ) -> Result<Arc<Mutex<KmsAsymmetricKey>>, Error> {
        // Check whether the algorithm is valid.
        Self::check_asymmmetric_supported_algorithms(key_algorithm, provider)?;
        // Create a new symmetric key object and store it into the key map.
        // Obtain a lock on the key map to start a critical section.
        let mut key_map = self.user_key_map.lock().unwrap();
        if key_map.contains_key(key_name) || self.key_file_exists(key_name, true) {
            return Err(Error::KeyAlreadyExists);
        }
        let new_key = match imported_key_data {
            Some(data) => KmsAsymmetricKey::import_key(provider, data, key_name, key_algorithm),
            None => KmsAsymmetricKey::new(provider, key_name, key_algorithm),
        }?;
        {
            self.write_key_attributes_to_file(
                new_key.get_key_name(),
                Some(new_key.get_key_algorithm()),
                new_key.get_key_type(),
                new_key.get_key_origin(),
                new_key.get_key_provider(),
                &new_key.get_key_data(),
                true,
            )?;
        }
        let key_to_bind = Arc::new(Mutex::new(new_key));
        let key_to_insert = Arc::clone(&key_to_bind);
        key_map.insert(key_name.to_string(), key_to_insert);

        // End critical section.
        drop(key_map);

        Ok(key_to_bind)
    }

    /// Get an asymmetric key object and bind it to the user channel.
    ///
    /// # Arguments
    ///
    /// * `key_name` - The name for the key to be find.
    /// * `key` - The server end of the user channel to bind.
    fn get_asymmetric_private_key_and_bind(
        &self,
        key_name: &str,
        key: ServerEnd<AsymmetricPrivateKeyMarker>,
    ) -> Result<(), Error> {
        let key_to_bind = self.get_asymmetric_private_key(&key_name)?;
        self.bind_asymmetric_key_to_server(&key_name, key_to_bind, key)
    }

    /// Get an asymmetric key object.
    ///
    /// Find the asymmetric key object for the key name in the key map. If none is found, try to
    /// load the key object into memory from storage.
    ///
    /// # Arguments
    ///
    /// * `key_name` - The name for the key to be find.
    fn get_asymmetric_private_key(&self, key_name: &str) -> Result<Arc<Mutex<dyn KmsKey>>, Error> {
        // Start a critical section.
        let mut key_map = self.user_key_map.lock().unwrap();
        let key_to_bind = match key_map.get(key_name) {
            Some(key) => Arc::clone(key),
            None => {
                // The key is not in key map, read it from file.
                let provider_map = self.crypto_provider_map.read().unwrap();
                let key_attributes =
                    self.read_key_attributes_from_file(key_name, &provider_map, true)?;
                let asym_key = KmsAsymmetricKey::parse_key(key_name, key_attributes)?;
                let key_to_bind = Arc::new(Mutex::new(asym_key));
                let key_to_insert = Arc::clone(&key_to_bind);
                key_map.insert(key_name.to_string(), key_to_insert);
                key_to_bind
            }
        };
        // End the critical section.
        drop(key_map);

        Ok(key_to_bind)
    }

    /// Delete a key object.
    ///
    /// Delete the key data and key attributes from storage and remove the key from key map. Mark
    /// the key as deleted so that all the key handles currently possessed would return
    /// KEY_NOT_FOUND in the future.
    ///
    /// # Arguments
    ///
    /// * `key_name` - The name for the key to be deleted.
    fn delete_key(&self, key_name: &str) -> Result<(), Error> {
        // Obtain a lock on the user_key_map to start a critical section to make sure there is no
        // overlapping deleting/generating/importing/getting key operations.
        let mut key_map = self.user_key_map.lock().unwrap();
        // Always remove the key from key_map first. This would have no side effect even if the
        // delete operation fails early because we could always read the key from file and put
        // it back to the key_map later.
        if let Some(key) = key_map.remove(key_name) {
            // Set the deleted bit and ask the crypto provider to delete the key. If the key is
            // currently being used, this operation would blocked. However, if the key handle is
            // possessed in another job but there is no operation ongoing with the handle, we would
            // set the deleted bit so that the handle would fail on any further operations.
            key.lock().unwrap().delete()?;
        } else {
            // The key is not currently used, create an in-memory key structure.
            let provider_map = self.crypto_provider_map.read().unwrap();
            let key_attributes =
                self.read_key_attributes_from_file(key_name, &provider_map, true)?;
            // Ask the crypto provider to delete the key.
            let mut key = KmsAsymmetricKey::parse_key(key_name, key_attributes)?;
            key.delete()?;
        }
        // Remove the key files. If the key was already deleted before, the key must not exist in
        // the key map and the key file must has been deleted thus read_key_attributes_from_file
        // would return KEY_NOT_FOUND. We would never delete a same key file twice. If somehow the
        // previous attempt to remove key files failed and the key still exists, then we would retry
        // the removal here.
        let key_attributes_path = self.get_key_attributes_path(key_name, true);
        fs::remove_file(&key_attributes_path)
            .map_err(debug_err_fn!(Error::InternalError, "Failed to remove key files: {:?}"))?;

        // End the critical section.
        drop(key_map);
        Ok(())
    }

    /// Seal a piece of data. Return the sealed data in provider-specific format.
    ///
    /// Seal a piece of data using a sealing key. If the key does not exist, create the sealing key
    /// first.
    ///
    /// # Arguments
    ///
    /// * `data` - The buffer containing the data to be sealed.
    /// * `provider` - The crypto provider to do the encryption operation.
    fn seal_data(&self, data: Buffer, provider: &dyn CryptoProvider) -> Result<Buffer, Error> {
        if data.size > MAX_DATA_SIZE.into() {
            return Err(Error::InputTooLarge);
        }
        let sealing_key = self.get_sealing_key(provider)?;
        let mut result = Err(Error::InternalError);
        // The error, if any, would be return through the result variable, handle_request is
        // guaranteed to not return any FIDL error.
        sealing_key
            .lock()
            .unwrap()
            .handle_request(KeyRequestType::SealingKeyRequest(DataRequest {
                data,
                result: &mut result,
            }))
            .expect("Sealing key should not throw fidl error!");
        result
    }

    /// Unseal a piece of data. Return the original data.
    ///
    /// Unseal a piece of data originally sealed.
    ///
    /// # Arguments
    ///
    /// * `data` - The buffer containing the data to be unsealed.
    /// * `provider` - The crypto provider to do the decryption operation.
    fn unseal_data(&self, data: Buffer, provider: &dyn CryptoProvider) -> Result<Buffer, Error> {
        let sealed_data_size =
            provider.calculate_sealed_data_size(MAX_DATA_SIZE.into()).map_err(debug_err_fn!(
                Error::InternalError,
                "MAX_DATA_SIZE {} is too large, unable to get sealed data size, err: {:?}!",
                MAX_DATA_SIZE
            ))?;
        if data.size > sealed_data_size {
            return Err(Error::InputTooLarge);
        }
        if !self.key_file_exists(SEALING_KEY_NAME, false) {
            // If no sealing key exists, something is wrong.
            return Err(Error::KeyNotFound);
        }
        let sealing_key = self.get_sealing_key(provider)?;
        let mut result = Err(Error::InternalError);
        sealing_key
            .lock()
            .unwrap()
            .handle_request(KeyRequestType::UnsealingKeyRequest(DataRequest {
                data,
                result: &mut result,
            }))
            .expect("Unsealing key should not throw fidl error!");
        result
    }

    /// Get the sealing key object. If the sealing key does not exist, create a new one.
    fn get_sealing_key(
        &self,
        provider: &dyn CryptoProvider,
    ) -> Result<Arc<Mutex<dyn KmsKey>>, Error> {
        // Sealing key is managed internally, so we store them in internal_key_map.
        // Begin a critical section.
        let mut key_map = self.internal_key_map.lock().unwrap();
        let key_name = SEALING_KEY_NAME;
        let sealing_key = if !key_map.contains_key(key_name) {
            // If sealing key is not in the key map, load it in.
            let provider_map = self.crypto_provider_map.read().unwrap();
            // Sealing key is not a user key.
            let sealing_key =
                match self.read_key_attributes_from_file(&key_name, &provider_map, false) {
                    Ok(key_attributes) => KmsSealingKey::parse_key(key_name, key_attributes),
                    Err(Error::KeyNotFound) => {
                        warn!("No sealing key found, create new key.");
                        let new_key = KmsSealingKey::new(provider)?;
                        self.write_key_attributes_to_file(
                            new_key.get_key_name(),
                            None,
                            new_key.get_key_type(),
                            KeyOrigin::Generated,
                            new_key.get_key_provider(),
                            &new_key.get_key_data(),
                            false,
                        )?;
                        Ok(new_key)
                    }
                    Err(err) => Err(err),
                }?;
            let key_to_use = Arc::new(Mutex::new(sealing_key));
            let key_to_insert = Arc::clone(&key_to_use);
            key_map.insert(key_name.to_string(), key_to_insert);
            key_to_use
        } else {
            Arc::clone(&key_map[key_name])
        };
        // End critical section.
        drop(key_map);

        Ok(sealing_key)
    }

    /// Check whether a key algorithm is a valid asymmetric key algorithm and supported by provider.
    fn check_asymmmetric_supported_algorithms(
        key_algorithm: AsymmetricKeyAlgorithm,
        provider: &dyn CryptoProvider,
    ) -> Result<(), Error> {
        if provider
            .supported_asymmetric_algorithms()
            .iter()
            .find(|&alg| alg == &key_algorithm)
            .is_none()
        {
            warn!("The asymmetric algorithm is not supported.");
            // TODO: Add logic to fall back.
            return Err(Error::InternalError);
        }
        Ok(())
    }

    fn get_key_folder(&self, is_user_key: bool) -> PathBuf {
        if is_user_key {
            Path::new(&self.key_folder).join(USER_KEY_SUBFOLDER)
        } else {
            Path::new(&self.key_folder).join(INTERNAL_KEY_SUBFOLDER)
        }
    }

    fn get_key_attributes_path(&self, key_name: &str, is_user_key: bool) -> PathBuf {
        // We base64 encode the key name to prevent special characters.
        self.get_key_folder(is_user_key)
            .join(format!("key_{}.attr", base64::encode_config(key_name, base64::URL_SAFE)))
    }

    fn key_file_exists(&self, key_name: &str, is_user_key: bool) -> bool {
        let key_path = self.get_key_attributes_path(key_name, is_user_key);
        key_path.is_file()
    }

    fn write_key_attributes(
        &self,
        key_name: &str,
        serialized_key_attributes: &str,
        is_user_key: bool,
    ) -> Result<(), IOError> {
        fs::create_dir_all(self.get_key_folder(is_user_key))?;
        let key_attributes_path = self.get_key_attributes_path(key_name, is_user_key);
        fs::write(key_attributes_path, serialized_key_attributes)?;
        Ok(())
    }

    /// Write the key attributes to storage.
    ///
    /// If asymmetric_key_algorithm is None, this means that this is a sealing key and we do not
    /// care about algorithm, so we just fill algorithm number with 0.
    fn write_key_attributes_to_file(
        &self,
        key_name: &str,
        asymmetric_key_algorithm: Option<AsymmetricKeyAlgorithm>,
        key_type: KeyType,
        key_origin: KeyOrigin,
        key_provider: KeyProvider,
        key_data: &[u8],
        is_user_key: bool,
    ) -> Result<(), Error> {
        let key_algorithm_num = match asymmetric_key_algorithm {
            Some(alg) => alg.into_primitive(),
            None => 0,
        };
        let key_attributes = KeyAttributesJson {
            key_algorithm: key_algorithm_num,
            key_type,
            key_origin: key_origin.into_primitive(),
            key_provider: key_provider.into_primitive(),
            key_data: key_data.to_vec(),
        };
        let key_attributes_string = serde_json::to_string(&key_attributes)
            .expect("Failed to encode key attributes to JSON format.");
        self.write_key_attributes(key_name, &key_attributes_string, is_user_key)
            .map_err(debug_err_fn!(Error::InternalError, "Failed to write key attributes: {:?}"))
    }

    fn read_key_attributes(&self, key_name: &str, is_user_key: bool) -> Result<Vec<u8>, IOError> {
        let key_attributes_path = self.get_key_attributes_path(key_name, is_user_key);
        Ok(fs::read(key_attributes_path)?)
    }

    fn read_key_attributes_from_file<'a>(
        &self,
        key_name: &str,
        provider_map: &'a HashMap<KeyProvider, Box<dyn CryptoProvider>>,
        is_user_key: bool,
    ) -> Result<KeyAttributes<'a>, Error> {
        // Read the key attributes from file and parse it.
        let key_attributes_string =
            self.read_key_attributes(&key_name, is_user_key).map_err(|err| {
                if err.kind() == ErrorKind::NotFound {
                    return Error::KeyNotFound;
                }
                debug_err!(
                    Error::InternalError,
                    "Failed to read key attributes from key file: {:?}",
                    err
                )
            })?;
        let key_attributes_string =
            str::from_utf8(&key_attributes_string).map_err(debug_err_fn!(
                Error::InternalError,
                "Failed to parse JSON string as UTF8: {:?}! The stored key data is corrupted!"
            ))?;
        let key_attributes_json: KeyAttributesJson = serde_json::from_str(&key_attributes_string)
            .map_err(debug_err_fn!(
            Error::InternalError,
            "Failed to parse key attributes: {:?}, the stored key data is corrupted!"
        ))?;
        let key_provider = KeyProvider::from_primitive(key_attributes_json.key_provider)
            .ok_or_else(debug_err_fn_no_argument!(
                Error::InternalError,
                "Failed to convert key_provider! The stored key data is corrupted!"
            ))?;
        let provider = provider_map.get(&key_provider).ok_or_else(debug_err_fn_no_argument!(
            Error::InternalError,
            "Failed to find provider! The stored key data is corrupted!"
        ))?;
        let key_type = key_attributes_json.key_type;
        let asymmetric_key_algorithm = {
            if key_type == KeyType::AsymmetricPrivateKey {
                Some(
                    AsymmetricKeyAlgorithm::from_primitive(key_attributes_json.key_algorithm)
                        .ok_or_else(debug_err_fn_no_argument!(
                            Error::InternalError,
                            "Failed to convert key_algortihm! The stored key data is corrupted!"
                        ))?,
                )
            } else {
                None
            }
        };
        let key_origin = KeyOrigin::from_primitive(key_attributes_json.key_origin).ok_or_else(
            debug_err_fn_no_argument!(
                Error::InternalError,
                "Failed to convert key_origin! The stored key data is corrupted!"
            ),
        )?;
        Ok(KeyAttributes {
            asymmetric_key_algorithm,
            key_type,
            key_origin,
            provider: provider.as_ref(),
            key_data: key_attributes_json.key_data,
        })
    }

    /// Get a crypto provider according to name and pass that provider to a function.
    ///
    /// The input function takes an Option<&dyn CryptoProvider> as argument and the output would
    /// be the output of this function. During the function, a read lock to the crypto_provider_map
    /// would be hold to prevent modification to the map.
    pub fn with_provider<O, F: FnOnce(Option<&dyn CryptoProvider>) -> O>(
        &self,
        name: KeyProvider,
        f: F,
    ) -> O {
        f(self.crypto_provider_map.read().unwrap().get(&name).map(|provider| provider.as_ref()))
    }

    pub fn add_provider(&mut self, provider: Box<dyn CryptoProvider>) {
        let provider_map = &mut self.crypto_provider_map.write().unwrap();
        if provider_map.contains_key(&provider.get_name()) {
            panic!("Two providers should not have the same name!");
        }
        provider_map.insert(provider.get_name(), provider);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::common::{self as common, ASYMMETRIC_KEY_ALGORITHMS};
    use crate::crypto_provider::{mock_provider::MockProvider, CryptoProviderError};
    use fidl_fuchsia_kms::KeyOrigin;
    use tempfile::tempdir;
    static TEST_KEY_NAME: &str = "TestKey";

    /// Define a test case structure. It would do the necessary set up for a test case.
    struct TestCase {
        key_manager: KeyManager,
        mock_provider: Box<MockProvider>,
    }

    impl TestCase {
        /// Create a new test case. This would create a new key manager and set its provider to a
        /// new mock provider.
        fn new() -> Self {
            let tmp_key_folder = tempdir().unwrap();
            let mut key_manager = KeyManager::new();
            key_manager.set_key_folder(tmp_key_folder.path().to_str().unwrap());
            let mock_provider = Box::new(MockProvider::new());
            key_manager.add_provider(mock_provider.box_clone());
            TestCase { key_manager, mock_provider }
        }

        /// Get the mock provider set for this test case.
        fn get_mock_provider(&self) -> &MockProvider {
            &self.mock_provider
        }

        /// Get the key manager set for this test case.
        fn get_key_manager(&self) -> &KeyManager {
            return &self.key_manager;
        }
    }

    #[test]
    fn test_generate_asymmetric_key_mock_provider() {
        for algorithm in ASYMMETRIC_KEY_ALGORITHMS.iter() {
            generate_asymmetric_key_mock_provider(*algorithm);
        }
    }

    fn generate_asymmetric_key_mock_provider(key_algorithm: AsymmetricKeyAlgorithm) {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_output_data = common::generate_random_data(32);
        mock_provider.set_result(&test_output_data);
        let key = key_manager
            .generate_asymmetric_key(TEST_KEY_NAME, key_algorithm, mock_provider)
            .unwrap();
        let key = key.lock().unwrap();
        assert_eq!(TEST_KEY_NAME, key.get_key_name());
        assert_eq!(key_algorithm, key.get_key_algorithm());
        assert_eq!(test_output_data, key.get_key_data());
        assert_eq!(KeyOrigin::Generated, key.get_key_origin());
        assert_eq!(mock_provider.get_name(), key.get_key_provider());
        assert_eq!(mock_provider.get_called_key_name(), TEST_KEY_NAME);
    }

    #[test]
    fn test_generate_asymmetric_key_mock_provider_error() {
        for algorithm in ASYMMETRIC_KEY_ALGORITHMS.iter() {
            generate_asymmetric_key_mock_provider_error(*algorithm);
        }
    }

    fn generate_asymmetric_key_mock_provider_error(key_algorithm: AsymmetricKeyAlgorithm) {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        mock_provider.set_error();
        let result =
            key_manager.generate_asymmetric_key(TEST_KEY_NAME, key_algorithm, mock_provider);
        assert_eq!(Error::InternalError, result.unwrap_err());
    }

    #[test]
    fn test_get_asymmetric_key_mock_provider() {
        for algorithm in ASYMMETRIC_KEY_ALGORITHMS.iter() {
            get_asymmetric_key_mock_provider(*algorithm);
        }
    }

    fn get_asymmetric_key_mock_provider(key_algorithm: AsymmetricKeyAlgorithm) {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_key_data = common::generate_random_data(32);
        mock_provider.set_result(&test_key_data);
        let key_info = {
            let key = key_manager
                .generate_asymmetric_key(TEST_KEY_NAME, key_algorithm, mock_provider)
                .unwrap();
            let key_info = {
                let key = key.lock().unwrap();
                (key.get_key_name().to_string(), key.get_key_data())
            };
            let same_key = key_manager.get_asymmetric_private_key(TEST_KEY_NAME).unwrap();
            let same_key_lock = same_key.lock().unwrap();
            assert_eq!(same_key_lock.get_key_name(), &key_info.0);
            assert_eq!(same_key_lock.get_key_data(), key_info.1);
            key_info
        };

        // Clean up the cache
        KeyManager::clean_up(Arc::clone(&key_manager.user_key_map), TEST_KEY_NAME);

        // If we read again, it should read from file.
        let new_key_to_bind = key_manager.get_asymmetric_private_key(TEST_KEY_NAME).unwrap();
        let same_key_lock = new_key_to_bind.lock().unwrap();
        assert_eq!(same_key_lock.get_key_name(), &key_info.0);
        assert_eq!(same_key_lock.get_key_data(), key_info.1);
        assert_eq!(mock_provider.get_called_key_data(), key_info.1);
    }

    #[test]
    fn test_get_asymmetric_key_mock_provider_non_exists() {
        let test_case = TestCase::new();
        let key_manager = test_case.get_key_manager();
        // If we read again, it should read from file.
        let result = key_manager.get_asymmetric_private_key(TEST_KEY_NAME);
        assert_eq!(Error::KeyNotFound, result.unwrap_err());
    }

    #[test]
    fn test_import_asymmetric_key_mock_provider() {
        for algorithm in ASYMMETRIC_KEY_ALGORITHMS.iter() {
            import_asymmetric_key_mock_provider(*algorithm);
        }
    }

    fn import_asymmetric_key_mock_provider(key_algorithm: AsymmetricKeyAlgorithm) {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(32);
        let test_output_data = common::generate_random_data(32);
        mock_provider.set_result(&test_output_data);
        let key = key_manager
            .import_asymmetric_private_key(
                &test_input_data,
                TEST_KEY_NAME,
                key_algorithm,
                mock_provider,
            )
            .unwrap();
        let key = key.lock().unwrap();
        assert_eq!(TEST_KEY_NAME, key.get_key_name());
        assert_eq!(test_output_data, key.get_key_data());
        assert_eq!(key_algorithm, key.get_key_algorithm());
        assert_eq!(KeyOrigin::Imported, key.get_key_origin());
        assert_eq!(mock_provider.get_name(), key.get_key_provider());
        assert_eq!(mock_provider.get_called_key_data(), test_input_data);
        assert_eq!(mock_provider.get_called_key_name(), TEST_KEY_NAME);
    }

    #[test]
    fn test_import_asymmetric_key_mock_already_exists() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let key_algorithm = AsymmetricKeyAlgorithm::EcdsaSha512P521;
        let test_input_data = common::generate_random_data(32);
        let test_output_data = common::generate_random_data(32);
        mock_provider.set_result(&test_output_data);
        let _key_to_bind = key_manager.import_asymmetric_private_key(
            &test_input_data,
            TEST_KEY_NAME,
            key_algorithm,
            mock_provider,
        );
        let result = key_manager.import_asymmetric_private_key(
            &test_input_data,
            TEST_KEY_NAME,
            key_algorithm,
            mock_provider,
        );
        assert_eq!(Error::KeyAlreadyExists, result.unwrap_err());
    }

    #[test]
    fn test_import_asymmetric_key_mock_already_exists_generated() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let key_algorithm = AsymmetricKeyAlgorithm::EcdsaSha512P521;
        let test_input_data = common::generate_random_data(32);
        let test_output_data = common::generate_random_data(32);
        mock_provider.set_result(&test_output_data);
        let _key_to_bind = key_manager
            .generate_asymmetric_key(TEST_KEY_NAME, key_algorithm, mock_provider)
            .unwrap();
        let result = key_manager.import_asymmetric_private_key(
            &test_input_data,
            TEST_KEY_NAME,
            key_algorithm,
            mock_provider,
        );
        assert_eq!(Error::KeyAlreadyExists, result.unwrap_err());
    }

    #[test]
    fn test_delete_key_mock_provider() {
        for algorithm in ASYMMETRIC_KEY_ALGORITHMS.iter() {
            delete_key_mock_provider(*algorithm);
        }
    }

    fn delete_key_mock_provider(key_algorithm: AsymmetricKeyAlgorithm) {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(32);
        mock_provider.set_result(&test_input_data);
        // This make sure that key.delete would succeed.
        mock_provider.set_key_result(Ok(Vec::new()));
        {
            let key = key_manager
                .generate_asymmetric_key(TEST_KEY_NAME, key_algorithm, mock_provider)
                .unwrap();
            key_manager.delete_key(TEST_KEY_NAME).unwrap();
            // Try deleting the key again, should fail.
            assert_eq!(Error::KeyNotFound, key_manager.delete_key(TEST_KEY_NAME).unwrap_err());
            assert_eq!(true, key.lock().unwrap().is_deleted());
            // Try getting the deleted key, should get key_not_found.
            assert_eq!(
                Error::KeyNotFound,
                key_manager.get_asymmetric_private_key(TEST_KEY_NAME).unwrap_err()
            );
        }
        // Try getting the deleted key after all reference to the deleted key is freed, should get
        // key_not_found.
        assert_eq!(
            Error::KeyNotFound,
            key_manager.get_asymmetric_private_key(TEST_KEY_NAME).unwrap_err()
        );
    }

    #[test]
    fn delete_key_mock_provider_non_exists() {
        let test_case = TestCase::new();
        let key_manager = test_case.get_key_manager();
        let result = key_manager.delete_key(TEST_KEY_NAME);
        assert_eq!(Error::KeyNotFound, result.unwrap_err());
    }

    #[test]
    fn delete_key_mock_provider_error() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(32);
        mock_provider.set_result(&test_input_data);
        // This make sure that key.delete would succeed.
        mock_provider.set_key_result(Ok(Vec::new()));
        let _key_to_bind = key_manager
            .generate_asymmetric_key(
                TEST_KEY_NAME,
                AsymmetricKeyAlgorithm::EcdsaSha512P521,
                mock_provider,
            )
            .unwrap();
        mock_provider.set_key_operation_error();
        let result = key_manager.delete_key(TEST_KEY_NAME);
        assert_eq!(Err(Error::InternalError), result);
    }

    #[test]
    fn test_seal_data_mock_provider() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(256);
        let test_output_data = common::generate_random_data(256);
        let test_key_data = common::generate_random_data(32);
        mock_provider.set_result(&test_key_data);
        mock_provider.set_key_result(Ok(test_output_data.clone()));
        let output = key_manager
            .seal_data(common::data_to_buffer(&test_input_data).unwrap(), mock_provider)
            .unwrap();
        assert_eq!(test_output_data, common::buffer_to_data(output).unwrap());
    }

    #[test]
    fn test_seal_data_input_too_large() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(MAX_DATA_SIZE + 1);
        let test_output_data = common::generate_random_data(256);
        let test_key_data = common::generate_random_data(32);
        mock_provider.set_result(&test_key_data);
        mock_provider.set_key_result(Ok(test_output_data.clone()));
        let result =
            key_manager.seal_data(common::data_to_buffer(&test_input_data).unwrap(), mock_provider);
        assert_eq!(Err(Error::InputTooLarge), result);
    }

    #[test]
    fn test_unseal_data_mock_provider() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(256);
        let test_output_data = common::generate_random_data(256);
        let test_key_data = common::generate_random_data(32);
        mock_provider.set_result(&test_key_data);
        mock_provider.set_key_result(Ok(test_output_data.clone()));
        let encrypted_buffer = key_manager
            .seal_data(common::data_to_buffer(&test_input_data).unwrap(), mock_provider)
            .unwrap();
        let output = key_manager.unseal_data(encrypted_buffer, mock_provider).unwrap();
        assert_eq!(test_output_data, common::buffer_to_data(output).unwrap());
    }

    #[test]
    fn test_unseal_data_input_too_large() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        // For mock provider, the sealed data size is the same as the original data size.
        let test_input_data = common::generate_random_data(MAX_DATA_SIZE + 1);
        let test_output_data = common::generate_random_data(256);
        let test_key_data = common::generate_random_data(32);
        mock_provider.set_result(&test_key_data);
        mock_provider.set_key_result(Ok(test_output_data.clone()));
        let result = key_manager
            .unseal_data(common::data_to_buffer(&test_input_data).unwrap(), mock_provider);
        assert_eq!(Err(Error::InputTooLarge), result);
    }

    #[test]
    fn test_seal_unseal_data_mock_provider_error() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(256);
        let test_key_data = common::generate_random_data(256);
        mock_provider.set_result(&test_key_data);
        mock_provider.set_key_result(Err(CryptoProviderError::new("")));
        let result =
            key_manager.seal_data(common::data_to_buffer(&test_input_data).unwrap(), mock_provider);
        assert_eq!(Error::InternalError, result.unwrap_err());
    }

    #[test]
    fn test_delete_sealing_key_mock_provider() {
        let test_case = TestCase::new();
        let mock_provider = test_case.get_mock_provider();
        let key_manager = test_case.get_key_manager();
        let test_input_data = common::generate_random_data(256);
        let test_output_data = common::generate_random_data(256);
        mock_provider.set_result(&test_output_data);
        // This make sure that key.delete would succeed.
        mock_provider.set_key_result(Ok(Vec::new()));
        let _output = key_manager
            .seal_data(common::data_to_buffer(&test_input_data).unwrap(), mock_provider)
            .unwrap();

        // The sealing key should be in a separate name space than user keys.
        let result = key_manager.delete_key(SEALING_KEY_NAME);
        assert_eq!(Error::KeyNotFound, result.unwrap_err());
    }

    #[test]
    fn test_get_default_provider() {
        let key_manager = KeyManager::new();
        key_manager.with_provider(DEFAULT_PROVIDER, |provider| {
            assert_eq!(false, provider.is_none());
        });
    }
}
