Mercurial > pidgin
comparison libpurple/cipher.c @ 21909:6648cfa72842
merge of '72df99671f84834d934f83b25ce492f289d77063'
and 'c00604416a0d01f2fbf75b5cc6b6d4f9371e7a67'
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Fri, 21 Dec 2007 09:33:45 +0000 |
parents | f786e478e08b |
children | 76e0463db3aa |
comparison
equal
deleted
inserted
replaced
21897:a64a7bc69f42 | 21909:6648cfa72842 |
---|---|
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 */ |
338 NULL, /* decrypt */ | 347 NULL, /* decrypt */ |
339 NULL, /* set salt */ | 348 NULL, /* set salt */ |
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 | 352 NULL, /* set batch mode */ |
344 /* padding */ | 353 NULL, /* get batch mode */ |
345 NULL, | 354 md5_get_block_size, /* get block size */ |
346 NULL, | 355 NULL /* set key with len */ |
347 NULL, | |
348 NULL | |
349 }; | 356 }; |
350 | 357 |
351 /******************************************************************************* | 358 /******************************************************************************* |
352 * MD4 | 359 * MD4 |
353 ******************************************************************************/ | 360 ******************************************************************************/ |
578 | 585 |
579 g_free(md4_context); | 586 g_free(md4_context); |
580 md4_context = NULL; | 587 md4_context = NULL; |
581 } | 588 } |
582 | 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; | |
595 } | |
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 */ |
586 md4_init, /* init */ | 600 md4_init, /* init */ |
587 md4_reset, /* reset */ | 601 md4_reset, /* reset */ |
593 NULL, /* decrypt */ | 607 NULL, /* decrypt */ |
594 NULL, /* set salt */ | 608 NULL, /* set salt */ |
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 | 612 NULL, /* set batch mode */ |
599 /* padding */ | 613 NULL, /* get batch mode */ |
600 NULL, | 614 md4_get_block_size, /* get block size */ |
601 NULL, | 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 *****************************************************************************/ |
984 0); | 1188 0); |
985 } | 1189 } |
986 return 0; | 1190 return 0; |
987 } | 1191 } |
988 | 1192 |
1193 static gint | |
1194 des_decrypt(PurpleCipherContext *context, const guchar data[], | |
1195 size_t len, guchar output[], size_t *outlen) { | |
1196 int offset = 0; | |
1197 int i = 0; | |
1198 int tmp; | |
1199 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
1200 while(offset+8<=len) { | |
1201 des_ecb_crypt(purple_cipher_context_get_data(context), | |
1202 data+offset, | |
1203 output+offset, | |
1204 1); | |
1205 offset+=8; | |
1206 } | |
1207 *outlen = len; | |
1208 if(offset<len) { | |
1209 *outlen += len - offset; | |
1210 tmp = offset; | |
1211 while(tmp<len) { | |
1212 buf[i++] = data[tmp]; | |
1213 tmp++; | |
1214 } | |
1215 des_ecb_crypt(purple_cipher_context_get_data(context), | |
1216 buf, | |
1217 output+offset, | |
1218 1); | |
1219 } | |
1220 return 0; | |
1221 } | |
1222 | |
989 static void | 1223 static void |
990 des_init(PurpleCipherContext *context, gpointer extra) { | 1224 des_init(PurpleCipherContext *context, gpointer extra) { |
991 struct _des_ctx *mctx; | 1225 struct _des_ctx *mctx; |
992 mctx = g_new0(struct _des_ctx, 1); | 1226 mctx = g_new0(struct _des_ctx, 1); |
993 purple_cipher_context_set_data(context, mctx); | 1227 purple_cipher_context_set_data(context, mctx); |
1003 g_free(des_context); | 1237 g_free(des_context); |
1004 des_context = NULL; | 1238 des_context = NULL; |
1005 } | 1239 } |
1006 | 1240 |
1007 static PurpleCipherOps DESOps = { | 1241 static PurpleCipherOps DESOps = { |
1008 NULL, /* Set option */ | 1242 NULL, /* Set option */ |
1009 NULL, /* Get option */ | 1243 NULL, /* Get option */ |
1010 des_init, /* init */ | 1244 des_init, /* init */ |
1245 NULL, /* reset */ | |
1246 des_uninit, /* uninit */ | |
1247 NULL, /* set iv */ | |
1248 NULL, /* append */ | |
1249 NULL, /* digest */ | |
1250 des_encrypt, /* encrypt */ | |
1251 des_decrypt, /* decrypt */ | |
1252 NULL, /* set salt */ | |
1253 NULL, /* get salt size */ | |
1254 des_set_key, /* set key */ | |
1255 NULL, /* get key size */ | |
1256 NULL, /* set batch mode */ | |
1257 NULL, /* get batch mode */ | |
1258 NULL, /* get block size */ | |
1259 NULL /* set key with len */ | |
1260 }; | |
1261 | |
1262 /****************************************************************************** | |
1263 * Triple-DES | |
1264 *****************************************************************************/ | |
1265 | |
1266 typedef struct _des3_ctx | |
1267 { | |
1268 PurpleCipherBatchMode mode; | |
1269 guchar iv[8]; | |
1270 /* First key for encryption */ | |
1271 struct _des_ctx key1; | |
1272 /* Second key for decryption */ | |
1273 struct _des_ctx key2; | |
1274 /* Third key for encryption */ | |
1275 struct _des_ctx key3; | |
1276 } des3_ctx[1]; | |
1277 | |
1278 /* | |
1279 * Fill a DES3 context with subkeys calculated from 3 64bit key. | |
1280 * Does not check parity bits, but simply ignore them. | |
1281 * Does not check for weak keys. | |
1282 **/ | |
1283 static void | |
1284 des3_set_key(PurpleCipherContext *context, const guchar * key) | |
1285 { | |
1286 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
1287 int i; | |
1288 | |
1289 des_key_schedule (key + 0, ctx->key1.encrypt_subkeys); | |
1290 des_key_schedule (key + 8, ctx->key2.encrypt_subkeys); | |
1291 des_key_schedule (key + 16, ctx->key3.encrypt_subkeys); | |
1292 | |
1293 for (i = 0; i < 32; i += 2) | |
1294 { | |
1295 ctx->key1.decrypt_subkeys[i] = ctx->key1.encrypt_subkeys[30-i]; | |
1296 ctx->key1.decrypt_subkeys[i+1] = ctx->key1.encrypt_subkeys[31-i]; | |
1297 ctx->key2.decrypt_subkeys[i] = ctx->key2.encrypt_subkeys[30-i]; | |
1298 ctx->key2.decrypt_subkeys[i+1] = ctx->key2.encrypt_subkeys[31-i]; | |
1299 ctx->key3.decrypt_subkeys[i] = ctx->key3.encrypt_subkeys[30-i]; | |
1300 ctx->key3.decrypt_subkeys[i+1] = ctx->key3.encrypt_subkeys[31-i]; | |
1301 } | |
1302 } | |
1303 | |
1304 static gint | |
1305 des3_ecb_encrypt(struct _des3_ctx *ctx, const guchar data[], | |
1306 size_t len, guchar output[], size_t *outlen) | |
1307 { | |
1308 int offset = 0; | |
1309 int i = 0; | |
1310 int tmp; | |
1311 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
1312 while (offset + 8 <= len) { | |
1313 des_ecb_crypt(&ctx->key1, | |
1314 data+offset, | |
1315 output+offset, | |
1316 0); | |
1317 des_ecb_crypt(&ctx->key2, | |
1318 output+offset, | |
1319 buf, | |
1320 1); | |
1321 des_ecb_crypt(&ctx->key3, | |
1322 buf, | |
1323 output+offset, | |
1324 0); | |
1325 offset += 8; | |
1326 } | |
1327 *outlen = len; | |
1328 if (offset < len) { | |
1329 *outlen += len - offset; | |
1330 tmp = offset; | |
1331 memset(buf, 0, 8); | |
1332 while (tmp < len) { | |
1333 buf[i++] = data[tmp]; | |
1334 tmp++; | |
1335 } | |
1336 des_ecb_crypt(&ctx->key1, | |
1337 buf, | |
1338 output+offset, | |
1339 0); | |
1340 des_ecb_crypt(&ctx->key2, | |
1341 output+offset, | |
1342 buf, | |
1343 1); | |
1344 des_ecb_crypt(&ctx->key3, | |
1345 buf, | |
1346 output+offset, | |
1347 0); | |
1348 } | |
1349 return 0; | |
1350 } | |
1351 | |
1352 static gint | |
1353 des3_cbc_encrypt(struct _des3_ctx *ctx, const guchar data[], | |
1354 size_t len, guchar output[], size_t *outlen) | |
1355 { | |
1356 int offset = 0; | |
1357 int i = 0; | |
1358 int tmp; | |
1359 guint8 buf[8]; | |
1360 memcpy(buf, ctx->iv, 8); | |
1361 while (offset + 8 <= len) { | |
1362 for (i = 0; i < 8; i++) | |
1363 buf[i] ^= data[offset + i]; | |
1364 des_ecb_crypt(&ctx->key1, | |
1365 buf, | |
1366 output+offset, | |
1367 0); | |
1368 des_ecb_crypt(&ctx->key2, | |
1369 output+offset, | |
1370 buf, | |
1371 1); | |
1372 des_ecb_crypt(&ctx->key3, | |
1373 buf, | |
1374 output+offset, | |
1375 0); | |
1376 memcpy(buf, output+offset, 8); | |
1377 offset += 8; | |
1378 } | |
1379 *outlen = len; | |
1380 if (offset < len) { | |
1381 *outlen += len - offset; | |
1382 tmp = offset; | |
1383 i = 0; | |
1384 while (tmp < len) { | |
1385 buf[i++] ^= data[tmp]; | |
1386 tmp++; | |
1387 } | |
1388 des_ecb_crypt(&ctx->key1, | |
1389 buf, | |
1390 output+offset, | |
1391 0); | |
1392 des_ecb_crypt(&ctx->key2, | |
1393 output+offset, | |
1394 buf, | |
1395 1); | |
1396 des_ecb_crypt(&ctx->key3, | |
1397 buf, | |
1398 output+offset, | |
1399 0); | |
1400 } | |
1401 return 0; | |
1402 } | |
1403 | |
1404 static gint | |
1405 des3_encrypt(PurpleCipherContext *context, const guchar data[], | |
1406 size_t len, guchar output[], size_t *outlen) | |
1407 { | |
1408 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
1409 | |
1410 if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { | |
1411 return des3_ecb_encrypt(ctx, data, len, output, outlen); | |
1412 } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { | |
1413 return des3_cbc_encrypt(ctx, data, len, output, outlen); | |
1414 } else { | |
1415 g_return_val_if_reached(0); | |
1416 } | |
1417 | |
1418 return 0; | |
1419 } | |
1420 | |
1421 static gint | |
1422 des3_ecb_decrypt(struct _des3_ctx *ctx, const guchar data[], | |
1423 size_t len, guchar output[], size_t *outlen) | |
1424 { | |
1425 int offset = 0; | |
1426 int i = 0; | |
1427 int tmp; | |
1428 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
1429 while (offset + 8 <= len) { | |
1430 /* NOTE: Apply key in reverse */ | |
1431 des_ecb_crypt(&ctx->key3, | |
1432 data+offset, | |
1433 output+offset, | |
1434 1); | |
1435 des_ecb_crypt(&ctx->key2, | |
1436 output+offset, | |
1437 buf, | |
1438 0); | |
1439 des_ecb_crypt(&ctx->key1, | |
1440 buf, | |
1441 output+offset, | |
1442 1); | |
1443 offset+=8; | |
1444 } | |
1445 *outlen = len; | |
1446 if (offset < len) { | |
1447 *outlen += len - offset; | |
1448 tmp = offset; | |
1449 memset(buf, 0, 8); | |
1450 while (tmp < len) { | |
1451 buf[i++] = data[tmp]; | |
1452 tmp++; | |
1453 } | |
1454 des_ecb_crypt(&ctx->key3, | |
1455 buf, | |
1456 output+offset, | |
1457 1); | |
1458 des_ecb_crypt(&ctx->key2, | |
1459 output+offset, | |
1460 buf, | |
1461 0); | |
1462 des_ecb_crypt(&ctx->key1, | |
1463 buf, | |
1464 output+offset, | |
1465 1); | |
1466 } | |
1467 return 0; | |
1468 } | |
1469 | |
1470 static gint | |
1471 des3_cbc_decrypt(struct _des3_ctx *ctx, const guchar data[], | |
1472 size_t len, guchar output[], size_t *outlen) | |
1473 { | |
1474 int offset = 0; | |
1475 int i = 0; | |
1476 int tmp; | |
1477 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
1478 guint8 link[8]; | |
1479 memcpy(link, ctx->iv, 8); | |
1480 while (offset + 8 <= len) { | |
1481 des_ecb_crypt(&ctx->key3, | |
1482 data+offset, | |
1483 output+offset, | |
1484 1); | |
1485 des_ecb_crypt(&ctx->key2, | |
1486 output+offset, | |
1487 buf, | |
1488 0); | |
1489 des_ecb_crypt(&ctx->key1, | |
1490 buf, | |
1491 output+offset, | |
1492 1); | |
1493 for (i = 0; i < 8; i++) | |
1494 output[offset + i] ^= link[i]; | |
1495 memcpy(link, data + offset, 8); | |
1496 offset+=8; | |
1497 } | |
1498 *outlen = len; | |
1499 if(offset<len) { | |
1500 *outlen += len - offset; | |
1501 tmp = offset; | |
1502 memset(buf, 0, 8); | |
1503 i = 0; | |
1504 while(tmp<len) { | |
1505 buf[i++] = data[tmp]; | |
1506 tmp++; | |
1507 } | |
1508 des_ecb_crypt(&ctx->key3, | |
1509 buf, | |
1510 output+offset, | |
1511 1); | |
1512 des_ecb_crypt(&ctx->key2, | |
1513 output+offset, | |
1514 buf, | |
1515 0); | |
1516 des_ecb_crypt(&ctx->key1, | |
1517 buf, | |
1518 output+offset, | |
1519 1); | |
1520 for (i = 0; i < 8; i++) | |
1521 output[offset + i] ^= link[i]; | |
1522 } | |
1523 return 0; | |
1524 } | |
1525 | |
1526 static gint | |
1527 des3_decrypt(PurpleCipherContext *context, const guchar data[], | |
1528 size_t len, guchar output[], size_t *outlen) | |
1529 { | |
1530 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
1531 | |
1532 if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { | |
1533 return des3_ecb_decrypt(ctx, data, len, output, outlen); | |
1534 } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { | |
1535 return des3_cbc_decrypt(ctx, data, len, output, outlen); | |
1536 } else { | |
1537 g_return_val_if_reached(0); | |
1538 } | |
1539 | |
1540 return 0; | |
1541 } | |
1542 | |
1543 static void | |
1544 des3_set_batch(PurpleCipherContext *context, PurpleCipherBatchMode mode) | |
1545 { | |
1546 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
1547 | |
1548 ctx->mode = mode; | |
1549 } | |
1550 | |
1551 static PurpleCipherBatchMode | |
1552 des3_get_batch(PurpleCipherContext *context) | |
1553 { | |
1554 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
1555 | |
1556 return ctx->mode; | |
1557 } | |
1558 | |
1559 static void | |
1560 des3_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) | |
1561 { | |
1562 struct _des3_ctx *ctx; | |
1563 | |
1564 g_return_if_fail(len == 8); | |
1565 | |
1566 ctx = purple_cipher_context_get_data(context); | |
1567 | |
1568 memcpy(ctx->iv, iv, len); | |
1569 } | |
1570 | |
1571 static void | |
1572 des3_init(PurpleCipherContext *context, gpointer extra) | |
1573 { | |
1574 struct _des3_ctx *mctx; | |
1575 mctx = g_new0(struct _des3_ctx, 1); | |
1576 purple_cipher_context_set_data(context, mctx); | |
1577 } | |
1578 | |
1579 static void | |
1580 des3_uninit(PurpleCipherContext *context) | |
1581 { | |
1582 struct _des3_ctx *des3_context; | |
1583 | |
1584 des3_context = purple_cipher_context_get_data(context); | |
1585 memset(des3_context, 0, sizeof(des3_context)); | |
1586 | |
1587 g_free(des3_context); | |
1588 des3_context = NULL; | |
1589 } | |
1590 | |
1591 static PurpleCipherOps DES3Ops = { | |
1592 NULL, /* Set option */ | |
1593 NULL, /* Get option */ | |
1594 des3_init, /* init */ | |
1011 NULL, /* reset */ | 1595 NULL, /* reset */ |
1012 des_uninit, /* uninit */ | 1596 des3_uninit, /* uninit */ |
1013 NULL, /* set iv */ | 1597 des3_set_iv, /* set iv */ |
1014 NULL, /* append */ | 1598 NULL, /* append */ |
1015 NULL, /* digest */ | 1599 NULL, /* digest */ |
1016 des_encrypt, /* encrypt */ | 1600 des3_encrypt, /* encrypt */ |
1017 NULL, /* decrypt */ | 1601 des3_decrypt, /* decrypt */ |
1018 NULL, /* set salt */ | 1602 NULL, /* set salt */ |
1019 NULL, /* get salt size */ | 1603 NULL, /* get salt size */ |
1020 des_set_key, /* set key */ | 1604 des3_set_key, /* set key */ |
1021 NULL, /* get key size */ | 1605 NULL, /* get key size */ |
1022 | 1606 des3_set_batch, /* set batch mode */ |
1023 /* padding */ | 1607 des3_get_batch, /* get batch mode */ |
1024 NULL, | 1608 NULL, /* get block size */ |
1025 NULL, | 1609 NULL /* set key with len */ |
1026 NULL, | |
1027 NULL | |
1028 }; | 1610 }; |
1029 | |
1030 | 1611 |
1031 /******************************************************************************* | 1612 /******************************************************************************* |
1032 * SHA-1 | 1613 * SHA-1 |
1033 ******************************************************************************/ | 1614 ******************************************************************************/ |
1615 #define SHA1_HMAC_BLOCK_SIZE 64 | |
1034 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) | 1616 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) |
1035 | 1617 |
1036 struct SHA1Context { | 1618 struct SHA1Context { |
1037 guint32 H[5]; | 1619 guint32 H[5]; |
1038 guint32 W[80]; | 1620 guint32 W[80]; |
1247 | 1829 |
1248 if(out_len) | 1830 if(out_len) |
1249 *out_len = 20; | 1831 *out_len = 20; |
1250 | 1832 |
1251 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; | |
1252 } | 1841 } |
1253 | 1842 |
1254 static PurpleCipherOps SHA1Ops = { | 1843 static PurpleCipherOps SHA1Ops = { |
1255 sha1_set_opt, /* Set Option */ | 1844 sha1_set_opt, /* Set Option */ |
1256 sha1_get_opt, /* Get Option */ | 1845 sha1_get_opt, /* Get Option */ |
1264 NULL, /* decrypt */ | 1853 NULL, /* decrypt */ |
1265 NULL, /* set salt */ | 1854 NULL, /* set salt */ |
1266 NULL, /* get salt size */ | 1855 NULL, /* get salt size */ |
1267 NULL, /* set key */ | 1856 NULL, /* set key */ |
1268 NULL, /* get key size */ | 1857 NULL, /* get key size */ |
1269 | 1858 NULL, /* set batch mode */ |
1270 /* padding */ | 1859 NULL, /* get batch mode */ |
1271 NULL, | 1860 sha1_get_block_size, /* get block size */ |
1272 NULL, | 1861 NULL /* set key with len */ |
1273 NULL, | |
1274 NULL | |
1275 }; | 1862 }; |
1276 | 1863 |
1277 /******************************************************************************* | 1864 /******************************************************************************* |
1278 * RC4 | 1865 * RC4 |
1279 ******************************************************************************/ | 1866 ******************************************************************************/ |
1433 NULL, /* decrypt */ | 2020 NULL, /* decrypt */ |
1434 NULL, /* set salt */ | 2021 NULL, /* set salt */ |
1435 NULL, /* get salt size */ | 2022 NULL, /* get salt size */ |
1436 rc4_set_key, /* set key */ | 2023 rc4_set_key, /* set key */ |
1437 rc4_get_key_size, /* get key size */ | 2024 rc4_get_key_size, /* get key size */ |
1438 | 2025 NULL, /* set batch mode */ |
1439 /* padding */ | 2026 NULL, /* get batch mode */ |
1440 NULL, | 2027 NULL, /* get block size */ |
1441 NULL, | 2028 NULL /* set key with len */ |
1442 NULL, | |
1443 NULL | |
1444 }; | 2029 }; |
1445 | 2030 |
1446 /******************************************************************************* | 2031 /******************************************************************************* |
1447 * Structs | 2032 * Structs |
1448 ******************************************************************************/ | 2033 ******************************************************************************/ |
1508 caps |= PURPLE_CIPHER_CAPS_GET_SALT_SIZE; | 2093 caps |= PURPLE_CIPHER_CAPS_GET_SALT_SIZE; |
1509 if(ops->set_key) | 2094 if(ops->set_key) |
1510 caps |= PURPLE_CIPHER_CAPS_SET_KEY; | 2095 caps |= PURPLE_CIPHER_CAPS_SET_KEY; |
1511 if(ops->get_key_size) | 2096 if(ops->get_key_size) |
1512 caps |= PURPLE_CIPHER_CAPS_GET_KEY_SIZE; | 2097 caps |= PURPLE_CIPHER_CAPS_GET_KEY_SIZE; |
2098 if(ops->set_batch_mode) | |
2099 caps |= PURPLE_CIPHER_CAPS_SET_BATCH_MODE; | |
2100 if(ops->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; | |
1513 | 2106 |
1514 return caps; | 2107 return caps; |
1515 } | 2108 } |
1516 | 2109 |
1517 gboolean | 2110 gboolean |
1634 PURPLE_SUBTYPE_CIPHER)); | 2227 PURPLE_SUBTYPE_CIPHER)); |
1635 | 2228 |
1636 purple_ciphers_register_cipher("md5", &MD5Ops); | 2229 purple_ciphers_register_cipher("md5", &MD5Ops); |
1637 purple_ciphers_register_cipher("sha1", &SHA1Ops); | 2230 purple_ciphers_register_cipher("sha1", &SHA1Ops); |
1638 purple_ciphers_register_cipher("md4", &MD4Ops); | 2231 purple_ciphers_register_cipher("md4", &MD4Ops); |
2232 purple_ciphers_register_cipher("hmac", &HMACOps); | |
1639 purple_ciphers_register_cipher("des", &DESOps); | 2233 purple_ciphers_register_cipher("des", &DESOps); |
2234 purple_ciphers_register_cipher("des3", &DES3Ops); | |
1640 purple_ciphers_register_cipher("rc4", &RC4Ops); | 2235 purple_ciphers_register_cipher("rc4", &RC4Ops); |
1641 } | 2236 } |
1642 | 2237 |
1643 void | 2238 void |
1644 purple_ciphers_uninit() { | 2239 purple_ciphers_uninit() { |
1962 purple_debug_info("cipher", "the %s cipher does not support the " | 2557 purple_debug_info("cipher", "the %s cipher does not support the " |
1963 "get_key_size operation\n", cipher->name); | 2558 "get_key_size operation\n", cipher->name); |
1964 | 2559 |
1965 return -1; | 2560 return -1; |
1966 } | 2561 } |
2562 } | |
2563 | |
2564 void | |
2565 purple_cipher_context_set_batch_mode(PurpleCipherContext *context, | |
2566 PurpleCipherBatchMode mode) | |
2567 { | |
2568 PurpleCipher *cipher = NULL; | |
2569 | |
2570 g_return_if_fail(context); | |
2571 | |
2572 cipher = context->cipher; | |
2573 g_return_if_fail(cipher); | |
2574 | |
2575 if(cipher->ops && cipher->ops->set_batch_mode) | |
2576 cipher->ops->set_batch_mode(context, mode); | |
2577 else | |
2578 purple_debug_info("cipher", "The %s cipher does not support the " | |
2579 "set_batch_mode operation\n", cipher->name); | |
2580 } | |
2581 | |
2582 PurpleCipherBatchMode | |
2583 purple_cipher_context_get_batch_mode(PurpleCipherContext *context) | |
2584 { | |
2585 PurpleCipher *cipher = NULL; | |
2586 | |
2587 g_return_val_if_fail(context, -1); | |
2588 | |
2589 cipher = context->cipher; | |
2590 g_return_val_if_fail(cipher, -1); | |
2591 | |
2592 if(cipher->ops && cipher->ops->get_batch_mode) | |
2593 return cipher->ops->get_batch_mode(context); | |
2594 else { | |
2595 purple_debug_info("cipher", "The %s cipher does not support the " | |
2596 "get_batch_mode operation\n", cipher->name); | |
2597 return -1; | |
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); | |
1967 } | 2636 } |
1968 | 2637 |
1969 void | 2638 void |
1970 purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { | 2639 purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { |
1971 g_return_if_fail(context); | 2640 g_return_if_fail(context); |