From: Stephan Bosch Date: Sat, 7 Jan 2023 01:39:09 +0000 (+0100) Subject: lib-auth: password-scheme-scram - Split off auth_scram_generate_key_data() from scram... X-Git-Tag: 2.4.0~3123 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4699c41b080a09c3257d64e9073eea71ea58c98a;p=thirdparty%2Fdovecot%2Fcore.git lib-auth: password-scheme-scram - Split off auth_scram_generate_key_data() from scram_generate(). Moved to auth-scram. --- diff --git a/src/lib-auth/auth-scram.c b/src/lib-auth/auth-scram.c index a1b5460e8d..eeb78c3d20 100644 --- a/src/lib-auth/auth-scram.c +++ b/src/lib-auth/auth-scram.c @@ -2,7 +2,10 @@ #include "lib.h" #include "safe-memset.h" +#include "base64.h" #include "hmac.h" +#include "randgen.h" +#include "str.h" #include "auth-scram.h" @@ -64,3 +67,49 @@ void auth_scram_hi(const struct hash_method *hmethod, result[k] ^= U[k]; } } + +void auth_scram_generate_key_data(const struct hash_method *hmethod, + const char *plaintext, unsigned int rounds, + unsigned int *iter_count_r, + const char **salt_r, + unsigned char stored_key_r[], + unsigned char server_key_r[]) +{ + struct hmac_context ctx; + unsigned char salt[16]; + unsigned char salted_password[hmethod->digest_size]; + unsigned char client_key[hmethod->digest_size]; + + if (rounds == 0) + rounds = AUTH_SCRAM_DEFAULT_ITERATE_COUNT; + else { + rounds = I_MAX(I_MIN(AUTH_SCRAM_MAX_ITERATE_COUNT, rounds), + AUTH_SCRAM_MIN_ITERATE_COUNT); + } + *iter_count_r = rounds; + + random_fill(salt, sizeof(salt)); + *salt_r = str_c(t_base64_encode(0, 0, salt, sizeof(salt))); + + /* FIXME: credentials should be SASLprepped UTF8 data here */ + auth_scram_hi(hmethod, + (const unsigned char *)plaintext, strlen(plaintext), + salt, sizeof(salt), rounds, salted_password); + + /* Calculate ClientKey */ + hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); + hmac_update(&ctx, "Client Key", 10); + hmac_final(&ctx, client_key); + + /* Calculate StoredKey */ + hash_method_get_digest(hmethod, client_key, sizeof(client_key), + stored_key_r); + + /* Calculate ServerKey */ + hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); + hmac_update(&ctx, "Server Key", 10); + hmac_final(&ctx, server_key_r); + + safe_memset(salted_password, 0, sizeof(salted_password)); + safe_memset(client_key, 0, sizeof(client_key)); +} diff --git a/src/lib-auth/auth-scram.h b/src/lib-auth/auth-scram.h index 91fff2b8dc..0a6ba936d9 100644 --- a/src/lib-auth/auth-scram.h +++ b/src/lib-auth/auth-scram.h @@ -1,6 +1,12 @@ #ifndef AUTH_SCRAM_H #define AUTH_SCRAM_H +/* SCRAM allowed iteration count range. RFC says it SHOULD be at least 4096 */ +#define AUTH_SCRAM_MIN_ITERATE_COUNT 4096 +#define AUTH_SCRAM_MAX_ITERATE_COUNT INT_MAX + +#define AUTH_SCRAM_DEFAULT_ITERATE_COUNT 4096 + struct auth_scram_key_data { pool_t pool; const struct hash_method *hmethod; @@ -18,4 +24,10 @@ void auth_scram_hi(const struct hash_method *hmethod, const unsigned char *salt, size_t salt_size, unsigned int i, unsigned char *result); +void auth_scram_generate_key_data(const struct hash_method *hmethod, + const char *plaintext, unsigned int rounds, + unsigned int *iter_count_r, + const char **salt_r, + unsigned char stored_key_r[], + unsigned char server_key_r[]); #endif diff --git a/src/lib-auth/password-scheme-scram.c b/src/lib-auth/password-scheme-scram.c index e6cdc62e87..c70ff2c607 100644 --- a/src/lib-auth/password-scheme-scram.c +++ b/src/lib-auth/password-scheme-scram.c @@ -12,7 +12,6 @@ #include "base64.h" #include "buffer.h" #include "hmac.h" -#include "randgen.h" #include "hash-method.h" #include "sha1.h" #include "sha2.h" @@ -20,12 +19,6 @@ #include "auth-scram.h" #include "password-scheme.h" -/* SCRAM allowed iteration count range. RFC says it SHOULD be at least 4096 */ -#define SCRAM_MIN_ITERATE_COUNT 4096 -#define SCRAM_MAX_ITERATE_COUNT INT_MAX - -#define SCRAM_DEFAULT_ITERATE_COUNT 4096 - 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, @@ -44,8 +37,8 @@ int scram_scheme_parse(const struct hash_method *hmethod, const char *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) { + *iter_count_r < AUTH_SCRAM_MIN_ITERATE_COUNT || + *iter_count_r > AUTH_SCRAM_MAX_ITERATE_COUNT) { *error_r = t_strdup_printf( "Invalid %s iteration count in passdb", name); return -1; @@ -123,50 +116,23 @@ void scram_generate(const struct hash_method *hmethod, const char *plaintext, size_t *size_r) { string_t *str; - struct hmac_context ctx; - unsigned char salt[16]; - unsigned char salted_password[hmethod->digest_size]; - unsigned char client_key[hmethod->digest_size]; + unsigned int iter_count; + const char *salt; unsigned char server_key[hmethod->digest_size]; unsigned char stored_key[hmethod->digest_size]; - if (rounds == 0) - rounds = SCRAM_DEFAULT_ITERATE_COUNT; - else { - rounds = I_MAX(I_MIN(SCRAM_MAX_ITERATE_COUNT, rounds), - SCRAM_MIN_ITERATE_COUNT); - } - random_fill(salt, sizeof(salt)); - - str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(salt))); - str_printfa(str, "%d,", rounds); - base64_encode(salt, sizeof(salt), str); - - /* FIXME: credentials should be SASLprepped UTF8 data here */ - auth_scram_hi(hmethod, - (const unsigned char *)plaintext, strlen(plaintext), - salt, sizeof(salt), rounds, salted_password); + auth_scram_generate_key_data(hmethod, plaintext, rounds, + &iter_count, &salt, + stored_key, server_key); - /* Calculate ClientKey */ - hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); - hmac_update(&ctx, "Client Key", 10); - hmac_final(&ctx, client_key); - - /* Calculate StoredKey */ - hash_method_get_digest(hmethod, client_key, sizeof(client_key), - stored_key); + str = t_str_new(strlen(salt) + 256); + str_printfa(str, "%d,", iter_count); + str_append(str, salt); str_append_c(str, ','); base64_encode(stored_key, sizeof(stored_key), str); - - /* Calculate ServerKey */ - hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); - hmac_update(&ctx, "Server Key", 10); - hmac_final(&ctx, server_key); str_append_c(str, ','); base64_encode(server_key, sizeof(server_key), str); - safe_memset(salted_password, 0, sizeof(salted_password)); - safe_memset(client_key, 0, sizeof(client_key)); safe_memset(server_key, 0, sizeof(server_key)); safe_memset(stored_key, 0, sizeof(stored_key));