1#[cfg(feature = "alloc")]
12use crate::alloc_prelude::*;
13
14use core::cmp::min;
15
16use dcrypt_internal::zeroing::{Zeroize, Zeroizing};
17
18use crate::error::{validate, Error, Result};
19use crate::hash::{HashAlgorithm, HashFunction};
20use crate::types::Digest;
21use dcrypt_common::security::{SecretBuffer, SecureZeroingType};
22
23const BLAKE2B_BLOCK_SIZE: usize = 128;
27const BLAKE2B_MAX_OUTPUT_SIZE: usize = 64;
28const BLAKE2B_ROUNDS: usize = 12;
29const BLAKE2B_KEY_SIZE: usize = 64; #[inline(always)]
32fn read_u64_le(bytes: &[u8]) -> u64 {
33 debug_assert!(bytes.len() >= 8);
34 let mut word = Zeroizing::new(0u64);
35 for (index, byte) in bytes[..8].iter().enumerate() {
36 *word |= u64::from(*byte) << (index * 8);
37 }
38 *word
39}
40
41#[inline(always)]
42fn read_u32_le(bytes: &[u8]) -> u32 {
43 debug_assert!(bytes.len() >= 4);
44 let mut word = Zeroizing::new(0u32);
45 for (index, byte) in bytes[..4].iter().enumerate() {
46 *word |= u32::from(*byte) << (index * 8);
47 }
48 *word
49}
50
51pub(crate) const BLAKE2B_IV: [u64; 8] = [
53 0x6A09_E667_F3BC_C908,
54 0xBB67_AE85_84CA_A73B,
55 0x3C6E_F372_FE94_F82B,
56 0xA54F_F53A_5F1D_36F1,
57 0x510E_527F_ADE6_82D1,
58 0x9B05_688C_2B3E_6C1F,
59 0x1F83_D9AB_FB41_BD6B,
60 0x5BE0_CD19_137E_2179,
61];
62
63const BLAKE2B_SIGMA: [[usize; 16]; BLAKE2B_ROUNDS] = [
65 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
66 [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
67 [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
68 [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
69 [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
70 [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
71 [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
72 [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
73 [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
74 [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
75 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
76 [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
77];
78
79#[allow(missing_docs)]
83pub enum Blake2bAlgorithm {}
84impl HashAlgorithm for Blake2bAlgorithm {
85 const OUTPUT_SIZE: usize = BLAKE2B_MAX_OUTPUT_SIZE;
86 const BLOCK_SIZE: usize = BLAKE2B_BLOCK_SIZE;
87 const ALGORITHM_ID: &'static str = "BLAKE2b";
88}
89
90#[allow(missing_docs)]
94#[derive(Clone)]
95pub struct Blake2b {
96 pub(crate) h: [u64; 8],
97 pub(crate) t: [u64; 2],
98 pub(crate) f: [u64; 2],
99 pub(crate) buf: [u8; BLAKE2B_BLOCK_SIZE],
100 pub(crate) buf_len: usize,
101 pub(crate) out_len: usize,
102 pub(crate) key: Option<SecretBuffer<BLAKE2B_KEY_SIZE>>, pub(crate) is_keyed: bool,
104}
105impl Zeroize for Blake2b {
106 fn zeroize(&mut self) {
107 self.h.zeroize();
108 self.t.zeroize();
109 self.f.zeroize();
110 self.buf.zeroize();
111 self.buf_len.zeroize();
112 self.out_len.zeroize();
113 self.key.zeroize();
114 self.is_keyed.zeroize();
115 }
116}
117impl Drop for Blake2b {
118 fn drop(&mut self) {
119 self.zeroize();
120 }
121}
122
123impl Blake2b {
127 pub fn with_output_size(out_len: usize) -> Self {
129 if !(1..=BLAKE2B_MAX_OUTPUT_SIZE).contains(&out_len) {
130 panic!("Blake2b output size must be between 1 and 64 bytes");
131 }
132 let mut instance = Self {
133 h: BLAKE2B_IV,
134 t: [0; 2],
135 f: [0; 2],
136 buf: [0; BLAKE2B_BLOCK_SIZE],
137 buf_len: 0,
138 out_len,
139 key: None,
140 is_keyed: false,
141 };
142 instance.h[0] ^= 0x0101_0000u64 | out_len as u64;
143 instance
144 }
145
146 pub fn with_parameter_block(param: [u8; 64], out_len: usize) -> Self {
155 if !(1..=BLAKE2B_MAX_OUTPUT_SIZE).contains(&out_len) {
156 panic!("Blake2b output size must be between 1 and 64 bytes");
157 }
158
159 let mut instance = Self {
160 h: BLAKE2B_IV,
161 t: [0; 2],
162 f: [0; 2],
163 buf: [0; BLAKE2B_BLOCK_SIZE],
164 buf_len: 0,
165 out_len,
166 key: None,
167 is_keyed: false,
168 };
169 for (i, chunk) in param.chunks_exact(8).enumerate() {
170 instance.h[i] ^= read_u64_le(chunk);
171 }
172 instance
173 }
174
175 pub fn with_key(key: &[u8], out_len: usize) -> Result<Self> {
182 if !(1..=BLAKE2B_MAX_OUTPUT_SIZE).contains(&out_len) {
183 return Err(Error::param(
184 "out_len",
185 "BLAKE2b output size must be between 1 and 64 bytes",
186 ));
187 }
188 if key.is_empty() || key.len() > BLAKE2B_KEY_SIZE {
189 return Err(Error::param(
190 "key",
191 "Key length must be between 1 and 64 bytes",
192 ));
193 }
194
195 let mut key_secret_buf = SecretBuffer::<BLAKE2B_KEY_SIZE>::zeroed();
197 key_secret_buf.as_mut()[..key.len()].copy_from_slice(key);
198
199 let param0 = (out_len as u64) | ((key.len() as u64) << 8) | (1u64 << 16) | (1u64 << 24); let mut blake2b = Blake2b {
205 h: BLAKE2B_IV,
206 t: [0; 2],
207 f: [0; 2],
208 buf: [0; BLAKE2B_BLOCK_SIZE],
209 buf_len: 0,
210 out_len,
211 key: Some(key_secret_buf),
212 is_keyed: true,
213 };
214 blake2b.h[0] ^= param0;
215
216 let mut key_block_padded = Zeroizing::new([0u8; BLAKE2B_BLOCK_SIZE]);
218 key_block_padded[..key.len()].copy_from_slice(key);
219 blake2b.update_internal(&*key_block_padded)?;
220
221 Ok(blake2b)
222 }
223
224 #[inline(always)]
229 fn blake2b_g(v: &mut [u64; 16], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) {
230 v[a] = v[a].wrapping_add(v[b]).wrapping_add(x);
231 v[d] = (v[d] ^ v[a]).rotate_right(32);
232 v[c] = v[c].wrapping_add(v[d]);
233 v[b] = (v[b] ^ v[c]).rotate_right(24);
234 v[a] = v[a].wrapping_add(v[b]).wrapping_add(y);
235 v[d] = (v[d] ^ v[a]).rotate_right(16);
236 v[c] = v[c].wrapping_add(v[d]);
237 v[b] = (v[b] ^ v[c]).rotate_right(63);
238 }
239
240 fn compress(&mut self, last: bool) -> Result<()> {
241 let mut v = Zeroizing::new([0u64; 16]);
242 v[..8].copy_from_slice(&self.h);
243 v[8..].copy_from_slice(&BLAKE2B_IV);
244 v[12] ^= self.t[0];
245 v[13] ^= self.t[1];
246 if last {
247 v[14] ^= 0xFFFF_FFFF_FFFF_FFFF;
248 } let mut m = Zeroizing::new([0u64; 16]);
251 for (i, elem) in m.iter_mut().enumerate().take(16) {
252 let idx = i * 8;
253 validate::max_length("BLAKE2b buffer slice", idx + 8, self.buf.len())?;
254 *elem = read_u64_le(&self.buf[idx..idx + 8]);
255 }
256 for s in BLAKE2B_SIGMA.iter().take(BLAKE2B_ROUNDS) {
257 Self::blake2b_g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]);
258 Self::blake2b_g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]);
259 Self::blake2b_g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]);
260 Self::blake2b_g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]);
261 Self::blake2b_g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]);
262 Self::blake2b_g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]);
263 Self::blake2b_g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]);
264 Self::blake2b_g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]);
265 }
266 for i in 0..8 {
267 self.h[i] ^= v[i] ^ v[i + 8];
268 }
269 Ok(())
270 }
271
272 fn update_internal(&mut self, mut input: &[u8]) -> Result<()> {
273 while !input.is_empty() {
274 let fill = min(input.len(), BLAKE2B_BLOCK_SIZE - self.buf_len);
275 self.buf[self.buf_len..self.buf_len + fill].copy_from_slice(&input[..fill]);
276 self.buf_len += fill;
277 input = &input[fill..];
278
279 if self.buf_len == BLAKE2B_BLOCK_SIZE {
280 if input.is_empty() {
281 break;
283 }
284 let inc = BLAKE2B_BLOCK_SIZE as u64;
286 self.t[0] = self.t[0].wrapping_add(inc);
287 if self.t[0] < inc {
288 self.t[1] = self.t[1].wrapping_add(1);
289 }
290 self.compress(false)?;
291 self.buf.zeroize();
292 self.buf_len = 0;
293 }
294 }
295 Ok(())
296 }
297
298 fn finalize_internal(&mut self) -> Result<Zeroizing<[u8; BLAKE2B_MAX_OUTPUT_SIZE]>> {
299 let inc = self.buf_len as u64;
301 self.t[0] = self.t[0].wrapping_add(inc);
302 if self.t[0] < inc {
303 self.t[1] = self.t[1].wrapping_add(1);
304 }
305
306 for b in &mut self.buf[self.buf_len..] {
308 *b = 0;
309 }
310 self.compress(true)?;
311
312 let mut out = Zeroizing::new([0u8; BLAKE2B_MAX_OUTPUT_SIZE]);
314 for (word_index, &word) in self.h.iter().enumerate() {
315 for byte in 0..8 {
316 let output_index = word_index * 8 + byte;
317 if output_index < self.out_len {
318 out[output_index] = (word >> (byte * 8)) as u8;
319 }
320 }
321 }
322 self.zeroize();
323 Ok(out)
324 }
325}
326
327impl HashFunction for Blake2b {
328 type Algorithm = Blake2bAlgorithm;
329 type Output = Digest<BLAKE2B_MAX_OUTPUT_SIZE>;
330
331 fn new() -> Self {
332 Blake2b::with_output_size(BLAKE2B_MAX_OUTPUT_SIZE)
333 }
334
335 fn update(&mut self, input: &[u8]) -> Result<&mut Self> {
336 self.update_internal(input)?;
337 Ok(self)
338 }
339
340 fn finalize(&mut self) -> Result<Self::Output> {
341 let out_len = self.out_len;
342 let hash = self.finalize_internal()?;
343 let mut digest = Digest::<BLAKE2B_MAX_OUTPUT_SIZE>::zeroed_with_len(out_len);
344 digest.as_mut().copy_from_slice(&hash[..out_len]);
345 Ok(digest)
346 }
347
348 fn output_size() -> usize {
349 Self::Algorithm::OUTPUT_SIZE
350 }
351 fn block_size() -> usize {
352 Self::Algorithm::BLOCK_SIZE
353 }
354 fn name() -> String {
355 Self::Algorithm::ALGORITHM_ID.to_string()
356 }
357}
358
359const BLAKE2S_BLOCK_SIZE: usize = 64;
361const BLAKE2S_MAX_OUTPUT_SIZE: usize = 32;
362const BLAKE2S_ROUNDS: usize = 10;
363const BLAKE2S_KEY_SIZE: usize = 32; const BLAKE2S_IV: [u32; 8] = [
365 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
366];
367const BLAKE2S_SIGMA: [[usize; 16]; BLAKE2S_ROUNDS] = [
368 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
369 [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
370 [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
371 [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
372 [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
373 [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
374 [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
375 [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
376 [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
377 [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
378];
379
380pub enum Blake2sAlgorithm {}
382
383impl HashAlgorithm for Blake2sAlgorithm {
385 const OUTPUT_SIZE: usize = BLAKE2S_MAX_OUTPUT_SIZE;
386 const BLOCK_SIZE: usize = BLAKE2S_BLOCK_SIZE;
387 const ALGORITHM_ID: &'static str = "BLAKE2s";
388}
389
390#[derive(Clone)]
392pub struct Blake2s {
393 h: [u32; 8],
394 t: [u32; 2],
395 f: [u32; 2],
396 buf: [u8; BLAKE2S_BLOCK_SIZE],
397 buf_len: usize,
398 out_len: usize,
399 key: Option<SecretBuffer<BLAKE2S_KEY_SIZE>>, is_keyed: bool,
401}
402
403impl Zeroize for Blake2s {
404 fn zeroize(&mut self) {
405 self.h.zeroize();
406 self.t.zeroize();
407 self.f.zeroize();
408 self.buf.zeroize();
409 self.buf_len.zeroize();
410 self.out_len.zeroize();
411 self.key.zeroize();
412 self.is_keyed.zeroize();
413 }
414}
415
416impl Drop for Blake2s {
418 fn drop(&mut self) {
419 self.zeroize();
420 }
421}
422
423impl Blake2s {
424 pub fn with_output_size(out_len: usize) -> Self {
434 if out_len == 0 || out_len > BLAKE2S_MAX_OUTPUT_SIZE {
435 panic!("Blake2s output size must be between 1 and 32 bytes");
436 }
437 let param0 = (out_len as u32) | (1u32 << 16) | (1u32 << 24); let mut instance = Blake2s {
439 h: BLAKE2S_IV,
440 t: [0; 2],
441 f: [0; 2],
442 buf: [0; BLAKE2S_BLOCK_SIZE],
443 buf_len: 0,
444 out_len,
445 key: None,
446 is_keyed: false,
447 };
448 instance.h[0] ^= param0;
449 instance
450 }
451
452 pub fn with_key(key: &[u8], out_len: usize) -> Result<Self> {
459 if !(1..=BLAKE2S_MAX_OUTPUT_SIZE).contains(&out_len) {
460 return Err(Error::param(
461 "out_len",
462 "BLAKE2s output size must be between 1 and 32 bytes",
463 ));
464 }
465 if key.is_empty() || key.len() > BLAKE2S_KEY_SIZE {
466 return Err(Error::param(
467 "key",
468 "Key length must be between 1 and 32 bytes",
469 ));
470 }
471
472 let mut key_secret_buf = SecretBuffer::<BLAKE2S_KEY_SIZE>::zeroed();
474 key_secret_buf.as_mut()[..key.len()].copy_from_slice(key);
475
476 let param0 = (out_len as u32) | ((key.len() as u32) << 8) | (1u32 << 16) | (1u32 << 24); let mut blake2s = Blake2s {
483 h: BLAKE2S_IV,
484 t: [0; 2],
485 f: [0; 2],
486 buf: [0; BLAKE2S_BLOCK_SIZE],
487 buf_len: 0,
488 out_len,
489 key: Some(key_secret_buf),
490 is_keyed: true,
491 };
492 blake2s.h[0] ^= param0;
493
494 let mut key_block_padded = Zeroizing::new([0u8; BLAKE2S_BLOCK_SIZE]);
497 key_block_padded[..key.len()].copy_from_slice(key);
498
499 blake2s.update_internal(&*key_block_padded)?;
500
501 Ok(blake2s)
502 }
503
504 fn g(v: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize, x: u32, y: u32) {
505 v[a] = v[a].wrapping_add(v[b]).wrapping_add(x);
506 v[d] = (v[d] ^ v[a]).rotate_right(16);
507 v[c] = v[c].wrapping_add(v[d]);
508 v[b] = (v[b] ^ v[c]).rotate_right(12);
509 v[a] = v[a].wrapping_add(v[b]).wrapping_add(y);
510 v[d] = (v[d] ^ v[a]).rotate_right(8);
511 v[c] = v[c].wrapping_add(v[d]);
512 v[b] = (v[b] ^ v[c]).rotate_right(7);
513 }
514
515 fn compress(&mut self, last: bool) -> Result<()> {
516 let mut v = Zeroizing::new([0u32; 16]);
517 v[..8].copy_from_slice(&self.h);
518 v[8..].copy_from_slice(&BLAKE2S_IV);
519 v[12] ^= self.t[0];
520 v[13] ^= self.t[1];
521 if last {
522 v[14] = !v[14];
523 }
524
525 let mut m = Zeroizing::new([0u32; 16]);
526 for (i, elem) in m.iter_mut().enumerate().take(16) {
527 let idx = i * 4;
528 validate::max_length("BLAKE2s buffer slice", idx + 4, self.buf.len())?;
530
531 *elem = read_u32_le(&self.buf[idx..idx + 4]);
532 }
533
534 for s in BLAKE2S_SIGMA.iter().take(BLAKE2S_ROUNDS) {
536 Self::g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]);
537 Self::g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]);
538 Self::g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]);
539 Self::g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]);
540 Self::g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]);
541 Self::g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]);
542 Self::g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]);
543 Self::g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]);
544 }
545
546 for i in 0..8 {
547 self.h[i] ^= v[i] ^ v[i + 8];
548 }
549
550 Ok(())
551 }
552
553 fn update_internal(&mut self, mut input: &[u8]) -> Result<()> {
554 while !input.is_empty() {
555 let fill = min(input.len(), BLAKE2S_BLOCK_SIZE - self.buf_len);
556 self.buf[self.buf_len..self.buf_len + fill].copy_from_slice(&input[..fill]);
557 self.buf_len += fill;
558 input = &input[fill..];
559
560 if self.buf_len == BLAKE2S_BLOCK_SIZE {
561 if input.is_empty() {
562 break;
564 }
565 let inc = BLAKE2S_BLOCK_SIZE as u32;
567 self.t[0] = self.t[0].wrapping_add(inc);
568 if self.t[0] < inc {
569 self.t[1] = self.t[1].wrapping_add(1);
570 }
571 self.compress(false)?;
572 self.buf.zeroize();
573 self.buf_len = 0;
574 }
575 }
576 Ok(())
577 }
578
579 fn finalize_internal(&mut self) -> Result<Zeroizing<[u8; BLAKE2S_MAX_OUTPUT_SIZE]>> {
580 let inc = self.buf_len as u32;
582 self.t[0] = self.t[0].wrapping_add(inc);
583 if self.t[0] < inc {
584 self.t[1] = self.t[1].wrapping_add(1);
585 }
586
587 for b in &mut self.buf[self.buf_len..] {
589 *b = 0;
590 }
591 self.compress(true)?;
592
593 let mut out = Zeroizing::new([0u8; BLAKE2S_MAX_OUTPUT_SIZE]);
595 for (word_index, &word) in self.h.iter().enumerate() {
596 for byte in 0..4 {
597 let output_index = word_index * 4 + byte;
598 if output_index < self.out_len {
599 out[output_index] = (word >> (byte * 8)) as u8;
600 }
601 }
602 }
603 self.zeroize();
604 Ok(out)
605 }
606}
607
608impl HashFunction for Blake2s {
609 type Algorithm = Blake2sAlgorithm;
610 type Output = Digest<BLAKE2S_MAX_OUTPUT_SIZE>;
611
612 fn new() -> Self {
613 Blake2s::with_output_size(BLAKE2S_MAX_OUTPUT_SIZE)
614 }
615
616 fn update(&mut self, input: &[u8]) -> Result<&mut Self> {
617 self.update_internal(input)?;
618 Ok(self)
619 }
620
621 fn finalize(&mut self) -> Result<Self::Output> {
622 let out_len = self.out_len;
623 let hash = self.finalize_internal()?;
624 let mut digest = Digest::<BLAKE2S_MAX_OUTPUT_SIZE>::zeroed_with_len(out_len);
625 digest.as_mut().copy_from_slice(&hash[..out_len]);
626 Ok(digest)
627 }
628
629 fn output_size() -> usize {
630 Self::Algorithm::OUTPUT_SIZE
631 }
632
633 fn block_size() -> usize {
634 Self::Algorithm::BLOCK_SIZE
635 }
636
637 fn name() -> String {
638 Self::Algorithm::ALGORITHM_ID.to_string()
639 }
640}
641
642impl SecureZeroingType for Blake2b {
644 fn zeroed() -> Self {
645 Blake2b::with_output_size(BLAKE2B_MAX_OUTPUT_SIZE)
646 }
647
648 fn secure_clone(&self) -> Self {
649 self.clone()
650 }
651}
652
653impl SecureZeroingType for Blake2s {
654 fn zeroed() -> Self {
655 Blake2s::with_output_size(BLAKE2S_MAX_OUTPUT_SIZE)
656 }
657
658 fn secure_clone(&self) -> Self {
659 self.clone()
660 }
661}
662
663#[cfg(test)]
664mod tests;