minisign/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 super::cryptoutil::{copy_memory, read_u64v_le, write_u64v_le};
8
9static IV: [u64; 8] = [
10    0x6a09e667f3bcc908,
11    0xbb67ae8584caa73b,
12    0x3c6ef372fe94f82b,
13    0xa54ff53a5f1d36f1,
14    0x510e527fade682d1,
15    0x9b05688c2b3e6c1f,
16    0x1f83d9abfb41bd6b,
17    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
35pub const BLAKE2B_BLOCKBYTES: usize = 128;
36pub const BLAKE2B_OUTBYTES: usize = 64;
37pub const BLAKE2B_KEYBYTES: usize = 64;
38pub const BLAKE2B_SALTBYTES: usize = 16;
39pub const 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 {
57    fn clone(&self) -> Blake2b {
58        *self
59    }
60}
61
62#[derive(Copy, Clone)]
63struct Blake2bParam {
64    digest_length: u8,
65    key_length: u8,
66    fanout: u8,
67    depth: u8,
68    leaf_length: u32,
69    node_offset: u64,
70    node_depth: u8,
71    inner_length: u8,
72    reserved: [u8; 14],
73    salt: [u8; BLAKE2B_SALTBYTES],
74    personal: [u8; BLAKE2B_PERSONALBYTES],
75}
76
77macro_rules! G( ($r:expr, $i:expr, $a:expr, $b:expr, $c:expr, $d:expr, $m:expr) => ({
78    $a = $a.wrapping_add($b).wrapping_add($m[SIGMA[$r][2*$i+0]]);
79    $d = ($d ^ $a).rotate_right(32);
80    $c = $c.wrapping_add($d);
81    $b = ($b ^ $c).rotate_right(24);
82    $a = $a.wrapping_add($b).wrapping_add($m[SIGMA[$r][2*$i+1]]);
83    $d = ($d ^ $a).rotate_right(16);
84    $c = $c .wrapping_add($d);
85    $b = ($b ^ $c).rotate_right(63);
86}));
87
88macro_rules! round( ($r:expr, $v:expr, $m:expr) => ( {
89    G!($r,0,$v[ 0],$v[ 4],$v[ 8],$v[12], $m);
90    G!($r,1,$v[ 1],$v[ 5],$v[ 9],$v[13], $m);
91    G!($r,2,$v[ 2],$v[ 6],$v[10],$v[14], $m);
92    G!($r,3,$v[ 3],$v[ 7],$v[11],$v[15], $m);
93    G!($r,4,$v[ 0],$v[ 5],$v[10],$v[15], $m);
94    G!($r,5,$v[ 1],$v[ 6],$v[11],$v[12], $m);
95    G!($r,6,$v[ 2],$v[ 7],$v[ 8],$v[13], $m);
96    G!($r,7,$v[ 3],$v[ 4],$v[ 9],$v[14], $m);
97  }
98));
99
100impl Blake2b {
101    fn set_lastnode(&mut self) {
102        self.f[1] = 0xffffffffffffffff;
103    }
104
105    fn set_lastblock(&mut self) {
106        if self.last_node != 0 {
107            self.set_lastnode();
108        }
109        self.f[0] = 0xffffffffffffffff;
110    }
111
112    fn increment_counter(&mut self, inc: u64) {
113        self.t[0] += inc;
114        self.t[1] += if self.t[0] < inc { 1 } else { 0 };
115    }
116
117    fn init0(param: Blake2bParam, digest_length: u8) -> Blake2b {
118        Blake2b {
119            h: IV,
120            t: [0, 0],
121            f: [0, 0],
122            buf: [0; 2 * BLAKE2B_BLOCKBYTES],
123            buflen: 0,
124            last_node: 0,
125            digest_length,
126            computed: false,
127            _key: [0; BLAKE2B_KEYBYTES],
128            _key_length: 0u8,
129            param,
130        }
131    }
132
133    fn apply_param(&mut self) {
134        use std::io::Write;
135
136        use super::cryptoutil::WriteExt;
137
138        let mut param_bytes: [u8; 64] = [0; 64];
139        {
140            let mut writer: &mut [u8] = &mut param_bytes;
141            writer.write_u8(self.param.digest_length).unwrap();
142            writer.write_u8(self.param.key_length).unwrap();
143            writer.write_u8(self.param.fanout).unwrap();
144            writer.write_u8(self.param.depth).unwrap();
145            writer.write_u32_le(self.param.leaf_length).unwrap();
146            writer.write_u64_le(self.param.node_offset).unwrap();
147            writer.write_u8(self.param.node_depth).unwrap();
148            writer.write_u8(self.param.inner_length).unwrap();
149            writer.write_all(&self.param.reserved).unwrap();
150            writer.write_all(&self.param.salt).unwrap();
151            writer.write_all(&self.param.personal).unwrap();
152        }
153
154        let mut param_words: [u64; 8] = [0; 8];
155        read_u64v_le(&mut param_words, &param_bytes);
156        for (h, param_word) in self.h.iter_mut().zip(param_words.iter()) {
157            *h ^= *param_word;
158        }
159    }
160
161    // init xors IV with input parameter block
162    fn init_param(p: Blake2bParam) -> Blake2b {
163        let mut b = Blake2b::init0(p, p.digest_length);
164        b.apply_param();
165        b
166    }
167
168    fn default_param(outlen: u8) -> Blake2bParam {
169        Blake2bParam {
170            digest_length: outlen,
171            key_length: 0,
172            fanout: 1,
173            depth: 1,
174            leaf_length: 0,
175            node_offset: 0,
176            node_depth: 0,
177            inner_length: 0,
178            reserved: [0; 14],
179            salt: [0; BLAKE2B_SALTBYTES],
180            personal: [0; BLAKE2B_PERSONALBYTES],
181        }
182    }
183
184    pub fn new(outlen: usize) -> Blake2b {
185        assert!(outlen > 0 && outlen <= BLAKE2B_OUTBYTES);
186        Blake2b::init_param(Blake2b::default_param(outlen as u8))
187    }
188
189    fn compress(&mut self) {
190        let mut ms: [u64; 16] = [0; 16];
191        let mut vs: [u64; 16] = [0; 16];
192
193        read_u64v_le(&mut ms, &self.buf[0..BLAKE2B_BLOCKBYTES]);
194
195        for (v, h) in vs.iter_mut().zip(self.h.iter()) {
196            *v = *h;
197        }
198
199        vs[8] = IV[0];
200        vs[9] = IV[1];
201        vs[10] = IV[2];
202        vs[11] = IV[3];
203        vs[12] = self.t[0] ^ IV[4];
204        vs[13] = self.t[1] ^ IV[5];
205        vs[14] = self.f[0] ^ IV[6];
206        vs[15] = self.f[1] ^ IV[7];
207        round!(0, vs, ms);
208        round!(1, vs, ms);
209        round!(2, vs, ms);
210        round!(3, vs, ms);
211        round!(4, vs, ms);
212        round!(5, vs, ms);
213        round!(6, vs, ms);
214        round!(7, vs, ms);
215        round!(8, vs, ms);
216        round!(9, vs, ms);
217        round!(10, vs, ms);
218        round!(11, vs, ms);
219
220        for (h_elem, (v_low, v_high)) in
221            self.h.iter_mut().zip(vs[0..8].iter().zip(vs[8..16].iter()))
222        {
223            *h_elem = *h_elem ^ *v_low ^ *v_high;
224        }
225    }
226
227    pub fn update(&mut self, mut input: &[u8]) {
228        while !input.is_empty() {
229            let left = self.buflen;
230            let fill = 2 * BLAKE2B_BLOCKBYTES - left;
231
232            if input.len() > fill {
233                copy_memory(&input[0..fill], &mut self.buf[left..]); // Fill buffer
234                self.buflen += fill;
235                self.increment_counter(BLAKE2B_BLOCKBYTES as u64);
236                self.compress();
237
238                let mut halves = self.buf.chunks_mut(BLAKE2B_BLOCKBYTES);
239                let first_half = halves.next().unwrap();
240                let second_half = halves.next().unwrap();
241                copy_memory(second_half, first_half);
242
243                self.buflen -= BLAKE2B_BLOCKBYTES;
244                input = &input[fill..input.len()];
245            } else {
246                // inlen <= fill
247                copy_memory(input, &mut self.buf[left..]);
248                self.buflen += input.len();
249                break;
250            }
251        }
252    }
253
254    pub fn finalize(&mut self, out: &mut [u8]) {
255        assert!(out.len() == self.digest_length as usize);
256        if !self.computed {
257            if self.buflen > BLAKE2B_BLOCKBYTES {
258                self.increment_counter(BLAKE2B_BLOCKBYTES as u64);
259                self.compress();
260                self.buflen -= BLAKE2B_BLOCKBYTES;
261
262                let mut halves = self.buf.chunks_mut(BLAKE2B_BLOCKBYTES);
263                let first_half = halves.next().unwrap();
264                let second_half = halves.next().unwrap();
265                copy_memory(second_half, first_half);
266            }
267
268            let incby = self.buflen as u64;
269            self.increment_counter(incby);
270            self.set_lastblock();
271            for b in self.buf[self.buflen..].iter_mut() {
272                *b = 0;
273            }
274            self.compress();
275
276            write_u64v_le(&mut self.buf[0..64], &self.h);
277            self.computed = true;
278        }
279        let outlen = out.len();
280        copy_memory(&self.buf[0..outlen], out);
281    }
282
283    #[allow(dead_code)]
284    pub fn blake2b(out: &mut [u8], input: &[u8]) {
285        let mut hasher: Blake2b = Blake2b::new(out.len());
286        hasher.update(input);
287        hasher.finalize(out);
288    }
289}