1use aes::{ctr, KeySize};
8use aead::{AeadEncryptor,AeadDecryptor};
9use cryptoutil::copy_memory;
10use symmetriccipher::SynchronousStreamCipher;
11use ghash::{Ghash};
12use util::fixed_time_eq;
13
14pub struct AesGcm<'a> {
15 cipher: Box<SynchronousStreamCipher + 'a>,
16 mac: Ghash,
17 finished: bool,
18 end_tag: [u8; 16]
19}
20
21impl<'a> 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 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
55impl<'a> AeadEncryptor for AesGcm<'static> {
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
68impl<'a> AeadDecryptor for AesGcm<'static> {
69 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)]
87mod 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;
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
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]
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]
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]
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"))]
211mod bench {
212 use test::Bencher;
213 use aes::KeySize;
214 use aes_gcm::AesGcm;
215 use aead::{AeadEncryptor, AeadDecryptor};
216
217 #[bench]
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]
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]
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}