| 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 } |
|