• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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