1
- macro_rules! blake2_impl {
1
+ macro_rules! blake2_compressor_impl {
2
2
(
3
- $state : ident, $fix_state : ident, $word: ident, $vec: ident, $bytes: ident,
3
+ $compressor : ident, $builder : ident, $word: ident, $vec: ident, $bytes: ident,
4
4
$R1: expr, $R2: expr, $R3: expr, $R4: expr, $IV: expr,
5
- $vardoc : expr, $doc : expr,
5
+ $XofLen : ident , $reserved_len : expr, $salt_len : expr,
6
6
) => {
7
7
8
8
use $crate:: as_bytes:: AsBytes ;
9
9
use $crate:: simd:: { Vector4 , $vec} ;
10
10
11
- use digest :: { Input , BlockInput , FixedOutput , VariableOutput , Reset } ;
12
- use digest :: InvalidOutputSize ;
11
+ use byte_tools :: copy ;
12
+ use core :: { mem , u8 , u32 } ;
13
13
use digest:: generic_array:: GenericArray ;
14
14
use digest:: generic_array:: typenum:: Unsigned ;
15
- use core:: cmp;
16
- use byte_tools:: { copy, zero} ;
17
- use crypto_mac:: { Mac , MacResult , InvalidKeyLength } ;
18
15
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
+ }
20
33
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
+ }
28
51
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
+ }
32
93
}
33
94
34
95
#[ inline( always) ]
35
96
fn iv0( ) -> $vec { $vec:: new( $IV[ 0 ] , $IV[ 1 ] , $IV[ 2 ] , $IV[ 3 ] ) }
36
97
#[ inline( always) ]
37
98
fn iv1( ) -> $vec { $vec:: new( $IV[ 4 ] , $IV[ 5 ] , $IV[ 6 ] , $IV[ 7 ] ) }
38
99
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
+
39
113
#[ inline( always) ]
40
114
fn quarter_round( v: & mut [ $vec; 4 ] , rd: u32 , rb: u32 , m: $vec) {
41
115
v[ 0 ] = v[ 0 ] . wrapping_add( v[ 1 ] ) . wrapping_add( m. from_le( ) ) ;
@@ -73,39 +147,131 @@ macro_rules! blake2_impl {
73
147
unshuffle( v) ;
74
148
}
75
149
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
+
76
248
impl $state {
77
249
/// Creates a new hashing context with a key.
78
250
///
79
251
/// **WARNING!** If you plan to use it for variable output MAC, then
80
252
/// make sure to compare codes in constant time! It can be done
81
253
/// for example by using `subtle` crate.
82
254
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,
94
269
n: output_size,
95
270
96
- t0: 0 ,
97
- m0: [ 0 ; 16 ] ,
271
+ t0: t ,
272
+ m0: m ,
98
273
h0: h0,
99
- } ;
100
-
101
- if kk > 0 {
102
- copy( key, state. m. as_mut_bytes( ) ) ;
103
- state. t = 2 * $bytes:: to_u64( ) ;
104
274
}
105
-
106
- state. t0 = state. t;
107
- state. m0 = state. m;
108
- state
109
275
}
110
276
111
277
#[ doc( hidden) ]
@@ -114,15 +280,10 @@ macro_rules! blake2_impl {
114
280
let kk = ( p[ 0 ] >> 8 ) as u8 as usize ;
115
281
assert!( nn >= 1 && nn <= $bytes:: to_usize( ) ) ;
116
282
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) ;
123
284
$state {
124
285
m: [ 0 ; 16 ] ,
125
- h: h0,
286
+ h: h0. clone ( ) ,
126
287
t: 0 ,
127
288
n: nn,
128
289
@@ -151,7 +312,7 @@ macro_rules! blake2_impl {
151
312
}
152
313
153
314
while rest. len( ) >= block {
154
- self . compress( 0 , 0 ) ;
315
+ self . h . compress( & self . m , 0 , 0 , self . t ) ;
155
316
156
317
let part = & rest[ ..block] ;
157
318
rest = & rest[ part. len( ) ..] ;
@@ -163,7 +324,7 @@ macro_rules! blake2_impl {
163
324
164
325
let n = rest. len( ) ;
165
326
if n > 0 {
166
- self . compress( 0 , 0 ) ;
327
+ self . h . compress( & self . m , 0 , 0 , self . t ) ;
167
328
168
329
copy( rest, & mut self . m. as_mut_bytes( ) ) ;
169
330
self . t = self . t. checked_add( rest. len( ) as u64 )
@@ -182,54 +343,10 @@ macro_rules! blake2_impl {
182
343
if off != 0 {
183
344
zero( & mut self . m. as_mut_bytes( ) [ off..] ) ;
184
345
}
185
-
186
- self . compress( !0 , f1) ;
187
-
188
- let buf = [ self . h[ 0 ] . to_le( ) , self . h[ 1 ] . to_le( ) ] ;
189
-
190
346
let mut out = GenericArray :: default ( ) ;
191
- copy ( buf . as_bytes ( ) , & mut out) ;
347
+ self . h . finalize ( & mut out, & self . m , f1 , self . t ) ;
192
348
out
193
349
}
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
- }
233
350
}
234
351
235
352
impl Default for $state {
@@ -269,7 +386,7 @@ macro_rules! blake2_impl {
269
386
fn reset( & mut self ) {
270
387
self . t = self . t0;
271
388
self . m = self . m0;
272
- self . h = self . h0;
389
+ self . h = self . h0. clone ( ) ;
273
390
}
274
391
}
275
392
0 commit comments