diff options
author | Ruslan N. Marchenko <me@ruff.mobi> | 2020-05-30 07:31:03 +0200 |
---|---|---|
committer | Ruslan N. Marchenko <me@ruff.mobi> | 2020-09-23 20:31:18 +0200 |
commit | 0f46ce192f9d3809282813286c04fdff48b1619d (patch) | |
tree | d060f2e962841b80ee7ddd16d983486ff1e1491d | |
parent | ce00127c0202ec1b66edc1bde6e349030059d0b8 (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.c | 41 | ||||
-rw-r--r-- | wocky/wocky-sasl-utils.c | 62 | ||||
-rw-r--r-- | wocky/wocky-sasl-utils.h | 3 |
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); |