Mercurial > pidgin.yaz
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