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