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 use crate::aes::Aes256Key;
16 pub use crate::prelude::*;
17 use core::marker::PhantomData;
18 use crypto_provider::{
19 aes::cbc::{AesCbcIv, AesCbcPkcs7Padded},
20 tinyvec::SliceVec,
21 };
22 use hex_literal::hex;
23 use rstest_reuse::template;
24
25 /// Tests for AES-256-CBC encryption
aes_256_cbc_test_encrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)26 pub fn aes_256_cbc_test_encrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
27 // https://github.com/google/wycheproof/blob/b063b4a/testvectors/aes_cbc_pkcs5_test.json#L1492
28 // tcId: 132
29 let key: Aes256Key =
30 hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
31 let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
32 let msg = hex!("3f56935def3f");
33 let expected_ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
34 assert_eq!(A::encrypt(&key, &iv, &msg), expected_ciphertext);
35 }
36
37 /// Tests for AES-256-CBC in-place encryption
aes_256_cbc_test_encrypt_in_place<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)38 pub fn aes_256_cbc_test_encrypt_in_place<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
39 // https://github.com/google/wycheproof/blob/b063b4a/testvectors/aes_cbc_pkcs5_test.json#L1492
40 // tcId: 132
41 let key: Aes256Key =
42 hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
43 let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
44 let msg = hex!("3f56935def3f");
45 let expected_ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
46 let mut msg_buffer_backing = [0_u8; 16];
47 let mut msg_buffer = SliceVec::from_slice_len(&mut msg_buffer_backing, 0);
48 msg_buffer.extend_from_slice(&msg);
49 A::encrypt_in_place(&key, &iv, &mut msg_buffer).unwrap();
50 assert_eq!(msg_buffer.as_slice(), &expected_ciphertext);
51 }
52
53 /// Tests for AES-256-CBC encryption, where the given buffer `SliceVec` is too short to contain the
54 /// output.
aes_256_cbc_test_encrypt_in_place_too_short<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)55 pub fn aes_256_cbc_test_encrypt_in_place_too_short<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
56 // https://github.com/google/wycheproof/blob/b063b4a/testvectors/aes_cbc_pkcs5_test.json#L1612
57 // tcId: 144
58 let key: Aes256Key =
59 hex!("4f097858a1aec62cf18f0966b2b120783aa4ae9149d3213109740506ae47adfe").into();
60 let iv: AesCbcIv = hex!("400aab92803bcbb44a96ef789655b34e");
61 let msg = hex!("ee53d8e5039e82d9fcca114e375a014febfea117a7e709d9008d43858e3660");
62 let mut msg_buffer_backing = [0_u8; 31];
63 let mut msg_buffer = SliceVec::from_slice_len(&mut msg_buffer_backing, 0);
64 msg_buffer.extend_from_slice(&msg);
65 A::encrypt_in_place(&key, &iv, &mut msg_buffer)
66 .expect_err("Encrypting AES with 15-byte buffer should fail");
67 // Buffer content is undefined, but test to make sure it doesn't contain half-decrypted data
68 assert!(
69 msg_buffer.as_slice() == [0_u8; 32] || msg_buffer.as_slice() == msg,
70 "Unrecognized content in buffer after decryption failure"
71 )
72 }
73
74 /// Tests for AES-256-CBC decryption
aes_256_cbc_test_decrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)75 pub fn aes_256_cbc_test_decrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
76 // https://github.com/google/wycheproof/blob/b063b4a/testvectors/aes_cbc_pkcs5_test.json#L1492
77 // tcId: 132
78 let key: Aes256Key =
79 hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
80 let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
81 let ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
82 let expected_msg = hex!("3f56935def3f");
83 assert_eq!(A::decrypt(&key, &iv, &ciphertext).unwrap(), expected_msg);
84 }
85
86 /// Tests for AES-256-CBC decryption with bad padding
aes_256_cbc_test_decrypt_bad_padding<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)87 pub fn aes_256_cbc_test_decrypt_bad_padding<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
88 // https://github.com/google/wycheproof/blob/b063b4a/testvectors/aes_cbc_pkcs5_test.json#L1690
89 // tcId: 151
90 let key: Aes256Key =
91 hex!("7c78f34dbce8f0557d43630266f59babd1cb92ba624bd1a8f45a2a91c84a804a").into();
92 let iv: AesCbcIv = hex!("f010f61c31c9aa8fa0d5be5f6b0f2f70");
93 let ciphertext = hex!("8881e9e02fa9e3037b397957ba1fb7ce64679a46621b792f643542a735f0bbbf");
94 A::decrypt(&key, &iv, &ciphertext).expect_err("Decryption with bad padding should fail");
95 }
96
97 /// Tests for AES-256-CBC in-place decryption
aes_256_cbc_test_decrypt_in_place<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>)98 pub fn aes_256_cbc_test_decrypt_in_place<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
99 // https://github.com/google/wycheproof/blob/b063b4a/testvectors/aes_cbc_pkcs5_test.json#L1492
100 // tcId: 132
101 let key: Aes256Key =
102 hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
103 let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
104 let mut ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
105 let expected_msg = hex!("3f56935def3f");
106 let mut msg_buffer = SliceVec::from(&mut ciphertext);
107 A::decrypt_in_place(&key, &iv, &mut msg_buffer).unwrap();
108 assert_eq!(msg_buffer.as_slice(), expected_msg);
109 }
110
111 /// Tests for AES-256-CBC in-place decryption with bad padding
aes_256_cbc_test_decrypt_in_place_bad_padding<A: AesCbcPkcs7Padded>( _marker: PhantomData<A>, )112 pub fn aes_256_cbc_test_decrypt_in_place_bad_padding<A: AesCbcPkcs7Padded>(
113 _marker: PhantomData<A>,
114 ) {
115 // https://github.com/google/wycheproof/blob/b063b4a/testvectors/aes_cbc_pkcs5_test.json#L1690
116 // tcId: 151
117 let key: Aes256Key =
118 hex!("7c78f34dbce8f0557d43630266f59babd1cb92ba624bd1a8f45a2a91c84a804a").into();
119 let iv: AesCbcIv = hex!("f010f61c31c9aa8fa0d5be5f6b0f2f70");
120 let ciphertext = hex!("8881e9e02fa9e3037b397957ba1fb7ce64679a46621b792f643542a735f0bbbf");
121 let mut msg_buffer_backing = ciphertext;
122 let mut msg_buffer = SliceVec::from(&mut msg_buffer_backing);
123 A::decrypt_in_place(&key, &iv, &mut msg_buffer)
124 .expect_err("Decryption with bad padding should fail");
125 // Buffer content is undefined, but test to make sure it doesn't contain half-decrypted data
126 assert!(
127 msg_buffer.as_slice() == [0_u8; 32] || msg_buffer.as_slice() == ciphertext,
128 "Unrecognized content in buffer after decryption failure"
129 )
130 }
131
132 /// Generates the test cases to validate the AES-256-CBC implementation.
133 /// For example, to test `MyAesCbc256Impl`:
134 ///
135 /// ```
136 /// use crypto_provider::aes::cbc::testing::*;
137 ///
138 /// mod tests {
139 /// #[apply(aes_256_cbc_test_cases)]
140 /// fn aes_256_cbc_tests(
141 /// testcase: CryptoProviderTestCases<PhantomData<MyAesCbc256Impl>>) {
142 /// testcase(PhantomData);
143 /// }
144 /// }
145 /// ```
146 #[template]
147 #[export]
148 #[rstest]
149 #[case::encrypt(aes_256_cbc_test_encrypt)]
150 #[case::encrypt_in_place(aes_256_cbc_test_encrypt_in_place)]
151 #[case::encrypt_in_place_too_short(aes_256_cbc_test_encrypt_in_place_too_short)]
152 #[case::decrypt(aes_256_cbc_test_decrypt)]
153 #[case::decrypt_bad_padding(aes_256_cbc_test_decrypt_bad_padding)]
154 #[case::decrypt_in_place_bad_padding(aes_256_cbc_test_decrypt_in_place_bad_padding)]
aes_256_cbc_test_cases<A: AesCbcPkcs7Padded>(#[case] testcase: CryptoProviderTestCases<F>)155 fn aes_256_cbc_test_cases<A: AesCbcPkcs7Padded>(#[case] testcase: CryptoProviderTestCases<F>) {}
156