Browse Source

Implement constant time equal check for admin, 2fa recover and 2fa remember tokens

Daniel García 6 years ago
parent
commit
9636f33fdb
4 changed files with 13 additions and 3 deletions
  1. 1 1
      src/api/admin.rs
  2. 2 1
      src/api/identity.rs
  3. 9 0
      src/crypto.rs
  4. 1 1
      src/db/models/user.rs

+ 1 - 1
src/api/admin.rs

@@ -89,7 +89,7 @@ fn post_admin_login(data: Form<LoginForm>, 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),
     }
 }
 

+ 2 - 1
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)?),
             }
         }

+ 9 - 0
src/crypto.rs

@@ -36,3 +36,12 @@ pub fn get_random(mut array: Vec<u8>) -> Vec<u8> {
 
     array
 }
+
+//
+// Constant time compare
+//
+pub fn ct_eq<T: AsRef<[u8]>, 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()
+}

+ 1 - 1
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
         }