]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Use mem_equals_timing_safe() for all password hash comparisons.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 11 Apr 2017 12:33:22 +0000 (15:33 +0300)
committerGitLab <gitlab@git.dovecot.net>
Tue, 11 Apr 2017 12:55:26 +0000 (15:55 +0300)
It's unlikely these could be used to perform timing attacks, since the
attacker would have to have broken MD5/SHA badly enough to be able to
quickly generate string that result in wanted hashes. Still, the extra
cost is almost nothing and it's always better to be super paranoid!

src/auth/auth-master-connection.c
src/auth/mech-apop.c
src/auth/mech-cram-md5.c
src/auth/mech-digest-md5.c
src/auth/mech-gssapi.c
src/auth/mech-ntlm.c
src/auth/mech-rpa.c
src/auth/mech-scram-sha1.c
src/auth/password-scheme-pbkdf2.c
src/auth/password-scheme-scram.c
src/auth/password-scheme.c

index ed81edcc5f039e0d3af563bf496bc47f7c8bdac4..a9de7c44737adb5e97bd28e01d0fbe6ec07d1415 100644 (file)
@@ -117,7 +117,7 @@ master_input_request(struct auth_master_connection *conn, const char *args)
                        client_pid);
                o_stream_nsend_str(conn->output,
                                   t_strdup_printf("FAIL\t%u\n", id));
