From 91090ef3e38020897ead92ed88a94762c8f04169 Mon Sep 17 00:00:00 2001 From: "Chris West (Faux)" Date: Sun, 14 Jan 2018 14:48:02 +0000 Subject: [PATCH 1/3] Upgrade hmac, sha2 and generic_array --- postgres-protocol/Cargo.toml | 6 +- postgres-protocol/src/authentication/sasl.rs | 59 +++++++++++--------- 2 files changed, 35 insertions(+), 30 deletions(-) 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::*; From 50e17acae627b1cf414dc2692498ae4e617fd7e2 Mon Sep 17 00:00:00 2001 From: "Chris West (Faux)" Date: Sun, 14 Jan 2018 15:31:48 +0000 Subject: [PATCH 2/3] generic-array requires Rust 1.20; 1.23 is out so N-2 is fine --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5d4bfbff..019f5e87 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,7 +27,7 @@ jobs: build: working_directory: ~/build docker: - - image: rust:1.19.0 + - image: rust:1.20.0 environment: RUSTFLAGS: -D warnings - image: sfackler/rust-postgres-test:3 From bcc0996f04c62effbe495e1535399af89b5d3b4a Mon Sep 17 00:00:00 2001 From: "Chris West (Faux)" Date: Mon, 15 Jan 2018 18:54:43 +0000 Subject: [PATCH 3/3] Hmac::new() is infalliable --- postgres-protocol/src/authentication/sasl.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/postgres-protocol/src/authentication/sasl.rs b/postgres-protocol/src/authentication/sasl.rs index 62e98aa9..a9570cef 100644 --- a/postgres-protocol/src/authentication/sasl.rs +++ b/postgres-protocol/src/authentication/sasl.rs @@ -33,9 +33,9 @@ fn normalize(pass: &[u8]) -> Vec { } } -fn hi(str: &[u8], salt: &[u8], i: u32) -> io::Result> { +fn hi(str: &[u8], salt: &[u8], i: u32) -> GenericArray { let mut hmac = Hmac::::new(str) - .map_err(|_| invalid_key_length_error())?; + .expect("HMAC is able to accept all key sizes"); hmac.input(salt); hmac.input(&[0, 0, 0, 1]); let mut prev = hmac.result().code(); @@ -52,7 +52,7 @@ fn hi(str: &[u8], salt: &[u8], i: u32) -> io::Result> { } } - Ok(hi) + hi } enum State { @@ -149,10 +149,10 @@ 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) - .map_err(|_| invalid_key_length_error())?; + .expect("HMAC is able to accept all key sizes"); hmac.input(b"Client Key"); let client_key = hmac.result().code(); @@ -166,7 +166,7 @@ impl ScramSha256 { let auth_message = format!("n=,r={},{},{}", client_nonce, message, self.message); let mut hmac = Hmac::::new(&stored_key) - .map_err(|_| invalid_key_length_error())?; + .expect("HMAC is able to accept all key sizes"); hmac.input(auth_message.as_bytes()); let client_signature = hmac.result(); @@ -219,12 +219,12 @@ impl ScramSha256 { }; let mut hmac = Hmac::::new(&salted_password) - .map_err(|_| invalid_key_length_error())?; + .expect("HMAC is able to accept all key sizes"); hmac.input(b"Server Key"); let server_key = hmac.result(); let mut hmac = Hmac::::new(&server_key.code()) - .map_err(|_| invalid_key_length_error())?; + .expect("HMAC is able to accept all key sizes"); hmac.input(auth_message.as_bytes()); hmac.verify(&verifier).map_err(|_| io::Error::new( io::ErrorKind::InvalidInput, @@ -399,10 +399,6 @@ 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::*;