]>
Commit | Line | Data |
---|---|---|
3ee932bc VK |
1 | //! Low level AES functionality |
2 | //! | |
3 | //! The `symm` module should be used in preference to this module in most cases. | |
4 | use ffi; | |
5 | use std::mem; | |
6 | use libc::c_int; | |
7 | ||
8 | use symm::Mode; | |
9 | ||
10 | #[derive(Debug)] | |
11 | pub struct KeyError(()); | |
12 | ||
13 | pub struct AesKey(ffi::AES_KEY); | |
14 | ||
15 | impl AesKey { | |
16 | /// Prepares a key for encryption. | |
17 | /// | |
18 | /// # Failure | |
19 | /// | |
20 | /// Returns an error if the key is not 128, 192, or 256 bits. | |
21 | pub fn new_encrypt(key: &[u8]) -> Result<AesKey, KeyError> { | |
22 | unsafe { | |
23 | assert!(key.len() <= c_int::max_value() as usize / 8); | |
24 | ||
25 | let mut aes_key = mem::uninitialized(); | |
82fc9e21 VK |
26 | let r = ffi::AES_set_encrypt_key( |
27 | key.as_ptr() as *const _, | |
28 | key.len() as c_int * 8, | |
29 | &mut aes_key, | |
30 | ); | |
3ee932bc VK |
31 | if r == 0 { |
32 | Ok(AesKey(aes_key)) | |
33 | } else { | |
34 | Err(KeyError(())) | |
35 | } | |
36 | } | |
37 | } | |
38 | ||
39 | /// Prepares a key for decryption. | |
40 | /// | |
41 | /// # Failure | |
42 | /// | |
43 | /// Returns an error if the key is not 128, 192, or 256 bits. | |
44 | pub fn new_decrypt(key: &[u8]) -> Result<AesKey, KeyError> { | |
45 | unsafe { | |
46 | assert!(key.len() <= c_int::max_value() as usize / 8); | |
47 | ||
48 | let mut aes_key = mem::uninitialized(); | |
82fc9e21 VK |
49 | let r = ffi::AES_set_decrypt_key( |
50 | key.as_ptr() as *const _, | |
51 | key.len() as c_int * 8, | |
52 | &mut aes_key, | |
53 | ); | |
3ee932bc VK |
54 | |
55 | if r == 0 { | |
56 | Ok(AesKey(aes_key)) | |
57 | } else { | |
58 | Err(KeyError(())) | |
59 | } | |
60 | } | |
61 | } | |
62 | } | |
63 | ||
64 | /// Performs AES IGE encryption or decryption | |
65 | /// | |
66 | /// # Panics | |
67 | /// | |
68 | /// Panics if `in_` is not the same length as `out`, if that length is not a multiple of 16, or if | |
69 | /// `iv` is not at least 32 bytes. | |
70 | pub fn aes_ige(in_: &[u8], out: &mut [u8], key: &AesKey, iv: &mut [u8], mode: Mode) { | |
71 | unsafe { | |
72 | assert!(in_.len() == out.len()); | |
73 | assert!(in_.len() % ffi::AES_BLOCK_SIZE as usize == 0); | |
74 | assert!(iv.len() >= ffi::AES_BLOCK_SIZE as usize * 2); | |
75 | ||
76 | let mode = match mode { | |
77 | Mode::Encrypt => ffi::AES_ENCRYPT, | |
78 | Mode::Decrypt => ffi::AES_DECRYPT, | |
79 | }; | |
82fc9e21 VK |
80 | ffi::AES_ige_encrypt( |
81 | in_.as_ptr() as *const _, | |
82 | out.as_mut_ptr() as *mut _, | |
83 | in_.len(), | |
84 | &key.0, | |
85 | iv.as_mut_ptr() as *mut _, | |
86 | mode, | |
87 | ); | |
3ee932bc VK |
88 | } |
89 | } | |
90 | ||
91 | #[cfg(test)] | |
92 | mod test { | |
93 | use hex::FromHex; | |
94 | ||
95 | use symm::Mode; | |
96 | use super::*; | |
97 | ||
98 | // From https://www.mgp25.com/AESIGE/ | |
99 | #[test] | |
100 | fn ige_vector_1() { | |
101 | let raw_key = "000102030405060708090A0B0C0D0E0F"; | |
102 | let raw_iv = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"; | |
103 | let raw_pt = "0000000000000000000000000000000000000000000000000000000000000000"; | |
104 | let raw_ct = "1A8519A6557BE652E9DA8E43DA4EF4453CF456B4CA488AA383C79C98B34797CB"; | |
105 | ||
106 | let key = AesKey::new_encrypt(&Vec::from_hex(raw_key).unwrap()).unwrap(); | |
107 | let mut iv = Vec::from_hex(raw_iv).unwrap(); | |
108 | let pt = Vec::from_hex(raw_pt).unwrap(); | |
109 | let ct = Vec::from_hex(raw_ct).unwrap(); | |
110 | ||
111 | let mut ct_actual = vec![0; ct.len()]; | |
112 | aes_ige(&pt, &mut ct_actual, &key, &mut iv, Mode::Encrypt); | |
113 | assert_eq!(ct_actual, ct); | |
114 | ||
115 | let key = AesKey::new_decrypt(&Vec::from_hex(raw_key).unwrap()).unwrap(); | |
116 | let mut iv = Vec::from_hex(raw_iv).unwrap(); | |
117 | let mut pt_actual = vec![0; pt.len()]; | |
118 | aes_ige(&ct, &mut pt_actual, &key, &mut iv, Mode::Decrypt); | |
119 | assert_eq!(pt_actual, pt); | |
120 | } | |
121 | } |