1use constants::*;
10use key::Key;
11use pad::{Padding, pkcs7_pad};
12use Padding::PKCS7;
13use state::State;
14
15pub mod pad;
16pub mod key;
17mod state;
18mod xor;
19mod math;
20mod word;
21mod constants;
22mod ctr;
23
24#[derive(PartialEq, Debug)]
25pub struct AESEncryptionOptions<'a> {
26 pub block_cipher_mode: &'a BlockCipherMode<'a>,
27 pub padding: &'a Padding,
28}
29
30impl<'a> AESEncryptionOptions<'a> {
31 pub fn new(block_cipher_mode: &'a BlockCipherMode, padding: &'a Padding) -> Self {
32 AESEncryptionOptions {
33 block_cipher_mode,
34 padding,
35 }
36 }
37}
38
39impl Default for AESEncryptionOptions<'_> {
40 fn default() -> Self {
41 AESEncryptionOptions::new(&BlockCipherMode::ECB, &Padding::None)
42 }
43}
44
45#[derive(PartialEq, Debug)]
47pub struct Block(pub [[u8; 4]; Nb]);
48
49impl Block {
50 pub fn empty() -> Self {
51 Block([[0; 4]; Nb])
52 }
53}
54
55#[derive(PartialEq, Debug)]
56pub enum BlockCipherMode<'a> {
57 ECB,
58 CBC(&'a Iv),
59 CTR(&'a Nonce),
60}
61
62pub type Iv = Block;
63pub type Nonce = [u8; 8];
64
65pub fn encrypt_aes_128(raw_bytes: &[u8], key: &Key, options: &AESEncryptionOptions) -> Vec<u8> {
72 let block_size = 16;
73
74 let w = &key.do_key_expansion().0;
75 let bytes = &if options.padding == &PKCS7 {
76 pkcs7_pad(raw_bytes, block_size)
77 } else {
78 if let BlockCipherMode::CTR(nonce) = &options.block_cipher_mode {
79 ctr::generate_ctr_byte_stream_for_length(raw_bytes.len(), &nonce)
80 } else {
81 raw_bytes.to_vec()
82 }
83 };
84 let parts = bytes_to_parts(bytes);
85
86 let mut cipher: Vec<u8> = Vec::with_capacity(raw_bytes.len());
87 let mut previous_state: State = State::empty();
88
89 for (i, part) in parts.iter().enumerate() {
90 let mut state = State::from_part(part);
91 if let BlockCipherMode::CBC(iv) = &options.block_cipher_mode {
92 if i == 0 {
93 state.xor_with_iv(&iv);
94 } else {
95 state.xor_with_state(&previous_state);
96 };
97 }
98
99 state.add_round_key(&w[0..Nb]);
100
101 for round in 1..Nr {
102 state.sub_bytes();
103 state.shift_rows();
104 state.mix_columns();
105 state.add_round_key(&w[round * Nb..(round + 1) * Nb]);
106 }
107
108 state.sub_bytes();
109 state.shift_rows();
110 state.add_round_key(&w[Nr * Nb..(Nr + 1) * Nb]);
111
112 if let BlockCipherMode::CBC(_iv) = &options.block_cipher_mode {
113 previous_state = state.clone();
114 }
115
116 cipher.append(state.to_block().as_mut());
117 }
118
119 if let BlockCipherMode::CTR(_nonce) = &options.block_cipher_mode {
120 xor::fixed_key_xor(&raw_bytes, &cipher)
121 } else {
122 cipher
123 }
124}
125
126pub fn decrypt_aes_128(cipher: &[u8], key: &Key, mode: &BlockCipherMode) -> Vec<u8> {
128 if let BlockCipherMode::CTR(_nonce) = mode {
129 panic!("Cannot decrypt using CTR block cipher mode. Use encryption instead.");
130 }
131
132 let w = &key.do_key_expansion().0;
133 let parts = bytes_to_parts(cipher);
134 let mut deciphered: Vec<u8> = Vec::with_capacity(cipher.len());
135 let mut previous_state = State::empty();
136
137 for (i, part) in parts.iter().enumerate() {
138 let mut state = State::from_part(part);
139
140 state.add_round_key(&w[Nr * Nb..(Nr + 1) * Nb]);
141
142 for round in (1..Nr).rev() {
143 state.inv_shift_rows();
144 state.inv_sub_bytes();
145 state.add_round_key(&w[round * Nb..(round + 1) * Nb]);
146 state.inv_mix_columns();
147 }
148
149 state.inv_shift_rows();
150 state.inv_sub_bytes();
151 state.add_round_key(&w[0..Nb]);
152
153 if let BlockCipherMode::CBC(iv) = mode {
154 if i == 0 {
155 state.xor_with_iv(iv);
156 } else {
157 state.xor_with_state(&previous_state);
158 };
159 previous_state = State::from_part(part);
160 }
161
162 deciphered.append(state.to_block().as_mut());
163 }
164
165 deciphered
166}
167
168pub fn bytes_to_parts(bytes: &[u8]) -> Vec<&[u8]> {
170 let block_size = 16usize;
171
172 bytes.chunks_exact(block_size).collect()
173}
174
175#[cfg(test)]
178mod tests {
179 use pad::Padding;
180
181 use super::*;
182
183 const ECB_KEY: Key = Key([
184 0x00, 0x01, 0x02, 0x03,
185 0x04, 0x05, 0x06, 0x07,
186 0x08, 0x09, 0x0a, 0x0b,
187 0x0c, 0x0d, 0x0e, 0x0f
188 ]);
189 const RAW_ECB: [u8; 16] = [
190 0x0, 0x11, 0x22, 0x33,
191 0x44, 0x55, 0x66, 0x77,
192 0x88, 0x99, 0xaa, 0xbb,
193 0xcc, 0xdd, 0xee, 0xff
194 ];
195 const CIPHERED_ECB: [u8; 16] = [
196 0x69, 0xc4, 0xe0, 0xd8,
197 0x6a, 0x7b, 0x04, 0x30,
198 0xd8, 0xcd, 0xb7, 0x80,
199 0x70, 0xb4, 0xc5, 0x5a
200 ];
201
202 const CBC_KEY: Key = Key([
203 0x2b, 0x7e, 0x15, 0x16,
204 0x28, 0xae, 0xd2, 0xa6,
205 0xab, 0xf7, 0x15, 0x88,
206 0x09, 0xcf, 0x4f, 0x3c
207 ]);
208 const CBC_IV: Iv = Block([
209 [0x00, 0x01, 0x02, 0x03],
210 [0x04, 0x05, 0x06, 0x07],
211 [0x08, 0x09, 0x0a, 0x0b],
212 [0x0c, 0x0d, 0x0e, 0x0f]
213 ]);
214 const CIPHERED_CBC: [u8; 16] = [
215 0x76, 0x49, 0xab, 0xac,
216 0x81, 0x19, 0xb2, 0x46,
217 0xce, 0xe9, 0x8e, 0x9b,
218 0x12, 0xe9, 0x19, 0x7d
219 ];
220 const RAW_CBC: [u8; 16] = [
221 0x6b, 0xc1, 0xbe, 0xe2,
222 0x2e, 0x40, 0x9f, 0x96,
223 0xe9, 0x3d, 0x7e, 0x11,
224 0x73, 0x93, 0x17, 0x2a
225 ];
226
227 const CTR_KEY: Key = Key([
228 0x2b, 0x7e, 0x15, 0x16,
229 0x28, 0xae, 0xd2, 0xa6,
230 0xab, 0xf7, 0x15, 0x88,
231 0x09, 0xcf, 0x4f, 0x3c
232 ]);
233 const CTR_NONCE: Nonce = [0xff; 8];
234 const RAW_CTR: [u8; 16] = [
235 0x30, 0xc8, 0x1c, 0x46,
236 0xa3, 0x5c, 0xe4, 0x11,
237 0xe5, 0xfb, 0xc1, 0x19,
238 0x1a, 0x0a, 0x52, 0xef
239 ];
240 const CIPHERED_CTR: [u8; 16] = [
241 0x27, 0x5c, 0x37, 0xf4,
242 0xd3, 0x53, 0xf9, 0x93,
243 0x2f, 0x6c, 0xd4, 0x60,
244 0xa1, 0xc2, 0xb2, 0x25
245 ];
246
247 #[test]
248 fn default_encryption_options_are_ecb_with_no_padding() {
249 let encryption_options = AESEncryptionOptions::default();
250
251 assert_eq!(encryption_options.block_cipher_mode, &BlockCipherMode::ECB);
252 assert_eq!(encryption_options.padding, &Padding::None);
253 }
254
255 #[test]
256 fn empty_produces_empty_block() {
257 let block = Block::empty();
258 let expected_block = [
259 [0, 0, 0, 0],
260 [0, 0, 0, 0],
261 [0, 0, 0, 0],
262 [0, 0, 0, 0],
263 ];
264
265 assert_eq!(block.0, expected_block);
266 }
267
268 #[test]
269 fn encrypts_in_ecb_mode() {
270 let actual_cipher = encrypt_aes_128(
271 &RAW_ECB,
272 &ECB_KEY,
273 &AESEncryptionOptions::new(
274 &BlockCipherMode::ECB,
275 &Padding::None,
276 ),
277 );
278
279 assert_eq!(actual_cipher, CIPHERED_ECB);
280 }
281
282 #[test]
283 fn decrypts_in_ecb_mode() {
284 let actual_raw = decrypt_aes_128(
285 &CIPHERED_ECB,
286 &ECB_KEY,
287 &BlockCipherMode::ECB,
288 );
289
290 assert_eq!(actual_raw, RAW_ECB);
291 }
292
293 #[test]
294 fn encrypts_in_cbc_mode() {
295 let actual_cipher = encrypt_aes_128(
296 &RAW_CBC,
297 &CBC_KEY,
298 &AESEncryptionOptions::new(
299 &BlockCipherMode::CBC(&CBC_IV),
300 &Padding::None,
301 ),
302 );
303
304 assert_eq!(actual_cipher, CIPHERED_CBC);
305 }
306
307 #[test]
308 fn decrypts_in_cbc_mode() {
309 let actual_raw = decrypt_aes_128(
310 &CIPHERED_CBC,
311 &CBC_KEY,
312 &BlockCipherMode::CBC(&CBC_IV),
313 );
314
315 assert_eq!(actual_raw, RAW_CBC);
316 }
317
318 #[test]
319 fn encrypts_in_ctr_mode() {
320 let actual_cipher = encrypt_aes_128(
321 &RAW_CTR,
322 &CTR_KEY,
323 &AESEncryptionOptions::new(
324 &BlockCipherMode::CTR(&CTR_NONCE),
325 &Padding::None,
326 ),
327 );
328
329 assert_eq!(actual_cipher, CIPHERED_CTR);
330 }
331
332 #[test]
333 fn decrypts_in_ctr_mode() {
334 let actual_raw = encrypt_aes_128(
336 &CIPHERED_CTR,
337 &CTR_KEY,
338 &AESEncryptionOptions::new(
339 &BlockCipherMode::CTR(&CTR_NONCE),
340 &Padding::None,
341 ),
342 );
343
344 assert_eq!(actual_raw, RAW_CTR);
345 }
346
347 #[test]
348 #[should_panic(expected = "Cannot decrypt using CTR block cipher mode. Use encryption instead.")]
349 fn decryption_in_ctr_mode_should_panic() {
350 decrypt_aes_128(
351 &CIPHERED_CTR,
352 &CTR_KEY,
353 &BlockCipherMode::CTR(&CTR_NONCE),
354 );
355 }
356
357 #[test]
358 fn bytes_to_parts_converts_bytes_to_parts_of_block_size_length() {
359 let bytes: [u8; 32] = [
360 0x00, 0x01, 0x02, 0x03,
361 0x04, 0x05, 0x06, 0x07,
362 0x08, 0x09, 0x10, 0x11,
363 0x12, 0x13, 0x14, 0x15,
364 0x16, 0x17, 0x18, 0x19,
365 0x20, 0x21, 0x22, 0x23,
366 0x24, 0x25, 0x26, 0x27,
367 0x28, 0x29, 0x30, 0x31
368 ];
369 let expected_parts = vec![
370 &bytes[..16],
371 &bytes[16..]
372 ];
373
374 assert_eq!(bytes_to_parts(&bytes.to_vec()), expected_parts);
375 }
376}