crypto/
ghash.rs

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
18use std::ops::BitXor;
19use std::mem;
20use cryptoutil::copy_memory;
21
22use cryptoutil::{read_u32_be, write_u32_be};
23use mac::{Mac, MacResult};
24use 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)]
29struct Gf128 { d: simd::u32x4 }
30
31impl Gf128 {
32    fn new(a: u32, b: u32, c: u32, d: u32) -> Gf128 {
33        Gf128 { d: simd::u32x4(a, b, c, d) }
34    }
35
36    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
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
59    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
67    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
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
84    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
93impl BitXor for Gf128 {
94    type Output = Gf128;
95
96    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)]
103pub struct Ghash {
104    hs: [Gf128; 128],
105    state: Gf128,
106    a_len: usize,
107    rest: Option<[u8; 16]>,
108    finished: bool
109}
110
111impl 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)]
115pub struct GhashWithC {
116    hs: [Gf128; 128],
117    state: Gf128,
118    a_len: usize,
119    c_len: usize,
120    rest: Option<[u8; 16]>
121}
122
123impl Clone for GhashWithC { fn clone(&self) -> GhashWithC { *self } }
124
125fn 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
161impl Ghash {
162    /// Creates a new GHASH state, with `h` as the key
163    #[inline]
164    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
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]
192    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]
200    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]
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
234impl GhashWithC {
235    /// Feeds data for GHASH's C input
236    #[inline]
237    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]
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
259impl Mac for Ghash {
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
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
272    fn result(&mut self) -> MacResult {
273        let mut mac = [0u8; 16];
274        self.raw_result(&mut mac[..]);
275        MacResult::new(&mac[..])
276    }
277
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
293    fn output_bytes(&self) -> usize { 16 }
294}
295
296#[cfg(test)]
297mod 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]
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]
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"))]
534mod bench {
535    use test::Bencher;
536    use mac::Mac;
537    use ghash::Ghash;
538
539    #[bench]
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]
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]
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}