| // 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)?) |
| } |
| } |