@@ -9,6 +9,7 @@ use std::io;
99use std:: iter;
1010use std:: mem;
1111use std:: str;
12+ use tokio:: task:: yield_now;
1213
1314const NONCE_LENGTH : usize = 24 ;
1415
@@ -32,7 +33,7 @@ fn normalize(pass: &[u8]) -> Vec<u8> {
3233 }
3334}
3435
35- pub ( crate ) fn hi ( str : & [ u8 ] , salt : & [ u8 ] , i : u32 ) -> [ u8 ; 32 ] {
36+ pub ( crate ) async fn hi ( str : & [ u8 ] , salt : & [ u8 ] , iterations : u32 ) -> [ u8 ; 32 ] {
3637 let mut hmac =
3738 Hmac :: < Sha256 > :: new_from_slice ( str) . expect ( "HMAC is able to accept all key sizes" ) ;
3839 hmac. update ( salt) ;
@@ -41,14 +42,19 @@ pub(crate) fn hi(str: &[u8], salt: &[u8], i: u32) -> [u8; 32] {
4142
4243 let mut hi = prev;
4344
44- for _ in 1 ..i {
45+ for i in 1 ..iterations {
4546 let mut hmac = Hmac :: < Sha256 > :: new_from_slice ( str) . expect ( "already checked above" ) ;
4647 hmac. update ( & prev) ;
4748 prev = hmac. finalize ( ) . into_bytes ( ) ;
4849
4950 for ( hi, prev) in hi. iter_mut ( ) . zip ( prev) {
5051 * hi ^= prev;
5152 }
53+ // yield every ~250us
54+ // hopefully reduces tail latencies
55+ if i % 1024 == 0 {
56+ yield_now ( ) . await
57+ }
5258 }
5359
5460 hi. into ( )
@@ -200,7 +206,7 @@ impl ScramSha256 {
200206 /// Updates the state machine with the response from the backend.
201207 ///
202208 /// This should be called when an `AuthenticationSASLContinue` message is received.
203- pub fn update ( & mut self , message : & [ u8 ] ) -> io:: Result < ( ) > {
209+ pub async fn update ( & mut self , message : & [ u8 ] ) -> io:: Result < ( ) > {
204210 let ( client_nonce, password, channel_binding) =
205211 match mem:: replace ( & mut self . state , State :: Done ) {
206212 State :: Update {
@@ -227,7 +233,7 @@ impl ScramSha256 {
227233 Err ( e) => return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput , e) ) ,
228234 } ;
229235
230- let salted_password = hi ( & password, & salt, parsed. iteration_count ) ;
236+ let salted_password = hi ( & password, & salt, parsed. iteration_count ) . await ;
231237
232238 let make_key = |name| {
233239 let mut hmac = Hmac :: < Sha256 > :: new_from_slice ( & salted_password)
@@ -481,8 +487,8 @@ mod test {
481487 }
482488
483489 // recorded auth exchange from psql
484- #[ test]
485- fn exchange ( ) {
490+ #[ tokio :: test]
491+ async fn exchange ( ) {
486492 let password = "foobar" ;
487493 let nonce = "9IZ2O01zb9IgiIZ1WJ/zgpJB" ;
488494
@@ -502,7 +508,7 @@ mod test {
502508 ) ;
503509 assert_eq ! ( str :: from_utf8( scram. message( ) ) . unwrap( ) , client_first) ;
504510
505- scram. update ( server_first. as_bytes ( ) ) . unwrap ( ) ;
511+ scram. update ( server_first. as_bytes ( ) ) . await . unwrap ( ) ;
506512 assert_eq ! ( str :: from_utf8( scram. message( ) ) . unwrap( ) , client_final) ;
507513
508514 scram. finish ( server_final. as_bytes ( ) ) . unwrap ( ) ;
0 commit comments