summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan N. Marchenko <me@ruff.mobi>2020-05-30 07:31:03 +0200
committerRuslan N. Marchenko <me@ruff.mobi>2020-09-23 20:31:18 +0200
commit0f46ce192f9d3809282813286c04fdff48b1619d (patch)
treed060f2e962841b80ee7ddd16d983486ff1e1491d
parentce00127c0202ec1b66edc1bde6e349030059d0b8 (diff)
Migrate SASL SCRAM to extendable hashing algorithm
Move to Glib GChecksum and GHmac implementation, add hash-algo property to select algorithm, default to SHA1 to preserve compatibility
-rw-r--r--wocky/wocky-sasl-scram.c41
-rw-r--r--wocky/wocky-sasl-utils.c62
-rw-r--r--wocky/wocky-sasl-utils.h3
3 files changed, 42 insertions, 64 deletions
diff --git a/wocky/wocky-sasl-scram.c b/wocky/wocky-sasl-scram.c
index 7a051fd..c267347 100644
--- a/wocky/wocky-sasl-scram.c
+++ b/wocky/wocky-sasl-scram.c
@@ -46,6 +46,7 @@ enum
PROP_SERVER = 1,
PROP_CB_TYPE,
PROP_CB_DATA,
+ PROP_HASH_ALGO,
PROP_USERNAME,
PROP_PASSWORD
};
@@ -54,6 +55,7 @@ struct _WockySaslScramPrivate
{
WockySaslScramState state;
WockyTLSBindingType cb_type;
+ GChecksumType hash_algo;
const gchar *gs2_flag;
gchar *cb_data;
gchar *username;
@@ -87,6 +89,10 @@ wocky_sasl_scram_get_property (
switch (property_id)
{
+ case PROP_HASH_ALGO:
+ g_value_set_int (value, priv->hash_algo);
+ break;
+
case PROP_CB_TYPE:
g_value_set_enum (value, priv->cb_type);
break;
@@ -121,6 +127,10 @@ wocky_sasl_scram_set_property (
switch (property_id)
{
+ case PROP_HASH_ALGO:
+ priv->hash_algo = g_value_get_int (value);
+ break;
+
case PROP_CB_TYPE:
priv->cb_type = g_value_get_enum (value);
break;
@@ -186,6 +196,12 @@ wocky_sasl_scram_class_init (
object_class->set_property = wocky_sasl_scram_set_property;
object_class->get_property = wocky_sasl_scram_get_property;
+ g_object_class_install_property (object_class, PROP_HASH_ALGO,
+ g_param_spec_int ("hash-algo", "hash algorithm",
+ "The type of the Hash Algorithm to use for HMAC from GChecksumType",
+ G_CHECKSUM_SHA1, G_CHECKSUM_SHA512, G_CHECKSUM_SHA1,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
g_object_class_install_property (object_class, PROP_CB_TYPE,
g_param_spec_enum ("cb-type", "binding type",
"The type of the TLS Channel Binding to use in SASL negotiation",
@@ -381,7 +397,8 @@ scram_calculate_salted_password (WockySaslScram *self)
g_byte_array_append (salt, one, sizeof (one));
/* Calculate U1 */
- result = sasl_calculate_hmac_sha1 ((guint8 *) priv->password, pass_len,
+ result = sasl_calculate_hmac (priv->hash_algo,
+ (guint8 *) priv->password, pass_len,
salt->data, salt->len);
prev = g_byte_array_sized_new (result->len);
@@ -390,7 +407,8 @@ scram_calculate_salted_password (WockySaslScram *self)
/* Calculate U2 and onwards, while keeping a rolling result */
for (i = 1; i < priv->iterations; i++)
{
- GByteArray *U = sasl_calculate_hmac_sha1 ((guint8 *) priv->password,
+ GByteArray *U = sasl_calculate_hmac (priv->hash_algo,
+ (guint8 *) priv->password,
pass_len, prev->data, prev->len);
g_byte_array_unref (prev);
@@ -418,27 +436,29 @@ scram_make_client_proof (WockySaslScram *self)
WockySaslScramPrivate *priv = self->priv;
gchar *proof = NULL;
GByteArray *client_key, *client_signature;
- gsize len = WOCKY_SHA1_DIGEST_SIZE;
- guint8 stored_key[WOCKY_SHA1_DIGEST_SIZE];
+ gsize len = g_checksum_type_get_length (priv->hash_algo);
+ guint8 *stored_key;
GChecksum *checksum;
+ stored_key = g_new (guint8, len);
/* Calculate the salted password and save it for later as we need it to
* verify the servers reply */
scram_calculate_salted_password (self);
- client_key = sasl_calculate_hmac_sha1 (priv->salted_password->data,
+ client_key = sasl_calculate_hmac (priv->hash_algo,
+ priv->salted_password->data,
priv->salted_password->len, (guint8 *) CLIENT_KEY_STR,
strlen (CLIENT_KEY_STR));
- checksum = g_checksum_new (G_CHECKSUM_SHA1);
+ checksum = g_checksum_new (priv->hash_algo);
g_checksum_update (checksum, client_key->data, client_key->len);
g_checksum_get_digest (checksum, stored_key, &len);
g_checksum_free (checksum);
DEBUG ("auth message: %s", priv->auth_message);
- client_signature = sasl_calculate_hmac_sha1 (stored_key,
- WOCKY_SHA1_DIGEST_SIZE,
+ client_signature = sasl_calculate_hmac (priv->hash_algo,
+ stored_key, len,
(guint8 *) priv->auth_message, strlen (priv->auth_message));
/* xor signature and key, overwriting key */
@@ -446,6 +466,7 @@ scram_make_client_proof (WockySaslScram *self)
proof = g_base64_encode (client_key->data, client_key->len);
+ g_free (stored_key);
g_byte_array_unref (client_key);
g_byte_array_unref (client_signature);
@@ -570,11 +591,11 @@ scram_check_server_verification (WockySaslScram *self,
gchar *v;
gboolean ret;
- server_key = sasl_calculate_hmac_sha1 (
+ server_key = sasl_calculate_hmac (priv->hash_algo,
priv->salted_password->data, priv->salted_password->len,
(guint8 *) SERVER_KEY_STR, strlen (SERVER_KEY_STR));
- server_signature = sasl_calculate_hmac_sha1 (server_key->data,
+ server_signature = sasl_calculate_hmac (priv->hash_algo, server_key->data,
server_key->len, (guint8 *) priv->auth_message,
strlen (priv->auth_message));
diff --git a/wocky/wocky-sasl-utils.c b/wocky/wocky-sasl-utils.c
index 5dbad28..56f643b 100644
--- a/wocky/wocky-sasl-utils.c
+++ b/wocky/wocky-sasl-utils.c
@@ -44,64 +44,20 @@ sasl_generate_base64_nonce (void)
}
GByteArray *
-sasl_calculate_hmac_sha1 (guint8 *key,
+sasl_calculate_hmac (GChecksumType digest_type,
+ guint8 *key,
gsize key_len,
guint8 *text,
gsize text_len)
{
-/* Calculate the HMAC keyed hash algorithm as defined in RFC2104, using
- * SHA-1 as the hash algorithm */
- GChecksum *checksum;
- guint8 k_ipad[WOCKY_SHA1_BLOCK_SIZE];
- guint8 k_opad[WOCKY_SHA1_BLOCK_SIZE];
- guint8 inner_checksum[WOCKY_SHA1_DIGEST_SIZE];
- GByteArray *result;
- gsize len = WOCKY_SHA1_DIGEST_SIZE, i;
+ GHmac *hmac = g_hmac_new (digest_type, key, key_len);
+ gsize len = g_checksum_type_get_length (digest_type);
+ guint8 *digest = g_new (guint8, len);
- memset (k_ipad, 0x36, WOCKY_SHA1_BLOCK_SIZE);
- memset (k_opad, 0x5c, WOCKY_SHA1_BLOCK_SIZE);
+ g_hmac_update (hmac, text, text_len);
+ g_hmac_get_digest (hmac, digest, &len);
- if (key_len > WOCKY_SHA1_BLOCK_SIZE)
- {
- guchar k[WOCKY_SHA1_DIGEST_SIZE];
-
- checksum = g_checksum_new (G_CHECKSUM_SHA1);
- g_checksum_update (checksum, key, key_len);
- g_checksum_get_digest (checksum, k, &len);
- g_checksum_free (checksum);
-
- for (i = 0; i < WOCKY_SHA1_DIGEST_SIZE; i++)
- {
- k_ipad[i] ^= k[i];
- k_opad[i] ^= k[i];
- }
- }
- else
- {
- for (i = 0; i < key_len; i++)
- {
- k_ipad[i] ^= key[i];
- k_opad[i] ^= key[i];
- }
- }
-
- /* inner checksum */
- checksum = g_checksum_new (G_CHECKSUM_SHA1);
- g_checksum_update (checksum, k_ipad, WOCKY_SHA1_BLOCK_SIZE);
- g_checksum_update (checksum, text, text_len);
- g_checksum_get_digest (checksum, inner_checksum, &len);
- g_checksum_free (checksum);
-
- /* outer checksum */
- result = g_byte_array_new ();
- g_byte_array_set_size (result, WOCKY_SHA1_DIGEST_SIZE);
-
- checksum = g_checksum_new (G_CHECKSUM_SHA1);
- g_checksum_update (checksum, k_opad, WOCKY_SHA1_BLOCK_SIZE);
- g_checksum_update (checksum, inner_checksum, WOCKY_SHA1_DIGEST_SIZE);
- g_checksum_get_digest (checksum, result->data, &len);
- g_checksum_free (checksum);
-
- return result;
+ g_hmac_unref (hmac);
+ return g_byte_array_new_take (digest, len);
}
diff --git a/wocky/wocky-sasl-utils.h b/wocky/wocky-sasl-utils.h
index 0858b39..dfd5626 100644
--- a/wocky/wocky-sasl-utils.h
+++ b/wocky/wocky-sasl-utils.h
@@ -28,7 +28,8 @@
#define WOCKY_SHA1_DIGEST_SIZE 20
gchar * sasl_generate_base64_nonce (void);
-GByteArray * sasl_calculate_hmac_sha1 (guint8 *key,
+GByteArray * sasl_calculate_hmac (GChecksumType digest_type,
+ guint8 *key,
gsize key_len,
guint8 *text,
gsize text_len);