1313use std:: fmt:: Display ;
1414use std:: num:: NonZeroU32 ;
1515
16+ use aws_lc_rs:: constant_time:: verify_slices_are_equal;
17+ use aws_lc_rs:: digest;
18+ use aws_lc_rs:: hmac;
19+ use aws_lc_rs:: rand:: { SecureRandom , SystemRandom } ;
1620use base64:: prelude:: * ;
1721use itertools:: Itertools ;
1822use mz_ore:: secure:: { Zeroize , Zeroizing } ;
@@ -67,13 +71,13 @@ pub enum VerifyError {
6771
6872#[ derive( Debug ) ]
6973pub enum HashError {
70- Openssl ( openssl :: error:: ErrorStack ) ,
74+ Crypto ( aws_lc_rs :: error:: Unspecified ) ,
7175}
7276
7377impl Display for HashError {
7478 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
7579 match self {
76- HashError :: Openssl ( e) => write ! ( f, "OpenSSL error: {}" , e) ,
80+ HashError :: Crypto ( e) => write ! ( f, "crypto error: {}" , e) ,
7781 }
7882 }
7983}
@@ -84,8 +88,9 @@ pub fn hash_password(
8488 password : & Password ,
8589 iterations : & NonZeroU32 ,
8690) -> Result < PasswordHash , HashError > {
91+ let rng = SystemRandom :: new ( ) ;
8792 let mut salt = Zeroizing :: new ( [ 0u8 ; DEFAULT_SALT_SIZE ] ) ;
88- openssl :: rand :: rand_bytes ( & mut * salt) . map_err ( HashError :: Openssl ) ?;
93+ rng . fill ( & mut * salt) . map_err ( HashError :: Crypto ) ?;
8994
9095 let hash = hash_password_inner (
9196 & HashOpts {
@@ -103,8 +108,9 @@ pub fn hash_password(
103108}
104109
105110pub fn generate_nonce ( client_nonce : & str ) -> Result < String , HashError > {
111+ let rng = SystemRandom :: new ( ) ;
106112 let mut nonce = Zeroizing :: new ( [ 0u8 ; 24 ] ) ;
107- openssl :: rand :: rand_bytes ( & mut * nonce) . map_err ( HashError :: Openssl ) ?;
113+ rng . fill ( & mut * nonce) . map_err ( HashError :: Crypto ) ?;
108114 let nonce = BASE64_STANDARD . encode ( & * nonce) ;
109115 let new_nonce = format ! ( "{}{}" , client_nonce, nonce) ;
110116 Ok ( new_nonce)
@@ -134,10 +140,7 @@ pub fn scram256_hash(password: &Password, iterations: &NonZeroU32) -> Result<Str
134140}
135141
136142fn constant_time_compare ( a : & [ u8 ] , b : & [ u8 ] ) -> bool {
137- if a. len ( ) != b. len ( ) {
138- return false ;
139- }
140- openssl:: memcmp:: eq ( a, b)
143+ verify_slices_are_equal ( a, b) . is_ok ( )
141144}
142145
143146/// Verifies a password against a SCRAM-SHA-256 hash.
@@ -205,7 +208,8 @@ pub fn sasl_verify(
205208 . collect ( ) ,
206209 ) ;
207210
208- if !constant_time_compare ( & openssl:: sha:: sha256 ( & client_key) , & stored_key) {
211+ let computed_stored_key = digest:: digest ( & digest:: SHA256 , & client_key) ;
212+ if !constant_time_compare ( computed_stored_key. as_ref ( ) , & stored_key) {
209213 return Err ( VerifyError :: InvalidPassword ) ;
210214 }
211215
@@ -215,18 +219,9 @@ pub fn sasl_verify(
215219}
216220
217221fn generate_signature ( key : & [ u8 ] , message : & str ) -> Result < Zeroizing < Vec < u8 > > , VerifyError > {
218- let signing_key =
219- openssl:: pkey:: PKey :: hmac ( key) . map_err ( |e| VerifyError :: Hash ( HashError :: Openssl ( e) ) ) ?;
220- let mut signer =
221- openssl:: sign:: Signer :: new ( openssl:: hash:: MessageDigest :: sha256 ( ) , & signing_key)
222- . map_err ( |e| VerifyError :: Hash ( HashError :: Openssl ( e) ) ) ?;
223- signer
224- . update ( message. as_bytes ( ) )
225- . map_err ( |e| VerifyError :: Hash ( HashError :: Openssl ( e) ) ) ?;
226- let signature = signer
227- . sign_to_vec ( )
228- . map_err ( |e| VerifyError :: Hash ( HashError :: Openssl ( e) ) ) ?;
229- Ok ( Zeroizing :: new ( signature) )
222+ let signing_key = hmac:: Key :: new ( hmac:: HMAC_SHA256 , key) ;
223+ let tag = hmac:: sign ( & signing_key, message. as_bytes ( ) ) ;
224+ Ok ( Zeroizing :: new ( tag. as_ref ( ) . to_vec ( ) ) )
230225}
231226
232227// Generate a mock challenge based on the username and client nonce
@@ -236,11 +231,13 @@ pub fn mock_sasl_challenge(username: &str, mock_nonce: &str, iterations: &NonZer
236231 let mut buf = Vec :: with_capacity ( username. len ( ) + mock_nonce. len ( ) ) ;
237232 buf. extend_from_slice ( username. as_bytes ( ) ) ;
238233 buf. extend_from_slice ( mock_nonce. as_bytes ( ) ) ;
239- let digest = openssl:: sha:: sha256 ( & buf) ;
234+ let hash = digest:: digest ( & digest:: SHA256 , & buf) ;
235+ let mut salt = [ 0u8 ; DEFAULT_SALT_SIZE ] ;
236+ salt. copy_from_slice ( hash. as_ref ( ) ) ;
240237
241238 HashOpts {
242239 iterations : iterations. to_owned ( ) ,
243- salt : digest ,
240+ salt,
244241 }
245242}
246243
@@ -313,17 +310,16 @@ impl Display for ScramSha256Hash {
313310}
314311
315312fn scram256_hash_inner ( hashed_password : PasswordHash ) -> ScramSha256Hash {
316- let signing_key = openssl:: pkey:: PKey :: hmac ( & hashed_password. hash ) . unwrap ( ) ;
317- let mut signer =
318- openssl:: sign:: Signer :: new ( openssl:: hash:: MessageDigest :: sha256 ( ) , & signing_key) . unwrap ( ) ;
319- signer. update ( b"Client Key" ) . unwrap ( ) ;
320- let client_key = Zeroizing :: new ( signer. sign_to_vec ( ) . unwrap ( ) ) ;
321- let stored_key = openssl:: sha:: sha256 ( & client_key) ;
322- let mut signer =
323- openssl:: sign:: Signer :: new ( openssl:: hash:: MessageDigest :: sha256 ( ) , & signing_key) . unwrap ( ) ;
324- signer. update ( b"Server Key" ) . unwrap ( ) ;
313+ let signing_key = hmac:: Key :: new ( hmac:: HMAC_SHA256 , & hashed_password. hash ) ;
314+ let client_key_tag = hmac:: sign ( & signing_key, b"Client Key" ) ;
315+ let client_key = Zeroizing :: new ( client_key_tag. as_ref ( ) . to_vec ( ) ) ;
316+ let stored_key_digest = digest:: digest ( & digest:: SHA256 , & client_key) ;
317+ let mut stored_key = [ 0u8 ; SHA256_OUTPUT_LEN ] ;
318+ stored_key. copy_from_slice ( stored_key_digest. as_ref ( ) ) ;
319+
320+ let server_key_tag = hmac:: sign ( & signing_key, b"Server Key" ) ;
325321 let mut server_key = Zeroizing :: new ( [ 0u8 ; SHA256_OUTPUT_LEN ] ) ;
326- signer . sign ( server_key. as_mut ( ) ) . unwrap ( ) ;
322+ server_key. copy_from_slice ( server_key_tag . as_ref ( ) ) ;
327323
328324 ScramSha256Hash {
329325 iterations : hashed_password. iterations ,
@@ -338,14 +334,13 @@ fn hash_password_inner(
338334 password : & [ u8 ] ,
339335) -> Result < [ u8 ; SHA256_OUTPUT_LEN ] , HashError > {
340336 let mut salted_password = Zeroizing :: new ( [ 0u8 ; SHA256_OUTPUT_LEN ] ) ;
341- openssl:: pkcs5:: pbkdf2_hmac (
342- password,
337+ aws_lc_rs:: pbkdf2:: derive (
338+ aws_lc_rs:: pbkdf2:: PBKDF2_HMAC_SHA256 ,
339+ opts. iterations ,
343340 & opts. salt ,
344- opts. iterations . get ( ) . try_into ( ) . unwrap ( ) ,
345- openssl:: hash:: MessageDigest :: sha256 ( ) ,
341+ password,
346342 & mut * salted_password,
347- )
348- . map_err ( HashError :: Openssl ) ?;
343+ ) ;
349344 Ok ( * salted_password)
350345}
351346
@@ -358,7 +353,7 @@ mod tests {
358353 const DEFAULT_ITERATIONS : NonZeroU32 = NonZeroU32 :: new ( 60 ) . expect ( "Trust me on this" ) ;
359354
360355 #[ mz_ore:: test]
361- #[ cfg_attr( miri, ignore) ] // unsupported operation: can't call foreign function `OPENSSL_init_ssl` on OS `linux`
356+ #[ cfg_attr( miri, ignore) ] // unsupported operation: can't call foreign function on OS `linux`
362357 fn test_hash_password ( ) {
363358 let password = "password" . to_string ( ) ;
364359 let iterations = NonZeroU32 :: new ( 100 ) . expect ( "Trust me on this" ) ;
@@ -370,7 +365,7 @@ mod tests {
370365 }
371366
372367 #[ mz_ore:: test]
373- #[ cfg_attr( miri, ignore) ] // unsupported operation: can't call foreign function `OPENSSL_init_ssl` on OS `linux`
368+ #[ cfg_attr( miri, ignore) ] // unsupported operation: can't call foreign function on OS `linux`
374369 fn test_scram256_hash ( ) {
375370 let password = "password" . into ( ) ;
376371 let scram_hash =
@@ -436,12 +431,9 @@ mod tests {
436431 let salted_password = hash_password_with_opts ( & opts, & password)
437432 . expect ( "hash password" )
438433 . hash ;
439- let signing_key = openssl:: pkey:: PKey :: hmac ( & salted_password) . expect ( "signing key" ) ;
440- let mut signer =
441- openssl:: sign:: Signer :: new ( openssl:: hash:: MessageDigest :: sha256 ( ) , & signing_key)
442- . expect ( "signer" ) ;
443- signer. update ( b"Client Key" ) . expect ( "update" ) ;
444- let client_key = signer. sign_to_vec ( ) . expect ( "client key" ) ;
434+ let signing_key = hmac:: Key :: new ( hmac:: HMAC_SHA256 , & salted_password) ;
435+ let client_key = hmac:: sign ( & signing_key, b"Client Key" ) ;
436+ let client_key = client_key. as_ref ( ) ;
445437 // client_proof = client_key XOR client_signature
446438 let client_signature =
447439 generate_signature ( & stored_key, auth_message) . expect ( "client signature" ) ;
0 commit comments