changeset 16398:eca698c354d0

RC4 support in cipher.c - patch from Nathan Peterson (uvwarning) See: https://sourceforge.net/tracker/?func=detail&atid=300235&aid=1694487&group_id=235
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Wed, 25 Apr 2007 03:14:11 +0000
parents 81015b477483
children 18d766d252f3
files libpurple/cipher.c
diffstat 1 files changed, 148 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/cipher.c	Sat Apr 21 04:58:13 2007 +0000
+++ b/libpurple/cipher.c	Wed Apr 25 03:14:11 2007 +0000
@@ -1251,6 +1251,153 @@
 };
 
 /*******************************************************************************
+ * 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 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       */
+	NULL           /* get key size  */
+};
+
+/*******************************************************************************
  * Structs
  ******************************************************************************/
 struct _PurpleCipher {
@@ -1444,6 +1591,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