libpurple/ciphers/rc4cipher.c

changeset 38413
e35c6b6ca094
parent 38412
e25c73450414
child 38414
3892b306732f
equal deleted inserted replaced
38412:e25c73450414 38413:e35c6b6ca094
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 "internal.h"
23 #include "glibcompat.h"
24
25 #include "rc4cipher.h"
26
27 /*******************************************************************************
28 * Structs
29 ******************************************************************************/
30 #define PURPLE_RC4_CIPHER_GET_PRIVATE(obj) \
31 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherPrivate))
32
33 typedef struct {
34 guchar state[256];
35 guchar x;
36 guchar y;
37 gint key_len;
38 } PurpleRC4CipherPrivate;
39
40 /******************************************************************************
41 * Enums
42 *****************************************************************************/
43 enum {
44 PROP_ZERO,
45 PROP_KEY_LEN,
46 PROP_KEY,
47 PROP_LAST,
48 };
49
50 /******************************************************************************
51 * Globals
52 *****************************************************************************/
53 static GObjectClass *parent_class = NULL;
54 static GParamSpec *properties[PROP_LAST];
55
56 /******************************************************************************
57 * Cipher Stuff
58 *****************************************************************************/
59 static void
60 purple_rc4_cipher_reset(PurpleCipher *cipher) {
61 PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
62 PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
63 guint i;
64
65 for(i = 0; i < 256; i++)
66 priv->state[i] = i;
67 priv->x = 0;
68 priv->y = 0;
69
70 /* default is 5 bytes (40bit key) */
71 priv->key_len = 5;
72 }
73
74 static void
75 purple_rc4_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) {
76 PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
77 PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
78 guchar *state;
79 guchar temp_swap;
80 guchar x, y;
81 guint i;
82
83 x = 0;
84 y = 0;
85 state = &priv->state[0];
86 priv->key_len = len;
87 for(i = 0; i < 256; i++)
88 {
89 y = (key[x] + state[i] + y) % 256;
90 temp_swap = state[i];
91 state[i] = state[y];
92 state[y] = temp_swap;
93 x = (x + 1) % len;
94 }
95
96 g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_KEY]);
97 }
98
99 static ssize_t
100 purple_rc4_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len,
101 guchar output[], size_t out_size)
102 {
103 PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
104 guchar temp_swap;
105 guchar x, y, z;
106 guchar *state;
107 guint i;
108 PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
109
110 x = priv->x;
111 y = priv->y;
112 state = &priv->state[0];
113
114 for(i = 0; i < in_len; i++)
115 {
116 x = (x + 1) % 256;
117 y = (state[x] + y) % 256;
118 temp_swap = state[x];
119 state[x] = state[y];
120 state[y] = temp_swap;
121 z = state[x] + (state[y]) % 256;
122 output[i] = input[i] ^ state[z];
123 }
124 priv->x = x;
125 priv->y = y;
126
127 return in_len;
128 }
129
130 /******************************************************************************
131 * Object Stuff
132 *****************************************************************************/
133 static void
134 purple_rc4_cipher_set_property(GObject *obj, guint param_id,
135 const GValue *value, GParamSpec *pspec)
136 {
137 PurpleCipher *cipher = PURPLE_CIPHER(obj);
138 PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj);
139
140 switch(param_id) {
141 case PROP_KEY_LEN:
142 purple_rc4_cipher_set_key_len(rc4_cipher, g_value_get_int(value));
143 break;
144 case PROP_KEY:
145 {
146 guchar *key = (guchar *)g_value_get_string(value);
147 purple_rc4_cipher_set_key(cipher, key, strlen((gchar *) key));
148 }
149 break;
150 default:
151 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
152 break;
153 }
154 }
155
156 static void
157 purple_rc4_cipher_get_property(GObject *obj, guint param_id, GValue *value,
158 GParamSpec *pspec)
159 {
160 PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj);
161
162 switch(param_id) {
163 case PROP_KEY_LEN:
164 g_value_set_int(value,
165 purple_rc4_cipher_get_key_len(rc4_cipher));
166 break;
167 default:
168 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
169 break;
170 }
171 }
172
173 static void
174 purple_rc4_cipher_class_init(PurpleRC4CipherClass *klass) {
175 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
176 PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass);
177
178 parent_class = g_type_class_peek_parent(klass);
179
180 obj_class->set_property = purple_rc4_cipher_set_property;
181 obj_class->get_property = purple_rc4_cipher_get_property;
182
183 cipher_class->reset = purple_rc4_cipher_reset;
184 cipher_class->encrypt = purple_rc4_cipher_encrypt;
185 cipher_class->set_key = purple_rc4_cipher_set_key;
186
187 g_type_class_add_private(klass, sizeof(PurpleRC4CipherPrivate));
188
189 properties[PROP_KEY_LEN] = g_param_spec_int("key-len", "key-len", "key-len",
190 G_MININT, G_MAXINT, 0,
191 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
192
193 properties[PROP_KEY] = g_param_spec_string("key", "key", "key", NULL,
194 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
195
196 g_object_class_install_properties(obj_class, PROP_LAST, properties);
197 }
198
199 static void
200 purple_rc4_cipher_init(PurpleCipher *cipher) {
201 purple_rc4_cipher_reset(cipher);
202 }
203
204 /******************************************************************************
205 * API
206 *****************************************************************************/
207 GType
208 purple_rc4_cipher_get_type(void) {
209 static GType type = 0;
210
211 if(type == 0) {
212 static const GTypeInfo info = {
213 sizeof(PurpleRC4CipherClass),
214 NULL,
215 NULL,
216 (GClassInitFunc)purple_rc4_cipher_class_init,
217 NULL,
218 NULL,
219 sizeof(PurpleRC4Cipher),
220 0,
221 (GInstanceInitFunc)purple_rc4_cipher_init,
222 NULL,
223 };
224
225 type = g_type_register_static(PURPLE_TYPE_CIPHER,
226 "PurpleRC4Cipher",
227 &info, 0);
228 }
229
230 return type;
231 }
232
233 PurpleCipher *
234 purple_rc4_cipher_new(void) {
235 return g_object_new(PURPLE_TYPE_RC4_CIPHER, NULL);
236 }
237
238 void
239 purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher,
240 gint key_len)
241 {
242 PurpleRC4CipherPrivate *priv;
243
244 g_return_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher));
245
246 priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
247 priv->key_len = key_len;
248
249 g_object_notify_by_pspec(G_OBJECT(rc4_cipher), properties[PROP_KEY_LEN]);
250 }
251
252 gint
253 purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher)
254 {
255 PurpleRC4CipherPrivate *priv;
256
257 g_return_val_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher), 0);
258
259 priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
260
261 return priv->key_len;
262 }

mercurial