blob: c7f5d5fb34f0569c5d6a1565747718b422966d8e [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.
//! Traits for AES-CTR.
use super::AesKey;
/// An implementation of AES-CTR.
///
/// An AesCtr impl must only be used for encryption _or_ decryption, not both. Since CTR mode
/// is stateful, mixing encrypts and decrypts may advance the internal state in unexpected ways.
/// Create separate encrypt/decrypt instances if both operations are needed.
pub trait AesCtr {
/// The [AesKey] this cipher uses. See [super::Aes128Key] and [super::Aes256Key] for the common AES-128 and
/// AES-256 cases.
type Key: AesKey;
/// Build a `Self` from key material.
fn new(key: &Self::Key, iv: [u8; 16]) -> Self;
/// Encrypt the data in place, advancing the counter state appropriately.
fn encrypt(&mut self, data: &mut [u8]);
/// Decrypt the data in place, advancing the counter state appropriately.
fn decrypt(&mut self, data: &mut [u8]);
}
/// Module for testing implementations of this crate.
#[cfg(feature = "testing")]
pub mod testing {
use super::AesCtr;
use crate::aes::{Aes128Key, Aes256Key};
pub use crate::testing::prelude;
use core::marker;
use hex_literal::hex;
use rstest_reuse::template;
/// Test AES-128-CTR encryption
pub fn aes_128_ctr_test_encrypt<A: AesCtr<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.1
let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
let mut block: [u8; 16];
let mut cipher = A::new(&key, iv);
block = hex!("6bc1bee22e409f96e93d7e117393172a");
cipher.encrypt(&mut block);
let expected_ciphertext_1 = hex!("874d6191b620e3261bef6864990db6ce");
assert_eq!(expected_ciphertext_1, block);
block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
cipher.encrypt(&mut block);
let expected_ciphertext_2 = hex!("9806f66b7970fdff8617187bb9fffdff");
assert_eq!(expected_ciphertext_2, block);
block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
cipher.encrypt(&mut block);
let expected_ciphertext_3 = hex!("5ae4df3edbd5d35e5b4f09020db03eab");
assert_eq!(expected_ciphertext_3, block);
block = hex!("f69f2445df4f9b17ad2b417be66c3710");
cipher.encrypt(&mut block);
let expected_ciphertext_3 = hex!("1e031dda2fbe03d1792170a0f3009cee");
assert_eq!(expected_ciphertext_3, block);
}
/// Test AES-128-CTR decryption
pub fn aes_128_ctr_test_decrypt<A: AesCtr<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.2
let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
let mut block: [u8; 16];
let mut cipher = A::new(&key, iv);
block = hex!("874d6191b620e3261bef6864990db6ce");
cipher.encrypt(&mut block);
let expected_plaintext_1 = hex!("6bc1bee22e409f96e93d7e117393172a");
assert_eq!(expected_plaintext_1, block);
block = hex!("9806f66b7970fdff8617187bb9fffdff");
cipher.encrypt(&mut block);
let expected_plaintext_2 = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
assert_eq!(expected_plaintext_2, block);
block = hex!("5ae4df3edbd5d35e5b4f09020db03eab");
cipher.encrypt(&mut block);
let expected_plaintext_3 = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
assert_eq!(expected_plaintext_3, block);
block = hex!("1e031dda2fbe03d1792170a0f3009cee");
cipher.encrypt(&mut block);
let expected_plaintext_3 = hex!("f69f2445df4f9b17ad2b417be66c3710");
assert_eq!(expected_plaintext_3, block);
}
/// Test AES-256-CTR encryption
pub fn aes_256_ctr_test_encrypt<A: AesCtr<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.5
let key: Aes256Key =
hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
let mut block: [u8; 16];
let mut cipher = A::new(&key, iv);
block = hex!("6bc1bee22e409f96e93d7e117393172a");
cipher.encrypt(&mut block);
let expected_ciphertext_1 = hex!("601ec313775789a5b7a7f504bbf3d228");
assert_eq!(expected_ciphertext_1, block);
block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
cipher.encrypt(&mut block);
let expected_ciphertext_2 = hex!("f443e3ca4d62b59aca84e990cacaf5c5");
assert_eq!(expected_ciphertext_2, block);
block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
cipher.encrypt(&mut block);
let expected_ciphertext_3 = hex!("2b0930daa23de94ce87017ba2d84988d");
assert_eq!(expected_ciphertext_3, block);
block = hex!("f69f2445df4f9b17ad2b417be66c3710");
cipher.encrypt(&mut block);
let expected_ciphertext_3 = hex!("dfc9c58db67aada613c2dd08457941a6");
assert_eq!(expected_ciphertext_3, block);
}
/// Test AES-256-CTR decryption
pub fn aes_256_ctr_test_decrypt<A: AesCtr<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.6
let key: Aes256Key =
hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
let mut block: [u8; 16];
let mut cipher = A::new(&key, iv);
block = hex!("601ec313775789a5b7a7f504bbf3d228");
cipher.encrypt(&mut block);
let expected_plaintext_1 = hex!("6bc1bee22e409f96e93d7e117393172a");
assert_eq!(expected_plaintext_1, block);
block = hex!("f443e3ca4d62b59aca84e990cacaf5c5");
cipher.encrypt(&mut block);
let expected_plaintext_2 = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
assert_eq!(expected_plaintext_2, block);
block = hex!("2b0930daa23de94ce87017ba2d84988d");
cipher.encrypt(&mut block);
let expected_plaintext_3 = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
assert_eq!(expected_plaintext_3, block);
block = hex!("dfc9c58db67aada613c2dd08457941a6");
cipher.encrypt(&mut block);
let expected_plaintext_3 = hex!("f69f2445df4f9b17ad2b417be66c3710");
assert_eq!(expected_plaintext_3, block);
}
/// Generates the test cases to validate the AES-128-CTR implementation.
/// For example, to test `MyAesCtr128Impl`:
///
/// ```
/// use crypto_provider::aes::ctr::testing::*;
///
/// mod tests {
/// #[apply(aes_128_ctr_test_cases)]
/// fn aes_128_ctr_tests(testcase: CryptoProviderTestCase<MyAesCtr128Impl>) {
/// testcase(MyAesCtr128Impl);
/// }
/// }
/// ```
#[template]
#[export]
#[rstest]
#[case::encrypt(aes_128_ctr_test_encrypt)]
#[case::decrypt(aes_128_ctr_test_decrypt)]
fn aes_128_ctr_test_cases<F: AesCtrFactory<Key = Aes128Key>>(
#[case] testcase: CryptoProviderTestCase<F>,
) {
}
/// Generates the test cases to validate the AES-256-CTR implementation.
/// For example, to test `MyAesCtr256Impl`:
///
/// ```
/// use crypto_provider::aes::ctr::testing::*;
///
/// mod tests {
/// #[apply(aes_256_ctr_test_cases_impl)]
/// fn aes_256_ctr_tests(testcase: CryptoProviderTestCase<MyAesCtr256Impl>) {
/// testcase(MyAesCtr256Impl);
/// }
/// }
/// ```
#[template]
#[export]
#[rstest]
#[case::encrypt(aes_256_ctr_test_encrypt)]
#[case::decrypt(aes_256_ctr_test_decrypt)]
fn aes_256_ctr_test_cases<F: AesCtrFactory<Key = Aes256Key>>(
#[case] testcase: CryptoProviderTestCase<F>,
) {
}
}