77//! Now this crate serves primarily as a wrapper over two SHA256 crates: `sha2` and `ring` – which
88//! it switches between at runtime based on the availability of SHA intrinsics.
99
10+ mod sha2_impl;
11+
1012pub use self :: DynamicContext as Context ;
11- use sha2:: Digest ;
13+
14+ #[ cfg( target_arch = "x86_64" ) ]
15+ use sha2_impl:: Sha2CrateImpl ;
1216
1317#[ cfg( feature = "zero_hash_cache" ) ]
1418use lazy_static:: lazy_static;
@@ -54,35 +58,6 @@ pub trait Sha256 {
5458 fn hash_fixed ( & self , input : & [ u8 ] ) -> [ u8 ; HASH_LEN ] ;
5559}
5660
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-
8661/// Implementation of SHA256 using the `ring` crate (fastest on CPUs without SHA extensions).
8762pub struct RingImpl ;
8863
@@ -120,34 +95,39 @@ impl Sha256 for RingImpl {
12095
12196/// Default dynamic implementation that switches between available implementations.
12297pub enum DynamicImpl {
98+ #[ cfg( target_arch = "x86_64" ) ]
12399 Sha2 ,
124100 Ring ,
125101}
126102
127103// Runtime latch for detecting the availability of SHA extensions on x86_64.
128104//
129105// 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" ) ]
131107cpufeatures:: new!( x86_sha_extensions, "sha" , "sse2" , "ssse3" , "sse4.1" ) ;
132108
133109#[ inline( always) ]
134110pub fn have_sha_extensions ( ) -> bool {
135- #[ cfg( all ( feature = "detect-cpufeatures" , target_arch = "x86_64" ) ) ]
111+ #[ cfg( target_arch = "x86_64" ) ]
136112 return x86_sha_extensions:: get ( ) ;
137113
138- #[ cfg( not( all ( feature = "detect-cpufeatures" , target_arch = "x86_64" ) ) ) ]
114+ #[ cfg( not( target_arch = "x86_64" ) ) ]
139115 return false ;
140116}
141117
142118impl DynamicImpl {
143119 /// Choose the best available implementation based on the currently executing CPU.
144120 #[ inline( always) ]
145121 pub fn best ( ) -> Self {
122+ #[ cfg( target_arch = "x86_64" ) ]
146123 if have_sha_extensions ( ) {
147124 Self :: Sha2
148125 } else {
149126 Self :: Ring
150127 }
128+
129+ #[ cfg( not( target_arch = "x86_64" ) ) ]
130+ Self :: Ring
151131 }
152132}
153133
@@ -157,6 +137,7 @@ impl Sha256 for DynamicImpl {
157137 #[ inline( always) ]
158138 fn hash ( & self , input : & [ u8 ] ) -> Vec < u8 > {
159139 match self {
140+ #[ cfg( target_arch = "x86_64" ) ]
160141 Self :: Sha2 => Sha2CrateImpl . hash ( input) ,
161142 Self :: Ring => RingImpl . hash ( input) ,
162143 }
@@ -165,6 +146,7 @@ impl Sha256 for DynamicImpl {
165146 #[ inline( always) ]
166147 fn hash_fixed ( & self , input : & [ u8 ] ) -> [ u8 ; HASH_LEN ] {
167148 match self {
149+ #[ cfg( target_arch = "x86_64" ) ]
168150 Self :: Sha2 => Sha2CrateImpl . hash_fixed ( input) ,
169151 Self :: Ring => RingImpl . hash_fixed ( input) ,
170152 }
@@ -175,27 +157,31 @@ impl Sha256 for DynamicImpl {
175157///
176158/// This enum ends up being 8 bytes larger than the largest inner context.
177159pub enum DynamicContext {
160+ #[ cfg( target_arch = "x86_64" ) ]
178161 Sha2 ( sha2:: Sha256 ) ,
179162 Ring ( ring:: digest:: Context ) ,
180163}
181164
182165impl Sha256Context for DynamicContext {
183166 fn new ( ) -> Self {
184167 match DynamicImpl :: best ( ) {
168+ #[ cfg( target_arch = "x86_64" ) ]
185169 DynamicImpl :: Sha2 => Self :: Sha2 ( Sha256Context :: new ( ) ) ,
186170 DynamicImpl :: Ring => Self :: Ring ( Sha256Context :: new ( ) ) ,
187171 }
188172 }
189173
190174 fn update ( & mut self , bytes : & [ u8 ] ) {
191175 match self {
176+ #[ cfg( target_arch = "x86_64" ) ]
192177 Self :: Sha2 ( ctxt) => Sha256Context :: update ( ctxt, bytes) ,
193178 Self :: Ring ( ctxt) => Sha256Context :: update ( ctxt, bytes) ,
194179 }
195180 }
196181
197182 fn finalize ( self ) -> [ u8 ; HASH_LEN ] {
198183 match self {
184+ #[ cfg( target_arch = "x86_64" ) ]
199185 Self :: Sha2 ( ctxt) => Sha256Context :: finalize ( ctxt) ,
200186 Self :: Ring ( ctxt) => Sha256Context :: finalize ( ctxt) ,
201187 }
0 commit comments