blob: 83e48deb99274ffe65441d0bbfdb4c8c4509d92b [file] [log] [blame]
// Copyright 2022 Google LLC
//
// Licensed 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.
//! An abstraction layer around AES implementations.
//!
//! The design is an attempt to make it easy to provide implementations that are both idiomatic
//! Rust (e.g. RustCrypto) as well as FFI-backed (e.g. openssl and other C impls).
use core::{array, fmt};
pub mod ctr;
#[cfg(feature = "alloc")]
pub mod cbc;
/// Block size in bytes for AES (and XTS-AES)
pub const BLOCK_SIZE: usize = 16;
/// A single AES block.
pub type AesBlock = [u8; BLOCK_SIZE];
/// Helper trait to enforce encryption and decryption with the same size key
pub trait Aes {
/// The AES key containing the raw bytes used to for key scheduling
type Key: AesKey;
/// The cipher used for encryption
type EncryptCipher: AesEncryptCipher<Key = Self::Key>;
/// the cipher used for decryption
type DecryptCipher: AesDecryptCipher<Key = Self::Key>;
}
/// The base AesCipher trait which describes common operations to both encryption and decryption ciphers
pub trait AesCipher {
/// The type of the key used which holds the raw bytes used in key scheduling
type Key: AesKey;
/// Creates a new cipher from the AesKey
fn new(key: &Self::Key) -> Self;
}
/// An AES cipher used for encrypting blocks
pub trait AesEncryptCipher: AesCipher {
/// Encrypt `block` in place.
fn encrypt(&self, block: &mut AesBlock);
}
/// An AES cipher used for decrypting blocks
pub trait AesDecryptCipher: AesCipher {
/// Decrypt `block` in place.
fn decrypt(&self, block: &mut AesBlock);
}
/// An appropriately sized `[u8; N]` array that the key can be constructed from, e.g. `[u8; 16]`
/// for AES-128.
pub trait AesKey: for<'a> TryFrom<&'a [u8], Error = Self::TryFromError> {
/// The error used by the `TryFrom` implementation used to construct `Self::Array` from a
/// slice. For the typical case of `Self::Array` being an `[u8; N]`, this would be
/// `core::array::TryFromSliceError`.
///
/// This is broken out as a separate type to allow the `fmt::Debug` requirement needed for
/// `expect()`.
type TryFromError: fmt::Debug;
/// The byte array type the key can be represented with
type Array;
/// Key size in bytes -- must match the length of `Self::KeyBytes`.`
///
/// Unfortunately `KeyBytes` can't reference this const in the type declaration, so it must be
/// specified separately.
const KEY_SIZE: usize;
/// Returns the key material as a slice
fn as_slice(&self) -> &[u8];
/// Returns the key material as an array
fn as_array(&self) -> &Self::Array;
}
/// An AES-128 key.
#[derive(Clone)]
pub struct Aes128Key {
key: [u8; 16],
}
impl AesKey for Aes128Key {
type TryFromError = array::TryFromSliceError;
type Array = [u8; 16];
const KEY_SIZE: usize = 16;
fn as_slice(&self) -> &[u8] {
&self.key
}
fn as_array(&self) -> &Self::Array {
&self.key
}
}
impl TryFrom<&[u8]> for Aes128Key {
type Error = array::TryFromSliceError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
value.try_into().map(|arr| Self { key: arr })
}
}
impl From<[u8; 16]> for Aes128Key {
fn from(arr: [u8; 16]) -> Self {
Self { key: arr }
}
}
/// An AES-256 key.
#[derive(Clone)]
pub struct Aes256Key {
key: [u8; 32],
}
impl AesKey for Aes256Key {
type TryFromError = array::TryFromSliceError;
type Array = [u8; 32];
const KEY_SIZE: usize = 32;
fn as_slice(&self) -> &[u8] {
&self.key
}
fn as_array(&self) -> &Self::Array {
&self.key
}
}
impl TryFrom<&[u8]> for Aes256Key {
type Error = array::TryFromSliceError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
value.try_into().map(|arr| Self { key: arr })
}
}
impl From<[u8; 32]> for Aes256Key {
fn from(arr: [u8; 32]) -> Self {
Self { key: arr }
}
}