cpw.darkrain42.xmpp.scram: c7d60579: How is it that there's no programmatic w...

darkrain42 at pidgin.im darkrain42 at pidgin.im
Sun Nov 8 13:46:10 EST 2009


-----------------------------------------------------------------
Revision: c7d6057930fe6daf84905eecbfe2ae6f3c9fdc56
Ancestor: f1adcdecf1191aa4810fae1c92417e0f177e30ee
Author: darkrain42 at pidgin.im
Date: 2009-11-08T18:38:30
Branch: im.pidgin.cpw.darkrain42.xmpp.scram
URL: http://d.pidgin.im/viewmtn/revision/info/c7d6057930fe6daf84905eecbfe2ae6f3c9fdc56

Modified files:
        libpurple/protocols/jabber/auth_scram.c

ChangeLog: 

How is it that there's no programmatic way to get the output size of the hash functions without resorting to a hardcoded table?  Or did I miss something?

-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/auth_scram.c	a88eda59afe86838f4fb4dec48e147f0676e3f1f
+++ libpurple/protocols/jabber/auth_scram.c	73a2f4ae4dfab60bdb1e2245a918378b03a688eb
@@ -28,47 +28,81 @@
 #include "cipher.h"
 #include "debug.h"
 
+static const struct {
+	const char *hash;
+	guint size;
+} hash_sizes[] = {
+	{ "sha1", 20 },
+	{ "sha224", 28 },
+	{ "sha256", 32 },
+	{ "sha384", 48 },
+	{ "sha512", 64 }
+};
+
+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;
+}
+
 GString *jabber_auth_scram_hi(const gchar *hash, const GString *str,
                               GString *salt, guint iterations)
 {
 	PurpleCipherContext *context;
 	GString *result;
 	guint i;
-	guchar prev[20], tmp[20]; /* FIXME: Hardcoded 20 */
+	guint hash_len;
+	guchar *prev, *tmp;
 
 	g_return_val_if_fail(hash != NULL, NULL);
 	g_return_val_if_fail(str != NULL && str->len > 0, NULL);
 	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_len);
+	tmp = 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
 	 * octet first. */
 	g_string_append_len(salt, "\0\0\0\1", 4);
 
-	result = g_string_sized_new(20); /* FIXME: Hardcoded 20 */
+	result = g_string_sized_new(hash_len);
 
 	/* Compute U0 */
 	purple_cipher_context_set_option(context, "hash", (gpointer)hash);
 	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, result->allocated_len, (guchar *)result->str, &(result->len));
+	purple_cipher_context_digest(context, hash_len, (guchar *)result->str, &(result->len));
 
-	memcpy(prev, result->str, result->len);
+	memcpy(prev, result->str, hash_len);
 
 	/* Compute U1...Ui */
 	for (i = 1; i < iterations; ++i) {
 		guint j;
 		purple_cipher_context_set_option(context, "hash", (gpointer)hash);
 		purple_cipher_context_set_key_with_len(context, (guchar *)str->str, str->len);
-		purple_cipher_context_append(context, prev, result->len);
-		purple_cipher_context_digest(context, sizeof(tmp), tmp, NULL);
+		purple_cipher_context_append(context, prev, hash_len);
+		purple_cipher_context_digest(context, hash_len, tmp, NULL);
 
-		for (j = 0; j < 20; ++j)
+		for (j = 0; j < hash_len; ++j)
 			result->str[j] ^= tmp[j];
 
-		memcpy(prev, tmp, result->len);
+		memcpy(prev, tmp, hash_len);
 	}
 
 	purple_cipher_context_destroy(context);


More information about the Commits mailing list