crypto/
blake2b.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
7use 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, // whether the final digest has been computed
53    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, &param_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    // init xors IV with input parameter block
161    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..]); // Fill buffer
261                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 { // inlen <= fill
273                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    /**
349     * Process input data.
350     *
351     * # Arguments
352     * * data - The input data to process.
353     *
354     */
355    fn input(&mut self, data: &[u8]) {
356        self.update(data);
357    }
358
359    /**
360     * Reset the Mac state to begin processing another input stream.
361     */
362    fn reset(&mut self) {
363        Blake2b::reset(self);
364    }
365
366    /**
367     * Obtain the result of a Mac computation as a MacResult.
368     */
369    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    /**
376     * Obtain the result of a Mac computation as [u8]. This method should be used very carefully
377     * since incorrect use of the Mac code could result in permitting a timing attack which defeats
378     * the security provided by a Mac function.
379     */
380    fn raw_result(&mut self, output: &mut [u8]) {
381        self.finalize(output);
382    }
383
384    /**
385     * Get the size of the Mac code, in bytes.
386     */
387    fn output_bytes(&self) -> usize { self.digest_length as usize }
388}
389
390#[cfg(test)]
391mod digest_tests {
392    //use cryptoutil::test::test_digest_1million_random;
393    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            // Test that it works when accepting the message all at once
412            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            // Test that it works when accepting the message in pieces
421            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            // Examples from wikipedia
441            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            // from: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-test.txt
458            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}