1 // Copyright 2022 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! Traits for AES-CBC 256 with PKCS7 padding. 16 17 extern crate alloc; 18 use alloc::vec::Vec; 19 20 use super::Aes256Key; 21 22 /// Type of the initialization vector for AES-CBC 23 pub type AesCbcIv = [u8; 16]; 24 25 /// Trait for implementing AES-CBC with PKCS7 padding. 26 pub trait AesCbcPkcs7Padded { 27 /// Encrypt message using `key` and `iv`, returning a ciphertext. encrypt(key: &Aes256Key, iv: &AesCbcIv, message: &[u8]) -> Vec<u8>28 fn encrypt(key: &Aes256Key, iv: &AesCbcIv, message: &[u8]) -> Vec<u8>; 29 /// Decrypt ciphertext using `key` and `iv`, returning the original message if `Ok()` otherwise 30 /// a `DecryptionError` indicating the type of error that occurred while decrypting. decrypt( key: &Aes256Key, iv: &AesCbcIv, ciphertext: &[u8], ) -> Result<Vec<u8>, DecryptionError>31 fn decrypt( 32 key: &Aes256Key, 33 iv: &AesCbcIv, 34 ciphertext: &[u8], 35 ) -> Result<Vec<u8>, DecryptionError>; 36 } 37 38 /// Error type for describing what went wrong decrypting a ciphertext. 39 #[derive(Debug, PartialEq, Eq)] 40 pub enum DecryptionError { 41 /// Invalid padding, the input ciphertext does not have valid PKCS7 padding. If you get this 42 /// error, check the encryption side generating this data to make sure it is adding the padding 43 /// correctly. Exposing padding errors can cause a padding oracle vulnerability. 44 BadPadding, 45 } 46 47 /// Module for testing implementations of this crate. 48 #[cfg(feature = "testing")] 49 pub mod testing { 50 use super::{Aes256Key, AesCbcIv, AesCbcPkcs7Padded}; 51 pub use crate::testing::prelude::*; 52 use core::marker::PhantomData; 53 use hex_literal::hex; 54 use rstest_reuse::template; 55 56 /// Tests for AES-256-CBC encryption aes_256_cbc_test_encrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)57 pub fn aes_256_cbc_test_encrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) { 58 // http://google3/third_party/wycheproof/testvectors/aes_cbc_pkcs5_test.json;l=1492;rcl=264817632 59 let key: Aes256Key = 60 hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into(); 61 let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb"); 62 let msg = hex!("3f56935def3f"); 63 let expected_ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48"); 64 assert_eq!(A::encrypt(&key, &iv, &msg), expected_ciphertext); 65 } 66 67 /// Tests for AES-256-CBC decryption aes_256_cbc_test_decrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)68 pub fn aes_256_cbc_test_decrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) { 69 // http://google3/third_party/wycheproof/testvectors/aes_cbc_pkcs5_test.json;l=1492;rcl=264817632 70 let key: Aes256Key = 71 hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into(); 72 let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb"); 73 let ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48"); 74 let expected_msg = hex!("3f56935def3f"); 75 assert_eq!(A::decrypt(&key, &iv, &ciphertext).unwrap(), expected_msg); 76 } 77 78 /// Generates the test cases to validate the AES-256-CBC implementation. 79 /// For example, to test `MyAesCbc256Impl`: 80 /// 81 /// ``` 82 /// use crypto_provider::aes::cbc::testing::*; 83 /// 84 /// mod tests { 85 /// #[apply(aes_256_cbc_test_cases)] 86 /// fn aes_256_cbc_tests( 87 /// testcase: CryptoProviderTestCases<PhantomData<MyAesCbc256Impl>>) { 88 /// testcase(PhantomData); 89 /// } 90 /// } 91 /// ``` 92 #[template] 93 #[export] 94 #[rstest] 95 #[case::encrypt(aes_256_cbc_test_encrypt)] 96 #[case::decrypt(aes_256_cbc_test_decrypt)] aes_256_cbc_test_cases<A: AesCbcPkcs7Padded>(#[case] testcase: CryptoProviderTestCases<F>)97 fn aes_256_cbc_test_cases<A: AesCbcPkcs7Padded>(#[case] testcase: CryptoProviderTestCases<F>) {} 98 } 99