changeset 26714:b0609afd2785

auth: mech-scram: Make implementation generic to support other hash algorithms.
author Stephan Bosch <stephan.bosch@dovecot.fi>
date Sun, 06 Jan 2019 23:08:38 +0100
parents c9c512d81aca
children da04226b4e91
files src/auth/Makefile.am src/auth/mech-scram.c src/auth/mech-scram.h
diffstat 3 files changed, 53 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/Makefile.am	Sun Jan 06 23:04:37 2019 +0100
+++ b/src/auth/Makefile.am	Sun Jan 06 23:08:38 2019 +0100
@@ -164,6 +164,7 @@
 	auth-master-connection.h \
 	mech-otp-skey-common.h \
 	mech-plain-common.h \
+	mech-scram.h \
 	auth-penalty.h \
 	auth-policy.h \
 	auth-request.h \
--- a/src/auth/mech-scram.c	Sun Jan 06 23:04:37 2019 +0100
+++ b/src/auth/mech-scram.c	Sun Jan 06 23:08:38 2019 +0100
@@ -21,6 +21,7 @@
 #include "strnum.h"
 #include "password-scheme.h"
 #include "mech.h"
+#include "mech-scram.h"
 
 /* s-nonce length */
 #define SCRAM_SERVER_NONCE_LEN 64
@@ -30,6 +31,9 @@
 
 	pool_t pool;
 
+	const struct hash_method *hash_method;
+	const char *password_scheme;
+
 	/* sent: */
 	const char *server_first_message;
 	const char *snonce;
@@ -42,8 +46,8 @@
 	buffer_t *proof;
 
 	/* stored */
