1 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4 // option. This file may not be copied, modified, or distributed
5 // except according to those terms.
6 
7 use aes::{ctr, KeySize};
8 use aead::{AeadEncryptor,AeadDecryptor};
9 use cryptoutil::copy_memory;
10 use symmetriccipher::SynchronousStreamCipher;
11 use ghash::{Ghash};
12 use util::fixed_time_eq;
13 
14 pub struct AesGcm<'a> {
15     cipher: Box<SynchronousStreamCipher + 'a>,
16     mac: Ghash,
17     finished: bool,
18     end_tag: [u8; 16]
19 }
20 
21 impl<'a> AesGcm<'a> {
new(key_size: KeySize, key: &[u8], nonce: &[u8], aad: &[u8]) -> AesGcm<'a>22     pub fn new (key_size: KeySize, key: &[u8], nonce: &[u8], aad: &[u8]) -> AesGcm<'a> {
23         assert!(key.len() == 16 || key.len() == 24 || key.len() == 32);
24         assert!(nonce.len() == 12);
25 
26         // GCM technically differs from CTR mode in how role overs are handled
27         // GCM only touches the right most 4 bytes while CTR roles all 16 over
28         // when the iv is only 96 bits (12 bytes) then 4 bytes of zeros are
29         // appended to it meaning you have to encrypt 2^37 bytes (256 gigabytes)
30         // of data before a difference crops up.
31         // The GCM handles nonces of other lengths by hashing them once with ghash
32         // this would cause the roleover behavior to potentially be triggered much
33         // earlier preventing the use of generic CTR mode.
34 
35         let mut iv = [0u8; 16];
36         copy_memory(nonce, &mut iv);
37         iv[15] = 1u8;
38         let mut cipher = ctr(key_size,key,&iv);
39         let temp_block = [0u8; 16];
40         let mut final_block = [0u8; 16];
41         cipher.process(&temp_block, &mut final_block);
42         let mut hash_key =  [0u8; 16];
43         let mut encryptor = ctr(key_size,key,&temp_block);
44         encryptor.process(&temp_block, &mut hash_key);
45         AesGcm {
46             cipher: cipher,
47             mac:  Ghash::new(&hash_key).input_a(aad),
48             finished: false,
49             end_tag: final_block
50         }
51     }
52 
53 }
54 
55 impl<'a> AeadEncryptor for AesGcm<'static> {
encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8])56     fn encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8]) {
57         assert!(input.len() == output.len());
58         assert!(!self.finished);
59         self.cipher.process(input, output);
60         let result = self.mac.input_c(output).result();
61         self.finished = true;
62         for i in 0..16 {
63             tag[i] = result[i] ^ self.end_tag[i];
64         }
65     }
66 }
67 
68 impl<'a> AeadDecryptor for AesGcm<'static> {
decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool69     fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8])  -> bool {
70         assert!(input.len() == output.len());
71         assert!(!self.finished);
72         self.finished = true;
73         let mut calc_tag = self.mac.input_c(input).result();
74         for i in 0..16 {
75             calc_tag[i] ^= self.end_tag[i];
76         }
77         if fixed_time_eq(&calc_tag, tag) {
78             self.cipher.process(input, output);
79             true
80         } else {
81             false
82         }
83     }
84 }
85 
86 #[cfg(test)]
87 mod test {
88     use aes::KeySize;
89     use aes_gcm::AesGcm;
90     use aead::{AeadEncryptor, AeadDecryptor};
91     use serialize::hex::FromHex;
92     use std::iter::repeat;
hex_to_bytes(raw_hex: &str) -> Vec<u8>93     fn hex_to_bytes(raw_hex: &str) -> Vec<u8> {
94         raw_hex.from_hex().ok().unwrap()
95     }
96     struct TestVector {
97                 key:  Vec<u8>,
98                 iv:  Vec<u8>,
99                 plain_text: Vec<u8>,
100                 cipher_text:  Vec<u8>,
101                 aad: Vec<u8>,
102                 tag:  Vec<u8>,
103             }
104 
get_test_vectors()-> [TestVector; 5]105     fn get_test_vectors()-> [TestVector; 5]{
106       [
107         TestVector {
108                 key: hex_to_bytes("00000000000000000000000000000000"),
109                 iv: hex_to_bytes("000000000000000000000000"),
110                 plain_text: hex_to_bytes(""),
111                 cipher_text: hex_to_bytes(""),
112                 aad: hex_to_bytes(""),
113                 tag: hex_to_bytes("58e2fccefa7e3061367f1d57a4e7455a")
114             },
115             TestVector {
116                 key: hex_to_bytes("00000000000000000000000000000000"),
117                 iv: hex_to_bytes("000000000000000000000000"),
118                 plain_text: hex_to_bytes("00000000000000000000000000000000"),
119                 cipher_text: hex_to_bytes("0388dace60b6a392f328c2b971b2fe78"),
120                 aad: hex_to_bytes(""),
121                 tag: hex_to_bytes("ab6e47d42cec13bdf53a67b21257bddf")
122             },
123             TestVector {
124                 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308"),
125                 iv: hex_to_bytes("cafebabefacedbaddecaf888"),
126                 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
127                 cipher_text: hex_to_bytes("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091"),
128                 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
129                 tag: hex_to_bytes("5bc94fbc3221a5db94fae95ae7121a47")
130             },
131             TestVector {
132                 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c"),
133                 iv: hex_to_bytes("cafebabefacedbaddecaf888"),
134                 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
135                 cipher_text: hex_to_bytes("3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710"),
136                 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
137                 tag: hex_to_bytes("2519498e80f1478f37ba55bd6d27618c")
138             },
139             TestVector {
140                 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"),
141                 iv: hex_to_bytes("cafebabefacedbaddecaf888"),
142                 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
143                 cipher_text: hex_to_bytes("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662"),
144                 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
145                 tag: hex_to_bytes("76fc6ece0f4e1768cddf8853bb2d551b")
146             },
147     ]
148 }
149     #[test]
aes_gcm_test()150     fn aes_gcm_test() {
151 
152         for item in get_test_vectors().iter() {
153             let key_size = match item.key.len() {
154                 16 => KeySize::KeySize128,
155                 24 => KeySize::KeySize192,
156                 32 => KeySize::KeySize256,
157                 _ => unreachable!()
158             };
159             let mut cipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]);
160             let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
161 
162             let mut out_tag: Vec<u8> = repeat(0).take(16).collect();
163 
164             cipher.encrypt(&item.plain_text[..], &mut out[..],&mut out_tag[..]);
165             assert_eq!(out, item.cipher_text);
166             assert_eq!(out_tag, item.tag);
167         }
168     }
169 
170     #[test]
aes_gcm_decrypt_test()171     fn aes_gcm_decrypt_test() {
172 
173         for item in get_test_vectors().iter() {
174             let key_size = match item.key.len() {
175                 16 => KeySize::KeySize128,
176                 24 => KeySize::KeySize192,
177                 32 => KeySize::KeySize256,
178                 _ => unreachable!()
179             };
180             let mut decipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]);
181             let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
182 
183             let result = decipher.decrypt(&item.cipher_text[..], &mut out[..], &item.tag[..]);
184             assert_eq!(out, item.plain_text);
185             assert!(result);
186         }
187     }
188     #[test]
aes_gcm_decrypt_fail_test()189     fn aes_gcm_decrypt_fail_test() {
190 
191         for item in get_test_vectors().iter() {
192             let key_size = match item.key.len() {
193                 16 => KeySize::KeySize128,
194                 24 => KeySize::KeySize192,
195                 32 => KeySize::KeySize256,
196                 _ => unreachable!()
197             };
198             let mut decipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]);
199             let tag: Vec<u8> = repeat(0).take(16).collect();
200             let mut out1: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
201             let out2: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
202             let result = decipher.decrypt(&item.cipher_text[..], &mut out1[..], &tag[..]);
203             assert_eq!(out1, out2);
204             assert!(!result);
205         }
206     }
207 
208 }
209 
210 #[cfg(all(test, feature = "with-bench"))]
211 mod bench {
212     use test::Bencher;
213     use aes::KeySize;
214     use aes_gcm::AesGcm;
215     use aead::{AeadEncryptor, AeadDecryptor};
216 
217     #[bench]
gsm_10(bh: & mut Bencher)218     pub fn gsm_10(bh: & mut Bencher) {
219     	let input = [1u8; 10];
220     	let aad = [3u8; 10];
221     	bh.iter( || {
222 	        let mut cipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad);
223 	        let mut decipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad);
224 
225 	        let mut output = [0u8; 10];
226 	        let mut tag = [0u8; 16];
227 	        let mut output2 = [0u8; 10];
228             cipher.encrypt(&input, &mut output, &mut tag);
229             decipher.decrypt(&output, &mut output2, &tag);
230 
231         });
232         bh.bytes = 10u64;
233     }
234 
235 
236     #[bench]
gsm_1k(bh: & mut Bencher)237     pub fn gsm_1k(bh: & mut Bencher) {
238     	let input = [1u8; 1024];
239     	let aad = [3u8; 1024];
240     	bh.iter( || {
241         let mut cipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad);
242         let mut decipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad);
243 
244         let mut output = [0u8; 1024];
245         let mut tag = [0u8; 16];
246         let mut output2 = [0u8; 1024];
247 
248             cipher.encrypt(&input, &mut output, &mut tag);
249             decipher.decrypt(&output, &mut output2, &tag);
250         });
251     	bh.bytes = 1024u64;
252 
253     }
254 
255     #[bench]
gsm_64k(bh: & mut Bencher)256     pub fn gsm_64k(bh: & mut Bencher) {
257     	let input = [1u8; 65536];
258     	let aad = [3u8; 65536];
259     	  bh.iter( || {
260         let mut cipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad);
261         let mut decipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad);
262 
263         let mut output = [0u8; 65536];
264         let mut tag = [0u8; 16];
265         let mut output2 = [0u8; 65536];
266 
267             cipher.encrypt(&input, &mut output, &mut tag);
268             decipher.decrypt(&output, &mut output2, &tag);
269 
270         });
271     	   bh.bytes = 65536u64;
272 
273     }
274 }
275