#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;
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;
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));
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, ',');
*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);
+}