-	unsigned char stored_key[SHA1_RESULTLEN];
-	unsigned char server_key[SHA1_RESULTLEN];
+	unsigned char *stored_key;
+	unsigned char *server_key;
 };
 
 static const char *get_scram_server_first(struct scram_auth_request *request,
@@ -72,17 +76,17 @@
 
 static const char *get_scram_server_final(struct scram_auth_request *request)
 {
+	const struct hash_method *hmethod = request->hash_method;
 	struct hmac_context ctx;
 	const char *auth_message;
-	unsigned char server_signature[SHA1_RESULTLEN];
+	unsigned char server_signature[hmethod->digest_size];
 	string_t *str;
 
 	auth_message = t_strconcat(request->client_first_message_bare, ",",
 			request->server_first_message, ",",
 			request->client_final_message_without_proof, NULL);
 
-	hmac_init(&ctx, request->server_key, sizeof(request->server_key),
-		  &hash_method_sha1);
+	hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod);
 	hmac_update(&ctx, auth_message, strlen(auth_message));
 	hmac_final(&ctx, server_signature);
 
@@ -222,19 +226,19 @@
 
 static bool verify_credentials(struct scram_auth_request *request)
 {
+	const struct hash_method *hmethod = request->hash_method;
 	struct hmac_context ctx;
 	const char *auth_message;
-	unsigned char client_key[SHA1_RESULTLEN];
-	unsigned char client_signature[SHA1_RESULTLEN];
-	unsigned char stored_key[SHA1_RESULTLEN];
+	unsigned char client_key[hmethod->digest_size];
+	unsigned char client_signature[hmethod->digest_size];
+	unsigned char stored_key[hmethod->digest_size];
 	size_t i;
 
 	auth_message = t_strconcat(request->client_first_message_bare, ",",
 			request->server_first_message, ",",
 			request->client_final_message_without_proof, NULL);
 
-	hmac_init(&ctx, request->stored_key, sizeof(request->stored_key),
-		  &hash_method_sha1);
+	hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod);
 	hmac_update(&ctx, auth_message, strlen(auth_message));
 	hmac_final(&ctx, client_signature);
 
@@ -242,7 +246,8 @@
 		client_key[i] =
 			((char*)request->proof->data)[i] ^ client_signature[i];
 
-	sha1_get_digest(client_key, sizeof(client_key), stored_key);
+	hash_method_get_digest(hmethod, client_key, sizeof(client_key),
+			       stored_key);
 
 	safe_memset(client_key, 0, sizeof(client_key));
 	safe_memset(client_signature, 0, sizeof(client_signature));
@@ -261,7 +266,8 @@
 
 	switch (result) {
 	case PASSDB_RESULT_OK:
-		if (scram_scheme_parse(&hash_method_sha1, "SCRAM-SHA-1",
+		if (scram_scheme_parse(request->hash_method,
+				       request->password_scheme,
 				       credentials, size, &iter_count, &salt,
 				       request->stored_key, request->server_key,
 				       &error) < 0) {
@@ -291,6 +297,7 @@
 				     const unsigned char *data, size_t size,
 				     const char **error_r)
 {
+	const struct hash_method *hmethod = request->hash_method;
 	const char **fields, *cbind_input, *nonce_str;
 	unsigned int field_count;
 	string_t *str;
@@ -328,7 +335,7 @@
 			*error_r = "Invalid base64 encoding";
 			return FALSE;
 		}
-		if (request->proof->used != SHA1_RESULTLEN) {
+		if (request->proof->used != hmethod->digest_size) {
 			*error_r = "Invalid ClientProof length";
 			return FALSE;
 		}
@@ -344,9 +351,8 @@
 	return TRUE;
 }
 
-static void mech_scram_sha1_auth_continue(struct auth_request *auth_request,
-					  const unsigned char *data,
-					  size_t data_size)
+void mech_scram_auth_continue(struct auth_request *auth_request,
+			      const unsigned char *data, size_t data_size)
 {
 	struct scram_auth_request *request =
 		(struct scram_auth_request *)auth_request;
@@ -358,9 +364,10 @@
 		/* Received client-first-message */
 		if (parse_scram_client_first(request, data,
 					     data_size, &error)) {
-			auth_request_lookup_credentials(&request->auth_request,
-							"SCRAM-SHA-1",
-							credentials_callback);
+			auth_request_lookup_credentials(
+				&request->auth_request,
+				request->password_scheme,
+				credentials_callback);
 			return;
 		}
 	} else {
@@ -386,19 +393,32 @@
 	auth_request_fail(auth_request);
 }
 
-static struct auth_request *mech_scram_sha1_auth_new(void)
+struct auth_request *
+mech_scram_auth_new(const struct hash_method *hash_method,
+		    const char *password_scheme)
 {
 	struct scram_auth_request *request;
 	pool_t pool;
 
-	pool = pool_alloconly_create(MEMPOOL_GROWING"scram_sha1_auth_request", 2048);
+	pool = pool_alloconly_create(MEMPOOL_GROWING"scram_auth_request", 2048);
 	request = p_new(pool, struct scram_auth_request, 1);
 	request->pool = pool;
 
+	request->hash_method = hash_method;
+	request->password_scheme = password_scheme;
+
+	request->stored_key = p_malloc(pool, hash_method->digest_size);
+	request->server_key = p_malloc(pool, hash_method->digest_size);
+
 	request->auth_request.pool = pool;
 	return &request->auth_request;
 }
 
+static struct auth_request *mech_scram_sha1_auth_new(void)
+{
+	return mech_scram_auth_new(&hash_method_sha1, "SCRAM-SHA-1");
+}
+
 const struct mech_module mech_scram_sha1 = {
 	"SCRAM-SHA-1",
 
@@ -407,6 +427,6 @@
 
 	mech_scram_sha1_auth_new,
 	mech_generic_auth_initial,
-	mech_scram_sha1_auth_continue,
+	mech_scram_auth_continue,
 	mech_generic_auth_free
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/mech-scram.h	Sun Jan 06 23:08:38 2019 +0100
@@ -0,0 +1,10 @@
+#ifndef MECH_SCRAM_H
+#define MECH_SCRAM_H
+
+struct auth_request *
+mech_scram_auth_new(const struct hash_method *hash_method,
+		    const char *password_scheme);
+void mech_scram_auth_continue(struct auth_request *auth_request,
+			      const unsigned char *data, size_t data_size);
+
+#endif