Mercurial > pidgin.yaz
comparison libpurple/cipher.c @ 21908:f786e478e08b
HMAC digest support from Elliott Sales de Andrade
committer: Gary Kramlich <grim@reaperworld.com>
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Thu, 20 Dec 2007 03:44:01 +0000 |
parents | 03463c52b9d7 |
children | 76e0463db3aa |
comparison
equal
deleted
inserted
replaced
21907:03463c52b9d7 | 21908:f786e478e08b |
---|---|
62 #include "value.h" | 62 #include "value.h" |
63 | 63 |
64 /******************************************************************************* | 64 /******************************************************************************* |
65 * MD5 | 65 * MD5 |
66 ******************************************************************************/ | 66 ******************************************************************************/ |
67 #define MD5_HMAC_BLOCK_SIZE 64 | |
68 | |
67 struct MD5Context { | 69 struct MD5Context { |
68 guint32 total[2]; | 70 guint32 total[2]; |
69 guint32 state[4]; | 71 guint32 state[4]; |
70 guchar buffer[64]; | 72 guchar buffer[64]; |
71 }; | 73 }; |
323 *out_len = 16; | 325 *out_len = 16; |
324 | 326 |
325 return TRUE; | 327 return TRUE; |
326 } | 328 } |
327 | 329 |
330 static size_t | |
331 md5_get_block_size(PurpleCipherContext *context) | |
332 { | |
333 /* This does not change (in this case) */ | |
334 return MD5_HMAC_BLOCK_SIZE; | |
335 } | |
336 | |
328 static PurpleCipherOps MD5Ops = { | 337 static PurpleCipherOps MD5Ops = { |
329 NULL, /* Set option */ | 338 NULL, /* Set option */ |
330 NULL, /* Get option */ | 339 NULL, /* Get option */ |
331 md5_init, /* init */ | 340 md5_init, /* init */ |
332 md5_reset, /* reset */ | 341 md5_reset, /* reset */ |
340 NULL, /* get salt size */ | 349 NULL, /* get salt size */ |
341 NULL, /* set key */ | 350 NULL, /* set key */ |
342 NULL, /* get key size */ | 351 NULL, /* get key size */ |
343 NULL, /* set batch mode */ | 352 NULL, /* set batch mode */ |
344 NULL, /* get batch mode */ | 353 NULL, /* get batch mode */ |
345 | 354 md5_get_block_size, /* get block size */ |
346 /* padding */ | 355 NULL /* set key with len */ |
347 NULL, | |
348 NULL | |
349 }; | 356 }; |
350 | 357 |
351 /******************************************************************************* | 358 /******************************************************************************* |
352 * MD4 | 359 * MD4 |
353 ******************************************************************************/ | 360 ******************************************************************************/ |
576 md4_context = purple_cipher_context_get_data(context); | 583 md4_context = purple_cipher_context_get_data(context); |
577 memset(md4_context, 0, sizeof(md4_context)); | 584 memset(md4_context, 0, sizeof(md4_context)); |
578 | 585 |
579 g_free(md4_context); | 586 g_free(md4_context); |
580 md4_context = NULL; | 587 md4_context = NULL; |
588 } | |
589 | |
590 static size_t | |
591 md4_get_block_size(PurpleCipherContext *context) | |
592 { | |
593 /* This does not change (in this case) */ | |
594 return MD4_HMAC_BLOCK_SIZE; | |
581 } | 595 } |
582 | 596 |
583 static PurpleCipherOps MD4Ops = { | 597 static PurpleCipherOps MD4Ops = { |
584 NULL, /* Set option */ | 598 NULL, /* Set option */ |
585 NULL, /* Get option */ | 599 NULL, /* Get option */ |
595 NULL, /* get salt size */ | 609 NULL, /* get salt size */ |
596 NULL, /* set key */ | 610 NULL, /* set key */ |
597 NULL, /* get key size */ | 611 NULL, /* get key size */ |
598 NULL, /* set batch mode */ | 612 NULL, /* set batch mode */ |
599 NULL, /* get batch mode */ | 613 NULL, /* get batch mode */ |
600 | 614 md4_get_block_size, /* get block size */ |
601 /* padding */ | 615 NULL /* set key with len */ |
602 NULL, | 616 }; |
603 NULL | 617 |
618 /******************************************************************************* | |
619 * HMAC | |
620 ******************************************************************************/ | |
621 | |
622 struct HMAC_Context { | |
623 PurpleCipherContext *hash; | |
624 char *name; | |
625 int blocksize; | |
626 guchar *opad; | |
627 }; | |
628 | |
629 static void | |
630 hmac_init(PurpleCipherContext *context, gpointer extra) | |
631 { | |
632 struct HMAC_Context *hctx; | |
633 hctx = g_new0(struct HMAC_Context, 1); | |
634 purple_cipher_context_set_data(context, hctx); | |
635 purple_cipher_context_reset(context, extra); | |
636 } | |
637 | |
638 static void | |
639 hmac_reset(PurpleCipherContext *context, gpointer extra) | |
640 { | |
641 struct HMAC_Context *hctx; | |
642 | |
643 hctx = purple_cipher_context_get_data(context); | |
644 | |
645 g_free(hctx->name); | |
646 hctx->name = NULL; | |
647 if (hctx->hash) | |
648 purple_cipher_context_destroy(hctx->hash); | |
649 hctx->hash = NULL; | |
650 hctx->blocksize = 0; | |
651 g_free(hctx->opad); | |
652 hctx->opad = NULL; | |
653 } | |
654 | |
655 static void | |
656 hmac_set_opt(PurpleCipherContext *context, const gchar *name, void *value) | |
657 { | |
658 struct HMAC_Context *hctx; | |
659 | |
660 hctx = purple_cipher_context_get_data(context); | |
661 | |
662 if (!strcmp(name, "hash")) { | |
663 g_free(hctx->name); | |
664 if (hctx->hash) | |
665 purple_cipher_context_destroy(hctx->hash); | |
666 hctx->name = g_strdup((char*)value); | |
667 hctx->hash = purple_cipher_context_new_by_name((char *)value, NULL); | |
668 hctx->blocksize = purple_cipher_context_get_block_size(hctx->hash); | |
669 } | |
670 } | |
671 | |
672 static void * | |
673 hmac_get_opt(PurpleCipherContext *context, const gchar *name) | |
674 { | |
675 struct HMAC_Context *hctx; | |
676 | |
677 hctx = purple_cipher_context_get_data(context); | |
678 | |
679 if (!strcmp(name, "hash")) { | |
680 return hctx->name; | |
681 } | |
682 | |
683 return NULL; | |
684 } | |
685 | |
686 static void | |
687 hmac_append(PurpleCipherContext *context, const guchar *data, size_t len) | |
688 { | |
689 struct HMAC_Context *hctx = purple_cipher_context_get_data(context); | |
690 | |
691 g_return_if_fail(hctx->hash != NULL); | |
692 | |
693 purple_cipher_context_append(hctx->hash, data, len); | |
694 } | |
695 | |
696 static gboolean | |
697 hmac_digest(PurpleCipherContext *context, size_t in_len, guchar *out, size_t *out_len) | |
698 { | |
699 struct HMAC_Context *hctx = purple_cipher_context_get_data(context); | |
700 PurpleCipherContext *hash = hctx->hash; | |
701 guchar *inner_hash; | |
702 size_t hash_len; | |
703 gboolean result; | |
704 | |
705 g_return_val_if_fail(hash != NULL, FALSE); | |
706 | |
707 inner_hash = g_malloc(100); /* TODO: Should be enough for now... */ | |
708 result = purple_cipher_context_digest(hash, 100, inner_hash, &hash_len); | |
709 | |
710 purple_cipher_context_reset(hash, NULL); | |
711 | |
712 purple_cipher_context_append(hash, hctx->opad, hctx->blocksize); | |
713 purple_cipher_context_append(hash, inner_hash, hash_len); | |
714 | |
715 g_free(inner_hash); | |
716 | |
717 result = result && purple_cipher_context_digest(hash, in_len, out, out_len); | |
718 | |
719 return result; | |
720 } | |
721 | |
722 static void | |
723 hmac_uninit(PurpleCipherContext *context) | |
724 { | |
725 struct HMAC_Context *hctx; | |
726 | |
727 purple_cipher_context_reset(context, NULL); | |
728 | |
729 hctx = purple_cipher_context_get_data(context); | |
730 | |
731 g_free(hctx); | |
732 } | |
733 | |
734 static void | |
735 hmac_set_key_with_len(PurpleCipherContext *context, const guchar * key, size_t key_len) | |
736 { | |
737 struct HMAC_Context *hctx = purple_cipher_context_get_data(context); | |
738 int blocksize, i; | |
739 guchar *ipad; | |
740 guchar *full_key; | |
741 | |
742 g_return_if_fail(hctx->hash != NULL); | |
743 | |
744 g_free(hctx->opad); | |
745 | |
746 blocksize = hctx->blocksize; | |
747 ipad = g_malloc(blocksize); | |
748 hctx->opad = g_malloc(blocksize); | |
749 | |
750 if (key_len > blocksize) { | |
751 purple_cipher_context_reset(hctx->hash, NULL); | |
752 purple_cipher_context_append(hctx->hash, key, key_len); | |
753 full_key = g_malloc(100); /* TODO: Should be enough for now... */ | |
754 purple_cipher_context_digest(hctx->hash, 100, full_key, &key_len); | |
755 } else | |
756 full_key = g_memdup(key, key_len); | |
757 | |
758 if (key_len < blocksize) { | |
759 full_key = g_realloc(full_key, blocksize); | |
760 memset(full_key + key_len, 0, blocksize - key_len); | |
761 } | |
762 | |
763 for(i = 0; i < blocksize; i++) { | |
764 ipad[i] = 0x36 ^ full_key[i]; | |
765 hctx->opad[i] = 0x5c ^ full_key[i]; | |
766 } | |
767 | |
768 g_free(full_key); | |
769 | |
770 purple_cipher_context_reset(hctx->hash, NULL); | |
771 purple_cipher_context_append(hctx->hash, ipad, blocksize); | |
772 g_free(ipad); | |
773 } | |
774 | |
775 static void | |
776 hmac_set_key(PurpleCipherContext *context, const guchar * key) | |
777 { | |
778 hmac_set_key_with_len(context, key, strlen(key)); | |
779 } | |
780 | |
781 static size_t | |
782 hmac_get_block_size(PurpleCipherContext *context) | |
783 { | |
784 struct HMAC_Context *hctx = purple_cipher_context_get_data(context); | |
785 | |
786 return hctx->blocksize; | |
787 } | |
788 | |
789 static PurpleCipherOps HMACOps = { | |
790 hmac_set_opt, /* Set option */ | |
791 hmac_get_opt, /* Get option */ | |
792 hmac_init, /* init */ | |
793 hmac_reset, /* reset */ | |
794 hmac_uninit, /* uninit */ | |
795 NULL, /* set iv */ | |
796 hmac_append, /* append */ | |
797 hmac_digest, /* digest */ | |
798 NULL, /* encrypt */ | |
799 NULL, /* decrypt */ | |
800 NULL, /* set salt */ | |
801 NULL, /* get salt size */ | |
802 hmac_set_key, /* set key */ | |
803 NULL, /* get key size */ | |
804 NULL, /* set batch mode */ | |
805 NULL, /* get batch mode */ | |
806 hmac_get_block_size, /* get block size */ | |
807 hmac_set_key_with_len /* set key with len */ | |
604 }; | 808 }; |
605 | 809 |
606 /****************************************************************************** | 810 /****************************************************************************** |
607 * DES | 811 * DES |
608 *****************************************************************************/ | 812 *****************************************************************************/ |
1049 NULL, /* get salt size */ | 1253 NULL, /* get salt size */ |
1050 des_set_key, /* set key */ | 1254 des_set_key, /* set key */ |
1051 NULL, /* get key size */ | 1255 NULL, /* get key size */ |
1052 NULL, /* set batch mode */ | 1256 NULL, /* set batch mode */ |
1053 NULL, /* get batch mode */ | 1257 NULL, /* get batch mode */ |
1054 | 1258 NULL, /* get block size */ |
1055 /* padding */ | 1259 NULL /* set key with len */ |
1056 NULL, | |
1057 NULL | |
1058 }; | 1260 }; |
1059 | 1261 |
1060 /****************************************************************************** | 1262 /****************************************************************************** |
1061 * Triple-DES | 1263 * Triple-DES |
1062 *****************************************************************************/ | 1264 *****************************************************************************/ |
1401 NULL, /* get salt size */ | 1603 NULL, /* get salt size */ |
1402 des3_set_key, /* set key */ | 1604 des3_set_key, /* set key */ |
1403 NULL, /* get key size */ | 1605 NULL, /* get key size */ |
1404 des3_set_batch, /* set batch mode */ | 1606 des3_set_batch, /* set batch mode */ |
1405 des3_get_batch, /* get batch mode */ | 1607 des3_get_batch, /* get batch mode */ |
1406 | 1608 NULL, /* get block size */ |
1407 /* padding */ | 1609 NULL /* set key with len */ |
1408 NULL, | |
1409 NULL | |
1410 }; | 1610 }; |
1411 | 1611 |
1412 /******************************************************************************* | 1612 /******************************************************************************* |
1413 * SHA-1 | 1613 * SHA-1 |
1414 ******************************************************************************/ | 1614 ******************************************************************************/ |
1615 #define SHA1_HMAC_BLOCK_SIZE 64 | |
1415 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) | 1616 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) |
1416 | 1617 |
1417 struct SHA1Context { | 1618 struct SHA1Context { |
1418 guint32 H[5]; | 1619 guint32 H[5]; |
1419 guint32 W[80]; | 1620 guint32 W[80]; |
1628 | 1829 |
1629 if(out_len) | 1830 if(out_len) |
1630 *out_len = 20; | 1831 *out_len = 20; |
1631 | 1832 |
1632 return TRUE; | 1833 return TRUE; |
1834 } | |
1835 | |
1836 static size_t | |
1837 sha1_get_block_size(PurpleCipherContext *context) | |
1838 { | |
1839 /* This does not change (in this case) */ | |
1840 return SHA1_HMAC_BLOCK_SIZE; | |
1633 } | 1841 } |
1634 | 1842 |
1635 static PurpleCipherOps SHA1Ops = { | 1843 static PurpleCipherOps SHA1Ops = { |
1636 sha1_set_opt, /* Set Option */ | 1844 sha1_set_opt, /* Set Option */ |
1637 sha1_get_opt, /* Get Option */ | 1845 sha1_get_opt, /* Get Option */ |
1647 NULL, /* get salt size */ | 1855 NULL, /* get salt size */ |
1648 NULL, /* set key */ | 1856 NULL, /* set key */ |
1649 NULL, /* get key size */ | 1857 NULL, /* get key size */ |
1650 NULL, /* set batch mode */ | 1858 NULL, /* set batch mode */ |
1651 NULL, /* get batch mode */ | 1859 NULL, /* get batch mode */ |
1652 | 1860 sha1_get_block_size, /* get block size */ |
1653 /* padding */ | 1861 NULL /* set key with len */ |
1654 NULL, | |
1655 NULL | |
1656 }; | 1862 }; |
1657 | 1863 |
1658 /******************************************************************************* | 1864 /******************************************************************************* |
1659 * RC4 | 1865 * RC4 |
1660 ******************************************************************************/ | 1866 ******************************************************************************/ |
1816 NULL, /* get salt size */ | 2022 NULL, /* get salt size */ |
1817 rc4_set_key, /* set key */ | 2023 rc4_set_key, /* set key */ |
1818 rc4_get_key_size, /* get key size */ | 2024 rc4_get_key_size, /* get key size */ |
1819 NULL, /* set batch mode */ | 2025 NULL, /* set batch mode */ |
1820 NULL, /* get batch mode */ | 2026 NULL, /* get batch mode */ |
1821 | 2027 NULL, /* get block size */ |
1822 /* padding */ | 2028 NULL /* set key with len */ |
1823 NULL, | |
1824 NULL | |
1825 }; | 2029 }; |
1826 | 2030 |
1827 /******************************************************************************* | 2031 /******************************************************************************* |
1828 * Structs | 2032 * Structs |
1829 ******************************************************************************/ | 2033 ******************************************************************************/ |
1893 caps |= PURPLE_CIPHER_CAPS_GET_KEY_SIZE; | 2097 caps |= PURPLE_CIPHER_CAPS_GET_KEY_SIZE; |
1894 if(ops->set_batch_mode) | 2098 if(ops->set_batch_mode) |
1895 caps |= PURPLE_CIPHER_CAPS_SET_BATCH_MODE; | 2099 caps |= PURPLE_CIPHER_CAPS_SET_BATCH_MODE; |
1896 if(ops->get_batch_mode) | 2100 if(ops->get_batch_mode) |
1897 caps |= PURPLE_CIPHER_CAPS_GET_BATCH_MODE; | 2101 caps |= PURPLE_CIPHER_CAPS_GET_BATCH_MODE; |
2102 if(ops->get_block_size) | |
2103 caps |= PURPLE_CIPHER_CAPS_GET_BLOCK_SIZE; | |
2104 if(ops->set_key_with_len) | |
2105 caps |= PURPLE_CIPHER_CAPS_SET_KEY_WITH_LEN; | |
1898 | 2106 |
1899 return caps; | 2107 return caps; |
1900 } | 2108 } |
1901 | 2109 |
1902 gboolean | 2110 gboolean |
2019 PURPLE_SUBTYPE_CIPHER)); | 2227 PURPLE_SUBTYPE_CIPHER)); |
2020 | 2228 |
2021 purple_ciphers_register_cipher("md5", &MD5Ops); | 2229 purple_ciphers_register_cipher("md5", &MD5Ops); |
2022 purple_ciphers_register_cipher("sha1", &SHA1Ops); | 2230 purple_ciphers_register_cipher("sha1", &SHA1Ops); |
2023 purple_ciphers_register_cipher("md4", &MD4Ops); | 2231 purple_ciphers_register_cipher("md4", &MD4Ops); |
2232 purple_ciphers_register_cipher("hmac", &HMACOps); | |
2024 purple_ciphers_register_cipher("des", &DESOps); | 2233 purple_ciphers_register_cipher("des", &DESOps); |
2025 purple_ciphers_register_cipher("des3", &DES3Ops); | 2234 purple_ciphers_register_cipher("des3", &DES3Ops); |
2026 purple_ciphers_register_cipher("rc4", &RC4Ops); | 2235 purple_ciphers_register_cipher("rc4", &RC4Ops); |
2027 } | 2236 } |
2028 | 2237 |
2385 else { | 2594 else { |
2386 purple_debug_info("cipher", "The %s cipher does not support the " | 2595 purple_debug_info("cipher", "The %s cipher does not support the " |
2387 "get_batch_mode operation\n", cipher->name); | 2596 "get_batch_mode operation\n", cipher->name); |
2388 return -1; | 2597 return -1; |
2389 } | 2598 } |
2599 } | |
2600 | |
2601 size_t | |
2602 purple_cipher_context_get_block_size(PurpleCipherContext *context) | |
2603 { | |
2604 PurpleCipher *cipher = NULL; | |
2605 | |
2606 g_return_val_if_fail(context, -1); | |
2607 | |
2608 cipher = context->cipher; | |
2609 g_return_val_if_fail(cipher, -1); | |
2610 | |
2611 if(cipher->ops && cipher->ops->get_block_size) | |
2612 return cipher->ops->get_block_size(context); | |
2613 else { | |
2614 purple_debug_info("cipher", "The %s cipher does not support the " | |
2615 "get_block_size operation\n", cipher->name); | |
2616 return -1; | |
2617 } | |
2618 } | |
2619 | |
2620 void | |
2621 purple_cipher_context_set_key_with_len(PurpleCipherContext *context, | |
2622 const guchar *key, size_t len) | |
2623 { | |
2624 PurpleCipher *cipher = NULL; | |
2625 | |
2626 g_return_if_fail(context); | |
2627 | |
2628 cipher = context->cipher; | |
2629 g_return_if_fail(cipher); | |
2630 | |
2631 if(cipher->ops && cipher->ops->set_key_with_len) | |
2632 cipher->ops->set_key_with_len(context, key, len); | |
2633 else | |
2634 purple_debug_info("cipher", "The %s cipher does not support the " | |
2635 "set_key_with_len operation\n", cipher->name); | |
2390 } | 2636 } |
2391 | 2637 |
2392 void | 2638 void |
2393 purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { | 2639 purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { |
2394 g_return_if_fail(context); | 2640 g_return_if_fail(context); |