comparison src/cipher.c @ 11329:f93d434ee222

[gaim-migrate @ 13541] added MD4 cipher needed for NTLM committer: Tailor Script <tailor@pidgin.im>
author Thomas Butter <tbutter>
date Tue, 23 Aug 2005 08:08:43 +0000
parents 8dca96cbcd64
children b0185f9214d3
comparison
equal deleted inserted replaced
11328:b8c93c40ee2e 11329:f93d434ee222
5 * to list here. Please refer to the COPYRIGHT file distributed with this 5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution. 6 * source distribution.
7 * 7 *
8 * Original md5 8 * Original md5
9 * Copyright (C) 2001-2003 Christophe Devine <c.devine@cr0.net> 9 * Copyright (C) 2001-2003 Christophe Devine <c.devine@cr0.net>
10 *
11 * Original md4 taken from linux kernel
12 * MD4 Message Digest Algorithm (RFC1320).
13 *
14 * Implementation derived from Andrew Tridgell and Steve French's
15 * CIFS MD4 implementation, and the cryptoapi implementation
16 * originally based on the public domain implementation written
17 * by Colin Plumb in 1993.
18 *
19 * Copyright (c) Andrew Tridgell 1997-1998.
20 * Modified by Steve French (sfrench@us.ibm.com) 2002
21 * Copyright (c) Cryptoapi developers.
22 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
23 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
10 * 24 *
11 * This program is free software; you can redistribute it and/or modify 25 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by 26 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or 27 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version. 28 * (at your option) any later version.
309 NULL, /* decrypt */ 323 NULL, /* decrypt */
310 NULL, /* set salt */ 324 NULL, /* set salt */
311 NULL, /* get salt size */ 325 NULL, /* get salt size */
312 NULL, /* set key */ 326 NULL, /* set key */
313 NULL /* get key size */ 327 NULL /* get key size */
328 };
329
330 /*******************************************************************************
331 * MD4
332 ******************************************************************************/
333 #define MD4_DIGEST_SIZE 16
334 #define MD4_HMAC_BLOCK_SIZE 64
335 #define MD4_BLOCK_WORDS 16
336 #define MD4_HASH_WORDS 4
337
338
339
340 struct MD4_Context {
341 guint32 hash[MD4_HASH_WORDS];
342 guint32 block[MD4_BLOCK_WORDS];
343 guint64 byte_count;
344 };
345
346 static inline guint32 lshift(guint32 x, unsigned int s)
347 {
348 x &= 0xFFFFFFFF;
349 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
350 }
351
352 static inline guint32 F(guint32 x, guint32 y, guint32 z)
353 {
354 return (x & y) | ((~x) & z);
355 }
356
357 static inline guint32 G(guint32 x, guint32 y, guint32 z)
358 {
359 return (x & y) | (x & z) | (y & z);
360 }
361
362 static inline guint32 H(guint32 x, guint32 y, guint32 z)
363 {
364 return x ^ y ^ z;
365 }
366
367 #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
368 #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (guint32)0x5A827999,s))
369 #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (guint32)0x6ED9EBA1,s))
370
371 static inline void le32_to_cpu_array(guint32 *buf, unsigned int words)
372 {
373 while (words--) {
374 *buf=GUINT_FROM_LE(*buf);
375 // __le32_to_cpus(buf);
376 buf++;
377 }
378 }
379
380 static inline void cpu_to_le32_array(guint32 *buf, unsigned int words)
381 {
382 while (words--) {
383 // __cpu_to_le32s(buf);
384 *buf=GUINT_TO_LE(*buf);
385 buf++;
386 }
387 }
388
389 static void md4_transform(guint32 *hash, guint32 const *in)
390 {
391 guint32 a, b, c, d;
392
393 a = hash[0];
394 b = hash[1];
395 c = hash[2];
396 d = hash[3];
397
398 ROUND1(a, b, c, d, in[0], 3);
399 ROUND1(d, a, b, c, in[1], 7);
400 ROUND1(c, d, a, b, in[2], 11);
401 ROUND1(b, c, d, a, in[3], 19);
402 ROUND1(a, b, c, d, in[4], 3);
403 ROUND1(d, a, b, c, in[5], 7);
404 ROUND1(c, d, a, b, in[6], 11);
405 ROUND1(b, c, d, a, in[7], 19);
406 ROUND1(a, b, c, d, in[8], 3);
407 ROUND1(d, a, b, c, in[9], 7);
408 ROUND1(c, d, a, b, in[10], 11);
409 ROUND1(b, c, d, a, in[11], 19);
410 ROUND1(a, b, c, d, in[12], 3);
411 ROUND1(d, a, b, c, in[13], 7);
412 ROUND1(c, d, a, b, in[14], 11);
413 ROUND1(b, c, d, a, in[15], 19);
414
415 ROUND2(a, b, c, d,in[ 0], 3);
416 ROUND2(d, a, b, c, in[4], 5);
417 ROUND2(c, d, a, b, in[8], 9);
418 ROUND2(b, c, d, a, in[12], 13);
419 ROUND2(a, b, c, d, in[1], 3);
420 ROUND2(d, a, b, c, in[5], 5);
421 ROUND2(c, d, a, b, in[9], 9);
422 ROUND2(b, c, d, a, in[13], 13);
423 ROUND2(a, b, c, d, in[2], 3);
424 ROUND2(d, a, b, c, in[6], 5);
425 ROUND2(c, d, a, b, in[10], 9);
426 ROUND2(b, c, d, a, in[14], 13);
427 ROUND2(a, b, c, d, in[3], 3);
428 ROUND2(d, a, b, c, in[7], 5);
429 ROUND2(c, d, a, b, in[11], 9);
430 ROUND2(b, c, d, a, in[15], 13);
431
432 ROUND3(a, b, c, d,in[ 0], 3);
433 ROUND3(d, a, b, c, in[8], 9);
434 ROUND3(c, d, a, b, in[4], 11);
435 ROUND3(b, c, d, a, in[12], 15);
436 ROUND3(a, b, c, d, in[2], 3);
437 ROUND3(d, a, b, c, in[10], 9);
438 ROUND3(c, d, a, b, in[6], 11);
439 ROUND3(b, c, d, a, in[14], 15);
440 ROUND3(a, b, c, d, in[1], 3);
441 ROUND3(d, a, b, c, in[9], 9);
442 ROUND3(c, d, a, b, in[5], 11);
443 ROUND3(b, c, d, a, in[13], 15);
444 ROUND3(a, b, c, d, in[3], 3);
445 ROUND3(d, a, b, c, in[11], 9);
446 ROUND3(c, d, a, b, in[7], 11);
447 ROUND3(b, c, d, a, in[15], 15);
448
449 hash[0] += a;
450 hash[1] += b;
451 hash[2] += c;
452 hash[3] += d;
453 }
454
455 static inline void md4_transform_helper(struct MD4_Context *ctx)
456 {
457 le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(guint32));
458 md4_transform(ctx->hash, ctx->block);
459 }
460
461 static void
462 md4_init(GaimCipherContext *context, gpointer extra) {
463 struct MD4_Context *mctx;
464 mctx = g_new0(struct MD4_Context, 1);
465 gaim_cipher_context_set_data(context, mctx);
466 gaim_cipher_context_reset(context, extra);
467
468 mctx->hash[0] = 0x67452301;
469 mctx->hash[1] = 0xefcdab89;
470 mctx->hash[2] = 0x98badcfe;
471 mctx->hash[3] = 0x10325476;
472 mctx->byte_count = 0;
473 }
474
475 static void
476 md4_reset(GaimCipherContext *context, gpointer extra) {
477 struct MD4_Context *mctx;
478
479 mctx = gaim_cipher_context_get_data(context);
480
481 mctx->hash[0] = 0x67452301;
482 mctx->hash[1] = 0xefcdab89;
483 mctx->hash[2] = 0x98badcfe;
484 mctx->hash[3] = 0x10325476;
485 mctx->byte_count = 0;
486 }
487
488 static void
489 md4_append(GaimCipherContext *context, const guchar *data, size_t len)
490 {
491 struct MD4_Context *mctx = gaim_cipher_context_get_data(context);
492 const guint32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
493
494 mctx->byte_count += len;
495
496 if (avail > len) {
497 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
498 data, len);
499 return;
500 }
501
502 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
503 data, avail);
504
505 md4_transform_helper(mctx);
506 data += avail;
507 len -= avail;
508
509 while (len >= sizeof(mctx->block)) {
510 memcpy(mctx->block, data, sizeof(mctx->block));
511 md4_transform_helper(mctx);
512 data += sizeof(mctx->block);
513 len -= sizeof(mctx->block);
514 }
515
516 memcpy(mctx->block, data, len);
517 }
518
519 static gboolean
520 md4_digest(GaimCipherContext *context, size_t in_len, guchar *out,
521 size_t *out_len)
522 {
523 struct MD4_Context *mctx = gaim_cipher_context_get_data(context);
524 const unsigned int offset = mctx->byte_count & 0x3f;
525 char *p = (char *)mctx->block + offset;
526 int padding = 56 - (offset + 1);
527
528
529 if(in_len<16) return FALSE;
530 if(out_len) *out_len = 16;
531 *p++ = 0x80;
532 if (padding < 0) {
533 memset(p, 0x00, padding + sizeof (guint64));
534 md4_transform_helper(mctx);
535 p = (char *)mctx->block;
536 padding = 56;
537 }
538
539 memset(p, 0, padding);
540 mctx->block[14] = mctx->byte_count << 3;
541 mctx->block[15] = mctx->byte_count >> 29;
542 le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
543 sizeof(guint64)) / sizeof(guint32));
544 md4_transform(mctx->hash, mctx->block);
545 cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(guint32));
546 memcpy(out, mctx->hash, sizeof(mctx->hash));
547 memset(mctx, 0, sizeof(*mctx));
548 return TRUE;
549 }
550
551 static void
552 md4_uninit(GaimCipherContext *context) {
553 struct MD4_Context *md4_context;
554
555 gaim_cipher_context_reset(context, NULL);
556
557 md4_context = gaim_cipher_context_get_data(context);
558 memset(md4_context, 0, sizeof(md4_context));
559
560 g_free(md4_context);
561 md4_context = NULL;
562 }
563
564 static GaimCipherOps MD4Ops = {
565 NULL, /* Set option */
566 NULL, /* Get option */
567 md4_init, /* init */
568 md4_reset, /* reset */
569 md4_uninit, /* uninit */
570 NULL, /* set iv */
571 md4_append, /* append */
572 md4_digest, /* digest */
573 NULL, /* encrypt */
574 NULL, /* decrypt */
575 NULL, /* set salt */
576 NULL, /* get salt size */
577 NULL, /* set key */
578 NULL /* get key size */
314 }; 579 };
315 580
316 /******************************************************************************* 581 /*******************************************************************************
317 * SHA-1 582 * SHA-1
318 ******************************************************************************/ 583 ******************************************************************************/
740 gaim_value_new(GAIM_TYPE_SUBTYPE, 1005 gaim_value_new(GAIM_TYPE_SUBTYPE,
741 GAIM_SUBTYPE_CIPHER)); 1006 GAIM_SUBTYPE_CIPHER));
742 1007
743 gaim_ciphers_register_cipher("md5", &MD5Ops); 1008 gaim_ciphers_register_cipher("md5", &MD5Ops);
744 gaim_ciphers_register_cipher("sha1", &SHA1Ops); 1009 gaim_ciphers_register_cipher("sha1", &SHA1Ops);
1010 gaim_ciphers_register_cipher("md4", &MD4Ops);
745 } 1011 }
746 1012
747 void 1013 void
748 gaim_ciphers_uninit() { 1014 gaim_ciphers_uninit() {
749 GaimCipher *cipher; 1015 GaimCipher *cipher;