1- #![ allow( clippy:: many_single_char_names) ]
21use crate :: consts:: K32 ;
32
4- #[ inline( always) ]
5- fn shr ( v : [ u32 ; 4 ] , o : u32 ) -> [ u32 ; 4 ] {
6- [ v[ 0 ] >> o, v[ 1 ] >> o, v[ 2 ] >> o, v[ 3 ] >> o]
7- }
8-
9- #[ inline( always) ]
10- fn shl ( v : [ u32 ; 4 ] , o : u32 ) -> [ u32 ; 4 ] {
11- [ v[ 0 ] << o, v[ 1 ] << o, v[ 2 ] << o, v[ 3 ] << o]
12- }
13-
14- #[ inline( always) ]
15- fn or ( a : [ u32 ; 4 ] , b : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
16- [ a[ 0 ] | b[ 0 ] , a[ 1 ] | b[ 1 ] , a[ 2 ] | b[ 2 ] , a[ 3 ] | b[ 3 ] ]
17- }
18-
19- #[ inline( always) ]
20- fn xor ( a : [ u32 ; 4 ] , b : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
21- [ a[ 0 ] ^ b[ 0 ] , a[ 1 ] ^ b[ 1 ] , a[ 2 ] ^ b[ 2 ] , a[ 3 ] ^ b[ 3 ] ]
22- }
23-
24- #[ inline( always) ]
25- fn add ( a : [ u32 ; 4 ] , b : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
26- [
27- a[ 0 ] . wrapping_add ( b[ 0 ] ) ,
28- a[ 1 ] . wrapping_add ( b[ 1 ] ) ,
29- a[ 2 ] . wrapping_add ( b[ 2 ] ) ,
30- a[ 3 ] . wrapping_add ( b[ 3 ] ) ,
31- ]
32- }
33-
34- #[ inline( always) ]
35- fn add_round_const ( mut a : [ u32 ; 4 ] , i : usize ) -> [ u32 ; 4 ] {
36- fn k ( i : usize , j : usize ) -> u32 {
37- // `read_volatile` forces compiler to read round constants from the static
38- // instead of inlining them, which improves codegen and performance on some platforms.
39- // On x86 targets 32-bit constants can be encoded using immediate argument on the `add`
40- // instruction, so it's more efficient to inline them.
41- cfg_if:: cfg_if! {
42- if #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ] {
43- use core:: ptr:: read as r;
44- } else {
45- use core:: ptr:: read_volatile as r;
46- }
3+ #[ rustfmt:: skip]
4+ macro_rules! repeat64 {
5+ ( $i: ident, $b: block) => {
6+ let $i = 0 ; $b; let $i = 1 ; $b; let $i = 2 ; $b; let $i = 3 ; $b;
7+ let $i = 4 ; $b; let $i = 5 ; $b; let $i = 6 ; $b; let $i = 7 ; $b;
8+ let $i = 8 ; $b; let $i = 9 ; $b; let $i = 10 ; $b; let $i = 11 ; $b;
9+ let $i = 12 ; $b; let $i = 13 ; $b; let $i = 14 ; $b; let $i = 15 ; $b;
10+ let $i = 16 ; $b; let $i = 17 ; $b; let $i = 18 ; $b; let $i = 19 ; $b;
11+ let $i = 20 ; $b; let $i = 21 ; $b; let $i = 22 ; $b; let $i = 23 ; $b;
12+ let $i = 24 ; $b; let $i = 25 ; $b; let $i = 26 ; $b; let $i = 27 ; $b;
13+ let $i = 28 ; $b; let $i = 29 ; $b; let $i = 30 ; $b; let $i = 31 ; $b;
14+ let $i = 32 ; $b; let $i = 33 ; $b; let $i = 34 ; $b; let $i = 35 ; $b;
15+ let $i = 36 ; $b; let $i = 37 ; $b; let $i = 38 ; $b; let $i = 39 ; $b;
16+ let $i = 40 ; $b; let $i = 41 ; $b; let $i = 42 ; $b; let $i = 43 ; $b;
17+ let $i = 44 ; $b; let $i = 45 ; $b; let $i = 46 ; $b; let $i = 47 ; $b;
18+ let $i = 48 ; $b; let $i = 49 ; $b; let $i = 50 ; $b; let $i = 51 ; $b;
19+ let $i = 52 ; $b; let $i = 53 ; $b; let $i = 54 ; $b; let $i = 55 ; $b;
20+ let $i = 56 ; $b; let $i = 57 ; $b; let $i = 58 ; $b; let $i = 59 ; $b;
21+ let $i = 60 ; $b; let $i = 61 ; $b; let $i = 62 ; $b; let $i = 63 ; $b;
22+ } ;
23+ }
24+
25+ /// Read round constant
26+ fn rk ( i : usize ) -> u32 {
27+ // `read_volatile` forces compiler to read round constants from the static
28+ // instead of inlining them, which improves codegen and performance on some platforms.
29+ // On x86 targets 32-bit constants can be encoded using immediate argument on the `add`
30+ // instruction, so it's more efficient to inline them.
31+ cfg_if:: cfg_if! {
32+ if #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ] {
33+ use core:: ptr:: read as r;
34+ } else {
35+ use core:: ptr:: read_volatile as r;
4736 }
48-
49- unsafe { r ( K32 . as_ptr ( ) . add ( 4 * i + j) ) }
50- }
51-
52- a[ 3 ] = a[ 3 ] . wrapping_add ( k ( i, 0 ) ) ;
53- a[ 2 ] = a[ 2 ] . wrapping_add ( k ( i, 1 ) ) ;
54- a[ 1 ] = a[ 1 ] . wrapping_add ( k ( i, 2 ) ) ;
55- a[ 0 ] = a[ 0 ] . wrapping_add ( k ( i, 3 ) ) ;
56- a
57- }
58-
59- fn sha256load ( v2 : [ u32 ; 4 ] , v3 : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
60- [ v3[ 3 ] , v2[ 0 ] , v2[ 1 ] , v2[ 2 ] ]
61- }
62-
63- fn sha256swap ( v0 : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
64- [ v0[ 2 ] , v0[ 3 ] , v0[ 0 ] , v0[ 1 ] ]
65- }
66-
67- fn sha256msg1 ( v0 : [ u32 ; 4 ] , v1 : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
68- // sigma 0 on vectors
69- #[ inline]
70- fn sigma0x4 ( x : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
71- let t1 = or ( shr ( x, 7 ) , shl ( x, 25 ) ) ;
72- let t2 = or ( shr ( x, 18 ) , shl ( x, 14 ) ) ;
73- let t3 = shr ( x, 3 ) ;
74- xor ( xor ( t1, t2) , t3)
75- }
76-
77- add ( v0, sigma0x4 ( sha256load ( v0, v1) ) )
78- }
79-
80- fn sha256msg2 ( v4 : [ u32 ; 4 ] , v3 : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
81- macro_rules! sigma1 {
82- ( $a: expr) => {
83- $a. rotate_right( 17 ) ^ $a. rotate_right( 19 ) ^ ( $a >> 10 )
84- } ;
8537 }
8638
87- let [ x3, x2, x1, x0] = v4;
88- let [ w15, w14, _, _] = v3;
89-
90- let w16 = x0. wrapping_add ( sigma1 ! ( w14) ) ;
91- let w17 = x1. wrapping_add ( sigma1 ! ( w15) ) ;
92- let w18 = x2. wrapping_add ( sigma1 ! ( w16) ) ;
93- let w19 = x3. wrapping_add ( sigma1 ! ( w17) ) ;
94-
95- [ w19, w18, w17, w16]
96- }
97-
98- fn sha256_digest_round_x2 ( cdgh : [ u32 ; 4 ] , abef : [ u32 ; 4 ] , wk : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
99- macro_rules! big_sigma0 {
100- ( $a: expr) => {
101- ( $a. rotate_right( 2 ) ^ $a. rotate_right( 13 ) ^ $a. rotate_right( 22 ) )
102- } ;
39+ unsafe {
40+ let p = K32 . as_ptr ( ) . add ( i) ;
41+ r ( p)
10342 }
104- macro_rules! big_sigma1 {
105- ( $a: expr) => {
106- ( $a. rotate_right( 6 ) ^ $a. rotate_right( 11 ) ^ $a. rotate_right( 25 ) )
107- } ;
108- }
109- macro_rules! bool3ary_202 {
110- ( $a: expr, $b: expr, $c: expr) => {
111- $c ^ ( $a & ( $b ^ $c) )
112- } ;
113- } // Choose, MD5F, SHA1C
114- macro_rules! bool3ary_232 {
115- ( $a: expr, $b: expr, $c: expr) => {
116- ( $a & $b) ^ ( $a & $c) ^ ( $b & $c)
117- } ;
118- } // Majority, SHA1M
119-
120- let [ _, _, wk1, wk0] = wk;
121- let [ a0, b0, e0, f0] = abef;
122- let [ c0, d0, g0, h0] = cdgh;
123-
124- // a round
125- let x0 = big_sigma1 ! ( e0)
126- . wrapping_add ( bool3ary_202 ! ( e0, f0, g0) )
127- . wrapping_add ( wk0)
128- . wrapping_add ( h0) ;
129- let y0 = big_sigma0 ! ( a0) . wrapping_add ( bool3ary_232 ! ( a0, b0, c0) ) ;
130- let ( a1, b1, c1, d1, e1, f1, g1, h1) = (
131- x0. wrapping_add ( y0) ,
132- a0,
133- b0,
134- c0,
135- x0. wrapping_add ( d0) ,
136- e0,
137- f0,
138- g0,
139- ) ;
140-
141- // a round
142- let x1 = big_sigma1 ! ( e1)
143- . wrapping_add ( bool3ary_202 ! ( e1, f1, g1) )
144- . wrapping_add ( wk1)
145- . wrapping_add ( h1) ;
146- let y1 = big_sigma0 ! ( a1) . wrapping_add ( bool3ary_232 ! ( a1, b1, c1) ) ;
147- let ( a2, b2, _, _, e2, f2, _, _) = (
148- x1. wrapping_add ( y1) ,
149- a1,
150- b1,
151- c1,
152- x1. wrapping_add ( d1) ,
153- e1,
154- f1,
155- g1,
156- ) ;
157-
158- [ a2, b2, e2, f2]
159- }
160-
161- fn schedule ( v0 : [ u32 ; 4 ] , v1 : [ u32 ; 4 ] , v2 : [ u32 ; 4 ] , v3 : [ u32 ; 4 ] ) -> [ u32 ; 4 ] {
162- let t1 = sha256msg1 ( v0, v1) ;
163- let t2 = sha256load ( v2, v3) ;
164- let t3 = add ( t1, t2) ;
165- sha256msg2 ( t3, v3)
166- }
167-
168- macro_rules! rounds4 {
169- ( $abef: ident, $cdgh: ident, $rest: expr, $i: expr) => { {
170- let t1 = add_round_const( $rest, $i) ;
171- $cdgh = sha256_digest_round_x2( $cdgh, $abef, t1) ;
172- let t2 = sha256swap( t1) ;
173- $abef = sha256_digest_round_x2( $abef, $cdgh, t2) ;
174- } } ;
175- }
176-
177- macro_rules! schedule_rounds4 {
178- (
179- $abef: ident, $cdgh: ident,
180- $w0: expr, $w1: expr, $w2: expr, $w3: expr, $w4: expr,
181- $i: expr
182- ) => { {
183- $w4 = schedule( $w0, $w1, $w2, $w3) ;
184- rounds4!( $abef, $cdgh, $w4, $i) ;
185- } } ;
18643}
18744
18845/// Process a block with the SHA-256 algorithm.
189- fn sha256_digest_block_u32 ( state : & mut [ u32 ; 8 ] , block : [ u32 ; 16 ] ) {
190- let mut abef = [ state[ 0 ] , state[ 1 ] , state[ 4 ] , state[ 5 ] ] ;
191- let mut cdgh = [ state[ 2 ] , state[ 3 ] , state[ 6 ] , state[ 7 ] ] ;
192-
193- // Rounds 0..64
194- let mut w0 = [ block[ 3 ] , block[ 2 ] , block[ 1 ] , block[ 0 ] ] ;
195- let mut w1 = [ block[ 7 ] , block[ 6 ] , block[ 5 ] , block[ 4 ] ] ;
196- let mut w2 = [ block[ 11 ] , block[ 10 ] , block[ 9 ] , block[ 8 ] ] ;
197- let mut w3 = [ block[ 15 ] , block[ 14 ] , block[ 13 ] , block[ 12 ] ] ;
198- let mut w4;
199-
200- rounds4 ! ( abef, cdgh, w0, 0 ) ;
201- rounds4 ! ( abef, cdgh, w1, 1 ) ;
202- rounds4 ! ( abef, cdgh, w2, 2 ) ;
203- rounds4 ! ( abef, cdgh, w3, 3 ) ;
204- schedule_rounds4 ! ( abef, cdgh, w0, w1, w2, w3, w4, 4 ) ;
205- schedule_rounds4 ! ( abef, cdgh, w1, w2, w3, w4, w0, 5 ) ;
206- schedule_rounds4 ! ( abef, cdgh, w2, w3, w4, w0, w1, 6 ) ;
207- schedule_rounds4 ! ( abef, cdgh, w3, w4, w0, w1, w2, 7 ) ;
208- schedule_rounds4 ! ( abef, cdgh, w4, w0, w1, w2, w3, 8 ) ;
209- schedule_rounds4 ! ( abef, cdgh, w0, w1, w2, w3, w4, 9 ) ;
210- schedule_rounds4 ! ( abef, cdgh, w1, w2, w3, w4, w0, 10 ) ;
211- schedule_rounds4 ! ( abef, cdgh, w2, w3, w4, w0, w1, 11 ) ;
212- schedule_rounds4 ! ( abef, cdgh, w3, w4, w0, w1, w2, 12 ) ;
213- schedule_rounds4 ! ( abef, cdgh, w4, w0, w1, w2, w3, 13 ) ;
214- schedule_rounds4 ! ( abef, cdgh, w0, w1, w2, w3, w4, 14 ) ;
215- schedule_rounds4 ! ( abef, cdgh, w1, w2, w3, w4, w0, 15 ) ;
46+ fn compress_block ( state : & mut [ u32 ; 8 ] , block : & [ u8 ; 64 ] ) {
47+ let mut block = super :: to_u32s ( block) ;
48+ let [ mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = * state;
49+
50+ repeat64 ! ( i, {
51+ let w = if i < 16 {
52+ block[ i]
53+ } else {
54+ let w15 = block[ ( i - 15 ) % 16 ] ;
55+ let s0 = ( w15. rotate_right( 7 ) ) ^ ( w15. rotate_right( 18 ) ) ^ ( w15 >> 3 ) ;
56+ let w2 = block[ ( i - 2 ) % 16 ] ;
57+ let s1 = ( w2. rotate_right( 17 ) ) ^ ( w2. rotate_right( 19 ) ) ^ ( w2 >> 10 ) ;
58+ block[ i % 16 ] = block[ i % 16 ]
59+ . wrapping_add( s0)
60+ . wrapping_add( block[ ( i - 7 ) % 16 ] )
61+ . wrapping_add( s1) ;
62+ block[ i % 16 ]
63+ } ;
21664
217- let [ a, b, e, f] = abef;
218- let [ c, d, g, h] = cdgh;
65+ let s1 = e. rotate_right( 6 ) ^ e. rotate_right( 11 ) ^ e. rotate_right( 25 ) ;
66+ let ch = ( e & f) ^ ( ( !e) & g) ;
67+ let t1 = s1
68+ . wrapping_add( ch)
69+ . wrapping_add( rk( i) )
70+ . wrapping_add( w)
71+ . wrapping_add( h) ;
72+ let s0 = a. rotate_right( 2 ) ^ a. rotate_right( 13 ) ^ a. rotate_right( 22 ) ;
73+ let maj = ( a & b) ^ ( a & c) ^ ( b & c) ;
74+ let t2 = s0. wrapping_add( maj) ;
75+
76+ h = g;
77+ g = f;
78+ f = e;
79+ e = d. wrapping_add( t1) ;
80+ d = c;
81+ c = b;
82+ b = a;
83+ a = t1. wrapping_add( t2) ;
84+ } ) ;
21985
22086 state[ 0 ] = state[ 0 ] . wrapping_add ( a) ;
22187 state[ 1 ] = state[ 1 ] . wrapping_add ( b) ;
@@ -228,7 +94,7 @@ fn sha256_digest_block_u32(state: &mut [u32; 8], block: [u32; 16]) {
22894}
22995
23096pub fn compress ( state : & mut [ u32 ; 8 ] , blocks : & [ [ u8 ; 64 ] ] ) {
231- for block in blocks. iter ( ) . map ( super :: to_u32s ) {
232- sha256_digest_block_u32 ( state, block) ;
97+ for block in blocks {
98+ compress_block ( state, block) ;
23399 }
234100}
0 commit comments