crypto/
blake2s.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_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, // whether the final digest has been computed
49    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, &param_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    // init xors IV with input parameter block
155    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..]); // Fill buffer
251                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 { // inlen <= fill
263                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    /**
339     * Process input data.
340     *
341     * # Arguments
342     * * data - The input data to process.
343     *
344     */
345    fn input(&mut self, data: &[u8]) {
346        self.update(data);
347    }
348
349    /**
350     * Reset the Mac state to begin processing another input stream.
351     */
352    fn reset(&mut self) {
353        Blake2s::reset(self);
354    }
355
356    /**
357     * Obtain the result of a Mac computation as a MacResult.
358     */
359    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    /**
366     * Obtain the result of a Mac computation as [u8]. This method should be used very carefully
367     * since incorrect use of the Mac code could result in permitting a timing attack which defeats
368     * the security provided by a Mac function.
369     */
370    fn raw_result(&mut self, output: &mut [u8]) {
371        self.finalize(output);
372    }
373
374    /**
375     * Get the size of the Mac code, in bytes.
376     */
377    fn output_bytes(&self) -> usize { self.digest_length as usize }
378}
379
380#[cfg(test)]
381mod digest_tests {
382    //use cryptoutil::test::test_digest_1million_random;
383    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            // Test that it works when accepting the message all at once
401            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            // Test that it works when accepting the message in pieces
410            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            // from: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2s-test.txt
430            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}