changeset 21955:64d17b868bcc

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!
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Tue, 11 Apr 2017 15:33:22 +0300
parents 1c952a42bf12
children fcaed9f9bb3f
files 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
diffstat 11 files changed, 22 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-master-connection.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/auth-master-connection.c	Tue Apr 11 15:33:22 2017 +0300
@@ -117,7 +117,7 @@
 			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,
--- a/src/auth/mech-apop.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/mech-apop.c	Tue Apr 11 15:33:22 2017 +0300
@@ -40,7 +40,7 @@
 	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
--- a/src/auth/mech-cram-md5.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/mech-cram-md5.c	Tue Apr 11 15:33:22 2017 +0300
@@ -67,7 +67,7 @@
 
 	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;
--- a/src/auth/mech-digest-md5.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/mech-digest-md5.c	Tue Apr 11 15:33:22 2017 +0300
@@ -208,7 +208,7 @@
 
 		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");
--- a/src/auth/mech-gssapi.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/mech-gssapi.c	Tue Apr 11 15:33:22 2017 +0300
@@ -274,7 +274,7 @@
 				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
--- a/src/auth/mech-ntlm.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/mech-ntlm.c	Tue Apr 11 15:33:22 2017 +0300
@@ -54,7 +54,7 @@
 	}
 
 	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 @@
 				    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 @@
 			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;
 	}
 }
 
--- a/src/auth/mech-rpa.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/mech-rpa.c	Tue Apr 11 15:33:22 2017 +0300
@@ -431,7 +431,7 @@
 
 	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
--- a/src/auth/mech-scram-sha1.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/mech-scram-sha1.c	Tue Apr 11 15:33:22 2017 +0300
@@ -246,7 +246,7 @@
 	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,
--- a/src/auth/password-scheme-pbkdf2.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/password-scheme-pbkdf2.c	Tue Apr 11 15:33:22 2017 +0300
@@ -78,5 +78,5 @@
 	}
 
 	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;
 }
--- a/src/auth/password-scheme-scram.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/password-scheme-scram.c	Tue Apr 11 15:33:22 2017 +0300
@@ -125,8 +125,8 @@
 
 	/* 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));
--- a/src/auth/password-scheme.c	Sun Apr 09 15:31:11 2017 +0300
+++ b/src/auth/password-scheme.c	Tue Apr 11 15:33:22 2017 +0300
@@ -99,7 +99,7 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 	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