-       } else if (memcmp(client_conn->cookie, cookie, sizeof(cookie)) != 0) {
+       } else if (!mem_equals_timing_safe(client_conn->cookie, cookie, sizeof(cookie))) {
                i_error("Master requested auth for client %u with invalid cookie",
                        client_pid);
                o_stream_nsend_str(conn->output,
index aed248d49fd20026d7a1c92ec6c6b0470dc6ea6b..e3a3cd3a49048bdeb42ea6ef6af6b398f76bd6c6 100644 (file)
@@ -40,7 +40,7 @@ static bool verify_credentials(struct apop_auth_request *request,
        md5_update(&ctx, credentials, size);
        md5_final(&ctx, digest);
 
-       return memcmp(digest, request->response_digest, 16) == 0;
+       return mem_equals_timing_safe(digest, request->response_digest, 16);
 }
 
 static void
index 5c5ea6147c46683579f162685956cc98504c99fb..c27022fc282efb9869c17c2e43219b9cb5462178 100644 (file)
@@ -67,7 +67,7 @@ static bool verify_credentials(struct cram_auth_request *request,
 
        response_hex = binary_to_hex(digest, sizeof(digest));
 
-       if (memcmp(response_hex, request->response, sizeof(digest)*2) != 0) {
+       if (!mem_equals_timing_safe(response_hex, request->response, sizeof(digest)*2)) {
                auth_request_log_info(&request->auth_request, AUTH_SUBSYS_MECH,
                                      "password mismatch");
                return FALSE;
index f0b8e464a6a2fb547d09c9b0ce2eeed0d305dd9c..c9a6183b57dcd3ebcccf315f0559483a69790979 100644 (file)
@@ -208,7 +208,7 @@ static bool verify_credentials(struct digest_auth_request *request,
 
                if (i == 0) {
                        /* verify response */
-                       if (memcmp(response_hex, request->response, 32) != 0) {
+                       if (!mem_equals_timing_safe(response_hex, request->response, 32)) {
                                auth_request_log_info(&request->auth_request,
                                                      AUTH_SUBSYS_MECH,
                                                      "password mismatch");
index 09d4f105b83d1b5893a46946285ffb98b87ec817..acf1e9bc2217f09d9e6eb76af62bd087ac9a47f9 100644 (file)
@@ -276,7 +276,7 @@ static bool mech_gssapi_oid_cmp(const gss_OID_desc *oid1,
                                const gss_OID_desc *oid2)
 {
        return oid1->length == oid2->length &&
-               memcmp(oid1->elements, oid2->elements, oid1->length) == 0;
+               mem_equals_timing_safe(oid1->elements, oid2->elements, oid1->length);
 }
 
 static int
index d190436745f0f34637a82d1ea90aa87a03503903..6a928f4dc6a6e55fedd266ca8b304d61f8d377d4 100644 (file)
@@ -54,7 +54,7 @@ static bool lm_verify_credentials(struct ntlm_auth_request *request,
        }
 
        ntlmssp_v1_response(credentials, request->challenge, lm_response);
-       return memcmp(lm_response, client_response, LM_RESPONSE_SIZE) == 0;
+       return mem_equals_timing_safe(lm_response, client_response, LM_RESPONSE_SIZE);
 }
 
 static void
@@ -118,8 +118,8 @@ ntlm_verify_credentials(struct ntlm_auth_request *request,
                                    response_length - NTLMSSP_V2_RESPONSE_SIZE,
                                    ntlm_v2_response);
 
-               return memcmp(ntlm_v2_response, client_response,
-                             NTLMSSP_V2_RESPONSE_SIZE) == 0 ? 1 : -1;
+               return mem_equals_timing_safe(ntlm_v2_response, client_response,
+                                             NTLMSSP_V2_RESPONSE_SIZE) ? 1 : -1;
        } else {
                unsigned char ntlm_response[NTLMSSP_RESPONSE_SIZE];
                const unsigned char *client_lm_response =
@@ -133,8 +133,8 @@ ntlm_verify_credentials(struct ntlm_auth_request *request,
                        ntlmssp_v1_response(credentials, request->challenge,
                                            ntlm_response);
 
-               return memcmp(ntlm_response, client_response,
-                             NTLMSSP_RESPONSE_SIZE) == 0 ? 1 : -1;
+               return mem_equals_timing_safe(ntlm_response, client_response,
+                                             NTLMSSP_RESPONSE_SIZE) ? 1 : -1;
        }
 }
 
index 4261d2a5d76e638e99510b1255edcb161de6be4c..00fe66971d3b0834f79a0101d343a0af71004a15 100644 (file)
@@ -431,7 +431,7 @@ static bool verify_credentials(struct rpa_auth_request *request,
 
        memcpy(request->pwd_md5, credentials, sizeof(request->pwd_md5));
        rpa_user_response(request, response);
-       return memcmp(response, request->user_response, sizeof(response)) == 0;
+       return mem_equals_timing_safe(response, request->user_response, sizeof(response));
 }
 
 static void
index 282ae9b9d5581c3155033e381dc8aa8f90fd1488..374f19ddf1d33a1225630a2ae25e87b42b3c145b 100644 (file)
@@ -246,7 +246,7 @@ static bool verify_credentials(struct scram_auth_request *request)
        safe_memset(client_key, 0, sizeof(client_key));
        safe_memset(client_signature, 0, sizeof(client_signature));
 
-       return memcmp(stored_key, request->stored_key, sizeof(stored_key)) == 0;
+       return mem_equals_timing_safe(stored_key, request->stored_key, sizeof(stored_key));
 }
 
 static void credentials_callback(enum passdb_result result,
index 074ddbb77d2b92bd57f4eb3d3e32e9d2c9585c95..098bf2d0e76f0955201e3902092c53cab3df19fa 100644 (file)
@@ -78,5 +78,5 @@ int pbkdf2_verify(const char *plaintext, const char *user ATTR_UNUSED,
        }
 
        pbkdf_run(plaintext, salt, rounds, key2);
-       return memcmp(key1, key2, sizeof(key1)) == 0 ? 1 : 0;
+       return mem_equals_timing_safe(key1, key2, sizeof(key1)) ? 1 : 0;
 }
index 3b96135c69e71259c7a7fb7b6a0aa60727829914..b0ec0016825da41fa5701295344c85cc261dbc39 100644 (file)
@@ -125,8 +125,8 @@ int scram_sha1_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
        /* Calculate StoredKey */
        sha1_get_digest(client_key, sizeof(client_key), calculated_stored_key);
-       ret = memcmp(stored_key, calculated_stored_key,
-                    sizeof(stored_key)) == 0 ? 1 : 0;
+       ret = mem_equals_timing_safe(stored_key, calculated_stored_key,
+                                    sizeof(stored_key)) ? 1 : 0;
 
        safe_memset(salted_password, 0, sizeof(salted_password));
        safe_memset(client_key, 0, sizeof(client_key));
index 03b8a98b8f9241acb2d9960fa9cb79721e9f64ee..2362e285b23982f12f117edbd603612fd7127a16 100644 (file)
@@ -99,7 +99,7 @@ int password_verify(const char *plaintext, const char *user, const char *scheme,
                s->password_generate(plaintext, user,
                                     &generated, &generated_size);
                ret = size != generated_size ? 0 :
-                       memcmp(generated, raw_password, size) == 0 ? 1 : 0;
+                       mem_equals_timing_safe(generated, raw_password, size) ? 1 : 0;
        }
 
        if (ret == 0)
@@ -471,7 +471,7 @@ static int ssha_verify(const char *plaintext, const char *user ATTR_UNUSED,
        sha1_loop(&ctx, plaintext, strlen(plaintext));
        sha1_loop(&ctx, raw_password + SHA1_RESULTLEN, size - SHA1_RESULTLEN);
        sha1_result(&ctx, sha1_digest);
-       return memcmp(sha1_digest, raw_password, SHA1_RESULTLEN) == 0 ? 1 : 0;
+       return mem_equals_timing_safe(sha1_digest, raw_password, SHA1_RESULTLEN) ? 1 : 0;
 }
 
 static void
@@ -513,8 +513,8 @@ static int ssha256_verify(const char *plaintext, const char *user ATTR_UNUSED,
        sha256_loop(&ctx, raw_password + SHA256_RESULTLEN,
                    size - SHA256_RESULTLEN);
        sha256_result(&ctx, sha256_digest);
-       return memcmp(sha256_digest, raw_password,
-                     SHA256_RESULTLEN) == 0 ? 1 : 0;
+       return mem_equals_timing_safe(sha256_digest, raw_password,
+                                     SHA256_RESULTLEN) ? 1 : 0;
 }
 
 static void
@@ -556,8 +556,8 @@ static int ssha512_verify(const char *plaintext, const char *user ATTR_UNUSED,
        sha512_loop(&ctx, raw_password + SHA512_RESULTLEN,
                    size - SHA512_RESULTLEN);
        sha512_result(&ctx, sha512_digest);
-       return memcmp(sha512_digest, raw_password,
-                     SHA512_RESULTLEN) == 0 ? 1 : 0;
+       return mem_equals_timing_safe(sha512_digest, raw_password,
+                                     SHA512_RESULTLEN) ? 1 : 0;
 }
 
 static void
@@ -598,7 +598,7 @@ static int smd5_verify(const char *plaintext, const char *user ATTR_UNUSED,
        md5_update(&ctx, plaintext, strlen(plaintext));
        md5_update(&ctx, raw_password + MD5_RESULTLEN, size - MD5_RESULTLEN);
        md5_final(&ctx, md5_digest);
-       return memcmp(md5_digest, raw_password, MD5_RESULTLEN) == 0 ? 1 : 0;
+       return mem_equals_timing_safe(md5_digest, raw_password, MD5_RESULTLEN) ? 1 : 0;
 }
 
 static void