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