From: Stephan Bosch Date: Sun, 6 Jan 2019 22:04:37 +0000 (+0100) Subject: auth: password-scheme: scram: Make implementation generic to support other hash algor... X-Git-Tag: 2.3.10~236 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fdd67b3501ae407221a5832f9c4556a9d70ed9b4;p=thirdparty%2Fdovecot%2Fcore.git auth: password-scheme: scram: Make implementation generic to support other hash algorithms. --- diff --git a/src/auth/mech-scram.c b/src/auth/mech-scram.c index 27e1cd2607..252ca15a62 100644 --- a/src/auth/mech-scram.c +++ b/src/auth/mech-scram.c @@ -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); diff --git a/src/auth/password-scheme-scram.c b/src/auth/password-scheme-scram.c index 60e41c0f41..0c7fdb4b00 100644 --- a/src/auth/password-scheme-scram.c +++ b/src/auth/password-scheme-scram.c @@ -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" @@ -23,36 +24,38 @@ #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); +} diff --git a/src/auth/password-scheme.h b/src/auth/password-scheme.h index aa51a50a5a..fbf562ef86 100644 --- a/src/auth/password-scheme.h +++ b/src/auth/password-scheme.h @@ -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,