From 9636f33fdbc070afcc80321359621c3bfe75535d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 11 Feb 2019 23:45:55 +0100 Subject: [PATCH] Implement constant time equal check for admin, 2fa recover and 2fa remember tokens --- src/api/admin.rs | 2 +- src/api/identity.rs | 3 ++- src/crypto.rs | 9 +++++++++ src/db/models/user.rs | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/api/admin.rs b/src/api/admin.rs index 1e7acdda..37b03c17 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -89,7 +89,7 @@ fn post_admin_login(data: Form, mut cookies: Cookies, ip: ClientIp) - fn _validate_token(token: &str) -> bool { match CONFIG.admin_token().as_ref() { None => false, - Some(t) => t == token, + Some(t) => crate::crypto::ct_eq(t, token), } } diff --git a/src/api/identity.rs b/src/api/identity.rs index 8638796b..5e38e20b 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -170,8 +170,9 @@ fn twofactor_auth( match TwoFactorType::from_i32(provider) { Some(TwoFactorType::Remember) => { + use crate::crypto::ct_eq; match device.twofactor_remember { - Some(ref remember) if remember == twofactor_code => return Ok(None), // No twofactor token needed here + Some(ref remember) if ct_eq(remember, twofactor_code) => return Ok(None), // No twofactor token needed here _ => err_json!(_json_err_twofactor(&providers, user_uuid, conn)?), } } diff --git a/src/crypto.rs b/src/crypto.rs index 9321f25f..628afcd0 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -36,3 +36,12 @@ pub fn get_random(mut array: Vec) -> Vec { array } + +// +// Constant time compare +// +pub fn ct_eq, U: AsRef<[u8]>>(a: T, b: U) -> bool { + use ring::constant_time::verify_slices_are_equal; + + verify_slices_are_equal(a.as_ref(), b.as_ref()).is_ok() +} diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 21ac1531..94ddc1ab 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -86,7 +86,7 @@ impl User { pub fn check_valid_recovery_code(&self, recovery_code: &str) -> bool { if let Some(ref totp_recover) = self.totp_recover { - recovery_code == totp_recover.to_lowercase() + crate::crypto::ct_eq(recovery_code, totp_recover.to_lowercase()) } else { false }