7
7
//! Now this crate serves primarily as a wrapper over two SHA256 crates: `sha2` and `ring` – which
8
8
//! it switches between at runtime based on the availability of SHA intrinsics.
9
9
10
+ mod sha2_impl;
11
+
10
12
pub use self :: DynamicContext as Context ;
11
- use sha2:: Digest ;
13
+
14
+ #[ cfg( target_arch = "x86_64" ) ]
15
+ use sha2_impl:: Sha2CrateImpl ;
12
16
13
17
#[ cfg( feature = "zero_hash_cache" ) ]
14
18
use lazy_static:: lazy_static;
@@ -54,35 +58,6 @@ pub trait Sha256 {
54
58
fn hash_fixed ( & self , input : & [ u8 ] ) -> [ u8 ; HASH_LEN ] ;
55
59
}
56
60
57
- /// Implementation of SHA256 using the `sha2` crate (fastest on CPUs with SHA extensions).
58
- struct Sha2CrateImpl ;
59
-
60
- impl Sha256Context for sha2:: Sha256 {
61
- fn new ( ) -> Self {
62
- sha2:: Digest :: new ( )
63
- }
64
-
65
- fn update ( & mut self , bytes : & [ u8 ] ) {
66
- sha2:: Digest :: update ( self , bytes)
67
- }
68
-
69
- fn finalize ( self ) -> [ u8 ; HASH_LEN ] {
70
- sha2:: Digest :: finalize ( self ) . into ( )
71
- }
72
- }
73
-
74
- impl Sha256 for Sha2CrateImpl {
75
- type Context = sha2:: Sha256 ;
76
-
77
- fn hash ( & self , input : & [ u8 ] ) -> Vec < u8 > {
78
- Self :: Context :: digest ( input) . into_iter ( ) . collect ( )
79
- }
80
-
81
- fn hash_fixed ( & self , input : & [ u8 ] ) -> [ u8 ; HASH_LEN ] {
82
- Self :: Context :: digest ( input) . into ( )
83
- }
84
- }
85
-
86
61
/// Implementation of SHA256 using the `ring` crate (fastest on CPUs without SHA extensions).
87
62
pub struct RingImpl ;
88
63
@@ -120,34 +95,39 @@ impl Sha256 for RingImpl {
120
95
121
96
/// Default dynamic implementation that switches between available implementations.
122
97
pub enum DynamicImpl {
98
+ #[ cfg( target_arch = "x86_64" ) ]
123
99
Sha2 ,
124
100
Ring ,
125
101
}
126
102
127
103
// Runtime latch for detecting the availability of SHA extensions on x86_64.
128
104
//
129
105
// Inspired by the runtime switch within the `sha2` crate itself.
130
- #[ cfg( all ( feature = "detect-cpufeatures" , target_arch = "x86_64" ) ) ]
106
+ #[ cfg( target_arch = "x86_64" ) ]
131
107
cpufeatures:: new!( x86_sha_extensions, "sha" , "sse2" , "ssse3" , "sse4.1" ) ;
132
108
133
109
#[ inline( always) ]
134
110
pub fn have_sha_extensions ( ) -> bool {
135
- #[ cfg( all ( feature = "detect-cpufeatures" , target_arch = "x86_64" ) ) ]
111
+ #[ cfg( target_arch = "x86_64" ) ]
136
112
return x86_sha_extensions:: get ( ) ;
137
113
138
- #[ cfg( not( all ( feature = "detect-cpufeatures" , target_arch = "x86_64" ) ) ) ]
114
+ #[ cfg( not( target_arch = "x86_64" ) ) ]
139
115
return false ;
140
116
}
141
117
142
118
impl DynamicImpl {
143
119
/// Choose the best available implementation based on the currently executing CPU.
144
120
#[ inline( always) ]
145
121
pub fn best ( ) -> Self {
122
+ #[ cfg( target_arch = "x86_64" ) ]
146
123
if have_sha_extensions ( ) {
147
124
Self :: Sha2
148
125
} else {
149
126
Self :: Ring
150
127
}
128
+
129
+ #[ cfg( not( target_arch = "x86_64" ) ) ]
130
+ Self :: Ring
151
131
}
152
132
}
153
133
@@ -157,6 +137,7 @@ impl Sha256 for DynamicImpl {
157
137
#[ inline( always) ]
158
138
fn hash ( & self , input : & [ u8 ] ) -> Vec < u8 > {
159
139
match self {
140
+ #[ cfg( target_arch = "x86_64" ) ]
160
141
Self :: Sha2 => Sha2CrateImpl . hash ( input) ,
161
142
Self :: Ring => RingImpl . hash ( input) ,
162
143
}
@@ -165,6 +146,7 @@ impl Sha256 for DynamicImpl {
165
146
#[ inline( always) ]
166
147
fn hash_fixed ( & self , input : & [ u8 ] ) -> [ u8 ; HASH_LEN ] {
167
148
match self {
149
+ #[ cfg( target_arch = "x86_64" ) ]
168
150
Self :: Sha2 => Sha2CrateImpl . hash_fixed ( input) ,
169
151
Self :: Ring => RingImpl . hash_fixed ( input) ,
170
152
}
@@ -175,27 +157,31 @@ impl Sha256 for DynamicImpl {
175
157
///
176
158
/// This enum ends up being 8 bytes larger than the largest inner context.
177
159
pub enum DynamicContext {
160
+ #[ cfg( target_arch = "x86_64" ) ]
178
161
Sha2 ( sha2:: Sha256 ) ,
179
162
Ring ( ring:: digest:: Context ) ,
180
163
}
181
164
182
165
impl Sha256Context for DynamicContext {
183
166
fn new ( ) -> Self {
184
167
match DynamicImpl :: best ( ) {
168
+ #[ cfg( target_arch = "x86_64" ) ]
185
169
DynamicImpl :: Sha2 => Self :: Sha2 ( Sha256Context :: new ( ) ) ,
186
170
DynamicImpl :: Ring => Self :: Ring ( Sha256Context :: new ( ) ) ,
187
171
}
188
172
}
189
173
190
174
fn update ( & mut self , bytes : & [ u8 ] ) {
191
175
match self {
176
+ #[ cfg( target_arch = "x86_64" ) ]
192
177
Self :: Sha2 ( ctxt) => Sha256Context :: update ( ctxt, bytes) ,
193
178
Self :: Ring ( ctxt) => Sha256Context :: update ( ctxt, bytes) ,
194
179
}
195
180
}
196
181
197
182
fn finalize ( self ) -> [ u8 ; HASH_LEN ] {
198
183
match self {
184
+ #[ cfg( target_arch = "x86_64" ) ]
199
185
Self :: Sha2 ( ctxt) => Sha256Context :: finalize ( ctxt) ,
200
186
Self :: Ring ( ctxt) => Sha256Context :: finalize ( ctxt) ,
201
187
}
0 commit comments