changeset 17008:34d9037a228c

RC4 support to libpurple's cipher.c. applied changes from 16cddf101af9bec7aa7546f67d791389bb82a8c5 through eb65d87cbe206ce460c3647f24e6cc06bb1e83fe Patch from Nathan Peterson to add RC4 support. applied changes from eb65d87cbe206ce460c3647f24e6cc06bb1e83fe through c27d5698b3cb75df5ec296031e29e46440ac2303 Add rc4_get_key_size.
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Thu, 10 May 2007 02:58:35 +0000
parents 9ded461750a9
children 2f9e5cde6f97
files libpurple/cipher.c
diffstat 1 files changed, 164 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/cipher.c	Wed May 09 04:09:56 2007 +0000
+++ b/libpurple/cipher.c	Thu May 10 02:58:35 2007 +0000
@@ -1275,6 +1275,169 @@
 };
 
 /*******************************************************************************
+ * RC4
+ ******************************************************************************/
+
+struct RC4Context {
+  guchar state[256];
+  guchar x;
+  guchar y;
+  gint key_len;
+};
+
+static void
+rc4_init(PurpleCipherContext *context, void *extra) {
+	struct RC4Context *rc4_ctx;
+	rc4_ctx = g_new0(struct RC4Context, 1);
+	purple_cipher_context_set_data(context, rc4_ctx);
+	purple_cipher_context_reset(context, extra);
+}
+
+
+static void
+rc4_reset(PurpleCipherContext *context, void *extra) {
+	struct RC4Context *rc4_ctx;
+	guint i;
+
+	rc4_ctx = purple_cipher_context_get_data(context);
+
+	g_return_if_fail(rc4_ctx);
+
+	for(i = 0; i < 256; i++)
+		rc4_ctx->state[i] = i;
+	rc4_ctx->x = 0;
+	rc4_ctx->y = 0;
+
+	/* default is 5 bytes (40bit key) */
+	rc4_ctx->key_len = 5;
+
+}
+
+static void
+rc4_uninit(PurpleCipherContext *context) {
+	struct RC4Context *rc4_ctx;
+
+	rc4_ctx = purple_cipher_context_get_data(context);
+	memset(rc4_ctx, 0, sizeof(rc4_ctx));
+
+	g_free(rc4_ctx);
+	rc4_ctx = NULL;
+}
+
+
+
+static void
+rc4_set_key (PurpleCipherContext *context, const guchar * key) {
+	struct RC4Context *ctx;
+	guchar *state;
+	guchar temp_swap;
+	guchar x, y;
+	guint i;
+
+	ctx = purple_cipher_context_get_data(context);
+
+	x = 0;
+	y = 0;
+	state = &ctx->state[0];
+	for(i = 0; i < 256; i++)
+	{
+		y = (key[x] + state[i] + y) % 256;
+		temp_swap = state[i];
+		state[i] = state[y];
+		state[y] = temp_swap;
+		x = (x + 1) % ctx->key_len;
+	}
+}
+
+static void
+rc4_set_opt(PurpleCipherContext *context, const gchar *name, void *value) {
+	struct RC4Context *ctx;
+
+	ctx = purple_cipher_context_get_data(context);
+
+	if(!strcmp(name, "key_len")) {
+		ctx->key_len = GPOINTER_TO_INT(value);
+	}
+}
+
+static size_t 
+rc4_get_key_size (PurpleCipherContext *context)
+{
+	struct RC4Context *ctx;
+
+	g_return_val_if_fail(context, -1);
+
+	ctx = purple_cipher_context_get_data(context);
+
+	g_return_val_if_fail(ctx, -1);
+
+	return ctx->key_len;
+}
+
+static void *
+rc4_get_opt(PurpleCipherContext *context, const gchar *name) {
+	struct RC4Context *ctx;
+
+	ctx = purple_cipher_context_get_data(context);
+
+	if(!strcmp(name, "key_len")) {
+		return GINT_TO_POINTER(ctx->key_len);
+	}
+
+	return NULL;
+}
+
+static gint
+rc4_encrypt(PurpleCipherContext *context, const guchar data[],
+	    size_t len, guchar output[], size_t *outlen) {
+	struct RC4Context *ctx;
+	guchar temp_swap;
+	guchar x, y, z;
+	guchar *state;
+	guint i;
+
+	ctx = purple_cipher_context_get_data(context);
+
+	x = ctx->x;
+	y = ctx->y;
+	state = &ctx->state[0];
+
+	for(i = 0; i < len; i++)
+	{
+		x = (x + 1) % 256;
+		y = (state[x] + y) % 256;
+		temp_swap = state[x];
+		state[x] = state[y];
+		state[y] = temp_swap;
+		z = state[x] + (state[y]) % 256;
+		output[i] = data[i] ^ state[z];
+	}
+	ctx->x = x;
+	ctx->y = y;
+	if(outlen)
+		*outlen = len;
+
+	return 0;
+}
+
+static PurpleCipherOps RC4Ops = {
+	rc4_set_opt,   /* Set Option    */
+	rc4_get_opt,   /* Get Option    */
+	rc4_init,      /* init          */
+	rc4_reset,     /* reset         */
+	rc4_uninit,    /* uninit        */
+	NULL,          /* set iv        */
+	NULL,          /* append        */
+	NULL,          /* digest        */
+	rc4_encrypt,   /* encrypt       */
+	NULL,          /* decrypt       */
+	NULL,          /* set salt      */
+	NULL,          /* get salt size */
+	rc4_set_key,   /* set key       */
+	rc4_get_key_size/* get key size  */
+};
+
+/*******************************************************************************
  * Structs
  ******************************************************************************/
 struct _PurpleCipher {
@@ -1468,6 +1631,7 @@
 	purple_ciphers_register_cipher("sha1", &SHA1Ops);
 	purple_ciphers_register_cipher("md4", &MD4Ops);
 	purple_ciphers_register_cipher("des", &DESOps);
+	purple_ciphers_register_cipher("rc4", &RC4Ops);
 }
 
 void