cpw.darkrain42.xmpp.scram: 6e866701: jabber: Clean up the SCRAM code a little...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Mon Nov 30 23:25:53 EST 2009
-----------------------------------------------------------------
Revision: 6e8667014ee07884cda5be513ae5c5bb713855b9
Ancestor: 0a951f474397791a42327c3a033585bd3e8c67bc
Author: darkrain42 at pidgin.im
Date: 2009-12-01T02:53:29
Branch: im.pidgin.cpw.darkrain42.xmpp.scram
URL: http://d.pidgin.im/viewmtn/revision/info/6e8667014ee07884cda5be513ae5c5bb713855b9
Modified files:
libpurple/protocols/jabber/auth_scram.c
libpurple/protocols/jabber/auth_scram.h
libpurple/tests/test_jabber_scram.c
ChangeLog:
jabber: Clean up the SCRAM code a little.
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/auth_scram.c 3c8722f9867dc069ac9c35d7ad737ecf33e0561b
+++ libpurple/protocols/jabber/auth_scram.c 022ddbb448c0ab860c4ad5ea1551018715877f05
@@ -28,59 +28,31 @@
#include "cipher.h"
#include "debug.h"
-static const struct {
- const char *mech_substr;
- const char *hash;
-} mech_hashes[] = {
- { "-SHA-1", "sha1" },
+static const JabberScramHash hashes[] = {
+ { "-SHA-1", "sha1", 20 },
};
-static const struct {
- const char *hash;
- guint size;
-} hash_sizes[] = {
- { "sha1", 20 },
-};
-
-static const gchar *mech_to_hash(const char *mech)
+static const JabberScramHash *mech_to_hash(const char *mech)
{
int i;
g_return_val_if_fail(mech != NULL && *mech != '\0', NULL);
- for (i = 0; i < G_N_ELEMENTS(mech_hashes); ++i) {
- if (strstr(mech, mech_hashes[i].mech_substr))
- return mech_hashes[i].hash;
+ for (i = 0; i < G_N_ELEMENTS(hashes); ++i) {
+ if (strstr(mech, hashes[i].mech_substr))
+ return &(hashes[i]);
}
purple_debug_error("jabber", "Unknown SCRAM mechanism %s\n", mech);
-
- return NULL;
+ g_return_val_if_reached(NULL);
}
-static guint hash_to_output_len(const gchar *hash)
-{
- int i;
-
- g_return_val_if_fail(hash != NULL && *hash != '\0', 0);
-
- for (i = 0; i < G_N_ELEMENTS(hash_sizes); ++i) {
- if (g_str_equal(hash, hash_sizes[i].hash))
- return hash_sizes[i].size;
- }
-
- purple_debug_error("jabber", "Unknown SCRAM hash function %s\n", hash);
-
- return 0;
-}
-
-guchar *jabber_scram_hi(const gchar *hash, const GString *str,
+guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str,
GString *salt, guint iterations)
{
PurpleCipherContext *context;
guchar *result;
guint i;
- guint hash_len;
guchar *prev, *tmp;
g_return_val_if_fail(hash != NULL, NULL);
@@ -88,13 +60,10 @@ guchar *jabber_scram_hi(const gchar *has
g_return_val_if_fail(salt != NULL && salt->len > 0, NULL);
g_return_val_if_fail(iterations > 0, NULL);
- hash_len = hash_to_output_len(hash);
- g_return_val_if_fail(hash_len > 0, NULL);
+ prev = g_new0(guint8, hash->size);
+ tmp = g_new0(guint8, hash->size);
+ result = g_new0(guint8, hash->size);
- prev = g_new0(guint8, hash_len);
- tmp = g_new0(guint8, hash_len);
- result = g_new0(guint8, hash_len);
-
context = purple_cipher_context_new_by_name("hmac", NULL);
/* Append INT(1), a four-octet encoding of the integer 1, most significant
@@ -102,25 +71,25 @@ guchar *jabber_scram_hi(const gchar *has
g_string_append_len(salt, "\0\0\0\1", 4);
/* Compute U0 */
- purple_cipher_context_set_option(context, "hash", (gpointer)hash);
+ purple_cipher_context_set_option(context, "hash", (gpointer)hash->name);
purple_cipher_context_set_key_with_len(context, (guchar *)str->str, str->len);
purple_cipher_context_append(context, (guchar *)salt->str, salt->len);
- purple_cipher_context_digest(context, hash_len, result, NULL);
+ purple_cipher_context_digest(context, hash->size, result, NULL);
- memcpy(prev, result, hash_len);
+ memcpy(prev, result, hash->size);
/* Compute U1...Ui */
for (i = 1; i < iterations; ++i) {
guint j;
- purple_cipher_context_set_option(context, "hash", (gpointer)hash);
+ purple_cipher_context_set_option(context, "hash", (gpointer)hash->name);
purple_cipher_context_set_key_with_len(context, (guchar *)str->str, str->len);
- purple_cipher_context_append(context, prev, hash_len);
- purple_cipher_context_digest(context, hash_len, tmp, NULL);
+ purple_cipher_context_append(context, prev, hash->size);
+ purple_cipher_context_digest(context, hash->size, tmp, NULL);
- for (j = 0; j < hash_len; ++j)
+ for (j = 0; j < hash->size; ++j)
result[j] ^= tmp[j];
- memcpy(prev, tmp, hash_len);
+ memcpy(prev, tmp, hash->size);
}
purple_cipher_context_destroy(context);
@@ -131,40 +100,41 @@ guchar *jabber_scram_hi(const gchar *has
/*
* Helper functions for doing the SCRAM calculations. The first argument
- * is the hash algorithm and the second (len) is the length of the output
- * buffer and key/data (the fourth argument).
+ * is the hash algorithm. All buffers must be of the appropriate size
+ * according to the JabberScramHash.
+ *
* "str" is a NULL-terminated string for hmac().
*
* Needless to say, these are fragile.
*/
static void
-hmac(const gchar *hash_alg, gsize len, guchar *out, const guchar *key, const gchar *str)
+hmac(const JabberScramHash *hash, guchar *out, const guchar *key, const gchar *str)
{
PurpleCipherContext *context;
context = purple_cipher_context_new_by_name("hmac", NULL);
- purple_cipher_context_set_option(context, "hash", (gpointer)hash_alg);
- purple_cipher_context_set_key_with_len(context, key, len);
+ purple_cipher_context_set_option(context, "hash", (gpointer)hash->name);
+ purple_cipher_context_set_key_with_len(context, key, hash->size);
purple_cipher_context_append(context, (guchar *)str, strlen(str));
- purple_cipher_context_digest(context, len, out, NULL);
+ purple_cipher_context_digest(context, hash->size, out, NULL);
purple_cipher_context_destroy(context);
}
static void
-hash(const gchar *hash_alg, gsize len, guchar *out, const guchar *data)
+hash(const JabberScramHash *hash, guchar *out, const guchar *data)
{
PurpleCipherContext *context;
- context = purple_cipher_context_new_by_name(hash_alg, NULL);
- purple_cipher_context_append(context, data, len);
- purple_cipher_context_digest(context, len, out, NULL);
+ context = purple_cipher_context_new_by_name(hash->name, NULL);
+ purple_cipher_context_append(context, data, hash->size);
+ purple_cipher_context_digest(context, hash->size, out, NULL);
purple_cipher_context_destroy(context);
}
gboolean
jabber_scram_calc_proofs(JabberScramData *data, GString *salt, guint iterations)
{
- guint hash_len = hash_to_output_len(data->hash);
+ guint hash_len = data->hash->size;
guint i;
GString *pass = g_string_new(data->password);
@@ -189,18 +159,18 @@ jabber_scram_calc_proofs(JabberScramData
return FALSE;
/* client_key = HMAC(salted_password, "Client Key") */
- hmac(data->hash, hash_len, client_key, salted_password, "Client Key");
+ hmac(data->hash, client_key, salted_password, "Client Key");
/* server_key = HMAC(salted_password, "Server Key") */
- hmac(data->hash, hash_len, server_key, salted_password, "Server Key");
+ hmac(data->hash, server_key, salted_password, "Server Key");
g_free(salted_password);
/* stored_key = HASH(client_key) */
- hash(data->hash, hash_len, stored_key, client_key);
+ hash(data->hash, stored_key, client_key);
/* client_signature = HMAC(stored_key, auth_message) */
- hmac(data->hash, hash_len, client_signature, stored_key, data->auth_message->str);
+ hmac(data->hash, client_signature, stored_key, data->auth_message->str);
/* server_signature = HMAC(server_key, auth_message) */
- hmac(data->hash, hash_len, (guchar *)data->server_signature->str, server_key, data->auth_message->str);
+ hmac(data->hash, (guchar *)data->server_signature->str, server_key, data->auth_message->str);
/* client_proof = client_key XOR client_signature */
for (i = 0; i < hash_len; ++i)
@@ -570,12 +540,6 @@ static JabberSaslMech scram_sha1_plus_me
};
#endif
-/* For tests */
-JabberSaslMech *jabber_scram_get_sha1(void)
-{
- return &scram_sha1_mech;
-}
-
JabberSaslMech **jabber_auth_get_scram_mechs(gint *count)
{
static JabberSaslMech *mechs[] = {
@@ -585,8 +549,6 @@ JabberSaslMech **jabber_auth_get_scram_m
#endif
};
- g_return_val_if_fail(count != NULL, NULL);
-
*count = G_N_ELEMENTS(mechs);
return mechs;
}
============================================================
--- libpurple/protocols/jabber/auth_scram.h 2ca54ce4052318fbc65cd3802f7fa089c88ba01a
+++ libpurple/protocols/jabber/auth_scram.h 8f7564b2c0ccae49e4c2ff83fac061d0ae4808cd
@@ -32,9 +32,14 @@
/* Per-connection state stored between messages.
* This is stored in js->auth_data_mech.
*/
+typedef struct {
+ const char *mech_substr;
+ const char *name;
+ guint size;
+} JabberScramHash;
typedef struct {
- const char *hash;
+ const JabberScramHash *hash;
char *cnonce;
GString *auth_message;
@@ -48,14 +53,10 @@ typedef struct {
#include "auth.h"
-JabberSaslMech *jabber_scram_get_sha1(void);
-
/**
* Implements the Hi() function as described in the SASL-SCRAM I-D.
*
- * @param hash The name of a hash function to be used with HMAC. This should
- * be suitable to be passed to the libpurple cipher API. Typically
- * it will be "sha1".
+ * @param hash The struct corresponding to the hash function to be used.
* @param str The string to perform the PBKDF2 operation on.
* @param salt The salt.
* @param iterations The number of iterations to perform.
@@ -64,7 +65,7 @@ JabberSaslMech *jabber_scram_get_sha1(vo
* NOT null-terminated and its length is the length of the binary
* output of the hash function in-use.
*/
-guchar *jabber_scram_hi(const char *hash, const GString *str,
+guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str,
GString *salt, guint iterations);
/**
============================================================
--- libpurple/tests/test_jabber_scram.c bdb6aa6515f209808bb118bf243f91d23ab50cb9
+++ libpurple/tests/test_jabber_scram.c 1f0f3a741b46abe5cddc81c87a2d8471b9a00fe1
@@ -4,10 +4,12 @@
#include "../util.h"
#include "../protocols/jabber/auth_scram.h"
+static JabberScramHash sha1_mech = { "-SHA-1", "sha1", 20 };
+
#define assert_pbkdf2_equal(password, salt, count, expected) { \
GString *p = g_string_new(password); \
GString *s = g_string_new(salt); \
- guchar *result = jabber_scram_hi("sha1", p, s, count); \
+ guchar *result = jabber_scram_hi(&sha1_mech, p, s, count); \
fail_if(result == NULL, "Hi() returned NULL"); \
fail_if(0 != memcmp(result, expected, 20), "Hi() returned invalid result"); \
g_string_free(s, TRUE); \
@@ -35,7 +37,7 @@ START_TEST(test_proofs)
const char *client_proof;
/* const char *server_signature; */
- data->hash = "sha1";
+ data->hash = &sha1_mech;
data->password = g_strdup("password");
data->auth_message = g_string_new("n=username at jabber.org,r=8jLxB5515dhFxBil5A0xSXMH,"
"r=8jLxB5515dhFxBil5A0xSXMHabc,s=c2FsdA==,i=1,"
@@ -60,7 +62,7 @@ START_TEST(test_mech)
gchar *out;
data->step = 1;
- data->hash = "sha1";
+ data->hash = &sha1_mech;
data->password = g_strdup("password");
data->cnonce = g_strdup("H7yDYKAWBCrM2Fa5SxGa4iez");
data->auth_message = g_string_new("n=paul,r=H7yDYKAWBCrM2Fa5SxGa4iez");
More information about the Commits
mailing list