blob: 20ef40a570b600f62f1bf20812e62e3ded07979b [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::ASYMMETRIC_KEY_ALGORITHMS;
use crate::crypto_provider::{
AsymmetricProviderKey, CryptoProvider, CryptoProviderError, ProviderKey, SealingProviderKey,
};
use fidl_fuchsia_kms::{AsymmetricKeyAlgorithm, KeyProvider};
use std::sync::{Arc, Mutex};
/// A mock crypto provider implementation.
///
/// This mock implementation is capable of recording the input data and be provided with output
/// data. Note that fields are references, so tester is able to keep a clone of the MockProvider
/// and use that to change the result during the test.
#[derive(Debug)]
pub struct MockProvider {
// Use Mutex to achieve interior mutability since this provider is expected to be not
// mutable.
key_name: Arc<Mutex<Option<String>>>,
key_data: Arc<Mutex<Option<Vec<u8>>>>,
result: Arc<Mutex<Result<Vec<u8>, CryptoProviderError>>>,
key_result: Arc<Mutex<Result<Vec<u8>, CryptoProviderError>>>,
}
impl CryptoProvider for MockProvider {
fn supported_asymmetric_algorithms(&self) -> &'static [AsymmetricKeyAlgorithm] {
// The mock provider supported all asymmetric algorithms.
ASYMMETRIC_KEY_ALGORITHMS
}
fn get_name(&self) -> KeyProvider {
KeyProvider::MockProvider
}
fn box_clone(&self) -> Box<dyn CryptoProvider> {
Box::new(MockProvider {
key_name: Arc::clone(&self.key_name),
key_data: Arc::clone(&self.key_data),
result: Arc::clone(&self.result),
key_result: Arc::clone(&self.key_result),
})
}
fn generate_asymmetric_key(
&self,
key_algorithm: AsymmetricKeyAlgorithm,
key_name: &str,
) -> Result<Box<dyn AsymmetricProviderKey>, CryptoProviderError> {
*self.key_name.lock().unwrap() = Some(key_name.to_string());
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
match result {
Err(err) => Err(err.clone()),
Ok(key_data) => Ok(Box::new(MockAsymmetricKey {
key_data: key_data.to_vec(),
key_algorithm,
result: Arc::clone(&self.key_result),
})),
}
}
fn import_asymmetric_key(
&self,
key_data: &[u8],
key_algorithm: AsymmetricKeyAlgorithm,
key_name: &str,
) -> Result<Box<dyn AsymmetricProviderKey>, CryptoProviderError> {
*self.key_name.lock().unwrap() = Some(key_name.to_string());
*self.key_data.lock().unwrap() = Some(key_data.to_vec());
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
match result {
Err(err) => Err(err.clone()),
Ok(result_data) => Ok(Box::new(MockAsymmetricKey {
key_data: result_data.clone(),
key_algorithm,
result: Arc::clone(&self.key_result),
})),
}
}
fn parse_asymmetric_key(
&self,
key_data: &[u8],
key_algorithm: AsymmetricKeyAlgorithm,
) -> Result<Box<dyn AsymmetricProviderKey>, CryptoProviderError> {
*self.key_data.lock().unwrap() = Some(key_data.to_vec());
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
match result {
Err(err) => Err(err.clone()),
Ok(_) => Ok(Box::new(MockAsymmetricKey {
key_data: key_data.to_vec(),
key_algorithm,
result: Arc::clone(&self.key_result),
})),
}
}
fn generate_sealing_key(
&self,
key_name: &str,
) -> Result<Box<dyn SealingProviderKey>, CryptoProviderError> {
*self.key_name.lock().unwrap() = Some(key_name.to_string());
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
match result {
Err(err) => Err(err.clone()),
Ok(key_data) => Ok(Box::new(MockSealingKey {
key_data: key_data.to_vec(),
result: Arc::clone(&self.key_result),
})),
}
}
fn parse_sealing_key(
&self,
key_data: &[u8],
) -> Result<Box<dyn SealingProviderKey>, CryptoProviderError> {
*self.key_data.lock().unwrap() = Some(key_data.to_vec());
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
match result {
Err(err) => Err(err.clone()),
Ok(_) => Ok(Box::new(MockSealingKey {
key_data: key_data.to_vec(),
result: Arc::clone(&self.key_result),
})),
}
}
fn calculate_sealed_data_size(
&self,
original_data_size: u64,
) -> Result<u64, CryptoProviderError> {
Ok(original_data_size)
}
}
/// A mock crypto provider class for unit tests.
#[allow(dead_code)]
impl MockProvider {
pub fn new() -> Self {
MockProvider {
key_name: Arc::new(Mutex::new(None)),
key_data: Arc::new(Mutex::new(None)),
result: Arc::new(Mutex::new(Err(CryptoProviderError::new("")))),
key_result: Arc::new(Mutex::new(Err(CryptoProviderError::new("")))),
}
}
/// Set every operation on this provider to return an error.
pub fn set_error(&self) {
*self.result.lock().unwrap() = Err(CryptoProviderError::new(""));
}
/// Set the return result for every operation on this provider.
pub fn set_result(&self, result: &[u8]) {
*self.result.lock().unwrap() = Ok(result.to_vec());
}
/// Set every operation on the key that is generated by this provider to return error.
pub fn set_key_operation_error(&self) {
*self.key_result.lock().unwrap() = Err(CryptoProviderError::new(""));
}
/// Set the return result for every operation on the key that is generated by this provider.
pub fn set_key_result(&self, key_result: Result<Vec<u8>, CryptoProviderError>) {
*self.key_result.lock().unwrap() = key_result;
}
/// Get the key data argument passed to this provider for generating/parsing/importing key.
pub fn get_called_key_data(&self) -> Vec<u8> {
let key_data: Option<Vec<u8>> = self.key_data.lock().unwrap().clone();
key_data.unwrap()
}
/// Get the key name argument passed to this provider for generating/parsing/importing key.
pub fn get_called_key_name(&self) -> String {
let key_name: Option<String> = self.key_name.lock().unwrap().clone();
key_name.unwrap()
}
}
#[derive(Debug)]
pub struct MockAsymmetricKey {
key_data: Vec<u8>,
key_algorithm: AsymmetricKeyAlgorithm,
result: Arc<Mutex<Result<Vec<u8>, CryptoProviderError>>>,
}
impl AsymmetricProviderKey for MockAsymmetricKey {
fn sign(&self, _data: &[u8]) -> Result<Vec<u8>, CryptoProviderError> {
self.result.lock().unwrap().clone()
}
fn get_der_public_key(&self) -> Result<Vec<u8>, CryptoProviderError> {
self.result.lock().unwrap().clone()
}
fn get_key_algorithm(&self) -> AsymmetricKeyAlgorithm {
self.key_algorithm
}
}
impl ProviderKey for MockAsymmetricKey {
fn delete(&mut self) -> Result<(), CryptoProviderError> {
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
match result {
Err(err) => Err(err.clone()),
Ok(_) => Ok(()),
}
}
fn get_key_data(&self) -> Vec<u8> {
self.key_data.to_vec()
}
fn get_key_provider(&self) -> KeyProvider {
MockProvider::new().get_name()
}
}
#[derive(Debug)]
pub struct MockSealingKey {
key_data: Vec<u8>,
result: Arc<Mutex<Result<Vec<u8>, CryptoProviderError>>>,
}
impl SealingProviderKey for MockSealingKey {
fn encrypt(&self, _data: &[u8]) -> Result<Vec<u8>, CryptoProviderError> {
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
result.clone()
}
fn decrypt(&self, _data: &[u8]) -> Result<Vec<u8>, CryptoProviderError> {
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
result.clone()
}
}
impl ProviderKey for MockSealingKey {
fn delete(&mut self) -> Result<(), CryptoProviderError> {
let result: &Result<Vec<u8>, CryptoProviderError> = &self.result.lock().unwrap();
match result {
Err(err) => Err(err.clone()),
Ok(_) => Ok(()),
}
}
fn get_key_data(&self) -> Vec<u8> {
self.key_data.to_vec()
}
fn get_key_provider(&self) -> KeyProvider {
MockProvider::new().get_name()
}
}