]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: password-scheme: scram: Make implementation generic to support other hash algor...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 6 Jan 2019 22:04:37 +0000 (23:04 +0100)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Wed, 4 Dec 2019 14:33:31 +0000 (14:33 +0000)
src/auth/mech-scram.c
src/auth/password-scheme-scram.c
src/auth/password-scheme.h

index 27e1cd2607a1ee1dca884d756a60a39bb9e54b3d..252ca15a62aa3ec914c25c0a63ec8e147749f304 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * SCRAM-SHA-1 SASL authentication, see RFC-5802
  *
@@ -260,9 +261,10 @@ static void credentials_callback(enum passdb_result result,
 
        switch (result) {
        case PASSDB_RESULT_OK:
-               if (scram_sha1_scheme_parse(credentials, size, &iter_count,
-                                           &salt, request->stored_key,
-                                           request->server_key, &error) < 0) {
+               if (scram_scheme_parse(&hash_method_sha1, "SCRAM-SHA-1",
+                                      credentials, size, &iter_count, &salt,
+                                      request->stored_key, request->server_key,
+                                      &error) < 0) {
                        e_info(auth_request->mech_event,
                               "%s", error);
                        auth_request_fail(auth_request);
index 60e41c0f417bb1ec7a5fc7cb2136bdc087850bf8..0c7fdb4b0089350b992935d87ed2ccb2ebb4874d 100644 (file)
@@ -13,6 +13,7 @@
 #include "buffer.h"
 #include "hmac.h"
 #include "randgen.h"
+#include "hash-method.h"
 #include "sha1.h"
 #include "str.h"
 #include "password-scheme.h"
 
 #define SCRAM_DEFAULT_ITERATE_COUNT 4096
 
-static void Hi(const unsigned char *str, size_t str_size,
-              const unsigned char *salt, size_t salt_size, unsigned int i,
-              unsigned char result[SHA1_RESULTLEN])
+static void
+Hi(const struct hash_method *hmethod, const unsigned char *str, size_t str_size,
+   const unsigned char *salt, size_t salt_size, unsigned int i,
+   unsigned char *result)
 {
        struct hmac_context ctx;
-       unsigned char U[SHA1_RESULTLEN];
+       unsigned char U[hmethod->digest_size];
        unsigned int j, k;
 
        /* Calculate U1 */
-       hmac_init(&ctx, str, str_size, &hash_method_sha1);
+       hmac_init(&ctx, str, str_size, hmethod);
        hmac_update(&ctx, salt, salt_size);
        hmac_update(&ctx, "\0\0\0\1", 4);
        hmac_final(&ctx, U);
 
-       memcpy(result, U, SHA1_RESULTLEN);
+       memcpy(result, U, hmethod->digest_size);
 
        /* Calculate U2 to Ui and Hi */
        for (j = 2; j <= i; j++) {
-               hmac_init(&ctx, str, str_size, &hash_method_sha1);
+               hmac_init(&ctx, str, str_size, hmethod);
                hmac_update(&ctx, U, sizeof(U));
                hmac_final(&ctx, U);
-               for (k = 0; k < SHA1_RESULTLEN; k++)
+               for (k = 0; k < hmethod->digest_size; k++)
                        result[k] ^= U[k];
        }
 }
 
-int scram_sha1_scheme_parse(const unsigned char *credentials, size_t size,
-                           unsigned int *iter_count_r, const char **salt_r,
-                           unsigned char stored_key_r[],
-                           unsigned char server_key_r[], const char **error_r)
+int scram_scheme_parse(const struct hash_method *hmethod, const char *name,
+                      const unsigned char *credentials, size_t size,
+                      unsigned int *iter_count_r, const char **salt_r,
+                      unsigned char stored_key_r[],
+                      unsigned char server_key_r[], const char **error_r)
 {
        const char *const *fields;
        buffer_t *buf;
@@ -61,71 +64,74 @@ int scram_sha1_scheme_parse(const unsigned char *credentials, size_t size,
        fields = t_strsplit(t_strndup(credentials, size), ",");
 
        if (str_array_length(fields) != 4) {
-               *error_r = "Invalid SCRAM-SHA-1 passdb entry format";
+               *error_r = t_strdup_printf(
+                       "Invalid %s passdb entry format", name);
                return -1;
        }
        if (str_to_uint(fields[0], iter_count_r) < 0 ||
            *iter_count_r < SCRAM_MIN_ITERATE_COUNT ||
            *iter_count_r > SCRAM_MAX_ITERATE_COUNT) {
-               *error_r = "Invalid SCRAM-SHA-1 iteration count in passdb";
+               *error_r = t_strdup_printf(
+                       "Invalid %s iteration count in passdb", name);
                return -1;
        }
        *salt_r = fields[1];
 
-       buf = t_buffer_create(SHA1_RESULTLEN);
+       buf = t_buffer_create(hmethod->digest_size);
        if (base64_decode(fields[2], strlen(fields[2]), NULL, buf) < 0 ||
-           buf->used != SHA1_RESULTLEN) {
-               *error_r = "Invalid SCRAM-SHA-1 StoredKey in passdb";
+           buf->used != hmethod->digest_size) {
+               *error_r = t_strdup_printf(
+                       "Invalid %s StoredKey in passdb", name);
                return -1;
        }
-       memcpy(stored_key_r, buf->data, SHA1_RESULTLEN);
+       memcpy(stored_key_r, buf->data, hmethod->digest_size);
 
        buffer_set_used_size(buf, 0);
        if (base64_decode(fields[3], strlen(fields[3]), NULL, buf) < 0 ||
-           buf->used != SHA1_RESULTLEN) {
-               *error_r = "Invalid SCRAM-SHA-1 ServerKey in passdb";
+           buf->used != hmethod->digest_size) {
+               *error_r = t_strdup_printf(
+                       "Invalid %s ServerKey in passdb", name);
                return -1;
        }
-       memcpy(server_key_r, buf->data, SHA1_RESULTLEN);
+       memcpy(server_key_r, buf->data, hmethod->digest_size);
        return 0;
 }
 
-int scram_sha1_verify(const char *plaintext,
-                     const struct password_generate_params *params ATTR_UNUSED,
-                     const unsigned char *raw_password, size_t size,
-                     const char **error_r)
+int scram_verify(const struct hash_method *hmethod, const char *scheme_name,
+                const char *plaintext, const unsigned char *raw_password,
+                size_t size, const char **error_r)
 {
        struct hmac_context ctx;
        const char *salt_base64;
        unsigned int iter_count;
        const unsigned char *salt;
        size_t salt_len;
-       unsigned char salted_password[SHA1_RESULTLEN];
-       unsigned char client_key[SHA1_RESULTLEN];
-       unsigned char stored_key[SHA1_RESULTLEN];
-       unsigned char calculated_stored_key[SHA1_RESULTLEN];
-       unsigned char server_key[SHA1_RESULTLEN];
+       unsigned char salted_password[hmethod->digest_size];
+       unsigned char client_key[hmethod->digest_size];
+       unsigned char stored_key[hmethod->digest_size];
+       unsigned char calculated_stored_key[hmethod->digest_size];
+       unsigned char server_key[hmethod->digest_size];
        int ret;
 
-       if (scram_sha1_scheme_parse(raw_password, size, &iter_count,
-                                   &salt_base64, stored_key,
-                                   server_key, error_r) < 0)
+       if (scram_scheme_parse(hmethod, scheme_name, raw_password, size,
+                              &iter_count, &salt_base64,
+                              stored_key, server_key, error_r) < 0)
                return -1;
 
        salt = buffer_get_data(t_base64_decode_str(salt_base64), &salt_len);
 
        /* FIXME: credentials should be SASLprepped UTF8 data here */
-       Hi((const unsigned char *)plaintext, strlen(plaintext), salt, salt_len,
-          iter_count, salted_password);
+       Hi(hmethod, (const unsigned char *)plaintext, strlen(plaintext),
+          salt, salt_len, iter_count, salted_password);
 
        /* Calculate ClientKey */
-       hmac_init(&ctx, salted_password, sizeof(salted_password),
-                 &hash_method_sha1);
+       hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
        hmac_update(&ctx, "Client Key", 10);
        hmac_final(&ctx, client_key);
 
        /* Calculate StoredKey */
-       sha1_get_digest(client_key, sizeof(client_key), calculated_stored_key);
+       hash_method_get_digest(hmethod, client_key, sizeof(client_key),
+                              calculated_stored_key);
        ret = mem_equals_timing_safe(stored_key, calculated_stored_key,
                                     sizeof(stored_key)) ? 1 : 0;
 
@@ -136,17 +142,16 @@ int scram_sha1_verify(const char *plaintext,
        return ret;
 }
 
-void scram_sha1_generate(const char *plaintext,
-                        const struct password_generate_params *params ATTR_UNUSED,
-                        const unsigned char **raw_password_r, size_t *size_r)
+void scram_generate(const struct hash_method *hmethod, const char *plaintext,
+                   const unsigned char **raw_password_r, size_t *size_r)
 {
        string_t *str;
        struct hmac_context ctx;
        unsigned char salt[16];
-       unsigned char salted_password[SHA1_RESULTLEN];
-       unsigned char client_key[SHA1_RESULTLEN];
-       unsigned char server_key[SHA1_RESULTLEN];
-       unsigned char stored_key[SHA1_RESULTLEN];
+       unsigned char salted_password[hmethod->digest_size];
+       unsigned char client_key[hmethod->digest_size];
+       unsigned char server_key[hmethod->digest_size];
+       unsigned char stored_key[hmethod->digest_size];
 
        random_fill(salt, sizeof(salt));
 
@@ -155,23 +160,22 @@ void scram_sha1_generate(const char *plaintext,
        base64_encode(salt, sizeof(salt), str);
 
        /* FIXME: credentials should be SASLprepped UTF8 data here */
-       Hi((const unsigned char *)plaintext, strlen(plaintext), salt,
+       Hi(hmethod, (const unsigned char *)plaintext, strlen(plaintext), salt,
           sizeof(salt), SCRAM_DEFAULT_ITERATE_COUNT, salted_password);
 
        /* Calculate ClientKey */
-       hmac_init(&ctx, salted_password, sizeof(salted_password),
-                 &hash_method_sha1);
+       hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
        hmac_update(&ctx, "Client Key", 10);
        hmac_final(&ctx, client_key);
 
        /* Calculate StoredKey */
-       sha1_get_digest(client_key, sizeof(client_key), stored_key);
+       hash_method_get_digest(hmethod, client_key, sizeof(client_key),
+                              stored_key);
        str_append_c(str, ',');
        base64_encode(stored_key, sizeof(stored_key), str);
 
        /* Calculate ServerKey */
-       hmac_init(&ctx, salted_password, sizeof(salted_password),
-                 &hash_method_sha1);
+       hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
        hmac_update(&ctx, "Server Key", 10);
        hmac_final(&ctx, server_key);
        str_append_c(str, ',');
@@ -185,3 +189,19 @@ void scram_sha1_generate(const char *plaintext,
        *raw_password_r = (const unsigned char *)str_c(str);
        *size_r = str_len(str);
 }
+
+int scram_sha1_verify(const char *plaintext,
+                     const struct password_generate_params *params ATTR_UNUSED,
+                     const unsigned char *raw_password, size_t size,
+                     const char **error_r)
+{
+       return scram_verify(&hash_method_sha1, "SCRAM-SHA-1", plaintext,
+                           raw_password, size, error_r);
+}
+
+void scram_sha1_generate(const char *plaintext,
+                        const struct password_generate_params *params ATTR_UNUSED,
+                         const unsigned char **raw_password_r, size_t *size_r)
+{
+       scram_generate(&hash_method_sha1, plaintext, raw_password_r, size_r);
+}
index aa51a50a5a2664a86c0132d3edeeaa22764934fc..fbf562ef86ee26cd57f512a7c68cfdb22d55a341 100644 (file)
@@ -3,6 +3,8 @@
 
 #define AUTH_LOG_MSG_PASSWORD_MISMATCH "Password mismatch"
 
+struct hash_method;
+
 enum password_encoding {
        PW_ENCODING_NONE,
        PW_ENCODING_BASE64,
@@ -100,10 +102,17 @@ int crypt_verify(const char *plaintext,
                 const unsigned char *raw_password, size_t size,
                 const char **error_r);
 
-int scram_sha1_scheme_parse(const unsigned char *credentials, size_t size,
-                           unsigned int *iter_count_r, const char **salt_r,
-                           unsigned char stored_key_r[],
-                           unsigned char server_key_r[], const char **error_r);
+int scram_scheme_parse(const struct hash_method *hmethod, const char *name,
+                      const unsigned char *credentials, size_t size,
+                      unsigned int *iter_count_r, const char **salt_r,
+                      unsigned char stored_key_r[],
+                      unsigned char server_key_r[], const char **error_r);
+int scram_verify(const struct hash_method *hmethod, const char *scheme_name,
+                const char *plaintext, const unsigned char *raw_password,
+                size_t size, const char **error_r);
+void scram_generate(const struct hash_method *hmethod, const char *plaintext,
+                   const unsigned char **raw_password_r, size_t *size_r);
+
 int scram_sha1_verify(const char *plaintext,
                      const struct password_generate_params *params ATTR_UNUSED,
                      const unsigned char *raw_password, size_t size,