1 // Copyright 2023 The BoringSSL Authors
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 //     https://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 extern crate alloc;
16 
17 use crate::cipher::{
18     BlockCipher, Cipher, CipherError, CipherInitPurpose, EvpAes128Cbc, EvpAes256Cbc,
19 };
20 use alloc::vec::Vec;
21 
22 /// AES-CBC-128 Cipher implementation.
23 pub struct Aes128Cbc(Cipher<EvpAes128Cbc>);
24 
25 impl BlockCipher for Aes128Cbc {
26     type Key = [u8; 16];
27     type Nonce = [u8; 16];
28 
new_encrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self29     fn new_encrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self {
30         Self(Cipher::new(key, nonce, CipherInitPurpose::Encrypt))
31     }
32 
new_decrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self33     fn new_decrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self {
34         Self(Cipher::new(key, nonce, CipherInitPurpose::Decrypt))
35     }
36 
encrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError>37     fn encrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError> {
38         // Note: Padding is enabled because we did not disable it with `EVP_CIPHER_CTX_set_padding`
39         self.0.encrypt(buffer)
40     }
41 
decrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError>42     fn decrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError> {
43         // Note: Padding is enabled because we did not disable it with `EVP_CIPHER_CTX_set_padding`
44         self.0.decrypt(buffer)
45     }
46 }
47 
48 /// AES-CBC-256 Cipher implementation.
49 pub struct Aes256Cbc(Cipher<EvpAes256Cbc>);
50 
51 impl BlockCipher for Aes256Cbc {
52     type Key = [u8; 32];
53     type Nonce = [u8; 16];
54 
new_encrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self55     fn new_encrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self {
56         Self(Cipher::new(key, nonce, CipherInitPurpose::Encrypt))
57     }
58 
new_decrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self59     fn new_decrypt(key: &Self::Key, nonce: &Self::Nonce) -> Self {
60         Self(Cipher::new(key, nonce, CipherInitPurpose::Decrypt))
61     }
62 
encrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError>63     fn encrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError> {
64         // Note: Padding is enabled because we did not disable it with `EVP_CIPHER_CTX_set_padding`
65         self.0.encrypt(buffer)
66     }
67 
decrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError>68     fn decrypt_padded(self, buffer: &[u8]) -> Result<Vec<u8>, CipherError> {
69         // Note: Padding is enabled because we did not disable it with `EVP_CIPHER_CTX_set_padding`
70         self.0.decrypt(buffer)
71     }
72 }
73 
74 #[allow(clippy::expect_used)]
75 #[cfg(test)]
76 mod test {
77     use super::*;
78     use crate::test_helpers::decode_hex;
79 
80     #[test]
aes_128_cbc_test_encrypt()81     fn aes_128_cbc_test_encrypt() {
82         // https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json#L30
83         // tcId: 2
84         let iv = decode_hex("c9ee3cd746bf208c65ca9e72a266d54f");
85         let key = decode_hex("e09eaa5a3f5e56d279d5e7a03373f6ea");
86 
87         let cipher = Aes128Cbc::new_encrypt(&key, &iv);
88         let msg: [u8; 16] = decode_hex("ef4eab37181f98423e53e947e7050fd0");
89 
90         let output = cipher.encrypt_padded(&msg).expect("Failed to encrypt");
91 
92         let expected_ciphertext: [u8; 32] =
93             decode_hex("d1fa697f3e2e04d64f1a0da203813ca5bc226a0b1d42287b2a5b994a66eaf14a");
94         assert_eq!(expected_ciphertext, &output[..]);
95     }
96 
97     #[test]
aes_128_cbc_test_encrypt_more_than_one_block()98     fn aes_128_cbc_test_encrypt_more_than_one_block() {
99         // https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json#L210
100         // tcId: 20
101         let iv = decode_hex("54f2459e40e002763144f4752cde2fb5");
102         let key = decode_hex("831e664c9e3f0c3094c0b27b9d908eb2");
103 
104         let cipher = Aes128Cbc::new_encrypt(&key, &iv);
105         let msg: [u8; 17] = decode_hex("26603bb76dd0a0180791c4ed4d3b058807");
106 
107         let output = cipher.encrypt_padded(&msg).expect("Failed to encrypt");
108 
109         let expected_ciphertext: [u8; 32] =
110             decode_hex("8d55dc10584e243f55d2bdbb5758b7fabcd58c8d3785f01c7e3640b2a1dadcd9");
111         assert_eq!(expected_ciphertext, &output[..]);
112     }
113 
114     #[test]
aes_128_cbc_test_decrypt()115     fn aes_128_cbc_test_decrypt() {
116         // https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json#L30
117         // tcId: 2
118         let key = decode_hex("e09eaa5a3f5e56d279d5e7a03373f6ea");
119         let iv = decode_hex("c9ee3cd746bf208c65ca9e72a266d54f");
120         let cipher = Aes128Cbc::new_decrypt(&key, &iv);
121         let ciphertext: [u8; 32] =
122             decode_hex("d1fa697f3e2e04d64f1a0da203813ca5bc226a0b1d42287b2a5b994a66eaf14a");
123         let decrypted = cipher
124             .decrypt_padded(&ciphertext)
125             .expect("Failed to decrypt");
126         let expected_plaintext: [u8; 16] = decode_hex("ef4eab37181f98423e53e947e7050fd0");
127         assert_eq!(expected_plaintext, &decrypted[..]);
128     }
129 
130     #[test]
aes_128_cbc_test_decrypt_empty_message()131     fn aes_128_cbc_test_decrypt_empty_message() {
132         // https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json#L20
133         // tcId: 1
134         let key = decode_hex("e34f15c7bd819930fe9d66e0c166e61c");
135         let iv = decode_hex("da9520f7d3520277035173299388bee2");
136         let cipher = Aes128Cbc::new_decrypt(&key, &iv);
137         let ciphertext: [u8; 16] = decode_hex("b10ab60153276941361000414aed0a9d");
138         let decrypted = cipher
139             .decrypt_padded(&ciphertext)
140             .expect("Failed to decrypt");
141         let expected_plaintext: [u8; 0] = decode_hex("");
142         assert_eq!(expected_plaintext, &decrypted[..]);
143     }
144 
145     #[test]
aes_256_cbc_test_encrypt()146     pub fn aes_256_cbc_test_encrypt() {
147         // https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json#L1412
148         // tcId: 124
149         let iv = decode_hex("9ec7b863ac845cad5e4673da21f5b6a9");
150         let key = decode_hex("612e837843ceae7f61d49625faa7e7494f9253e20cb3adcea686512b043936cd");
151 
152         let cipher = Aes256Cbc::new_encrypt(&key, &iv);
153         let msg: [u8; 16] = decode_hex("cc37fae15f745a2f40e2c8b192f2b38d");
154 
155         let output = cipher.encrypt_padded(&msg).expect("Failed to encrypt");
156 
157         let expected_ciphertext: [u8; 32] =
158             decode_hex("299295be47e9f5441fe83a7a811c4aeb2650333e681e69fa6b767d28a6ccf282");
159         assert_eq!(expected_ciphertext, &output[..]);
160     }
161 
162     #[test]
aes_256_cbc_test_encrypt_more_than_one_block()163     pub fn aes_256_cbc_test_encrypt_more_than_one_block() {
164         // https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json#L1582C24-L1582C24
165         // tcId: 141
166         let iv = decode_hex("4b74bd981ea9d074757c3e2ef515e5fb");
167         let key = decode_hex("73216fafd0022d0d6ee27198b2272578fa8f04dd9f44467fbb6437aa45641bf7");
168 
169         let cipher = Aes256Cbc::new_encrypt(&key, &iv);
170         let msg: [u8; 17] = decode_hex("d5247b8f6c3edcbfb1d591d13ece23d2f5");
171 
172         let output = cipher.encrypt_padded(&msg).expect("Failed to encrypt");
173 
174         let expected_ciphertext: [u8; 32] =
175             decode_hex("fbea776fb1653635f88e2937ed2450ba4e9063e96d7cdba04928f01cb85492fe");
176         assert_eq!(expected_ciphertext, &output[..]);
177     }
178 
179     #[test]
aes_256_cbc_test_decrypt()180     fn aes_256_cbc_test_decrypt() {
181         // https://github.com/google/wycheproof/blob/master/testvectors/aes_cbc_pkcs5_test.json#L1452
182         // tcId: 128
183         let key = decode_hex("ea3b016bdd387dd64d837c71683808f335dbdc53598a4ea8c5f952473fafaf5f");
184         let iv = decode_hex("fae3e2054113f6b3b904aadbfe59655c");
185         let cipher = Aes256Cbc::new_decrypt(&key, &iv);
186         let ciphertext: [u8; 16] = decode_hex("b90c326b72eb222ddb4dae47f2bc223c");
187         let decrypted = cipher
188             .decrypt_padded(&ciphertext)
189             .expect("Failed to decrypt");
190         let expected_plaintext: [u8; 2] = decode_hex("6601");
191         assert_eq!(expected_plaintext, &decrypted[..]);
192     }
193 }
194