blob: 994438f6b1ff566aa4d64070aba1c105058043ef [file] [log] [blame]
// 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::{Error, KeyProvider};
use fidl_fuchsia_mem::Buffer;
use log::error;
pub static SEALING_KEY_NAME: &str = ".SealingKey";
/// A sealing key object.
#[derive(Debug)]
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_key_provider(&self) -> KeyProvider {
self.provider_key.get_key_provider()
}
fn get_key_data(&self) -> Vec<u8> {
self.provider_key.get_key_data()
}
fn delete(&mut self) -> Result<(), Error> {
panic!("Sealing key should never be deleted!")
}
}
impl KmsSealingKey {
/// Generates a new sealing key object.
pub fn new(provider: &dyn CryptoProvider) -> Result<Self, Error> {
let provider_key = provider.generate_sealing_key(SEALING_KEY_NAME).map_err(
debug_err_fn!(Error::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, Error> {
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(Error::InternalError);
}
let provider_key = key_attributes
.provider
.parse_sealing_key(&key_attributes.key_data)
.map_err(debug_err_fn!(Error::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, Error> {
let input = common::buffer_to_data(buffer)?;
let output = self
.provider_key
.encrypt(&input)
.map_err(debug_err_fn!(Error::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, Error> {
let input = common::buffer_to_data(buffer)?;
let output = self
.provider_key
.decrypt(&input)
.map_err(debug_err_fn!(Error::InternalError, "Failed to decrypt data: {:?}"))?;
Ok(common::data_to_buffer(&output)?)
}
}