1use std::iter::repeat;
8use cryptoutil::{copy_memory, read_u64v_le, write_u64v_le};
9use digest::Digest;
10use mac::{Mac, MacResult};
11use util::secure_memset;
12
13static IV : [u64; 8] = [
14 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
15 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
16 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
17 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
18];
19
20static SIGMA : [[usize; 16]; 12] = [
21 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ],
22 [ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ],
23 [ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ],
24 [ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ],
25 [ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ],
26 [ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ],
27 [ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ],
28 [ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ],
29 [ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ],
30 [ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 ],
31 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ],
32 [ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ],
33];
34
35const BLAKE2B_BLOCKBYTES : usize = 128;
36const BLAKE2B_OUTBYTES : usize = 64;
37const BLAKE2B_KEYBYTES : usize = 64;
38const BLAKE2B_SALTBYTES : usize = 16;
39const BLAKE2B_PERSONALBYTES : usize = 16;
40
41#[derive(Copy)]
42pub struct Blake2b {
43 h: [u64; 8],
44 t: [u64; 2],
45 f: [u64; 2],
46 buf: [u8; 2*BLAKE2B_BLOCKBYTES],
47 buflen: usize,
48 key: [u8; BLAKE2B_KEYBYTES],
49 key_length: u8,
50 last_node: u8,
51 digest_length: u8,
52 computed: bool, param: Blake2bParam
54}
55
56impl Clone for Blake2b { fn clone(&self) -> Blake2b { *self } }
57
58#[derive(Copy, Clone)]
59struct Blake2bParam {
60 digest_length: u8,
61 key_length: u8,
62 fanout: u8,
63 depth: u8,
64 leaf_length: u32,
65 node_offset: u64,
66 node_depth: u8,
67 inner_length: u8,
68 reserved: [u8; 14],
69 salt: [u8; BLAKE2B_SALTBYTES],
70 personal: [u8; BLAKE2B_PERSONALBYTES],
71}
72
73macro_rules! G( ($r:expr, $i:expr, $a:expr, $b:expr, $c:expr, $d:expr, $m:expr) => ({
74 $a = $a.wrapping_add($b).wrapping_add($m[SIGMA[$r][2*$i+0]]);
75 $d = ($d ^ $a).rotate_right(32);
76 $c = $c.wrapping_add($d);
77 $b = ($b ^ $c).rotate_right(24);
78 $a = $a.wrapping_add($b).wrapping_add($m[SIGMA[$r][2*$i+1]]);
79 $d = ($d ^ $a).rotate_right(16);
80 $c = $c .wrapping_add($d);
81 $b = ($b ^ $c).rotate_right(63);
82}));
83
84macro_rules! round( ($r:expr, $v:expr, $m:expr) => ( {
85 G!($r,0,$v[ 0],$v[ 4],$v[ 8],$v[12], $m);
86 G!($r,1,$v[ 1],$v[ 5],$v[ 9],$v[13], $m);
87 G!($r,2,$v[ 2],$v[ 6],$v[10],$v[14], $m);
88 G!($r,3,$v[ 3],$v[ 7],$v[11],$v[15], $m);
89 G!($r,4,$v[ 0],$v[ 5],$v[10],$v[15], $m);
90 G!($r,5,$v[ 1],$v[ 6],$v[11],$v[12], $m);
91 G!($r,6,$v[ 2],$v[ 7],$v[ 8],$v[13], $m);
92 G!($r,7,$v[ 3],$v[ 4],$v[ 9],$v[14], $m);
93 }
94));
95
96impl Blake2b {
97 fn set_lastnode(&mut self) {
98 self.f[1] = 0xFFFFFFFFFFFFFFFF;
99 }
100
101 fn set_lastblock(&mut self) {
102 if self.last_node!=0 {
103 self.set_lastnode();
104 }
105 self.f[0] = 0xFFFFFFFFFFFFFFFF;
106 }
107
108 fn increment_counter(&mut self, inc : u64) {
109 self.t[0] += inc;
110 self.t[1] += if self.t[0] < inc { 1 } else { 0 };
111 }
112
113 fn init0(param: Blake2bParam, digest_length: u8, key: &[u8]) -> Blake2b {
114 assert!(key.len() <= BLAKE2B_KEYBYTES);
115 let mut b = Blake2b {
116 h: IV,
117 t: [0,0],
118 f: [0,0],
119 buf: [0; 2*BLAKE2B_BLOCKBYTES],
120 buflen: 0,
121 last_node: 0,
122 digest_length: digest_length,
123 computed: false,
124 key: [0; BLAKE2B_KEYBYTES],
125 key_length: key.len() as u8,
126 param: param
127 };
128 copy_memory(key, &mut b.key);
129 b
130 }
131
132 fn apply_param(&mut self) {
133 use std::io::Write;
134 use cryptoutil::WriteExt;
135
136 let mut param_bytes : [u8; 64] = [0; 64];
137 {
138 let mut writer: &mut [u8] = &mut param_bytes;
139 writer.write_u8(self.param.digest_length).unwrap();
140 writer.write_u8(self.param.key_length).unwrap();
141 writer.write_u8(self.param.fanout).unwrap();
142 writer.write_u8(self.param.depth).unwrap();
143 writer.write_u32_le(self.param.leaf_length).unwrap();
144 writer.write_u64_le(self.param.node_offset).unwrap();
145 writer.write_u8(self.param.node_depth).unwrap();
146 writer.write_u8(self.param.inner_length).unwrap();
147 writer.write_all(&self.param.reserved).unwrap();
148 writer.write_all(&self.param.salt).unwrap();
149 writer.write_all(&self.param.personal).unwrap();
150 }
151
152 let mut param_words : [u64; 8] = [0; 8];
153 read_u64v_le(&mut param_words, ¶m_bytes);
154 for (h, param_word) in self.h.iter_mut().zip(param_words.iter()) {
155 *h = *h ^ *param_word;
156 }
157 }
158
159
160 fn init_param( p: Blake2bParam, key: &[u8] ) -> Blake2b {
162 let mut b = Blake2b::init0(p, p.digest_length, key);
163 b.apply_param();
164 b
165 }
166
167 fn default_param(outlen: u8) -> Blake2bParam {
168 Blake2bParam {
169 digest_length: outlen,
170 key_length: 0,
171 fanout: 1,
172 depth: 1,
173 leaf_length: 0,
174 node_offset: 0,
175 node_depth: 0,
176 inner_length: 0,
177 reserved: [0; 14],
178 salt: [0; BLAKE2B_SALTBYTES],
179 personal: [0; BLAKE2B_PERSONALBYTES],
180 }
181 }
182
183 pub fn new(outlen: usize) -> Blake2b {
184 assert!(outlen > 0 && outlen <= BLAKE2B_OUTBYTES);
185 Blake2b::init_param(Blake2b::default_param(outlen as u8), &[])
186 }
187
188 fn apply_key(&mut self) {
189 let mut block : [u8; BLAKE2B_BLOCKBYTES] = [0; BLAKE2B_BLOCKBYTES];
190 copy_memory(&self.key[..self.key_length as usize], &mut block);
191 self.update(&block);
192 secure_memset(&mut block[..], 0);
193 }
194
195 pub fn new_keyed(outlen: usize, key: &[u8] ) -> Blake2b {
196 assert!(outlen > 0 && outlen <= BLAKE2B_OUTBYTES);
197 assert!(key.len() > 0 && key.len() <= BLAKE2B_KEYBYTES);
198
199 let param = Blake2bParam {
200 digest_length: outlen as u8,
201 key_length: key.len() as u8,
202 fanout: 1,
203 depth: 1,
204 leaf_length: 0,
205 node_offset: 0,
206 node_depth: 0,
207 inner_length: 0,
208 reserved: [0; 14],
209 salt: [0; BLAKE2B_SALTBYTES],
210 personal: [0; BLAKE2B_PERSONALBYTES],
211 };
212
213 let mut b = Blake2b::init_param(param, key);
214 b.apply_key();
215 b
216 }
217
218 fn compress(&mut self) {
219 let mut ms: [u64; 16] = [0; 16];
220 let mut vs: [u64; 16] = [0; 16];
221
222 read_u64v_le(&mut ms, &self.buf[0..BLAKE2B_BLOCKBYTES]);
223
224 for (v, h) in vs.iter_mut().zip(self.h.iter()) {
225 *v = *h;
226 }
227
228 vs[ 8] = IV[0];
229 vs[ 9] = IV[1];
230 vs[10] = IV[2];
231 vs[11] = IV[3];
232 vs[12] = self.t[0] ^ IV[4];
233 vs[13] = self.t[1] ^ IV[5];
234 vs[14] = self.f[0] ^ IV[6];
235 vs[15] = self.f[1] ^ IV[7];
236 round!( 0, vs, ms );
237 round!( 1, vs, ms );
238 round!( 2, vs, ms );
239 round!( 3, vs, ms );
240 round!( 4, vs, ms );
241 round!( 5, vs, ms );
242 round!( 6, vs, ms );
243 round!( 7, vs, ms );
244 round!( 8, vs, ms );
245 round!( 9, vs, ms );
246 round!( 10, vs, ms );
247 round!( 11, vs, ms );
248
249 for (h_elem, (v_low, v_high)) in self.h.iter_mut().zip( vs[0..8].iter().zip(vs[8..16].iter()) ) {
250 *h_elem = *h_elem ^ *v_low ^ *v_high;
251 }
252 }
253
254 fn update( &mut self, mut input: &[u8] ) {
255 while input.len() > 0 {
256 let left = self.buflen;
257 let fill = 2 * BLAKE2B_BLOCKBYTES - left;
258
259 if input.len() > fill {
260 copy_memory(&input[0..fill], &mut self.buf[left..]); self.buflen += fill;
262 self.increment_counter( BLAKE2B_BLOCKBYTES as u64);
263 self.compress();
264
265 let mut halves = self.buf.chunks_mut(BLAKE2B_BLOCKBYTES);
266 let first_half = halves.next().unwrap();
267 let second_half = halves.next().unwrap();
268 copy_memory(second_half, first_half);
269
270 self.buflen -= BLAKE2B_BLOCKBYTES;
271 input = &input[fill..input.len()];
272 } else { copy_memory(input, &mut self.buf[left..]);
274 self.buflen += input.len();
275 break;
276 }
277 }
278 }
279
280 fn finalize( &mut self, out: &mut [u8] ) {
281 assert!(out.len() == self.digest_length as usize);
282 if !self.computed {
283 if self.buflen > BLAKE2B_BLOCKBYTES {
284 self.increment_counter(BLAKE2B_BLOCKBYTES as u64);
285 self.compress();
286 self.buflen -= BLAKE2B_BLOCKBYTES;
287
288 let mut halves = self.buf.chunks_mut(BLAKE2B_BLOCKBYTES);
289 let first_half = halves.next().unwrap();
290 let second_half = halves.next().unwrap();
291 copy_memory(second_half, first_half);
292 }
293
294 let incby = self.buflen as u64;
295 self.increment_counter(incby);
296 self.set_lastblock();
297 for b in self.buf[self.buflen..].iter_mut() {
298 *b = 0;
299 }
300 self.compress();
301
302 write_u64v_le(&mut self.buf[0..64], &self.h);
303 self.computed = true;
304 }
305 let outlen = out.len();
306 copy_memory(&self.buf[0..outlen], out);
307 }
308
309 pub fn reset(&mut self) {
310 for (h_elem, iv_elem) in self.h.iter_mut().zip(IV.iter()) {
311 *h_elem = *iv_elem;
312 }
313 for t_elem in self.t.iter_mut() {
314 *t_elem = 0;
315 }
316 for f_elem in self.f.iter_mut() {
317 *f_elem = 0;
318 }
319 for b in self.buf.iter_mut() {
320 *b = 0;
321 }
322 self.buflen = 0;
323 self.last_node = 0;
324 self.computed = false;
325 self.apply_param();
326 if self.key_length > 0 {
327 self.apply_key();
328 }
329 }
330
331 pub fn blake2b(out: &mut[u8], input: &[u8], key: &[u8]) {
332 let mut hasher : Blake2b = if key.len() > 0 { Blake2b::new_keyed(out.len(), key) } else { Blake2b::new(out.len()) };
333
334 hasher.update(input);
335 hasher.finalize(out);
336 }
337}
338
339impl Digest for Blake2b {
340 fn reset(&mut self) { Blake2b::reset(self); }
341 fn input(&mut self, msg: &[u8]) { self.update(msg); }
342 fn result(&mut self, out: &mut [u8]) { self.finalize(out); }
343 fn output_bits(&self) -> usize { 8 * (self.digest_length as usize) }
344 fn block_size(&self) -> usize { 8 * BLAKE2B_BLOCKBYTES }
345}
346
347impl Mac for Blake2b {
348 fn input(&mut self, data: &[u8]) {
356 self.update(data);
357 }
358
359 fn reset(&mut self) {
363 Blake2b::reset(self);
364 }
365
366 fn result(&mut self) -> MacResult {
370 let mut mac: Vec<u8> = repeat(0).take(self.digest_length as usize).collect();
371 self.raw_result(&mut mac);
372 MacResult::new_from_owned(mac)
373 }
374
375 fn raw_result(&mut self, output: &mut [u8]) {
381 self.finalize(output);
382 }
383
384 fn output_bytes(&self) -> usize { self.digest_length as usize }
388}
389
390#[cfg(test)]
391mod digest_tests {
392 use blake2b::Blake2b;
394 use digest::Digest;
395 use serialize::hex::FromHex;
396
397
398 struct Test {
399 input: Vec<u8>,
400 output: Vec<u8>,
401 key: Option<Vec<u8>>,
402 }
403
404 fn test_hash(tests: &[Test]) {
405 for t in tests {
406 let mut sh = match t.key {
407 Some(ref key) => Blake2b::new_keyed(64, &key),
408 None => Blake2b::new(64)
409 };
410
411 sh.input(&t.input[..]);
413
414 let mut out = [0u8; 64];
415 sh.result(&mut out);
416 assert!(&out[..] == &t.output[..]);
417
418 sh.reset();
419
420 let len = t.input.len();
422 let mut left = len;
423 while left > 0 {
424 let take = (left + 1) / 2;
425 sh.input(&t.input[len - left..take + len - left]);
426 left -= take;
427 }
428
429 let mut out = [0u8; 64];
430 sh.result(&mut out);
431 assert!(&out[..] == &t.output[..]);
432
433 sh.reset();
434 }
435 }
436
437 #[test]
438 fn test_blake2b_digest() {
439 let tests = vec![
440 Test {
442 input: vec![],
443 output: "786a02f742015903c6c6fd852552d272\
444 912f4740e15847618a86e217f71f5419\
445 d25e1031afee585313896444934eb04b\
446 903a685b1448b755d56f701afe9be2ce".from_hex().unwrap(),
447 key: None
448 },
449 Test {
450 input: "The quick brown fox jumps over the lazy dog".as_bytes().to_vec(),
451 output: "a8add4bdddfd93e4877d2746e62817b1\
452 16364a1fa7bc148d95090bc7333b3673\
453 f82401cf7aa2e4cb1ecd90296e3f14cb\
454 5413f8ed77be73045b13914cdcd6a918".from_hex().unwrap(),
455 key: None
456 },
457 Test {
459 input: vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
460 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
461 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
462 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
463 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
464 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
465 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
466 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
467 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
468 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
469 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
470 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
471 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
472 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
473 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
474 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
475 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
476 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
477 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
478 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
479 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
480 0xfc, 0xfd, 0xfe],
481 output: vec![0x14, 0x27, 0x09, 0xd6, 0x2e, 0x28, 0xfc, 0xcc, 0xd0, 0xaf, 0x97,
482 0xfa, 0xd0, 0xf8, 0x46, 0x5b, 0x97, 0x1e, 0x82, 0x20, 0x1d, 0xc5,
483 0x10, 0x70, 0xfa, 0xa0, 0x37, 0x2a, 0xa4, 0x3e, 0x92, 0x48, 0x4b,
484 0xe1, 0xc1, 0xe7, 0x3b, 0xa1, 0x09, 0x06, 0xd5, 0xd1, 0x85, 0x3d,
485 0xb6, 0xa4, 0x10, 0x6e, 0x0a, 0x7b, 0xf9, 0x80, 0x0d, 0x37, 0x3d,
486 0x6d, 0xee, 0x2d, 0x46, 0xd6, 0x2e, 0xf2, 0xa4, 0x61],
487 key: Some(vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
488 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
489 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
490 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
491 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
492 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f])
493 },
494 ];
495
496 test_hash(&tests[..]);
497 }
498}
499
500
501#[cfg(test)]
502mod mac_tests {
503 use blake2b::Blake2b;
504 use mac::Mac;
505
506 #[test]
507 fn test_blake2b_mac() {
508 let key: Vec<u8> = (0..64).map(|i| i).collect();
509 let mut m = Blake2b::new_keyed(64, &key[..]);
510 m.input(&[1,2,4,8]);
511 let expected = [
512 0x8e, 0xc6, 0xcb, 0x71, 0xc4, 0x5c, 0x3c, 0x90,
513 0x91, 0xd0, 0x8a, 0x37, 0x1e, 0xa8, 0x5d, 0xc1,
514 0x22, 0xb5, 0xc8, 0xe2, 0xd9, 0xe5, 0x71, 0x42,
515 0xbf, 0xef, 0xce, 0x42, 0xd7, 0xbc, 0xf8, 0x8b,
516 0xb0, 0x31, 0x27, 0x88, 0x2e, 0x51, 0xa9, 0x21,
517 0x44, 0x62, 0x08, 0xf6, 0xa3, 0x58, 0xa9, 0xe0,
518 0x7d, 0x35, 0x3b, 0xd3, 0x1c, 0x41, 0x70, 0x15,
519 0x62, 0xac, 0xd5, 0x39, 0x4e, 0xee, 0x73, 0xae,
520 ];
521 assert_eq!(m.result().code().to_vec(), expected.to_vec());
522 }
523}
524
525#[cfg(all(test, feature = "with-bench"))]
526mod bench {
527 use test::Bencher;
528
529 use digest::Digest;
530 use blake2b::Blake2b;
531
532
533 #[bench]
534 pub fn blake2b_10(bh: & mut Bencher) {
535 let mut sh = Blake2b::new(64);
536 let bytes = [1u8; 10];
537 bh.iter( || {
538 sh.input(&bytes);
539 });
540 bh.bytes = bytes.len() as u64;
541 }
542
543 #[bench]
544 pub fn blake2b_1k(bh: & mut Bencher) {
545 let mut sh = Blake2b::new(64);
546 let bytes = [1u8; 1024];
547 bh.iter( || {
548 sh.input(&bytes);
549 });
550 bh.bytes = bytes.len() as u64;
551 }
552
553 #[bench]
554 pub fn blake2b_64k(bh: & mut Bencher) {
555 let mut sh = Blake2b::new(64);
556 let bytes = [1u8; 65536];
557 bh.iter( || {
558 sh.input(&bytes);
559 });
560 bh.bytes = bytes.len() as u64;
561 }
562}