diff --git a/postgres-protocol/Cargo.toml b/postgres-protocol/Cargo.toml index 59dba320..1765459d 100644 --- a/postgres-protocol/Cargo.toml +++ b/postgres-protocol/Cargo.toml @@ -12,10 +12,10 @@ base64 = "0.6" byteorder = "1.0" bytes = "0.4" fallible-iterator = "0.1" -generic-array = "0.8" -hmac = "0.4" +generic-array = "0.9" +hmac = "0.5" md5 = "0.3" memchr = "1.0" rand = "0.3" -sha2 = "0.6" +sha2 = "0.7" stringprep = "0.1" diff --git a/postgres-protocol/src/authentication/sasl.rs b/postgres-protocol/src/authentication/sasl.rs index 022782d0..62e98aa9 100644 --- a/postgres-protocol/src/authentication/sasl.rs +++ b/postgres-protocol/src/authentication/sasl.rs @@ -33,25 +33,26 @@ fn normalize(pass: &[u8]) -> Vec { } } -fn hi(str: &[u8], salt: &[u8], i: u32) -> GenericArray { - let mut hmac = Hmac::::new(str); +fn hi(str: &[u8], salt: &[u8], i: u32) -> io::Result> { + let mut hmac = Hmac::::new(str) + .map_err(|_| invalid_key_length_error())?; hmac.input(salt); hmac.input(&[0, 0, 0, 1]); - let mut prev = hmac.result(); + let mut prev = hmac.result().code(); - let mut hi = GenericArray::::clone_from_slice(prev.code()); + let mut hi = GenericArray::::clone_from_slice(&prev); for _ in 1..i { - let mut hmac = Hmac::::new(str); - hmac.input(prev.code()); - prev = hmac.result(); + let mut hmac = Hmac::::new(str).expect("already checked above"); + hmac.input(prev.as_slice()); + prev = hmac.result().code(); - for (hi, prev) in hi.iter_mut().zip(prev.code()) { - *hi ^= *prev; + for (hi, prev) in hi.iter_mut().zip(prev) { + *hi ^= prev; } } - hi + Ok(hi) } enum State { @@ -148,14 +149,15 @@ impl ScramSha256 { Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)), }; - let salted_password = hi(&password, &salt, parsed.iteration_count); + let salted_password = hi(&password, &salt, parsed.iteration_count)?; - let mut hmac = Hmac::::new(&salted_password); + let mut hmac = Hmac::::new(&salted_password) + .map_err(|_| invalid_key_length_error())?; hmac.input(b"Client Key"); - let client_key = hmac.result(); + let client_key = hmac.result().code(); let mut hash = Sha256::default(); - hash.input(client_key.code()); + hash.input(client_key.as_slice()); let stored_key = hash.result(); self.message.clear(); @@ -163,13 +165,14 @@ impl ScramSha256 { let auth_message = format!("n=,r={},{},{}", client_nonce, message, self.message); - let mut hmac = Hmac::::new(&stored_key); + let mut hmac = Hmac::::new(&stored_key) + .map_err(|_| invalid_key_length_error())?; hmac.input(auth_message.as_bytes()); let client_signature = hmac.result(); - let mut client_proof = GenericArray::::clone_from_slice(client_key.code()); + let mut client_proof = GenericArray::::clone_from_slice(&client_key); for (proof, signature) in client_proof.iter_mut().zip(client_signature.code()) { - *proof ^= *signature; + *proof ^= signature; } write!(&mut self.message, ",p={}", base64::encode(&*client_proof)).unwrap(); @@ -215,20 +218,18 @@ impl ScramSha256 { Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)), }; - let mut hmac = Hmac::::new(&salted_password); + let mut hmac = Hmac::::new(&salted_password) + .map_err(|_| invalid_key_length_error())?; hmac.input(b"Server Key"); let server_key = hmac.result(); - let mut hmac = Hmac::::new(server_key.code()); + let mut hmac = Hmac::::new(&server_key.code()) + .map_err(|_| invalid_key_length_error())?; hmac.input(auth_message.as_bytes()); - if hmac.verify(&verifier) { - Ok(()) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "SCRAM verification error", - )) - } + hmac.verify(&verifier).map_err(|_| io::Error::new( + io::ErrorKind::InvalidInput, + "SCRAM verification error", + )) } } @@ -398,6 +399,10 @@ enum ServerFinalMessage<'a> { Verifier(&'a str), } +fn invalid_key_length_error() -> io::Error { + io::Error::new(io::ErrorKind::InvalidInput, "invalid key length") +} + #[cfg(test)] mod test { use super::*;