blob: fa36d083049aa2c9f7eef33be2ee539c4f90a285 [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::crypto_provider::{
mundane_provider::MundaneSoftwareProvider, AsymmetricProviderKey, CryptoProvider,
CryptoProviderError, ProviderKey, SealingProviderKey,
};
use bincode;
use crypto::{aead::AeadDecryptor, aead::AeadEncryptor, aes::KeySize, aes_gcm::AesGcm};
use fidl_fuchsia_kms::{AsymmetricKeyAlgorithm, KeyProvider};
use mundane;
use serde::{Deserialize, Serialize};
use serde_json;
use std::convert::{TryFrom, TryInto};
const AES_KEY_SIZE: usize = 32;
const AES_IV_SIZE: usize = 12;
const AES_TAG_SIZE: usize = 16;
/// SoftwareProvider is a software based provider that supports symmetric and asymmetric operations.
///
/// SoftwareProvider uses MundaneSoftwareProvider for asymmetric operations and uses rust crypto
/// aes_gcm crate for sealing/unsealing operation. The key data is the plain text key material, so
/// its security depends on the security of the KMS module.
#[derive(Debug, Clone)]
pub struct SoftwareProvider {
mundane_provider: MundaneSoftwareProvider,
}
impl SoftwareProvider {
pub fn new() -> Self {
SoftwareProvider { mundane_provider: MundaneSoftwareProvider {} }
}
}
#[derive(Serialize, Deserialize, Debug)]
struct AesKey {
key: [u8; AES_KEY_SIZE],
}
#[derive(Serialize, Deserialize, Debug)]
struct EncryptedData {
iv: [u8; AES_IV_SIZE],
cipher_text: Vec<u8>,
tag: [u8; AES_TAG_SIZE],
}
#[derive(Debug)]
struct SoftwareSealingKey {
key_data: Vec<u8>,
inner_key: AesKey,
}
impl SoftwareSealingKey {
pub fn new(inner_key: AesKey) -> Result<Self, CryptoProviderError> {
let key_data = serde_json::to_vec(&inner_key).map_err(|err| {
CryptoProviderError::new(&format!(
"failed to marshal software sealing key as JSON: {:?}",
err
))
})?;
Ok(SoftwareSealingKey { key_data, inner_key })
}
}
impl ProviderKey for SoftwareSealingKey {
fn delete(&mut self) -> Result<(), CryptoProviderError> {
Ok(())
}
fn get_key_data(&self) -> Vec<u8> {
self.key_data.clone()
}
fn get_key_provider(&self) -> KeyProvider {
(SoftwareProvider::new()).get_name()
}
}
impl SealingProviderKey for SoftwareSealingKey {
fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>, CryptoProviderError> {
let inner_key = &self.inner_key;
let mut iv = [0; AES_IV_SIZE];
mundane::bytes::rand(&mut iv);
// We use empty Additional Authentication Data (AAD).
let mut key = AesGcm::new(KeySize::KeySize256, &inner_key.key, &iv, &[]);
let mut cipher_text = vec![0; data.len()];
let mut tag = [0; AES_TAG_SIZE];
key.encrypt(data, &mut cipher_text, &mut tag);
let output =
bincode::serialize(&EncryptedData { iv, cipher_text, tag }).map_err(|err| {
CryptoProviderError::new(&format!("failed to serialize encrypted data: {:?}", err))
})?;
Ok(output)
}
fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, CryptoProviderError> {
let inner_key = &self.inner_key;
let encrypted_data: EncryptedData = bincode::deserialize(data).map_err(|err| {
CryptoProviderError::new(&format!("failed to deserialize encrypted data: {:?}", err))
})?;
// We use empty Additional Authentication Data (AAD).
let mut key = AesGcm::new(KeySize::KeySize256, &inner_key.key, &encrypted_data.iv, &[]);
let mut plain_text = vec![0; encrypted_data.cipher_text.len()];
if !key.decrypt(&encrypted_data.cipher_text, &mut plain_text, &encrypted_data.tag) {
Err(CryptoProviderError::new("failed to decrypt data"))
} else {
Ok(plain_text)
}
}
}
#[derive(Debug)]
pub struct SoftwareAsymmetricPrivateKey {
mundane_key: Box<dyn AsymmetricProviderKey>,
}
impl ProviderKey for SoftwareAsymmetricPrivateKey {
fn delete(&mut self) -> Result<(), CryptoProviderError> {
self.mundane_key.delete()
}
fn get_key_data(&self) -> Vec<u8> {
self.mundane_key.get_key_data()
}
fn get_key_provider(&self) -> KeyProvider {
SoftwareProvider::new().get_name()
}
}
impl AsymmetricProviderKey for SoftwareAsymmetricPrivateKey {
fn sign(&self, data: &[u8]) -> Result<Vec<u8>, CryptoProviderError> {
self.mundane_key.sign(data)
}
fn get_der_public_key(&self) -> Result<Vec<u8>, CryptoProviderError> {
self.mundane_key.get_der_public_key()
}
fn get_key_algorithm(&self) -> AsymmetricKeyAlgorithm {
self.mundane_key.get_key_algorithm()
}
}
impl CryptoProvider for SoftwareProvider {
fn supported_asymmetric_algorithms(&self) -> &'static [AsymmetricKeyAlgorithm] {
self.mundane_provider.supported_asymmetric_algorithms()
}
fn get_name(&self) -> KeyProvider {
KeyProvider::SoftwareProvider
}
fn box_clone(&self) -> Box<dyn CryptoProvider> {
Box::new(SoftwareProvider::new())
}
fn generate_asymmetric_key(
&self,
key_algorithm: AsymmetricKeyAlgorithm,
key_name: &str,
) -> Result<Box<dyn AsymmetricProviderKey>, CryptoProviderError> {
let mundane_key = self.mundane_provider.generate_asymmetric_key(key_algorithm, key_name)?;
Ok(Box::new(SoftwareAsymmetricPrivateKey { mundane_key }))
}
fn import_asymmetric_key(
&self,
key_data: &[u8],
key_algorithm: AsymmetricKeyAlgorithm,
key_name: &str,
) -> Result<Box<dyn AsymmetricProviderKey>, CryptoProviderError> {
let mundane_key =
self.mundane_provider.import_asymmetric_key(key_data, key_algorithm, key_name)?;
Ok(Box::new(SoftwareAsymmetricPrivateKey { mundane_key }))
}
fn parse_asymmetric_key(
&self,
key_data: &[u8],
key_algorithm: AsymmetricKeyAlgorithm,
) -> Result<Box<dyn AsymmetricProviderKey>, CryptoProviderError> {
let mundane_key = self.mundane_provider.parse_asymmetric_key(key_data, key_algorithm)?;
Ok(Box::new(SoftwareAsymmetricPrivateKey { mundane_key }))
}
fn generate_sealing_key(
&self,
_key_name: &str,
) -> Result<Box<dyn SealingProviderKey>, CryptoProviderError> {
let mut key = [0; AES_KEY_SIZE];
mundane::bytes::rand(&mut key);
let inner_key = AesKey { key };
let sealing_key = SoftwareSealingKey::new(inner_key)?;
Ok(Box::new(sealing_key))
}
fn parse_sealing_key(
&self,
key_data: &[u8],
) -> Result<Box<dyn SealingProviderKey>, CryptoProviderError> {
let inner_key = serde_json::from_slice(key_data).map_err(|err| {
CryptoProviderError::new(&format!("failed to parse key data: {:?}", err))
})?;
Ok(Box::new(SoftwareSealingKey { key_data: key_data.to_vec(), inner_key }))
}
fn calculate_sealed_data_size(
&self,
original_data_size: u64,
) -> Result<u64, CryptoProviderError> {
let data_size = usize::try_from(original_data_size).map_err(|err| {
CryptoProviderError::new(&format!(
"failed to convert original data size to usize: {:?}",
err
))
})?;
let fake_encrypted_data = EncryptedData {
iv: [0; AES_IV_SIZE],
cipher_text: vec![0; data_size],
tag: [0; AES_TAG_SIZE],
};
let fake_sealed_data = bincode::serialize(&fake_encrypted_data).map_err(|err| {
CryptoProviderError::new(&format!(
"failed to serialize encrypted data to calculate size: {:?}",
err
))
})?;
usize::try_into(fake_sealed_data.len()).map_err(|err| {
CryptoProviderError::new(&format!(
"failed to convert sealed data size to u64: {:?}",
err
))
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::common;
static TEST_KEY_NAME: &str = "TestKey";
#[test]
fn test_generate_sealing_key_different_each_time() {
let software_provider = SoftwareProvider::new();
let sealing_key_one = software_provider.generate_sealing_key(TEST_KEY_NAME).unwrap();
let sealing_key_two = software_provider.generate_sealing_key(TEST_KEY_NAME).unwrap();
// Generating two different sealing key should get different key data.
assert_ne!(sealing_key_one.get_key_data(), sealing_key_two.get_key_data());
}
#[test]
// We need to make sure we use different iv for each encryption, so encrypting same data
// multiple times would generate different result.
fn test_sealed_data_different_each_time() {
let software_provider = SoftwareProvider::new();
let sealing_key = software_provider.generate_sealing_key(TEST_KEY_NAME).unwrap();
let data = common::generate_random_data(256);
let encrypted_data_one = sealing_key.encrypt(&data).unwrap();
let encrypted_data_two = sealing_key.encrypt(&data).unwrap();
assert_ne!(encrypted_data_one, encrypted_data_two);
}
#[test]
fn test_sealing_key_encrypt_decrypt() {
let software_provider = SoftwareProvider::new();
let sealing_key = software_provider.generate_sealing_key(TEST_KEY_NAME).unwrap();
let data = common::generate_random_data(256);
let encrypted_data = sealing_key.encrypt(&data).unwrap();
let decrypted_data = sealing_key.decrypt(&encrypted_data).unwrap();
// Decrypt an encrypted data should get the original data.
assert_eq!(data, decrypted_data);
}
#[test]
fn test_parse_sealing_key() {
let software_provider = SoftwareProvider::new();
let sealing_key = software_provider.generate_sealing_key(TEST_KEY_NAME).unwrap();
let data = common::generate_random_data(256);
let encrypted_data = sealing_key.encrypt(&data).unwrap();
let key_data = sealing_key.get_key_data();
// Generate a new sealing key using the same key data.
let new_sealing_key = software_provider.parse_sealing_key(&key_data).unwrap();
assert_eq!(key_data, new_sealing_key.get_key_data());
// The encrypted data encrypted by the previous key should be decrypted by the new key.
let decrypted_data = new_sealing_key.decrypt(&encrypted_data).unwrap();
assert_eq!(data, decrypted_data);
}
#[test]
fn test_caculate_sealed_data_size() {
let software_provider = SoftwareProvider::new();
let sealing_key = software_provider.generate_sealing_key(TEST_KEY_NAME).unwrap();
let data = common::generate_random_data(256);
let encrypted_data = sealing_key.encrypt(&data).unwrap();
// Calculating sealed data size for MAX_DATA_SIZE should be OK.
let sealed_data_size = software_provider.calculate_sealed_data_size(256).unwrap();
assert_eq!(encrypted_data.len(), sealed_data_size as usize);
}
}