~ubuntu-branches/ubuntu/quantal/pidgin/quantal

1.3.18 by Ari Pollak
Import upstream version 2.7.11
1
/*
2
 * purple
3
 *
4
 * Purple is the legal property of its developers, whose names are too numerous
5
 * to list here.  Please refer to the COPYRIGHT file distributed with this
6
 * source distribution.
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
21
 */
22
#include <cipher.h>
23
#include <util.h>
24
25
struct RC4Context {
26
	guchar state[256];
27
	guchar x;
28
	guchar y;
29
	gint key_len;
30
};
31
32
static void
33
rc4_init(PurpleCipherContext *context, void *extra) {
34
	struct RC4Context *rc4_ctx;
35
	rc4_ctx = g_new0(struct RC4Context, 1);
36
	purple_cipher_context_set_data(context, rc4_ctx);
37
	purple_cipher_context_reset(context, extra);
38
}
39
40
41
static void
42
rc4_reset(PurpleCipherContext *context, void *extra) {
43
	struct RC4Context *rc4_ctx;
44
	guint i;
45
46
	rc4_ctx = purple_cipher_context_get_data(context);
47
48
	g_return_if_fail(rc4_ctx);
49
50
	for(i = 0; i < 256; i++)
51
		rc4_ctx->state[i] = i;
52
	rc4_ctx->x = 0;
53
	rc4_ctx->y = 0;
54
55
	/* default is 5 bytes (40bit key) */
56
	rc4_ctx->key_len = 5;
57
58
}
59
60
static void
61
rc4_uninit(PurpleCipherContext *context) {
62
	struct RC4Context *rc4_ctx;
63
64
	rc4_ctx = purple_cipher_context_get_data(context);
65
	memset(rc4_ctx, 0, sizeof(*rc4_ctx));
66
67
	g_free(rc4_ctx);
68
	rc4_ctx = NULL;
69
}
70
71
72
73
static void
74
rc4_set_key (PurpleCipherContext *context, const guchar * key) {
75
	struct RC4Context *ctx;
76
	guchar *state;
77
	guchar temp_swap;
78
	guchar x, y;
79
	guint i;
80
81
	ctx = purple_cipher_context_get_data(context);
82
83
	x = 0;
84
	y = 0;
85
	state = &ctx->state[0];
86
	for(i = 0; i < 256; i++)
87
	{
88
		y = (key[x] + state[i] + y) % 256;
89
		temp_swap = state[i];
90
		state[i] = state[y];
91
		state[y] = temp_swap;
92
		x = (x + 1) % ctx->key_len;
93
	}
94
}
95
96
static void
97
rc4_set_opt(PurpleCipherContext *context, const gchar *name, void *value) {
98
	struct RC4Context *ctx;
99
100
	ctx = purple_cipher_context_get_data(context);
101
102
	if(purple_strequal(name, "key_len")) {
103
		ctx->key_len = GPOINTER_TO_INT(value);
104
	}
105
}
106
107
static size_t
108
rc4_get_key_size (PurpleCipherContext *context)
109
{
110
	struct RC4Context *ctx;
111
112
	g_return_val_if_fail(context, -1);
113
114
	ctx = purple_cipher_context_get_data(context);
115
116
	g_return_val_if_fail(ctx, -1);
117
118
	return ctx->key_len;
119
}
120
121
static void *
122
rc4_get_opt(PurpleCipherContext *context, const gchar *name) {
123
	struct RC4Context *ctx;
124
125
	ctx = purple_cipher_context_get_data(context);
126
127
	if(purple_strequal(name, "key_len")) {
128
		return GINT_TO_POINTER(ctx->key_len);
129
	}
130
131
	return NULL;
132
}
133
134
static gint
135
rc4_encrypt(PurpleCipherContext *context, const guchar data[],
136
            size_t len, guchar output[], size_t *outlen) {
137
	struct RC4Context *ctx;
138
	guchar temp_swap;
139
	guchar x, y, z;
140
	guchar *state;
141
	guint i;
142
143
	ctx = purple_cipher_context_get_data(context);
144
145
	x = ctx->x;
146
	y = ctx->y;
147
	state = &ctx->state[0];
148
149
	for(i = 0; i < len; i++)
150
	{
151
		x = (x + 1) % 256;
152
		y = (state[x] + y) % 256;
153
		temp_swap = state[x];
154
		state[x] = state[y];
155
		state[y] = temp_swap;
156
		z = state[x] + (state[y]) % 256;
157
		output[i] = data[i] ^ state[z];
158
	}
159
	ctx->x = x;
160
	ctx->y = y;
161
	if(outlen)
162
		*outlen = len;
163
164
	return 0;
165
}
166
167
static PurpleCipherOps RC4Ops = {
1.3.19 by Ari Pollak
Import upstream version 2.8.0
168
	rc4_set_opt,   /* Set Option    */
169
	rc4_get_opt,   /* Get Option    */
170
	rc4_init,      /* init          */
171
	rc4_reset,     /* reset         */
172
	rc4_uninit,    /* uninit        */
173
	NULL,          /* set iv        */
174
	NULL,          /* append        */
175
	NULL,          /* digest        */
176
	rc4_encrypt,   /* encrypt       */
177
	NULL,          /* decrypt       */
178
	NULL,          /* set salt      */
179
	NULL,          /* get salt size */
180
	rc4_set_key,   /* set key       */
181
	rc4_get_key_size, /* get key size  */
182
	NULL,          /* set batch mode */
183
	NULL,          /* get batch mode */
184
	NULL,          /* get block size */
185
	NULL           /* set key with len */
1.3.18 by Ari Pollak
Import upstream version 2.7.11
186
};
187
188
PurpleCipherOps *
189
purple_rc4_cipher_get_ops(void) {
190
	return &RC4Ops;
191
}
192