From: Timo Sirainen Date: Tue, 11 Apr 2017 12:33:22 +0000 (+0300) Subject: auth: Use mem_equals_timing_safe() for all password hash comparisons. X-Git-Tag: 2.3.0.rc1~1737 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ace06232cfa0e99ecca1040e8553b3216d025768;p=thirdparty%2Fdovecot%2Fcore.git auth: Use mem_equals_timing_safe() for all password hash comparisons. 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! --- diff --git a/src/auth/auth-master-connection.c b/src/auth/auth-master-connection.c index ed81edcc5f..a9de7c4473 100644 --- a/src/auth/auth-master-connection.c +++ b/src/auth/auth-master-connection.c @@ -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, diff --git a/src/auth/mech-apop.c b/src/auth/mech-apop.c index aed248d49f..e3a3cd3a49 100644 --- a/src/auth/mech-apop.c +++ b/src/auth/mech-apop.c @@ -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 diff --git a/src/auth/mech-cram-md5.c b/src/auth/mech-cram-md5.c index 5c5ea6147c..c27022fc28 100644 --- a/src/auth/mech-cram-md5.c +++ b/src/auth/mech-cram-md5.c @@ -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; diff --git a/src/auth/mech-digest-md5.c b/src/auth/mech-digest-md5.c index f0b8e464a6..c9a6183b57 100644 --- a/src/auth/mech-digest-md5.c +++ b/src/auth/mech-digest-md5.c @@ -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"); diff --git a/src/auth/mech-gssapi.c b/src/auth/mech-gssapi.c index 09d4f105b8..acf1e9bc22 100644 --- a/src/auth/mech-gssapi.c +++ b/src/auth/mech-gssapi.c @@ -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 diff --git a/src/auth/mech-ntlm.c b/src/auth/mech-ntlm.c index d190436745..6a928f4dc6 100644 --- a/src/auth/mech-ntlm.c +++ b/src/auth/mech-ntlm.c @@ -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; } } diff --git a/src/auth/mech-rpa.c b/src/auth/mech-rpa.c index 4261d2a5d7..00fe66971d 100644 --- a/src/auth/mech-rpa.c +++ b/src/auth/mech-rpa.c @@ -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 diff --git a/src/auth/mech-scram-sha1.c b/src/auth/mech-scram-sha1.c index 282ae9b9d5..374f19ddf1 100644 --- a/src/auth/mech-scram-sha1.c +++ b/src/auth/mech-scram-sha1.c @@ -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, diff --git a/src/auth/password-scheme-pbkdf2.c b/src/auth/password-scheme-pbkdf2.c index 074ddbb77d..098bf2d0e7 100644 --- a/src/auth/password-scheme-pbkdf2.c +++ b/src/auth/password-scheme-pbkdf2.c @@ -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; } diff --git a/src/auth/password-scheme-scram.c b/src/auth/password-scheme-scram.c index 3b96135c69..b0ec001682 100644 --- a/src/auth/password-scheme-scram.c +++ b/src/auth/password-scheme-scram.c @@ -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)); diff --git a/src/auth/password-scheme.c b/src/auth/password-scheme.c index 03b8a98b8f..2362e285b2 100644 --- a/src/auth/password-scheme.c +++ b/src/auth/password-scheme.c @@ -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