Skip to content

Commit f50ebb3

Browse files
committed
factor out compressor to reuse for blake2bp/sp
1 parent 6bc31b3 commit f50ebb3

File tree

6 files changed

+227
-102
lines changed

6 files changed

+227
-102
lines changed

blake2/src/blake2.rs

Lines changed: 213 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,115 @@
1-
macro_rules! blake2_impl {
1+
macro_rules! blake2_compressor_impl {
22
(
3-
$state:ident, $fix_state:ident, $word:ident, $vec:ident, $bytes:ident,
3+
$compressor:ident, $builder:ident, $word:ident, $vec:ident, $bytes:ident,
44
$R1:expr, $R2:expr, $R3:expr, $R4:expr, $IV:expr,
5-
$vardoc:expr, $doc:expr,
5+
$XofLen:ident, $reserved_len:expr, $salt_len:expr,
66
) => {
77

88
use $crate::as_bytes::AsBytes;
99
use $crate::simd::{Vector4, $vec};
1010

11-
use digest::{Input, BlockInput, FixedOutput, VariableOutput, Reset};
12-
use digest::InvalidOutputSize;
11+
use byte_tools::copy;
12+
use core::{mem, u8, u32};
1313
use digest::generic_array::GenericArray;
1414
use digest::generic_array::typenum::Unsigned;
15-
use core::cmp;
16-
use byte_tools::{copy, zero};
17-
use crypto_mac::{Mac, MacResult, InvalidKeyLength};
1815

19-
type Output = GenericArray<u8, $bytes>;
16+
#[derive(Clone, Copy)]
17+
#[repr(packed)]
18+
#[allow(unused)]
19+
pub struct $builder {
20+
digest_len: u8,
21+
key_len: u8,
22+
fanout: u8,
23+
depth: u8,
24+
leaf_len: u32,
25+
node_offs: u32,
26+
xof_len: $XofLen,
27+
node_depth: u8,
28+
inner_len: u8,
29+
reserved: [u8; $reserved_len],
30+
salt: [u8; $salt_len],
31+
personal: [u8; $salt_len],
32+
}
2033

21-
#[derive(Clone)]
22-
#[doc=$vardoc]
23-
pub struct $state {
24-
m: [$word; 16],
25-
h: [$vec; 2],
26-
t: u64,
27-
n: usize,
34+
impl $builder {
35+
pub fn new() -> Self {
36+
Self {
37+
digest_len: 0,
38+
key_len: 0,
39+
fanout: 1,
40+
depth: 1,
41+
leaf_len: 0,
42+
node_offs: 0,
43+
xof_len: 0,
44+
node_depth: 0,
45+
inner_len: 0,
46+
reserved: Default::default(),
47+
salt: Default::default(),
48+
personal: Default::default(),
49+
}
50+
}
2851

29-
h0: [$vec; 2],
30-
m0: [$word; 16],
31-
t0: u64,
52+
pub fn out(&mut self, out: usize) {
53+
assert!(out <= usize::from(u8::MAX));
54+
self.digest_len = out as u8;
55+
}
56+
57+
pub fn key(&mut self, kk: usize) {
58+
assert!(kk as usize <= $bytes::to_usize());
59+
self.key_len = kk as u8;
60+
}
61+
62+
pub fn fanout(&mut self, fanout: u8) {
63+
self.fanout = fanout;
64+
}
65+
66+
pub fn depth(&mut self, depth: u8) {
67+
self.depth = depth;
68+
}
69+
70+
pub fn node_depth(&mut self, node_depth: u8) {
71+
self.node_depth = node_depth;
72+
}
73+
74+
pub fn node_offset(&mut self, node_offs: usize) {
75+
assert!(node_offs <= u32::MAX as usize);
76+
assert!(node_offs as u32 <= u32::MAX);
77+
self.node_offs = u32::to_le(node_offs as u32);
78+
}
79+
80+
pub fn inner_length(&mut self, inner_len: u8) {
81+
self.inner_len = inner_len;
82+
}
83+
84+
pub fn build(&self) -> $compressor {
85+
assert!(self.digest_len > 0);
86+
// All fields of both types are Copy.
87+
// Field endianness is handled at field-setting time.
88+
let h0: [$vec; 2] = unsafe { mem::transmute(*self) };
89+
$compressor {
90+
h: [iv0() ^ h0[0].to_le(), iv1() ^ h0[1].to_le()],
91+
}
92+
}
3293
}
3394

3495
#[inline(always)]
3596
fn iv0() -> $vec { $vec::new($IV[0], $IV[1], $IV[2], $IV[3]) }
3697
#[inline(always)]
3798
fn iv1() -> $vec { $vec::new($IV[4], $IV[5], $IV[6], $IV[7]) }
3899

100+
#[derive(Clone)]
101+
pub struct $compressor {
102+
h: [$vec; 2],
103+
}
104+
105+
impl Default for $compressor {
106+
fn default() -> Self {
107+
Self {
108+
h: [$vec::new(0, 0, 0, 0), $vec::new(0, 0, 0, 0)]
109+
}
110+
}
111+
}
112+
39113
#[inline(always)]
40114
fn quarter_round(v: &mut [$vec; 4], rd: u32, rb: u32, m: $vec) {
41115
v[0] = v[0].wrapping_add(v[1]).wrapping_add(m.from_le());
@@ -73,39 +147,131 @@ macro_rules! blake2_impl {
73147
unshuffle(v);
74148
}
75149

150+
impl $compressor {
151+
pub fn with_parameter_block(p: &[$word; 8]) -> Self {
152+
let h0 = [
153+
iv0() ^ $vec::new(p[0], p[1], p[2], p[3]),
154+
iv1() ^ $vec::new(p[4], p[5], p[6], p[7]),
155+
];
156+
Self {
157+
h: h0,
158+
}
159+
}
160+
161+
pub fn compress(&mut self, m: &[$word; 16], f0: $word, f1: $word, t: u64) {
162+
use $crate::consts::SIGMA;
163+
164+
let h = &mut self.h;
165+
166+
let t0 = t as $word;
167+
let t1 = match $bytes::to_u8() {
168+
64 => 0,
169+
32 => (t >> 32) as $word,
170+
_ => unreachable!(),
171+
};
172+
173+
let mut v = [
174+
h[0],
175+
h[1],
176+
iv0(),
177+
iv1() ^ $vec::new(t0, t1, f0, f1),
178+
];
179+
180+
round(&mut v, m, &SIGMA[0]);
181+
round(&mut v, m, &SIGMA[1]);
182+
round(&mut v, m, &SIGMA[2]);
183+
round(&mut v, m, &SIGMA[3]);
184+
round(&mut v, m, &SIGMA[4]);
185+
round(&mut v, m, &SIGMA[5]);
186+
round(&mut v, m, &SIGMA[6]);
187+
round(&mut v, m, &SIGMA[7]);
188+
round(&mut v, m, &SIGMA[8]);
189+
round(&mut v, m, &SIGMA[9]);
190+
if $bytes::to_u8() == 64 {
191+
round(&mut v, m, &SIGMA[0]);
192+
round(&mut v, m, &SIGMA[1]);
193+
}
194+
195+
h[0] = h[0] ^ (v[0] ^ v[2]);
196+
h[1] = h[1] ^ (v[1] ^ v[3]);
197+
}
198+
199+
pub fn finalize(&mut self, out: &mut GenericArray<u8, $bytes>, m: &[$word; 16], f1: $word, t: u64) {
200+
self.compress(m, !0, f1, t);
201+
let buf = [self.h[0].to_le(), self.h[1].to_le()];
202+
copy(buf.as_bytes(), out);
203+
}
204+
205+
pub fn finalize_into_slice(&mut self, out: &mut [u8], m: &[$word; 16], f1: $word, t: u64) {
206+
self.compress(m, !0, f1, t);
207+
let buf = [self.h[0].to_le(), self.h[1].to_le()];
208+
out.copy_from_slice(buf.as_bytes());
209+
}
210+
211+
pub fn builder() -> $builder {
212+
$builder::new()
213+
}
214+
}
215+
}
216+
}
217+
218+
macro_rules! blake2_impl {
219+
(
220+
$state:ident, $fix_state:ident, $compressor:ident, $word:ident, $bytes:ident,
221+
$vardoc:expr, $doc:expr,
222+
) => {
223+
224+
use $crate::as_bytes::AsBytes;
225+
226+
use digest::{Input, BlockInput, FixedOutput, VariableOutput, Reset};
227+
use digest::InvalidOutputSize;
228+
use digest::generic_array::GenericArray;
229+
use digest::generic_array::typenum::Unsigned;
230+
use core::cmp;
231+
use byte_tools::{copy, zero};
232+
use crypto_mac::{Mac, MacResult, InvalidKeyLength};
233+
234+
type Output = GenericArray<u8, $bytes>;
235+
236+
#[derive(Clone)]
237+
#[doc=$vardoc]
238+
pub struct $state {
239+
n: usize,
240+
h: $compressor,
241+
m: [$word; 16],
242+
h0: $compressor,
243+
m0: [$word; 16],
244+
t: u64,
245+
t0: u64,
246+
}
247+
76248
impl $state {
77249
/// Creates a new hashing context with a key.
78250
///
79251
/// **WARNING!** If you plan to use it for variable output MAC, then
80252
/// make sure to compare codes in constant time! It can be done
81253
/// for example by using `subtle` crate.
82254
pub fn new_keyed(key: &[u8], output_size: usize) -> Self {
83-
let kk = key.len();
84-
assert!(kk <= $bytes::to_usize());
85-
assert!(output_size <= $bytes::to_usize());
86-
87-
let p0 = 0x0101_0000 ^ ((kk as $word) << 8) ^
88-
(output_size as $word);
89-
let h0 = [iv0() ^ $vec::new(p0, 0, 0, 0), iv1()];
90-
let mut state = $state {
91-
m: [0; 16],
92-
h: h0,
93-
t: 0,
255+
let mut h0 = $compressor::builder();
256+
h0.key(key.len());
257+
h0.out(output_size);
258+
let h0 = h0.build();
259+
let mut m = [0; 16];
260+
let mut t = 0;
261+
if !key.is_empty() {
262+
copy(key, m.as_mut_bytes());
263+
t = 2 * $bytes::to_u64();
264+
}
265+
$state {
266+
m,
267+
h: h0.clone(),
268+
t,
94269
n: output_size,
95270

96-
t0: 0,
97-
m0: [0; 16],
271+
t0: t,
272+
m0: m,
98273
h0: h0,
99-
};
100-
101-
if kk > 0 {
102-
copy(key, state.m.as_mut_bytes());
103-
state.t = 2 * $bytes::to_u64();
104274
}
105-
106-
state.t0 = state.t;
107-
state.m0 = state.m;
108-
state
109275
}
110276

111277
#[doc(hidden)]
@@ -114,15 +280,10 @@ macro_rules! blake2_impl {
114280
let kk = (p[0] >> 8) as u8 as usize;
115281
assert!(nn >= 1 && nn <= $bytes::to_usize());
116282
assert!(kk <= $bytes::to_usize());
117-
118-
let h0 = [
119-
iv0() ^ $vec::new(p[0], p[1], p[2], p[3]),
120-
iv1() ^ $vec::new(p[4], p[5], p[6], p[7]),
121-
];
122-
283+
let h0 = $compressor::with_parameter_block(p);
123284
$state {
124285
m: [0; 16],
125-
h: h0,
286+
h: h0.clone(),
126287
t: 0,
127288
n: nn,
128289

@@ -151,7 +312,7 @@ macro_rules! blake2_impl {
151312
}
152313

153314
while rest.len() >= block {
154-
self.compress(0, 0);
315+
self.h.compress(&self.m, 0, 0, self.t);
155316

156317
let part = &rest[..block];
157318
rest = &rest[part.len()..];
@@ -163,7 +324,7 @@ macro_rules! blake2_impl {
163324

164325
let n = rest.len();
165326
if n > 0 {
166-
self.compress(0, 0);
327+
self.h.compress(&self.m, 0, 0, self.t);
167328

168329
copy(rest, &mut self.m.as_mut_bytes());
169330
self.t = self.t.checked_add(rest.len() as u64)
@@ -182,54 +343,10 @@ macro_rules! blake2_impl {
182343
if off != 0 {
183344
zero(&mut self.m.as_mut_bytes()[off..]);
184345
}
185-
186-
self.compress(!0, f1);
187-
188-
let buf = [self.h[0].to_le(), self.h[1].to_le()];
189-
190346
let mut out = GenericArray::default();
191-
copy(buf.as_bytes(), &mut out);
347+
self.h.finalize(&mut out, &self.m, f1, self.t);
192348
out
193349
}
194-
195-
fn compress(&mut self, f0: $word, f1: $word) {
196-
use $crate::consts::SIGMA;
197-
198-
let m = &self.m;
199-
let h = &mut self.h;
200-
201-
let t0 = self.t as $word;
202-
let t1 = match $bytes::to_u8() {
203-
64 => 0,
204-
32 => (self.t >> 32) as $word,
205-
_ => unreachable!(),
206-
};
207-
208-
let mut v = [
209-
h[0],
210-
h[1],
211-
iv0(),
212-
iv1() ^ $vec::new(t0, t1, f0, f1),
213-
];
214-
215-
round(&mut v, m, &SIGMA[0]);
216-
round(&mut v, m, &SIGMA[1]);
217-
round(&mut v, m, &SIGMA[2]);
218-
round(&mut v, m, &SIGMA[3]);
219-
round(&mut v, m, &SIGMA[4]);
220-
round(&mut v, m, &SIGMA[5]);
221-
round(&mut v, m, &SIGMA[6]);
222-
round(&mut v, m, &SIGMA[7]);
223-
round(&mut v, m, &SIGMA[8]);
224-
round(&mut v, m, &SIGMA[9]);
225-
if $bytes::to_u8() == 64 {
226-
round(&mut v, m, &SIGMA[0]);
227-
round(&mut v, m, &SIGMA[1]);
228-
}
229-
230-
h[0] = h[0] ^ (v[0] ^ v[2]);
231-
h[1] = h[1] ^ (v[1] ^ v[3]);
232-
}
233350
}
234351

235352
impl Default for $state {
@@ -269,7 +386,7 @@ macro_rules! blake2_impl {
269386
fn reset(&mut self) {
270387
self.t = self.t0;
271388
self.m = self.m0;
272-
self.h = self.h0;
389+
self.h = self.h0.clone();
273390
}
274391
}
275392

0 commit comments

Comments
 (0)