1
1
macro_rules! blake2_impl {
2
2
(
3
- $state: ident, $fix_state: ident, $word: ident, $vec: ident, $bytes: ident,
4
- $R1: expr, $R2: expr, $R3: expr, $R4: expr, $IV: expr,
5
- $vardoc: expr, $doc: expr,
3
+ $state: ident, $fix_state: ident, $word: ident, $bytes: ident,
4
+ $vardoc: expr, $doc: expr, $lib: ident,
6
5
) => {
7
-
8
- use $crate:: as_bytes:: AsBytes ;
9
- use $crate:: simd:: { Vector4 , $vec} ;
10
-
11
6
use digest:: { Input , BlockInput , FixedOutput , VariableOutput , Reset } ;
12
7
use digest:: InvalidOutputSize ;
13
8
use digest:: generic_array:: GenericArray ;
14
9
use digest:: generic_array:: typenum:: Unsigned ;
15
- use core:: cmp;
16
- use byte_tools:: { copy, zero} ;
10
+ use byte_tools:: copy;
17
11
use crypto_mac:: { Mac , MacResult , InvalidKeyLength } ;
18
12
13
+ use $lib:: Params ;
14
+ use $lib:: State ;
15
+
19
16
type Output = GenericArray <u8 , $bytes>;
20
17
21
18
#[ derive( Clone ) ]
22
19
#[ doc=$vardoc]
23
20
pub struct $state {
24
- m: [ $word; 16 ] ,
25
- h: [ $vec; 2 ] ,
26
- t: u64 ,
27
- n: usize ,
28
-
29
- h0: [ $vec; 2 ] ,
30
- m0: [ $word; 16 ] ,
31
- t0: u64 ,
32
- }
33
-
34
- #[ inline( always) ]
35
- fn iv0( ) -> $vec { $vec:: new( $IV[ 0 ] , $IV[ 1 ] , $IV[ 2 ] , $IV[ 3 ] ) }
36
- #[ inline( always) ]
37
- fn iv1( ) -> $vec { $vec:: new( $IV[ 4 ] , $IV[ 5 ] , $IV[ 6 ] , $IV[ 7 ] ) }
38
-
39
- #[ inline( always) ]
40
- fn quarter_round( v: & mut [ $vec; 4 ] , rd: u32 , rb: u32 , m: $vec) {
41
- v[ 0 ] = v[ 0 ] . wrapping_add( v[ 1 ] ) . wrapping_add( m. from_le( ) ) ;
42
- v[ 3 ] = ( v[ 3 ] ^ v[ 0 ] ) . rotate_right_const( rd) ;
43
- v[ 2 ] = v[ 2 ] . wrapping_add( v[ 3 ] ) ;
44
- v[ 1 ] = ( v[ 1 ] ^ v[ 2 ] ) . rotate_right_const( rb) ;
45
- }
46
-
47
- #[ inline( always) ]
48
- fn shuffle( v: & mut [ $vec; 4 ] ) {
49
- v[ 1 ] = v[ 1 ] . shuffle_left_1( ) ;
50
- v[ 2 ] = v[ 2 ] . shuffle_left_2( ) ;
51
- v[ 3 ] = v[ 3 ] . shuffle_left_3( ) ;
52
- }
53
-
54
- #[ inline( always) ]
55
- fn unshuffle( v: & mut [ $vec; 4 ] ) {
56
- v[ 1 ] = v[ 1 ] . shuffle_right_1( ) ;
57
- v[ 2 ] = v[ 2 ] . shuffle_right_2( ) ;
58
- v[ 3 ] = v[ 3 ] . shuffle_right_3( ) ;
59
- }
60
-
61
- #[ inline( always) ]
62
- fn round( v: & mut [ $vec; 4 ] , m: & [ $word; 16 ] , s: & [ usize ; 16 ] ) {
63
- quarter_round( v, $R1, $R2, $vec:: gather( m,
64
- s[ 0 ] , s[ 2 ] , s[ 4 ] , s[ 6 ] ) ) ;
65
- quarter_round( v, $R3, $R4, $vec:: gather( m,
66
- s[ 1 ] , s[ 3 ] , s[ 5 ] , s[ 7 ] ) ) ;
67
-
68
- shuffle( v) ;
69
- quarter_round( v, $R1, $R2, $vec:: gather( m,
70
- s[ 8 ] , s[ 10 ] , s[ 12 ] , s[ 14 ] ) ) ;
71
- quarter_round( v, $R3, $R4, $vec:: gather( m,
72
- s[ 9 ] , s[ 11 ] , s[ 13 ] , s[ 15 ] ) ) ;
73
- unshuffle( v) ;
21
+ params: Params ,
22
+ state: State ,
23
+ output_size: usize ,
74
24
}
75
25
76
26
impl $state {
@@ -80,156 +30,33 @@ macro_rules! blake2_impl {
80
30
/// make sure to compare codes in constant time! It can be done
81
31
/// for example by using `subtle` crate.
82
32
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 ,
94
- n: output_size,
95
-
96
- t0: 0 ,
97
- m0: [ 0 ; 16 ] ,
98
- h0: h0,
99
- } ;
100
-
101
- if kk > 0 {
102
- copy( key, state. m. as_mut_bytes( ) ) ;
103
- state. t = 2 * $bytes:: to_u64( ) ;
104
- }
105
-
106
- state. t0 = state. t;
107
- state. m0 = state. m;
108
- state
109
- }
110
-
111
- #[ doc( hidden) ]
112
- pub fn with_parameter_block( p: & [ $word; 8 ] ) -> Self {
113
- let nn = p[ 0 ] as u8 as usize ;
114
- let kk = ( p[ 0 ] >> 8 ) as u8 as usize ;
115
- assert!( nn >= 1 && nn <= $bytes:: to_usize( ) ) ;
116
- 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
-
123
- $state {
124
- m: [ 0 ; 16 ] ,
125
- h: h0,
126
- t: 0 ,
127
- n: nn,
128
-
129
- t0: 0 ,
130
- m0: [ 0 ; 16 ] ,
131
- h0: h0,
33
+ let mut params = Params :: new( ) ;
34
+ params. hash_length( output_size) ;
35
+ params. key( key) ;
36
+ Self {
37
+ state: params. to_state( ) ,
38
+ params,
39
+ output_size,
132
40
}
133
41
}
134
42
135
43
/// Updates the hashing context with more data.
136
44
fn update( & mut self , data: & [ u8 ] ) {
137
- let mut rest = data;
138
-
139
- let block = 2 * $bytes:: to_usize( ) ;
140
-
141
- let off = self . t as usize % block;
142
- if off != 0 || self . t == 0 {
143
- let len = cmp:: min( block - off, rest. len( ) ) ;
144
-
145
- let part = & rest[ ..len] ;
146
- rest = & rest[ part. len( ) ..] ;
147
-
148
- copy( part, & mut self . m. as_mut_bytes( ) [ off..] ) ;
149
- self . t = self . t. checked_add( part. len( ) as u64 )
150
- . expect( "hash data length overflow" ) ;
151
- }
152
-
153
- while rest. len( ) >= block {
154
- self . compress( 0 , 0 ) ;
155
-
156
- let part = & rest[ ..block] ;
157
- rest = & rest[ part. len( ) ..] ;
158
-
159
- copy( part, & mut self . m. as_mut_bytes( ) ) ;
160
- self . t = self . t. checked_add( part. len( ) as u64 )
161
- . expect( "hash data length overflow" ) ;
162
- }
163
-
164
- let n = rest. len( ) ;
165
- if n > 0 {
166
- self . compress( 0 , 0 ) ;
167
-
168
- copy( rest, & mut self . m. as_mut_bytes( ) ) ;
169
- self . t = self . t. checked_add( rest. len( ) as u64 )
170
- . expect( "hash data length overflow" ) ;
171
- }
45
+ self . state. update( data) ;
172
46
}
173
47
174
48
#[ doc( hidden) ]
175
49
pub fn finalize_last_node( self ) -> Output {
176
- self . finalize_with_flag ( ! 0 )
50
+ self . finalize_with_last_node ( true )
177
51
}
178
52
179
-
180
- fn finalize_with_flag( mut self , f1: $word) -> Output {
181
- let off = self . t as usize % ( 2 * $bytes:: to_usize( ) ) ;
182
- if off != 0 {
183
- zero( & mut self . m. as_mut_bytes( ) [ off..] ) ;
184
- }
185
-
186
- self . compress( !0 , f1) ;
187
-
188
- let buf = [ self . h[ 0 ] . to_le( ) , self . h[ 1 ] . to_le( ) ] ;
189
-
53
+ fn finalize_with_last_node( mut self , last_node: bool ) -> Output {
54
+ self . state. set_last_node( last_node) ;
55
+ let hash = self . state. finalize( ) ;
190
56
let mut out = GenericArray :: default ( ) ;
191
- copy( buf . as_bytes( ) , & mut out) ;
57
+ copy( hash . as_bytes( ) , & mut out) ;
192
58
out
193
59
}
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
60
}
234
61
235
62
impl Default for $state {
@@ -255,21 +82,19 @@ macro_rules! blake2_impl {
255
82
}
256
83
257
84
fn output_size( & self ) -> usize {
258
- self . n
85
+ self . output_size
259
86
}
260
87
261
88
fn variable_result<F : FnOnce ( & [ u8 ] ) >( self , f: F ) {
262
- let n = self . n ;
263
- let res = self . finalize_with_flag ( 0 ) ;
89
+ let n = self . output_size ;
90
+ let res = self . finalize_with_last_node ( false ) ;
264
91
f( & res[ ..n] ) ;
265
92
}
266
93
}
267
94
268
95
impl Reset for $state {
269
96
fn reset( & mut self ) {
270
- self . t = self . t0;
271
- self . m = self . m0;
272
- self . h = self . h0;
97
+ self . state = self . params. to_state( ) ;
273
98
}
274
99
}
275
100
@@ -304,7 +129,7 @@ macro_rules! blake2_impl {
304
129
type OutputSize = $bytes;
305
130
306
131
fn fixed_result( self ) -> Output {
307
- self . state. finalize_with_flag ( 0 )
132
+ self . state. finalize_with_last_node ( false )
308
133
}
309
134
}
310
135
@@ -339,7 +164,7 @@ macro_rules! blake2_impl {
339
164
}
340
165
341
166
fn result( self ) -> MacResult <Self :: OutputSize > {
342
- MacResult :: new( self . state. finalize_with_flag ( 0 ) )
167
+ MacResult :: new( self . state. finalize_with_last_node ( false ) )
343
168
}
344
169
}
345
170
0 commit comments