blob: f5d5b00d61840271b7eceaf741622197bb85275a [file] [log] [blame]
// Copyright 2023 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.
// 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.
//! Implementation of `crypto_provider::aes` types using openssl's `symm` module.
use openssl::symm::{Cipher, Crypter, Mode};
use crypto_provider::aes::{
cbc::{AesCbcIv, DecryptionError},
ctr::NonceAndCounter,
Aes, Aes128Key, Aes256Key, AesBlock, AesCipher, AesDecryptCipher, AesEncryptCipher, AesKey,
};
/// Uber struct which contains impls for AES-128 fns
pub struct Aes128;
impl Aes for Aes128 {
type Key = Aes128Key;
type EncryptCipher = Aes128Cipher;
type DecryptCipher = Aes128Cipher;
}
/// Uber struct which contains impls for AES-256 fns
pub struct Aes256;
impl Aes for Aes256 {
type Key = Aes256Key;
type EncryptCipher = Aes256Cipher;
type DecryptCipher = Aes256Cipher;
}
/// Wrapper around openssl's AES-128 impl
pub struct Aes128Cipher(Aes128Key);
impl AesCipher for Aes128Cipher {
type Key = Aes128Key;
fn new(key: &Self::Key) -> Self {
Self(key.clone())
}
}
impl AesEncryptCipher for Aes128Cipher {
fn encrypt(&self, block: &mut AesBlock) {
// openssl requires the output to be at least 32 bytes long
let mut output = [0_u8; 32];
let mut crypter =
Crypter::new(Cipher::aes_128_ecb(), Mode::Encrypt, self.0.as_slice(), None).unwrap();
crypter.pad(false);
crypter.update(block, &mut output).unwrap();
block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
}
}
impl AesDecryptCipher for Aes128Cipher {
fn decrypt(&self, block: &mut AesBlock) {
// openssl requires the output to be at least 32 bytes long
let mut output = [0_u8; 32];
let mut crypter =
Crypter::new(Cipher::aes_128_ecb(), Mode::Decrypt, self.0.as_slice(), None).unwrap();
crypter.pad(false);
crypter.update(block, &mut output).unwrap();
block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
}
}
/// Wrapper around openssl's AES-128 impl
pub struct Aes256Cipher(Aes256Key);
impl AesCipher for Aes256Cipher {
type Key = Aes256Key;
fn new(key: &Self::Key) -> Self {
Self(key.clone())
}
}
impl AesEncryptCipher for Aes256Cipher {
fn encrypt(&self, block: &mut AesBlock) {
// openssl requires the output to be at least 32 bytes long
let mut output = [0_u8; 32];
let mut crypter =
Crypter::new(Cipher::aes_256_ecb(), Mode::Encrypt, self.0.as_slice(), None).unwrap();
crypter.pad(false);
crypter.update(block, &mut output).unwrap();
block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
}
}
impl AesDecryptCipher for Aes256Cipher {
fn decrypt(&self, block: &mut AesBlock) {
// openssl requires the output to be at least 32 bytes long
let mut output = [0_u8; 32];
let mut crypter =
Crypter::new(Cipher::aes_256_ecb(), Mode::Decrypt, self.0.as_slice(), None).unwrap();
crypter.pad(false);
crypter.update(block, &mut output).unwrap();
block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
}
}
/// OpenSSL implementation of AES-CBC-PKCS7.
pub struct OpenSslAesCbcPkcs7;
impl crypto_provider::aes::cbc::AesCbcPkcs7Padded for OpenSslAesCbcPkcs7 {
fn encrypt(key: &crypto_provider::aes::Aes256Key, iv: &AesCbcIv, message: &[u8]) -> Vec<u8> {
openssl::symm::encrypt(Cipher::aes_256_cbc(), key.as_slice(), Some(iv.as_slice()), message)
.unwrap()
}
fn decrypt(
key: &crypto_provider::aes::Aes256Key,
iv: &AesCbcIv,
ciphertext: &[u8],
) -> Result<Vec<u8>, DecryptionError> {
openssl::symm::decrypt(
Cipher::aes_256_cbc(),
key.as_slice(),
Some(iv.as_slice()),
ciphertext,
)
.map_err(|_| DecryptionError::BadPadding)
}
}
/// OpenSSL implementation of AES-CTR-128
pub struct OpenSslAesCtr128 {
enc_cipher: Crypter,
dec_cipher: Crypter,
}
impl crypto_provider::aes::ctr::AesCtr for OpenSslAesCtr128 {
type Key = crypto_provider::aes::Aes128Key;
fn new(key: &Self::Key, nonce_and_counter: NonceAndCounter) -> Self {
Self {
enc_cipher: Crypter::new(
Cipher::aes_128_ctr(),
Mode::Encrypt,
key.as_slice(),
Some(&nonce_and_counter.as_block_array()),
)
.unwrap(),
dec_cipher: Crypter::new(
Cipher::aes_128_ctr(),
Mode::Decrypt,
key.as_slice(),
Some(&nonce_and_counter.as_block_array()),
)
.unwrap(),
}
}
fn encrypt(&mut self, data: &mut [u8]) {
let mut in_slice = vec![0u8; data.len()];
in_slice.copy_from_slice(data);
let _ = self.enc_cipher.update(&in_slice, data);
}
fn decrypt(&mut self, data: &mut [u8]) {
let mut in_slice = vec![0u8; data.len()];
in_slice.copy_from_slice(data);
let _ = self.dec_cipher.update(&in_slice, data);
}
}
/// OpenSSL implementation of AES-CTR-256
pub struct OpenSslAesCtr256 {
enc_cipher: Crypter,
dec_cipher: Crypter,
}
impl crypto_provider::aes::ctr::AesCtr for OpenSslAesCtr256 {
type Key = crypto_provider::aes::Aes256Key;
fn new(key: &Self::Key, nonce_and_counter: NonceAndCounter) -> Self {
Self {
enc_cipher: Crypter::new(
Cipher::aes_256_ctr(),
Mode::Encrypt,
key.as_slice(),
Some(&nonce_and_counter.as_block_array()),
)
.unwrap(),
dec_cipher: Crypter::new(
Cipher::aes_256_ctr(),
Mode::Decrypt,
key.as_slice(),
Some(&nonce_and_counter.as_block_array()),
)
.unwrap(),
}
}
fn encrypt(&mut self, data: &mut [u8]) {
let mut in_slice = vec![0u8; data.len()];
in_slice.copy_from_slice(data);
let _ = self.enc_cipher.update(&in_slice, data);
}
fn decrypt(&mut self, data: &mut [u8]) {
let mut in_slice = vec![0u8; data.len()];
in_slice.copy_from_slice(data);
let _ = self.dec_cipher.update(&in_slice, data);
}
}
#[cfg(test)]
mod tests {
use core::marker::PhantomData;
use crypto_provider_test::aes::cbc::*;
use crypto_provider_test::aes::ctr::*;
use crypto_provider_test::aes::*;
use super::*;
#[apply(aes_128_ctr_test_cases)]
fn aes_128_ctr_test(testcase: CryptoProviderTestCase<OpenSslAesCtr128>) {
testcase(PhantomData);
}
#[apply(aes_256_ctr_test_cases)]
fn aes_256_ctr_test(testcase: CryptoProviderTestCase<OpenSslAesCtr256>) {
testcase(PhantomData);
}
#[apply(aes_128_encrypt_test_cases)]
fn aes_128_enc_test(testcase: CryptoProviderTestCase<Aes128Cipher>) {
testcase(PhantomData);
}
#[apply(aes_128_decrypt_test_cases)]
fn aes_128_dec_test(testcase: CryptoProviderTestCase<Aes128Cipher>) {
testcase(PhantomData);
}
#[apply(aes_256_encrypt_test_cases)]
fn aes_256_enc_test(testcase: CryptoProviderTestCase<Aes256Cipher>) {
testcase(PhantomData);
}
#[apply(aes_256_decrypt_test_cases)]
fn aes_256_dec_test(testcase: CryptoProviderTestCase<Aes256Cipher>) {
testcase(PhantomData);
}
#[apply(aes_256_cbc_test_cases)]
fn aes_256_cbc_test(testcase: CryptoProviderTestCase<OpenSslAesCbcPkcs7>) {
testcase(PhantomData);
}
}