Skip to main content

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 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            // Test that it works when accepting the message all at once
415            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            // Test that it works when accepting the message in pieces
424            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            // Examples from wikipedia
444            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            // from: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-test.txt
461            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}