| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| use anyhow::{bail, ensure, Context, Result}; |
| use serde::{Deserialize, Serialize}; |
| use std::convert::TryInto; |
| |
| use teaclave_crypto::*; |
| |
| pub const FILE_AUTH_TAG_LENGTH: usize = 16; |
| |
| #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, PartialEq)] |
| pub struct FileAuthTag { |
| tag: [u8; FILE_AUTH_TAG_LENGTH], |
| } |
| |
| impl FileAuthTag { |
| pub fn from_bytes(input: &[u8]) -> Result<Self> { |
| ensure!(input.len() == FILE_AUTH_TAG_LENGTH, "Invalid length"); |
| let mut file_auth_tag = FileAuthTag::default(); |
| file_auth_tag.tag.clone_from_slice(input); |
| Ok(file_auth_tag) |
| } |
| |
| pub fn from_hex(input: impl AsRef<str>) -> Result<Self> { |
| let hex = hex::decode(input.as_ref()).context("Illegal AuthTag provided")?; |
| let tag = hex |
| .as_slice() |
| .try_into() |
| .context("Illegal AuthTag provided")?; |
| Ok(FileAuthTag { tag }) |
| } |
| |
| pub fn to_hex(&self) -> String { |
| hex::encode(self.tag) |
| } |
| |
| pub fn to_bytes(&self) -> Vec<u8> { |
| self.tag.to_vec() |
| } |
| |
| #[cfg(test_mode)] |
| pub fn mock() -> Self { |
| Self { |
| tag: [0; FILE_AUTH_TAG_LENGTH], |
| } |
| } |
| } |
| |
| impl std::convert::From<[u8; FILE_AUTH_TAG_LENGTH]> for FileAuthTag { |
| fn from(tag: [u8; FILE_AUTH_TAG_LENGTH]) -> Self { |
| Self { tag } |
| } |
| } |
| |
| impl std::cmp::PartialEq<[u8]> for FileAuthTag { |
| fn eq(&self, other: &[u8]) -> bool { |
| self.tag == other |
| } |
| } |
| |
| impl std::cmp::PartialEq<[u8; FILE_AUTH_TAG_LENGTH]> for FileAuthTag { |
| fn eq(&self, other: &[u8; FILE_AUTH_TAG_LENGTH]) -> bool { |
| &self.tag[..] == other |
| } |
| } |
| |
| #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)] |
| pub enum FileCrypto { |
| AesGcm128(AesGcm128Key), |
| AesGcm256(AesGcm256Key), |
| TeaclaveFile128(TeaclaveFile128Key), |
| Raw, |
| } |
| |
| impl FileCrypto { |
| pub fn new(schema: &str, key: &[u8], iv: &[u8]) -> Result<Self> { |
| let info = match schema { |
| AesGcm128Key::SCHEMA => { |
| let crypto = AesGcm128Key::new(key, iv)?; |
| FileCrypto::AesGcm128(crypto) |
| } |
| AesGcm256Key::SCHEMA => { |
| let crypto = AesGcm256Key::new(key, iv)?; |
| FileCrypto::AesGcm256(crypto) |
| } |
| TeaclaveFile128Key::SCHEMA => { |
| ensure!(iv.is_empty(), "IV is not empty for teaclave_file_128"); |
| let crypto = TeaclaveFile128Key::new(key)?; |
| FileCrypto::TeaclaveFile128(crypto) |
| } |
| "raw" => FileCrypto::Raw, |
| _ => bail!("Invalid crypto schema: {}", schema), |
| }; |
| |
| Ok(info) |
| } |
| |
| pub fn schema(&self) -> &str { |
| match self { |
| FileCrypto::AesGcm128(_) => AesGcm128Key::SCHEMA, |
| FileCrypto::AesGcm256(_) => AesGcm256Key::SCHEMA, |
| FileCrypto::TeaclaveFile128(_) => TeaclaveFile128Key::SCHEMA, |
| FileCrypto::Raw => "raw", |
| } |
| } |
| |
| pub fn key_iv(&self) -> (Vec<u8>, Vec<u8>) { |
| match self { |
| FileCrypto::AesGcm128(crypto) => (crypto.key.to_vec(), crypto.iv.to_vec()), |
| FileCrypto::AesGcm256(crypto) => (crypto.key.to_vec(), crypto.iv.to_vec()), |
| FileCrypto::TeaclaveFile128(crypto) => (crypto.key.to_vec(), Vec::new()), |
| FileCrypto::Raw => (vec![], vec![]), |
| } |
| } |
| } |
| |
| impl std::convert::From<AesGcm128Key> for FileCrypto { |
| fn from(crypto: AesGcm128Key) -> Self { |
| FileCrypto::AesGcm128(crypto) |
| } |
| } |
| |
| impl std::convert::From<AesGcm256Key> for FileCrypto { |
| fn from(crypto: AesGcm256Key) -> Self { |
| FileCrypto::AesGcm256(crypto) |
| } |
| } |
| |
| impl std::convert::From<TeaclaveFile128Key> for FileCrypto { |
| fn from(crypto: TeaclaveFile128Key) -> Self { |
| FileCrypto::TeaclaveFile128(crypto) |
| } |
| } |
| |
| impl Default for FileCrypto { |
| fn default() -> Self { |
| FileCrypto::TeaclaveFile128(TeaclaveFile128Key::random()) |
| } |
| } |