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 /// This is an implementaiton of GHASH as used in GCM [1].
8 /// It is defined as GHASH(H, A, C), where H is a MAC key, A is authenticated data,
9 /// and C is the ciphertext. GHASH can be used as a keyed MAC, if C is left empty.
10 ///
11 /// In order to ensure constant time computation it uses the approach described in [2] section 5.2.
12 ///
13 /// [1] - "The Galois/Counter Mode of Operation (GCM)" - David A. McGrew and John Viega
14 ///       <http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf>
15 /// [2] - "Faster and Timing-Attack Resistant AES-GCM" - Emilia Käsper and Peter Schwabe
16 ///       <http://cryptojedi.org/papers/aesbs-20090616.pdf>
17 
18 use std::ops::BitXor;
19 use std::mem;
20 use cryptoutil::copy_memory;
21 
22 use cryptoutil::{read_u32_be, write_u32_be};
23 use mac::{Mac, MacResult};
24 use simd;
25 
26 // A struct representing an element in GF(2^128)
27 // x^0 is the msb, while x^127 is the lsb
28 #[derive(Clone, Copy)]
29 struct Gf128 { d: simd::u32x4 }
30 
31 impl Gf128 {
new(a: u32, b: u32, c: u32, d: u32) -> Gf12832     fn new(a: u32, b: u32, c: u32, d: u32) -> Gf128 {
33         Gf128 { d: simd::u32x4(a, b, c, d) }
34     }
35 
from_bytes(bytes: &[u8]) -> Gf12836     fn from_bytes(bytes: &[u8]) -> Gf128 {
37         assert!(bytes.len() == 16);
38         let d = read_u32_be(&bytes[0..4]);
39         let c = read_u32_be(&bytes[4..8]);
40         let b = read_u32_be(&bytes[8..12]);
41         let a = read_u32_be(&bytes[12..16]);
42         Gf128::new(a, b, c, d)
43     }
44 
to_bytes(&self) -> [u8; 16]45     fn to_bytes(&self) -> [u8; 16] {
46         let simd::u32x4(a, b, c, d) = self.d;
47         let mut result: [u8; 16] = unsafe { mem::uninitialized() };
48 
49         write_u32_be(&mut result[0..4], d);
50         write_u32_be(&mut result[4..8], c);
51         write_u32_be(&mut result[8..12], b);
52         write_u32_be(&mut result[12..16], a);
53 
54         result
55     }
56 
57     // Multiply the element by x modulo x^128
58     // This is equivalent to a rightshift in the bit representation
times_x(self) -> Gf12859     fn times_x(self) -> Gf128 {
60         let simd::u32x4(a, b, c, d) = self.d;
61         Gf128::new(a >> 1 | b << 31, b >> 1 | c << 31, c >> 1 |  d << 31, d >> 1)
62     }
63 
64     // Multiply the element by x modulo x^128 + x^7 + x^2 + x + 1
65     // This is equivalent to a rightshift, followed by an XOR iff the lsb was set,
66     // in the bit representation
times_x_reduce(self) -> Gf12867     fn times_x_reduce(self) -> Gf128 {
68         let r = Gf128::new(0, 0, 0, 0b1110_0001 << 24);
69         self.cond_xor(r, self.times_x())
70     }
71 
72     // Adds y, and multiplies with h using a precomputed array of the values h * x^0 to h * x^127
add_and_mul(&mut self, y: Gf128, hs: &[Gf128; 128])73     fn add_and_mul(&mut self, y: Gf128, hs: &[Gf128; 128]) {
74         *self = *self ^ y;
75         let mut x = mem::replace(self, Gf128::new(0, 0, 0, 0));
76 
77         for &y in hs.iter().rev() {
78             *self = x.cond_xor(y, *self);
79             x = x.times_x();
80         }
81     }
82 
83     // This XORs the value of y with x if the LSB of self is set, otherwise y is returned
cond_xor(self, x: Gf128, y: Gf128) -> Gf12884     fn cond_xor(self, x: Gf128, y: Gf128) -> Gf128 {
85         use simd::SimdExt;
86         let lsb = simd::u32x4(1, 0, 0, 0);
87         let simd::u32x4(m, _, _, _) = (self.d & lsb).simd_eq(lsb);
88         let mask = simd::u32x4(m, m, m, m);
89         Gf128 { d: (x.d & mask) ^ y.d }
90     }
91 }
92 
93 impl BitXor for Gf128 {
94     type Output = Gf128;
95 
bitxor(self, rhs: Gf128) -> Gf12896     fn bitxor(self, rhs: Gf128) -> Gf128 {
97         Gf128 { d: self.d ^ rhs.d }
98     }
99 }
100 
101 /// A structure representing the state of a GHASH computation
102 #[derive(Copy)]
103 pub struct Ghash {
104     hs: [Gf128; 128],
105     state: Gf128,
106     a_len: usize,
107     rest: Option<[u8; 16]>,
108     finished: bool
109 }
110 
clone(&self) -> Ghash111 impl Clone for Ghash { fn clone(&self) -> Ghash { *self } }
112 
113 /// A structure representing the state of a GHASH computation, after input for C was provided
114 #[derive(Copy)]
115 pub struct GhashWithC {
116     hs: [Gf128; 128],
117     state: Gf128,
118     a_len: usize,
119     c_len: usize,
120     rest: Option<[u8; 16]>
121 }
122 
clone(&self) -> GhashWithC123 impl Clone for GhashWithC { fn clone(&self) -> GhashWithC { *self } }
124 
update(state: &mut Gf128, len: &mut usize, data: &[u8], srest: &mut Option<[u8; 16]>, hs: &[Gf128; 128])125 fn update(state: &mut Gf128, len: &mut usize, data: &[u8], srest: &mut Option<[u8; 16]>,
126           hs: &[Gf128; 128]) {
127     let rest_len = *len % 16;
128     let data_len = data.len();
129     *len += data_len;
130 
131     let data = match srest.take() {
132         None => data,
133         Some(mut rest) => {
134             if 16 - rest_len > data_len {
135                 copy_memory(data, &mut rest[rest_len..]);
136                 *srest = Some(rest);
137                 return;
138             }
139 
140             let (fill, data) = data.split_at(16 - rest_len);
141             copy_memory(fill, &mut rest[rest_len..]);
142             state.add_and_mul(Gf128::from_bytes(&rest), hs);
143             data
144         }
145     };
146 
147     let (data, rest) = data.split_at(data_len - data_len % 16);
148 
149     for chunk in data.chunks(16) {
150         let x = Gf128::from_bytes(chunk);
151         state.add_and_mul(x, hs);
152     }
153 
154     if rest.len() != 0 {
155         let mut tmp = [0; 16];
156         copy_memory(rest, &mut tmp);
157         *srest = Some(tmp);
158     }
159 }
160 
161 impl Ghash {
162     /// Creates a new GHASH state, with `h` as the key
163     #[inline]
new(h: &[u8]) -> Ghash164     pub fn new(h: &[u8]) -> Ghash {
165         assert!(h.len() == 16);
166         let mut table: [Gf128; 128] = unsafe { mem::uninitialized() };
167 
168         // Precompute values for h * x^0 to h * x^127
169         let mut h = Gf128::from_bytes(h);
170         for poly in table.iter_mut() {
171             *poly = h;
172             h = h.times_x_reduce();
173         }
174 
175         Ghash {
176             hs: table,
177             state: Gf128::new(0, 0, 0, 0),
178             a_len: 0,
179             rest: None,
180             finished: false
181         }
182     }
183 
flush(&mut self)184     fn flush(&mut self) {
185         for rest in self.rest.take().iter() {
186             self.state.add_and_mul(Gf128::from_bytes(rest), &self.hs);
187         }
188     }
189 
190     /// Feeds data for GHASH's A input
191     #[inline]
input_a(mut self, a: &[u8]) -> Ghash192     pub fn input_a(mut self, a: &[u8]) -> Ghash {
193         assert!(!self.finished);
194         update(&mut self.state, &mut self.a_len, a, &mut self.rest, &self.hs);
195         self
196     }
197 
198     /// Feeds data for GHASH's C input
199     #[inline]
input_c(mut self, c: &[u8]) -> GhashWithC200     pub fn input_c(mut self, c: &[u8]) -> GhashWithC {
201         assert!(!self.finished);
202         self.flush();
203 
204         let mut c_len = 0;
205         update(&mut self.state, &mut c_len, c, &mut self.rest, &self.hs);
206 
207         let Ghash { hs, state, a_len, rest, .. } = self;
208         GhashWithC {
209             hs: hs,
210             state: state,
211             a_len: a_len,
212             c_len: c_len,
213             rest: rest
214         }
215     }
216 
217     /// Retrieve the digest result
218     #[inline]
result(mut self) -> [u8; 16]219     pub fn result(mut self) -> [u8; 16] {
220         if !self.finished {
221             self.flush();
222 
223             let a_len = self.a_len as u64 * 8;
224             let lens = Gf128::new(0, 0, a_len as u32, (a_len >> 32) as u32);
225             self.state.add_and_mul(lens, &self.hs);
226 
227             self.finished = true;
228         }
229 
230         self.state.to_bytes()
231     }
232 }
233 
234 impl GhashWithC {
235     /// Feeds data for GHASH's C input
236     #[inline]
input_c(mut self, c: &[u8]) -> GhashWithC237     pub fn input_c(mut self, c: &[u8]) -> GhashWithC {
238         update(&mut self.state, &mut self.c_len, c, &mut self.rest, &self.hs);
239         self
240     }
241 
242     /// Retrieve the digest result
243     #[inline]
result(mut self) -> [u8; 16]244     pub fn result(mut self) -> [u8; 16] {
245         for rest in self.rest.take().iter() {
246             self.state.add_and_mul(Gf128::from_bytes(rest), &self.hs);
247         }
248 
249         let a_len = self.a_len as u64 * 8;
250         let c_len = self.c_len as u64 * 8;
251         let lens = Gf128::new(c_len as u32, (c_len >> 32) as u32,
252                               a_len as u32, (a_len >> 32) as u32);
253         self.state.add_and_mul(lens, &self.hs);
254 
255         self.state.to_bytes()
256     }
257 }
258 
259 impl Mac for Ghash {
input(&mut self, data: &[u8])260     fn input(&mut self, data: &[u8]) {
261         assert!(!self.finished);
262         update(&mut self.state, &mut self.a_len, data, &mut self.rest, &self.hs);
263     }
264 
reset(&mut self)265     fn reset(&mut self) {
266         self.state = Gf128::new(0, 0, 0, 0);
267         self.a_len = 0;
268         self.rest = None;
269         self.finished = false;
270     }
271 
result(&mut self) -> MacResult272     fn result(&mut self) -> MacResult {
273         let mut mac = [0u8; 16];
274         self.raw_result(&mut mac[..]);
275         MacResult::new(&mac[..])
276     }
277 
raw_result(&mut self, output: &mut [u8])278     fn raw_result(&mut self, output: &mut [u8]) {
279         assert!(output.len() >= 16);
280         if !self.finished {
281             self.flush();
282 
283             let a_len = self.a_len as u64 * 8;
284             let lens = Gf128::new(0, 0, a_len as u32, (a_len >> 32) as u32);
285             self.state.add_and_mul(lens, &self.hs);
286 
287             self.finished = true;
288         }
289 
290         copy_memory(&self.state.to_bytes(), output);
291     }
292 
output_bytes(&self) -> usize293     fn output_bytes(&self) -> usize { 16 }
294 }
295 
296 #[cfg(test)]
297 mod test {
298     use ghash::Ghash;
299 
300     // Test cases from:
301     // <http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf>
302     static CASES: &'static [(&'static [u8], &'static [u8], &'static [u8], &'static [u8])] = &[
303         // Format: (H, A, C, GHASH(H, A, C))
304 
305         // Test 1
306         (&[0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b,
307            0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e],
308          &[],
309          &[],
310          &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
312 
313         // Test 2
314         (&[0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b,
315            0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e],
316          &[],
317          &[0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
318            0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78],
319          &[0xf3, 0x8c, 0xbb, 0x1a, 0xd6, 0x92, 0x23, 0xdc,
320            0xc3, 0x45, 0x7a, 0xe5, 0xb6, 0xb0, 0xf8, 0x85]),
321 
322         // Test 3
323         (&[0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d,
324            0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78],
325          &[],
326          &[0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
327            0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
328            0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
329            0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
330            0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85],
331          &[0x7f, 0x1b, 0x32, 0xb8, 0x1b, 0x82, 0x0d, 0x02,
332            0x61, 0x4f, 0x88, 0x95, 0xac, 0x1d, 0x4e, 0xac]),
333 
334         // Test 4
335         (&[0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d,
336            0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78],
337          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
338            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
339          &[0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
340            0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
341            0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
342            0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
343            0x3d, 0x58, 0xe0, 0x91],
344          &[0x69, 0x8e, 0x57, 0xf7, 0x0e, 0x6e, 0xcc, 0x7f,
345            0xd9, 0x46, 0x3b, 0x72, 0x60, 0xa9, 0xae, 0x5f]),
346 
347         // Test 5
348         (&[0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d,
349            0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78],
350          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
351            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
352          &[0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a,
353            0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9,
354            0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09,
355            0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
356            0xc2, 0x3f, 0x45, 0x98],
357          &[0xdf, 0x58, 0x6b, 0xb4, 0xc2, 0x49, 0xb9, 0x2c,
358            0xb6, 0x92, 0x28, 0x77, 0xe4, 0x44, 0xd3, 0x7b]),
359 
360         // Test 6
361         (&[0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d,
362            0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78],
363          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
364            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
365          &[0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f,
366            0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c,
367            0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc,
368            0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
369            0x4c, 0x34, 0xae, 0xe5],
370          &[0x1c, 0x5a, 0xfe, 0x97, 0x60, 0xd3, 0x93, 0x2f,
371            0x3c, 0x9a, 0x87, 0x8a, 0xac, 0x3d, 0xc3, 0xde]),
372 
373         // Test 7
374         (&[0xaa, 0xe0, 0x69, 0x92, 0xac, 0xbf, 0x52, 0xa3,
375            0xe8, 0xf4, 0xa9, 0x6e, 0xc9, 0x30, 0x0b, 0xd7],
376          &[],
377          &[],
378          &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
380 
381         // Test 8
382         (&[0xaa, 0xe0, 0x69, 0x92, 0xac, 0xbf, 0x52, 0xa3,
383            0xe8, 0xf4, 0xa9, 0x6e, 0xc9, 0x30, 0x0b, 0xd7],
384          &[],
385          &[0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
386            0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00],
387          &[0xe2, 0xc6, 0x3f, 0x0a, 0xc4, 0x4a, 0xd0, 0xe0,
388            0x2e, 0xfa, 0x05, 0xab, 0x67, 0x43, 0xd4, 0xce]),
389 
390         // Test 9
391         (&[0x46, 0x69, 0x23, 0xec, 0x9a, 0xe6, 0x82, 0x21,
392            0x4f, 0x2c, 0x08, 0x2b, 0xad, 0xb3, 0x92, 0x49],
393          &[],
394          &[0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a,
395            0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4,
396            0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61,
397            0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
398            0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56],
399          &[0x51, 0x11, 0x0d, 0x40, 0xf6, 0xc8, 0xff, 0xf0,
400            0xeb, 0x1a, 0xe3, 0x34, 0x45, 0xa8, 0x89, 0xf0]),
401 
402         // Test 10
403         (&[0x46, 0x69, 0x23, 0xec, 0x9a, 0xe6, 0x82, 0x21,
404            0x4f, 0x2c, 0x08, 0x2b, 0xad, 0xb3, 0x92, 0x49],
405          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
406            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
407          &[0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a,
408            0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4,
409            0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61,
410            0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
411            0xcc, 0xda, 0x27, 0x10],
412          &[0xed, 0x2c, 0xe3, 0x06, 0x2e, 0x4a, 0x8e, 0xc0,
413            0x6d, 0xb8, 0xb4, 0xc4, 0x90, 0xe8, 0xa2, 0x68]),
414 
415         // Test 11
416         (&[0x46, 0x69, 0x23, 0xec, 0x9a, 0xe6, 0x82, 0x21,
417            0x4f, 0x2c, 0x08, 0x2b, 0xad, 0xb3, 0x92, 0x49],
418          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
419            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
420          &[0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32,
421            0x4d, 0xb8, 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 0x83, 0x47, 0x28, 0x0f,
422            0xc4, 0x50, 0x70, 0x57, 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 0xc6, 0x65,
423            0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
424            0xa0, 0xf0, 0x62, 0xf7],
425          &[0x1e, 0x6a, 0x13, 0x38, 0x06, 0x60, 0x78, 0x58,
426            0xee, 0x80, 0xea, 0xf2, 0x37, 0x06, 0x40, 0x89]),
427 
428         // Test 12
429         (&[0x46, 0x69, 0x23, 0xec, 0x9a, 0xe6, 0x82, 0x21,
430            0x4f, 0x2c, 0x08, 0x2b, 0xad, 0xb3, 0x92, 0x49],
431          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
432            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
433          &[0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc,
434            0xf9, 0xff, 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 0x6e, 0xf7, 0xb7, 0x98,
435            0x28, 0x66, 0x6e, 0x45, 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 0xe2, 0xf0,
436            0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
437            0xe9, 0xb7, 0x37, 0x3b],
438          &[0x82, 0x56, 0x7f, 0xb0, 0xb4, 0xcc, 0x37, 0x18,
439            0x01, 0xea, 0xde, 0xc0, 0x05, 0x96, 0x8e, 0x94]),
440 
441         // Test 13
442         (&[0xdc, 0x95, 0xc0, 0x78, 0xa2, 0x40, 0x89, 0x89,
443            0xad, 0x48, 0xa2, 0x14, 0x92, 0x84, 0x20, 0x87],
444          &[],
445          &[],
446          &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
448 
449         // Test 14
450         (&[0xdc, 0x95, 0xc0, 0x78, 0xa2, 0x40, 0x89, 0x89,
451            0xad, 0x48, 0xa2, 0x14, 0x92, 0x84, 0x20, 0x87],
452          &[],
453          &[0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
454            0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18],
455          &[0x83, 0xde, 0x42, 0x5c, 0x5e, 0xdc, 0x5d, 0x49,
456            0x8f, 0x38, 0x2c, 0x44, 0x10, 0x41, 0xca, 0x92]),
457 
458         // Test 15
459         (&[0xac, 0xbe, 0xf2, 0x05, 0x79, 0xb4, 0xb8, 0xeb,
460            0xce, 0x88, 0x9b, 0xac, 0x87, 0x32, 0xda, 0xd7],
461          &[],
462          &[0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
463            0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
464            0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
465            0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
466            0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad],
467          &[0x4d, 0xb8, 0x70, 0xd3, 0x7c, 0xb7, 0x5f, 0xcb,
468            0x46, 0x09, 0x7c, 0x36, 0x23, 0x0d, 0x16, 0x12]),
469 
470         // Test 16
471         (&[0xac, 0xbe, 0xf2, 0x05, 0x79, 0xb4, 0xb8, 0xeb,
472            0xce, 0x88, 0x9b, 0xac, 0x87, 0x32, 0xda, 0xd7],
473          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
474            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
475          &[0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
476            0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
477            0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
478            0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
479            0xbc, 0xc9, 0xf6, 0x62],
480          &[0x8b, 0xd0, 0xc4, 0xd8, 0xaa, 0xcd, 0x39, 0x1e,
481            0x67, 0xcc, 0xa4, 0x47, 0xe8, 0xc3, 0x8f, 0x65]),
482 
483         // Test 17
484         (&[0xac, 0xbe, 0xf2, 0x05, 0x79, 0xb4, 0xb8, 0xeb,
485            0xce, 0x88, 0x9b, 0xac, 0x87, 0x32, 0xda, 0xd7],
486          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
487            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
488          &[0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98,
489            0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7,
490            0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c,
491            0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
492            0xf4, 0x7c, 0x9b, 0x1f],
493          &[0x75, 0xa3, 0x42, 0x88, 0xb8, 0xc6, 0x8f, 0x81,
494            0x1c, 0x52, 0xb2, 0xe9, 0xa2, 0xf9, 0x7f, 0x63]),
495 
496         // Test 18
497         (&[0xac, 0xbe, 0xf2, 0x05, 0x79, 0xb4, 0xb8, 0xeb,
498            0xce, 0x88, 0x9b, 0xac, 0x87, 0x32, 0xda, 0xd7],
499          &[0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
500            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2],
501          &[0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e,
502            0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f,
503            0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3,
504            0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
505            0x44, 0xae, 0x7e, 0x3f],
506          &[0xd5, 0xff, 0xcf, 0x6f, 0xc5, 0xac, 0x4d, 0x69,
507            0x72, 0x21, 0x87, 0x42, 0x1a, 0x7f, 0x17, 0x0b])
508     ];
509 
510     #[test]
hash()511     fn hash() {
512         for &(h, a, c, g) in CASES.iter() {
513             let ghash = Ghash::new(h);
514             assert_eq!(&ghash.input_a(a).input_c(c).result()[..], g);
515         }
516     }
517 
518     #[test]
split_input()519     fn split_input() {
520         for &(h, a, c, g) in CASES.iter() {
521             let ghash = Ghash::new(h);
522             let (a1, a2) = a.split_at(a.len() / 2);
523             let (c1, c2) = c.split_at(c.len() / 2);
524             assert_eq!(&ghash.input_a(a1)
525                             .input_a(a2)
526                             .input_c(c1)
527                             .input_c(c2)
528                             .result()[..], g);
529         }
530     }
531 }
532 
533 #[cfg(all(test, feature = "with-bench"))]
534 mod bench {
535     use test::Bencher;
536     use mac::Mac;
537     use ghash::Ghash;
538 
539     #[bench]
ghash_10(bh: & mut Bencher)540     pub fn ghash_10(bh: & mut Bencher) {
541         let mut mac = [0u8; 16];
542         let key     = [0u8; 16];
543         let bytes   = [1u8; 10];
544         bh.iter( || {
545             let mut ghash = Ghash::new(&key);
546             ghash.input(&bytes);
547             ghash.raw_result(&mut mac);
548         });
549         bh.bytes = bytes.len() as u64;
550     }
551 
552     #[bench]
ghash_1k(bh: & mut Bencher)553     pub fn ghash_1k(bh: & mut Bencher) {
554         let mut mac = [0u8; 16];
555         let key     = [0u8; 16];
556         let bytes   = [1u8; 1024];
557         bh.iter( || {
558             let mut ghash = Ghash::new(&key);
559             ghash.input(&bytes);
560             ghash.raw_result(&mut mac);
561         });
562         bh.bytes = bytes.len() as u64;
563     }
564 
565     #[bench]
ghash_64k(bh: & mut Bencher)566     pub fn ghash_64k(bh: & mut Bencher) {
567         let mut mac = [0u8; 16];
568         let key     = [0u8; 16];
569         let bytes   = [1u8; 65536];
570         bh.iter( || {
571             let mut ghash = Ghash::new(&key);
572             ghash.input(&bytes);
573             ghash.raw_result(&mut mac);
574         });
575         bh.bytes = bytes.len() as u64;
576     }
577 }
578