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