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 hex;
396
397 fn decode_hex(value: &str) -> Vec<u8> {
398 hex::FromHex::from_hex(value).unwrap()
399 }
400
401 struct Test {
402 input: Vec<u8>,
403 output: Vec<u8>,
404 key: Option<Vec<u8>>,
405 }
406
407 fn test_hash(tests: &[Test]) {
408 for t in tests {
409 let mut sh = match t.key {
410 Some(ref key) => Blake2b::new_keyed(64, &key),
411 None => Blake2b::new(64)
412 };
413
414 sh.input(&t.input[..]);
416
417 let mut out = [0u8; 64];
418 sh.result(&mut out);
419 assert!(&out[..] == &t.output[..]);
420
421 sh.reset();
422
423 let len = t.input.len();
425 let mut left = len;
426 while left > 0 {
427 let take = (left + 1) / 2;
428 sh.input(&t.input[len - left..take + len - left]);
429 left -= take;
430 }
431
432 let mut out = [0u8; 64];
433 sh.result(&mut out);
434 assert!(&out[..] == &t.output[..]);
435
436 sh.reset();
437 }
438 }
439
440 #[test]
441 fn test_blake2b_digest() {
442 let tests = vec![
443 Test {
445 input: vec![],
446 output: decode_hex("786a02f742015903c6c6fd852552d272\
447 912f4740e15847618a86e217f71f5419\
448 d25e1031afee585313896444934eb04b\
449 903a685b1448b755d56f701afe9be2ce"),
450 key: None
451 },
452 Test {
453 input: "The quick brown fox jumps over the lazy dog".as_bytes().to_vec(),
454 output: decode_hex("a8add4bdddfd93e4877d2746e62817b1\
455 16364a1fa7bc148d95090bc7333b3673\
456 f82401cf7aa2e4cb1ecd90296e3f14cb\
457 5413f8ed77be73045b13914cdcd6a918"),
458 key: None
459 },
460 Test {
462 input: vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
463 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
464 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
465 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
466 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
467 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
468 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
469 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
470 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
471 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
472 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
473 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
474 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
475 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
476 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
477 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
478 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
479 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
480 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
481 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
482 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
483 0xfc, 0xfd, 0xfe],
484 output: vec![0x14, 0x27, 0x09, 0xd6, 0x2e, 0x28, 0xfc, 0xcc, 0xd0, 0xaf, 0x97,
485 0xfa, 0xd0, 0xf8, 0x46, 0x5b, 0x97, 0x1e, 0x82, 0x20, 0x1d, 0xc5,
486 0x10, 0x70, 0xfa, 0xa0, 0x37, 0x2a, 0xa4, 0x3e, 0x92, 0x48, 0x4b,
487 0xe1, 0xc1, 0xe7, 0x3b, 0xa1, 0x09, 0x06, 0xd5, 0xd1, 0x85, 0x3d,
488 0xb6, 0xa4, 0x10, 0x6e, 0x0a, 0x7b, 0xf9, 0x80, 0x0d, 0x37, 0x3d,
489 0x6d, 0xee, 0x2d, 0x46, 0xd6, 0x2e, 0xf2, 0xa4, 0x61],
490 key: Some(vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
491 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
492 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
493 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
494 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
495 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f])
496 },
497 ];
498
499 test_hash(&tests[..]);
500 }
501}
502
503
504#[cfg(test)]
505mod mac_tests {
506 use blake2b::Blake2b;
507 use mac::Mac;
508
509 #[test]
510 fn test_blake2b_mac() {
511 let key: Vec<u8> = (0..64).map(|i| i).collect();
512 let mut m = Blake2b::new_keyed(64, &key[..]);
513 m.input(&[1,2,4,8]);
514 let expected = [
515 0x8e, 0xc6, 0xcb, 0x71, 0xc4, 0x5c, 0x3c, 0x90,
516 0x91, 0xd0, 0x8a, 0x37, 0x1e, 0xa8, 0x5d, 0xc1,
517 0x22, 0xb5, 0xc8, 0xe2, 0xd9, 0xe5, 0x71, 0x42,
518 0xbf, 0xef, 0xce, 0x42, 0xd7, 0xbc, 0xf8, 0x8b,
519 0xb0, 0x31, 0x27, 0x88, 0x2e, 0x51, 0xa9, 0x21,
520 0x44, 0x62, 0x08, 0xf6, 0xa3, 0x58, 0xa9, 0xe0,
521 0x7d, 0x35, 0x3b, 0xd3, 0x1c, 0x41, 0x70, 0x15,
522 0x62, 0xac, 0xd5, 0x39, 0x4e, 0xee, 0x73, 0xae,
523 ];
524 assert_eq!(m.result().code().to_vec(), expected.to_vec());
525 }
526}
527
528#[cfg(all(test, feature = "with-bench"))]
529mod bench {
530 use test::Bencher;
531
532 use digest::Digest;
533 use blake2b::Blake2b;
534
535
536 #[bench]
537 pub fn blake2b_10(bh: & mut Bencher) {
538 let mut sh = Blake2b::new(64);
539 let bytes = [1u8; 10];
540 bh.iter( || {
541 sh.input(&bytes);
542 });
543 bh.bytes = bytes.len() as u64;
544 }
545
546 #[bench]
547 pub fn blake2b_1k(bh: & mut Bencher) {
548 let mut sh = Blake2b::new(64);
549 let bytes = [1u8; 1024];
550 bh.iter( || {
551 sh.input(&bytes);
552 });
553 bh.bytes = bytes.len() as u64;
554 }
555
556 #[bench]
557 pub fn blake2b_64k(bh: & mut Bencher) {
558 let mut sh = Blake2b::new(64);
559 let bytes = [1u8; 65536];
560 bh.iter( || {
561 sh.input(&bytes);
562 });
563 bh.bytes = bytes.len() as u64;
564 }
565}