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
54impl<'a> AeadEncryptor for AesGcm<'static> {
55 fn encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8]) {
56 assert!(input.len() == output.len());
57 assert!(!self.finished);
58 self.cipher.process(input, output);
59 let result = self.mac.input_c(output).result();
60 self.finished = true;
61 for i in 0..16 {
62 tag[i] = result[i] ^ self.end_tag[i];
63 }
64 }
65}
66
67impl<'a> AeadDecryptor for AesGcm<'static> {
68 fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
69 assert!(input.len() == output.len());
70 assert!(!self.finished);
71 self.finished = true;
72 let mut calc_tag = self.mac.input_c(input).result();
73 for i in 0..16 {
74 calc_tag[i] ^= self.end_tag[i];
75 }
76 if fixed_time_eq(&calc_tag, tag) {
77 self.cipher.process(input, output);
78 true
79 } else {
80 false
81 }
82 }
83}
84
85#[cfg(test)]
86mod test {
87 use aes::KeySize;
88 use aes_gcm::AesGcm;
89 use aead::{AeadEncryptor, AeadDecryptor};
90 use hex;
91 use std::iter::repeat;
92 fn hex_to_bytes(raw_hex: &str) -> Vec<u8> {
93 hex::FromHex::from_hex(raw_hex).ok().unwrap()
94 }
95 struct TestVector {
96 key: Vec<u8>,
97 iv: Vec<u8>,
98 plain_text: Vec<u8>,
99 cipher_text: Vec<u8>,
100 aad: Vec<u8>,
101 tag: Vec<u8>,
102 }
103
104 fn get_test_vectors()-> [TestVector; 5]{
105 [
106 TestVector {
107 key: hex_to_bytes("00000000000000000000000000000000"),
108 iv: hex_to_bytes("000000000000000000000000"),
109 plain_text: hex_to_bytes(""),
110 cipher_text: hex_to_bytes(""),
111 aad: hex_to_bytes(""),
112 tag: hex_to_bytes("58e2fccefa7e3061367f1d57a4e7455a")
113 },
114 TestVector {
115 key: hex_to_bytes("00000000000000000000000000000000"),
116 iv: hex_to_bytes("000000000000000000000000"),
117 plain_text: hex_to_bytes("00000000000000000000000000000000"),
118 cipher_text: hex_to_bytes("0388dace60b6a392f328c2b971b2fe78"),
119 aad: hex_to_bytes(""),
120 tag: hex_to_bytes("ab6e47d42cec13bdf53a67b21257bddf")
121 },
122 TestVector {
123 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308"),
124 iv: hex_to_bytes("cafebabefacedbaddecaf888"),
125 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
126 cipher_text: hex_to_bytes("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091"),
127 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
128 tag: hex_to_bytes("5bc94fbc3221a5db94fae95ae7121a47")
129 },
130 TestVector {
131 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c"),
132 iv: hex_to_bytes("cafebabefacedbaddecaf888"),
133 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
134 cipher_text: hex_to_bytes("3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710"),
135 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
136 tag: hex_to_bytes("2519498e80f1478f37ba55bd6d27618c")
137 },
138 TestVector {
139 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"),
140 iv: hex_to_bytes("cafebabefacedbaddecaf888"),
141 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
142 cipher_text: hex_to_bytes("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662"),
143 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
144 tag: hex_to_bytes("76fc6ece0f4e1768cddf8853bb2d551b")
145 },
146 ]
147}
148 #[test]
149 fn aes_gcm_test() {
150
151 for item in get_test_vectors().iter() {
152 let key_size = match item.key.len() {
153 16 => KeySize::KeySize128,
154 24 => KeySize::KeySize192,
155 32 => KeySize::KeySize256,
156 _ => unreachable!()
157 };
158 let mut cipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]);
159 let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
160
161 let mut out_tag: Vec<u8> = repeat(0).take(16).collect();
162
163 cipher.encrypt(&item.plain_text[..], &mut out[..],&mut out_tag[..]);
164 assert_eq!(out, item.cipher_text);
165 assert_eq!(out_tag, item.tag);
166 }
167 }
168
169 #[test]
170 fn aes_gcm_decrypt_test() {
171
172 for item in get_test_vectors().iter() {
173 let key_size = match item.key.len() {
174 16 => KeySize::KeySize128,
175 24 => KeySize::KeySize192,
176 32 => KeySize::KeySize256,
177 _ => unreachable!()
178 };
179 let mut decipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]);
180 let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
181
182 let result = decipher.decrypt(&item.cipher_text[..], &mut out[..], &item.tag[..]);
183 assert_eq!(out, item.plain_text);
184 assert!(result);
185 }
186 }
187 #[test]
188 fn aes_gcm_decrypt_fail_test() {
189
190 for item in get_test_vectors().iter() {
191 let key_size = match item.key.len() {
192 16 => KeySize::KeySize128,
193 24 => KeySize::KeySize192,
194 32 => KeySize::KeySize256,
195 _ => unreachable!()
196 };
197 let mut decipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]);
198 let tag: Vec<u8> = repeat(0).take(16).collect();
199 let mut out1: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
200 let out2: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
201 let result = decipher.decrypt(&item.cipher_text[..], &mut out1[..], &tag[..]);
202 assert_eq!(out1, out2);
203 assert!(!result);
204 }
205 }
206
207}
208
209#[cfg(all(test, feature = "with-bench"))]
210mod bench {
211 use test::Bencher;
212 use aes::KeySize;
213 use aes_gcm::AesGcm;
214 use aead::{AeadEncryptor, AeadDecryptor};
215 use hex::FromHex;
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}