// 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::{self as common, DataRequest, KeyAttributes, KeyRequestType, KeyType, KmsKey};
use crate::crypto_provider::{CryptoProvider, SealingProviderKey};
use fidl_fuchsia_kms::Status;
use fidl_fuchsia_mem::Buffer;
use log::error;

pub static SEALING_KEY_NAME: &str = ".SealingKey";

/// A sealing key object.
pub struct KmsSealingKey {
    provider_key: Box<dyn SealingProviderKey>,
    key_name: String,
}

impl KmsKey for KmsSealingKey {
    fn get_key_name(&self) -> &str {
        &self.key_name
    }

    fn is_deleted(&self) -> bool {
        // Sealing key would never be deleted.
        false
    }

    /// Handles a seal_key/unseal_key request.
    ///
    /// The request type is expected to be SealingKeyRequest or UnsealingKeyRequest. The request is
    /// constructed by KeyManager and is not from user thus it would not contain a channel to send
    /// the request back to user. As a result, this function would never return a FIDL error. The
    /// result for the request is returned through the result pointer in the request object.
    ///
    /// # Panics
    ///
    /// Panics if the request is neither SealingKeyRequest or UnsealingKeyRequest.
    fn handle_request(&self, req: KeyRequestType) -> Result<(), fidl::Error> {
        if let KeyRequestType::SealingKeyRequest(DataRequest { data, result }) = req {
            *result = self.seal_data(data);
        } else if let KeyRequestType::UnsealingKeyRequest(DataRequest { data, result }) = req {
            *result = self.unseal_data(data);
        } else {
            panic!("Invalid request!");
        }
        Ok(())
    }

    fn get_key_type(&self) -> KeyType {
        KeyType::SealingKey
    }

    fn get_provider_name(&self) -> &str {
        self.provider_key.get_provider_name()
    }

    fn get_key_data(&self) -> Vec<u8> {
        self.provider_key.get_key_data()
    }

    fn delete(&mut self) -> Result<(), Status> {
        panic!("Sealing key should never be deleted!")
    }
}

impl KmsSealingKey {
    /// Generates a new sealing key object.
    pub fn new(provider: &dyn CryptoProvider) -> Result<Self, Status> {
        let provider_key = provider.generate_sealing_key(SEALING_KEY_NAME).map_err(
            debug_err_fn!(Status::InternalError, "Failed to generate sealing key, err: {:?}."),
        )?;
        Ok(KmsSealingKey { provider_key, key_name: SEALING_KEY_NAME.to_string() })
    }

    /// Parse the key data and generate a new KmsSealingKey object.
    ///
    /// # Arguments
    ///
    /// * `key_name` - The name for the new key.
    /// * `key_attributes` - The attributes for the new key.
    pub fn parse_key(key_name: &str, key_attributes: KeyAttributes) -> Result<Self, Status> {
        if key_attributes.key_type != KeyType::SealingKey {
            // The key is a different type. This should not happen unless the key file is corrupted.
            error!("The sealing key file is corrupted!");
            return Err(Status::InternalError);
        }

        let provider_key = key_attributes
            .provider
            .parse_sealing_key(&key_attributes.key_data)
            .map_err(debug_err_fn!(Status::ParseKeyError, "Failed to parse sealing key: {:?}."))?;
        Ok(KmsSealingKey { provider_key, key_name: key_name.to_string() })
    }

    /// Use the key to seal data.
    ///
    /// #  Arguments:
    ///
    /// * `buffer` - The vmo buffer containing the data to be sealed.
    fn seal_data(&self, buffer: Buffer) -> Result<Buffer, Status> {
        let input = common::buffer_to_data(buffer)?;
        let output = self
            .provider_key
            .encrypt(&input)
            .map_err(debug_err_fn!(Status::InternalError, "Failed to encrypt data: {:?}"))?;
        Ok(common::data_to_buffer(&output)?)
    }

    /// Use the key to unseal data.
    ///
    /// #  Arguments:
    ///
    /// * `buffer` - The vmo buffer containing the data to be unsealed.
    fn unseal_data(&self, buffer: Buffer) -> Result<Buffer, Status> {
        let input = common::buffer_to_data(buffer)?;
        let output = self
            .provider_key
            .decrypt(&input)
            .map_err(debug_err_fn!(Status::InternalError, "Failed to decrypt data: {:?}"))?;
        Ok(common::data_to_buffer(&output)?)
    }
}
