comparison src/protocols/sametime/meanwhile/cipher.c @ 10969:3ef77720e577

[gaim-migrate @ 12790] importing meanwhile library for use in the sametime plugin committer: Tailor Script <tailor@pidgin.im>
author Christopher O'Brien <siege@pidgin.im>
date Sun, 05 Jun 2005 02:50:13 +0000
parents
children 0110fc7c6a8a
comparison
equal deleted inserted replaced
10968:e0d5038fbb7e 10969:3ef77720e577
1
2 /*
3 Meanwhile - Unofficial Lotus Sametime Community Client Library
4 Copyright (C) 2004 Christopher (siege) O'Brien
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the Free
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24
25 #include "mw_channel.h"
26 #include "mw_cipher.h"
27 #include "mw_debug.h"
28 #include "mw_session.h"
29
30
31 /** From RFC2268 */
32 static unsigned char PT[] = {
33 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
34 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
35 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
36 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
37 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
38 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
39 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
40 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
41 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
42 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
43 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
44 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
45 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
46 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
47 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
48 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
49 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
50 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
51 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
52 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
53 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
54 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
55 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
56 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
57 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
58 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
59 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
60 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
61 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
62 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
63 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
64 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
65 };
66
67
68 void rand_key(char *key, gsize keylen) {
69 srand(clock());
70 while(keylen--) key[keylen] = rand() & 0xff;
71 }
72
73
74 void mwIV_init(char *iv) {
75 static unsigned char normal_iv[] = {
76 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
77 };
78 memcpy(iv, normal_iv, 8);
79
80 /*
81 *iv++ = 0x01; *iv++ = 0x23;
82 *iv++ = 0x45; *iv++ = 0x67;
83 *iv++ = 0x89; *iv++ = 0xab;
84 *iv++ = 0xcd; *iv = 0xef;
85 */
86 }
87
88
89 /* This does not seem to produce the same results as normal RC2 key
90 expansion would, but it works, so eh. It might be smart to farm
91 this out to mozilla or openssl */
92 void mwKeyExpand(int *ekey, const char *key, gsize keylen) {
93 char tmp[128];
94 int i, j;
95
96 /*
97 g_message("expanding key from:");
98 pretty_print(key, keylen);
99 */
100
101 if(keylen > 128) keylen = 128;
102 memcpy(tmp, key, keylen);
103
104 for(i = 0; keylen < 128; i++) {
105 tmp[keylen] = PT[ (tmp[keylen - 1] + tmp[i]) & 0xff ];
106 keylen++;
107 }
108
109 tmp[0] = PT[ tmp[0] & 0xff ];
110
111 for(i = 0, j = 0; i < 64; i++) {
112 ekey[i] = (tmp[j] & 0xff) | (tmp[j+1] << 8);
113 j += 2;
114 }
115 }
116
117
118 /* normal RC2 encryption given a full 128-byte (as 64 ints) key */
119 static void mwEncryptBlock(const int *ekey, char *out) {
120 int a = (out[7] << 8) | (out[6] & 0xff);
121 int b = (out[5] << 8) | (out[4] & 0xff);
122 int c = (out[3] << 8) | (out[2] & 0xff);
123 int d = (out[1] << 8) | (out[0] & 0xff);
124
125 int i, j;
126
127 for(i = 0; i < 16; i++) {
128 j = i * 4;
129
130 d += ((c & (a ^ 0xffff)) + (b & a) + ekey[j++]);
131 d = (d << 1) | (d >> 15 & 0x0001);
132
133 c += ((b & (d ^ 0xffff)) + (a & d) + ekey[j++]);
134 c = (c << 2) | (c >> 14 & 0x0003);
135
136 b += ((a & (c ^ 0xffff)) + (d & c) + ekey[j++]);
137 b = (b << 3) | (b >> 13 & 0x0007);
138
139 a += ((d & (b ^ 0xffff)) + (c & b) + ekey[j++]);
140 a = (a << 5) | (a >> 11 & 0x001f);
141
142 if(i == 4 || i == 10) {
143 d += ekey[a & 0x003f];
144 c += ekey[d & 0x003f];
145 b += ekey[c & 0x003f];
146 a += ekey[b & 0x003f];
147 }
148 }
149
150 *out++ = d & 0xff;
151 *out++ = (d >> 8) & 0xff;
152 *out++ = c & 0xff;
153 *out++ = (c >> 8) & 0xff;
154 *out++ = b & 0xff;
155 *out++ = (b >> 8) & 0xff;
156 *out++ = a & 0xff;
157 *out++ = (a >> 8) & 0xff;
158 }
159
160
161 void mwEncryptExpanded(const int *ekey, char *iv,
162 struct mwOpaque *in_data,
163 struct mwOpaque *out_data) {
164
165 char *i = in_data->data;
166 gsize i_len = in_data->len;
167
168 char *o;
169 gsize o_len;
170
171 int x, y;
172
173 /* pad upwards to a multiple of 8 */
174 o_len = (i_len & -8) + 8;
175 o = g_malloc(o_len);
176
177 out_data->data = o;
178 out_data->len = o_len;
179
180 /* figure out the amount of padding */
181 y = o_len - i_len;
182
183 /* copy in to out, and write padding bytes */
184 memcpy(o, i, i_len);
185 memset(o + i_len, y, y);
186
187 /* encrypt in blocks */
188 for(x = o_len; x > 0; x -= 8) {
189 for(y = 8; y--; o[y] ^= iv[y]);
190 mwEncryptBlock(ekey, o);
191 memcpy(iv, o, 8);
192 o += 8;
193 }
194 }
195
196
197 void mwEncrypt(const char *key, gsize keylen, char *iv,
198 struct mwOpaque *in, struct mwOpaque *out) {
199
200 int ekey[64];
201 mwKeyExpand(ekey, key, keylen);
202 mwEncryptExpanded(ekey, iv, in, out);
203 }
204
205
206 static void mwDecryptBlock(const int *ekey, char *out) {
207 int a = (out[7] << 8) | (out[6] & 0xff);
208 int b = (out[5] << 8) | (out[4] & 0xff);
209 int c = (out[3] << 8) | (out[2] & 0xff);
210 int d = (out[1] << 8) | (out[0] & 0xff);
211
212 int i, j;
213
214 for(i = 16; i--; ) {
215 j = i * 4 + 3;
216
217 a = (a << 11) | (a >> 5 & 0x07ff);
218 a -= ((d & (b ^ 0xffff)) + (c & b) + ekey[j--]);
219
220 b = (b << 13) | (b >> 3 & 0x1fff);
221 b -= ((a & (c ^ 0xffff)) + (d & c) + ekey[j--]);
222
223 c = (c << 14) | (c >> 2 & 0x3fff);
224 c -= ((b & (d ^ 0xffff)) + (a & d) + ekey[j--]);
225
226 d = (d << 15) | (d >> 1 & 0x7fff);
227 d -= ((c & (a ^ 0xffff)) + (b & a) + ekey[j--]);
228
229 if(i == 5 || i == 11) {
230 a -= ekey[b & 0x003f];
231 b -= ekey[c & 0x003f];
232 c -= ekey[d & 0x003f];
233 d -= ekey[a & 0x003f];
234 }
235 }
236
237 *out++ = d & 0xff;
238 *out++ = (d >> 8) & 0xff;
239 *out++ = c & 0xff;
240 *out++ = (c >> 8) & 0xff;
241 *out++ = b & 0xff;
242 *out++ = (b >> 8) & 0xff;
243 *out++ = a & 0xff;
244 *out++ = (a >> 8) & 0xff;
245 }
246
247
248 void mwDecryptExpanded(const int *ekey, char *iv,
249 struct mwOpaque *in_data,
250 struct mwOpaque *out_data) {
251
252 char *i = in_data->data;
253 gsize i_len = in_data->len;
254
255 char *o;
256 gsize o_len;
257
258 int x, y;
259
260 /* this doesn't check to ensure that in_data->len is a multiple of
261 8, which is damn well ought to be. */
262
263 o = g_malloc(i_len);
264 o_len = i_len;
265 memcpy(o, i, i_len);
266
267 out_data->data = o;
268 out_data->len = o_len;
269
270 for(x = o_len; x > 0; x -= 8) {
271 /* decrypt a block */
272 mwDecryptBlock(ekey, o);
273
274 /* modify the initialization vector */
275 for(y = 8; y--; o[y] ^= iv[y]);
276 memcpy(iv, i, 8);
277 i += 8;
278 o += 8;
279 }
280
281 /* shorten the length by the value of the filler in the padding
282 bytes */
283 out_data->len -= *(o - 1);
284 }
285
286
287 void mwDecrypt(const char *key, gsize keylen, char *iv,
288 struct mwOpaque *in, struct mwOpaque *out) {
289
290 int ekey[64];
291 mwKeyExpand(ekey, key, keylen);
292 mwDecryptExpanded(ekey, iv, in, out);
293 }
294
295
296 struct mwCipher_RC2_40 {
297 struct mwCipher cipher;
298 int session_key[64];
299 gboolean ready;
300 };
301
302
303 struct mwCipherInstance_RC2_40 {
304 struct mwCipherInstance instance;
305 int incoming_key[64];
306 char outgoing_iv[8];
307 char incoming_iv[8];
308 };
309
310
311 static const char *get_name_RC2_40() {
312 return "RC2/40 Cipher";
313 }
314
315
316 static const char *get_desc_RC2_40() {
317 return "RC2, 40-bit effective key";
318 }
319
320
321 static int encrypt_RC2_40(struct mwCipherInstance *ci,
322 struct mwOpaque *data) {
323
324 struct mwCipherInstance_RC2_40 *cir;
325 struct mwCipher_RC2_40 *cr;
326 struct mwOpaque o = { 0, 0 };
327
328 cir = (struct mwCipherInstance_RC2_40 *) ci;
329 cr = (struct mwCipher_RC2_40 *) ci->cipher;
330
331 mwEncryptExpanded(cr->session_key, cir->outgoing_iv, data, &o);
332
333 mwOpaque_clear(data);
334 data->data = o.data;
335 data->len = o.len;
336
337 return 0;
338 }
339
340
341 static int decrypt_RC2_40(struct mwCipherInstance *ci,
342 struct mwOpaque *data) {
343
344 struct mwCipherInstance_RC2_40 *cir;
345 struct mwCipher_RC2_40 *cr;
346 struct mwOpaque o = { 0, 0 };
347
348 cir = (struct mwCipherInstance_RC2_40 *) ci;
349 cr = (struct mwCipher_RC2_40 *) ci->cipher;
350
351 mwDecryptExpanded(cir->incoming_key, cir->incoming_iv, data, &o);
352
353 mwOpaque_clear(data);
354 data->data = o.data;
355 data->len = o.len;
356
357 return 0;
358 }
359
360
361 static struct mwCipherInstance *new_instance_RC2_40(struct mwCipher *cipher,
362 struct mwChannel *chan) {
363 struct mwCipher_RC2_40 *cr;
364 struct mwCipherInstance_RC2_40 *cir;
365 struct mwCipherInstance *ci;
366
367 cr = (struct mwCipher_RC2_40 *) cipher;
368
369 cir = g_new0(struct mwCipherInstance_RC2_40, 1);
370 ci = &cir->instance;
371
372 ci->cipher = cipher;
373 ci->channel = chan;
374
375 /* a bit of lazy initialization here */
376 if(! cr->ready) {
377 struct mwLoginInfo *info = mwSession_getLoginInfo(cipher->session);
378 mwKeyExpand(cr->session_key, info->login_id, 5);
379 cr->ready = TRUE;
380 }
381
382 mwIV_init(cir->incoming_iv);
383 mwIV_init(cir->outgoing_iv);
384
385 return ci;
386 }
387
388
389 static struct mwEncryptItem *new_item_RC2_40(struct mwCipherInstance *ci) {
390 struct mwEncryptItem *e = g_new0(struct mwEncryptItem, 1);
391 e->id = mwCipher_RC2_40;
392 return e;
393 }
394
395
396 static void accept_RC2_40(struct mwCipherInstance *ci) {
397 struct mwCipherInstance_RC2_40 *cir;
398 struct mwLoginInfo *info = mwChannel_getUser(ci->channel);
399
400 cir = (struct mwCipherInstance_RC2_40 *) ci;
401 mwKeyExpand(cir->incoming_key, info->login_id, 5);
402 }
403
404
405 static void accepted_RC2_40(struct mwCipherInstance *ci,
406 struct mwEncryptItem *item) {
407 accept_RC2_40(ci);
408 }
409
410
411 struct mwCipher *mwCipher_new_RC2_40(struct mwSession *s) {
412 struct mwCipher_RC2_40 *cr = g_new0(struct mwCipher_RC2_40, 1);
413 struct mwCipher *c = &cr->cipher;
414
415 c->session = s;
416 c->type = mwCipher_RC2_40;
417 c->get_name = get_name_RC2_40;
418 c->get_desc = get_desc_RC2_40;
419 c->new_instance = new_instance_RC2_40;
420 c->new_item = new_item_RC2_40;
421
422 c->accepted = accepted_RC2_40;
423 c->accept = accept_RC2_40;
424
425 c->encrypt = encrypt_RC2_40;
426 c->decrypt = decrypt_RC2_40;
427
428 return c;
429 }
430
431
432 struct mwSession *mwCipher_getSession(struct mwCipher *cipher) {
433 g_return_val_if_fail(cipher != NULL, NULL);
434 return cipher->session;
435 }
436
437
438 guint16 mwCipher_getType(struct mwCipher *cipher) {
439 /* oh man, this is a bad failover... who the hell decided to make
440 zero a real cipher id?? */
441 g_return_val_if_fail(cipher != NULL, 0x00);
442 return cipher->type;
443 }
444
445
446 const char *mwCipher_getName(struct mwCipher *cipher) {
447 g_return_val_if_fail(cipher != NULL, NULL);
448 g_return_val_if_fail(cipher->get_name != NULL, NULL);
449 return cipher->get_name();
450 }
451
452
453 const char *mwCipher_getDesc(struct mwCipher *cipher) {
454 g_return_val_if_fail(cipher != NULL, NULL);
455 g_return_val_if_fail(cipher->get_desc != NULL, NULL);
456 return cipher->get_desc();
457 }
458
459
460 void mwCipher_free(struct mwCipher *cipher) {
461 if(! cipher) return;
462
463 if(cipher->clear)
464 cipher->clear(cipher);
465
466 g_free(cipher);
467 }
468
469
470 struct mwCipherInstance *mwCipher_newInstance(struct mwCipher *cipher,
471 struct mwChannel *chan) {
472 g_return_val_if_fail(cipher != NULL, NULL);
473 g_return_val_if_fail(chan != NULL, NULL);
474 g_return_val_if_fail(cipher->new_instance != NULL, NULL);
475 return cipher->new_instance(cipher, chan);
476 }
477
478
479 struct mwCipher *mwCipherInstance_getCipher(struct mwCipherInstance *ci) {
480 g_return_val_if_fail(ci != NULL, NULL);
481 return ci->cipher;
482 }
483
484
485 struct mwChannel *mwCipherInstance_getChannel(struct mwCipherInstance *ci) {
486 g_return_val_if_fail(ci != NULL, NULL);
487 return ci->channel;
488 }
489
490
491 struct mwEncryptItem *mwCipherInstance_newItem(struct mwCipherInstance *ci) {
492 struct mwCipher *cipher;
493
494 g_return_val_if_fail(ci != NULL, NULL);
495 cipher = ci->cipher;
496
497 g_return_val_if_fail(cipher != NULL, NULL);
498 g_return_val_if_fail(cipher->new_item != NULL, NULL);
499
500 return cipher->new_item(ci);
501 }
502
503
504 void mwCipherInstance_offered(struct mwCipherInstance *ci,
505 struct mwEncryptItem *item) {
506 struct mwCipher *cipher;
507
508 g_return_if_fail(ci != NULL);
509
510 cipher = ci->cipher;
511 g_return_if_fail(cipher != NULL);
512
513 if(cipher->offered) cipher->offered(ci, item);
514 }
515
516
517 void mwCipherInstance_offer(struct mwCipherInstance *ci) {
518 struct mwCipher *cipher;
519
520 g_return_if_fail(ci != NULL);
521
522 cipher = ci->cipher;
523 g_return_if_fail(cipher != NULL);
524
525 if(cipher->offer) cipher->offer(ci);
526 }
527
528
529 void mwCipherInstance_accepted(struct mwCipherInstance *ci,
530 struct mwEncryptItem *item) {
531 struct mwCipher *cipher;
532
533 g_return_if_fail(ci != NULL);
534
535 cipher = ci->cipher;
536 g_return_if_fail(cipher != NULL);
537
538 if(cipher->accepted) cipher->accepted(ci, item);
539 }
540
541
542 void mwCipherInstance_accept(struct mwCipherInstance *ci) {
543 struct mwCipher *cipher;
544
545 g_return_if_fail(ci != NULL);
546
547 cipher = ci->cipher;
548 g_return_if_fail(cipher != NULL);
549
550 if(cipher->accept) cipher->accept(ci);
551 }
552
553
554 int mwCipherInstance_encrypt(struct mwCipherInstance *ci,
555 struct mwOpaque *data) {
556 struct mwCipher *cipher;
557
558 g_return_val_if_fail(data != NULL, 0);
559
560 if(! ci) return 0;
561 cipher = ci->cipher;
562
563 g_return_val_if_fail(cipher != NULL, -1);
564
565 return (cipher->encrypt)?
566 cipher->encrypt(ci, data): 0;
567 }
568
569
570 int mwCipherInstance_decrypt(struct mwCipherInstance *ci,
571 struct mwOpaque *data) {
572 struct mwCipher *cipher;
573
574 g_return_val_if_fail(data != NULL, 0);
575
576 if(! ci) return 0;
577 cipher = ci->cipher;
578
579 g_return_val_if_fail(cipher != NULL, -1);
580
581 return (cipher->decrypt)?
582 cipher->decrypt(ci, data): 0;
583 }
584
585
586 void mwCipherInstance_free(struct mwCipherInstance *ci) {
587 struct mwCipher *cipher;
588
589 if(! ci) return;
590
591 cipher = ci->cipher;
592
593 if(cipher && cipher->clear_instance)
594 cipher->clear_instance(ci);
595
596 g_free(ci);
597 }
598