Mercurial > pidgin
comparison src/cipher.c @ 10687:b256ce6b85b8
[gaim-migrate @ 12235]
grim says this is really fixed this time.
committer: Tailor Script <tailor@pidgin.im>
| author | Etan Reisner <pidgin@unreliablesource.net> |
|---|---|
| date | Sat, 12 Mar 2005 01:10:37 +0000 |
| parents | 72a5babfa8b4 |
| children | 5c56223fa24f |
comparison
equal
deleted
inserted
replaced
| 10686:212946f774c0 | 10687:b256ce6b85b8 |
|---|---|
| 252 memcpy((md5_context->buffer + left), data, len); | 252 memcpy((md5_context->buffer + left), data, len); |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 | 255 |
| 256 static gboolean | 256 static gboolean |
| 257 md5_digest(GaimCipherContext *context, size_t *len, guint8 digest[16]) { | 257 md5_digest(GaimCipherContext *context, size_t in_len, guint8 digest[16], |
| 258 size_t *out_len) | |
| 259 { | |
| 258 struct MD5Context *md5_context = NULL; | 260 struct MD5Context *md5_context = NULL; |
| 259 guint32 last, pad; | 261 guint32 last, pad; |
| 260 guint32 high, low; | 262 guint32 high, low; |
| 261 guint8 message[8]; | 263 guint8 message[8]; |
| 262 guint8 padding[64] = { | 264 guint8 padding[64] = { |
| 264 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 267 }; | 269 }; |
| 268 | 270 |
| 269 g_return_val_if_fail(len, FALSE); | 271 g_return_val_if_fail(in_len >= 16, FALSE); |
| 270 g_return_val_if_fail(*len >= 16, FALSE); | |
| 271 | 272 |
| 272 md5_context = gaim_cipher_context_get_data(context); | 273 md5_context = gaim_cipher_context_get_data(context); |
| 273 | 274 |
| 274 high = (md5_context->total[0] >> 29) | 275 high = (md5_context->total[0] >> 29) |
| 275 | (md5_context->total[1] << 3); | 276 | (md5_context->total[1] << 3); |
| 286 | 287 |
| 287 MD5_PUT_GUINT32(md5_context->state[0], digest, 0); | 288 MD5_PUT_GUINT32(md5_context->state[0], digest, 0); |
| 288 MD5_PUT_GUINT32(md5_context->state[1], digest, 4); | 289 MD5_PUT_GUINT32(md5_context->state[1], digest, 4); |
| 289 MD5_PUT_GUINT32(md5_context->state[2], digest, 8); | 290 MD5_PUT_GUINT32(md5_context->state[2], digest, 8); |
| 290 MD5_PUT_GUINT32(md5_context->state[3], digest, 12); | 291 MD5_PUT_GUINT32(md5_context->state[3], digest, 12); |
| 292 | |
| 293 if(out_len) | |
| 294 *out_len = 16; | |
| 291 | 295 |
| 292 return TRUE; | 296 return TRUE; |
| 293 } | 297 } |
| 294 | 298 |
| 295 static GaimCipherOps MD5Ops = { | 299 static GaimCipherOps MD5Ops = { |
| 488 sha1_ctx->sizeHi += (sha1_ctx->sizeLo < 8); | 492 sha1_ctx->sizeHi += (sha1_ctx->sizeLo < 8); |
| 489 } | 493 } |
| 490 } | 494 } |
| 491 | 495 |
| 492 static gboolean | 496 static gboolean |
| 493 sha1_digest(GaimCipherContext *context, size_t *len, guint8 digest[20]) { | 497 sha1_digest(GaimCipherContext *context, size_t in_len, guint8 digest[20], |
| 498 size_t *out_len) | |
| 499 { | |
| 494 struct SHA1Context *sha1_ctx; | 500 struct SHA1Context *sha1_ctx; |
| 495 guint8 pad0x80 = 0x80, pad0x00 = 0x00; | 501 guint8 pad0x80 = 0x80, pad0x00 = 0x00; |
| 496 guint8 padlen[8]; | 502 guint8 padlen[8]; |
| 497 gint i; | 503 gint i; |
| 498 | 504 |
| 499 g_return_val_if_fail(len, FALSE); | 505 g_return_val_if_fail(in_len >= 20, FALSE); |
| 500 g_return_val_if_fail(*len <= 20, FALSE); | |
| 501 | 506 |
| 502 sha1_ctx = gaim_cipher_context_get_data(context); | 507 sha1_ctx = gaim_cipher_context_get_data(context); |
| 503 | 508 |
| 504 g_return_val_if_fail(sha1_ctx, FALSE); | 509 g_return_val_if_fail(sha1_ctx, FALSE); |
| 505 | 510 |
| 522 digest[i] = (guint8)(sha1_ctx->H[i / 4] >> 24); | 527 digest[i] = (guint8)(sha1_ctx->H[i / 4] >> 24); |
| 523 sha1_ctx->H[i / 4] <<= 8; | 528 sha1_ctx->H[i / 4] <<= 8; |
| 524 } | 529 } |
| 525 | 530 |
| 526 gaim_cipher_context_reset(context, NULL); | 531 gaim_cipher_context_reset(context, NULL); |
| 532 | |
| 533 if(out_len) | |
| 534 *out_len = 20; | |
| 527 | 535 |
| 528 return TRUE; | 536 return TRUE; |
| 529 } | 537 } |
| 530 | 538 |
| 531 static GaimCipherOps SHA1Ops = { | 539 static GaimCipherOps SHA1Ops = { |
| 614 caps |= GAIM_CIPHER_CAPS_GET_KEY_SIZE; | 622 caps |= GAIM_CIPHER_CAPS_GET_KEY_SIZE; |
| 615 | 623 |
| 616 return caps; | 624 return caps; |
| 617 } | 625 } |
| 618 | 626 |
| 619 void | 627 gboolean |
| 620 gaim_cipher_digest_region(const gchar *name, const guint8 *data, | 628 gaim_cipher_digest_region(const gchar *name, const guint8 *data, |
| 621 size_t data_len, guint8 digest[], size_t *digest_len) | 629 size_t data_len, size_t in_len, |
| 630 guint8 digest[], size_t *out_len) | |
| 622 { | 631 { |
| 623 GaimCipher *cipher; | 632 GaimCipher *cipher; |
| 624 GaimCipherContext *context; | 633 GaimCipherContext *context; |
| 625 | 634 gboolean ret = FALSE; |
| 626 g_return_if_fail(name); | 635 |
| 627 g_return_if_fail(data); | 636 g_return_val_if_fail(name, FALSE); |
| 637 g_return_val_if_fail(data, FALSE); | |
| 628 | 638 |
| 629 cipher = gaim_ciphers_find_cipher(name); | 639 cipher = gaim_ciphers_find_cipher(name); |
| 630 | 640 |
| 631 g_return_if_fail(cipher); | 641 g_return_val_if_fail(cipher, FALSE); |
| 632 | 642 |
| 633 if(!cipher->ops->append || !cipher->ops->digest) { | 643 if(!cipher->ops->append || !cipher->ops->digest) { |
| 634 gaim_debug_info("cipher", "gaim_cipher_region failed: " | 644 gaim_debug_info("cipher", "gaim_cipher_region failed: " |
| 635 "the %s cipher does not support appending and or " | 645 "the %s cipher does not support appending and or " |
| 636 "digesting.", cipher->name); | 646 "digesting.", cipher->name); |
| 637 return; | 647 return FALSE; |
| 638 } | 648 } |
| 639 | 649 |
| 640 context = gaim_cipher_context_new(cipher, NULL); | 650 context = gaim_cipher_context_new(cipher, NULL); |
| 641 gaim_cipher_context_append(context, data, data_len); | 651 gaim_cipher_context_append(context, data, data_len); |
| 642 gaim_cipher_context_digest(context, digest_len, digest); | 652 ret = gaim_cipher_context_digest(context, in_len, digest, out_len); |
| 643 gaim_cipher_context_destroy(context); | 653 gaim_cipher_context_destroy(context); |
| 654 | |
| 655 return ret; | |
| 644 } | 656 } |
| 645 | 657 |
| 646 /****************************************************************************** | 658 /****************************************************************************** |
| 647 * GaimCiphers API | 659 * GaimCiphers API |
| 648 *****************************************************************************/ | 660 *****************************************************************************/ |
| 889 gaim_debug_info("cipher", "the %s cipher does not support the append " | 901 gaim_debug_info("cipher", "the %s cipher does not support the append " |
| 890 "operation\n", cipher->name); | 902 "operation\n", cipher->name); |
| 891 } | 903 } |
| 892 | 904 |
| 893 gboolean | 905 gboolean |
| 894 gaim_cipher_context_digest(GaimCipherContext *context, size_t *len, | 906 gaim_cipher_context_digest(GaimCipherContext *context, size_t in_len, |
| 895 guint8 digest[]) | 907 guint8 digest[], size_t *out_len) |
| 896 { | 908 { |
| 897 GaimCipher *cipher = NULL; | 909 GaimCipher *cipher = NULL; |
| 898 | 910 |
| 899 g_return_val_if_fail(context, FALSE); | 911 g_return_val_if_fail(context, FALSE); |
| 900 | 912 |
| 901 cipher = context->cipher; | 913 cipher = context->cipher; |
| 902 g_return_val_if_fail(context, FALSE); | 914 g_return_val_if_fail(context, FALSE); |
| 903 | 915 |
| 904 if(cipher->ops && cipher->ops->digest) | 916 if(cipher->ops && cipher->ops->digest) |
| 905 return cipher->ops->digest(context, len, digest); | 917 return cipher->ops->digest(context, in_len, digest, out_len); |
| 906 else { | 918 else { |
| 907 gaim_debug_info("cipher", "the %s cipher does not support the digest " | 919 gaim_debug_info("cipher", "the %s cipher does not support the digest " |
| 908 "operation\n", cipher->name); | 920 "operation\n", cipher->name); |
| 909 return FALSE; | 921 return FALSE; |
| 910 } | 922 } |
| 911 } | 923 } |
| 912 | 924 |
| 913 gboolean | 925 gboolean |
| 914 gaim_cipher_context_digest_to_str(GaimCipherContext *context, size_t *len, | 926 gaim_cipher_context_digest_to_str(GaimCipherContext *context, size_t in_len, |
| 915 gchar digest_s[]) | 927 gchar digest_s[], size_t *out_len) |
| 916 { | 928 { |
| 917 /* 16k is a bit excessive, will tweak later. */ | 929 /* 8k is a bit excessive, will tweak later. */ |
| 918 guint8 digest[BUF_LEN * 4]; | 930 guint8 digest[BUF_LEN * 4]; |
| 919 gint n = 0; | 931 gint n = 0; |
| 920 size_t dlen = 0; | 932 size_t dlen = 0; |
| 921 | 933 |
| 922 g_return_val_if_fail(context, FALSE); | 934 g_return_val_if_fail(context, FALSE); |
| 923 g_return_val_if_fail(digest_s, FALSE); | 935 g_return_val_if_fail(digest_s, FALSE); |
| 924 | 936 |
| 925 if(!gaim_cipher_context_digest(context, &dlen, digest)) | 937 if(!gaim_cipher_context_digest(context, sizeof(digest), digest, &dlen)) |
| 926 return FALSE; | 938 return FALSE; |
| 927 | 939 |
| 928 dlen *= 2; | 940 if(in_len < dlen * 2) |
| 929 | 941 return FALSE; |
| 930 if(len) | |
| 931 *len = dlen; | |
| 932 | 942 |
| 933 for(n = 0; n < dlen; n++) | 943 for(n = 0; n < dlen; n++) |
| 934 sprintf(digest_s + (n * 2), "%02x", digest[n]); | 944 sprintf(digest_s + (n * 2), "%02x", digest[n]); |
| 935 | 945 |
| 936 digest_s[n * 2] = '\0'; | 946 digest_s[n * 2] = '\0'; |
| 947 | |
| 948 if(out_len) | |
| 949 *out_len = dlen * 2; | |
| 937 | 950 |
| 938 return TRUE; | 951 return TRUE; |
| 939 } | 952 } |
| 940 | 953 |
| 941 gint | 954 gint |
