Mercurial > vim
comparison src/blowfish.c @ 2184:5028c4d6d825 vim73
Fixed encryption big/little endian test.
Use uint32_t to avoid crash on 64 bit machines.
Added error numbers for Blowfish errors.
Fixed the tiny version not building.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Mon, 17 May 2010 20:32:55 +0200 |
parents | 3cb515c62e9c |
children | f9aec8acb188 |
comparison
equal
deleted
inserted
replaced
2182:3cb515c62e9c | 2184:5028c4d6d825 |
---|---|
1 /* vi:set ts=8 sts=4 sw=4: | 1 /* vi:set ts=8 sts=4 sw=4: |
2 * | 2 * |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 * See README.txt for an overview of the Vim source code. | |
8 * | |
3 * Blowfish encryption for Vim; in Blowfish output feedback mode. | 9 * Blowfish encryption for Vim; in Blowfish output feedback mode. |
4 * GPL(C) Mohsin Ahmed, http://www.cs.albany.edu/~mosh | 10 * Contributed by Mohsin Ahmed, http://www.cs.albany.edu/~mosh |
5 * Based on http://www.schneier.com/blowfish.html by Bruce Schneier. | 11 * Based on http://www.schneier.com/blowfish.html by Bruce Schneier. |
6 */ | 12 */ |
7 | 13 |
8 #include "vim.h" | 14 #include "vim.h" |
9 | 15 |
13 | 19 |
14 #define BF_BLOCK 8 | 20 #define BF_BLOCK 8 |
15 #define BF_OFB_LEN (8*(BF_BLOCK)) | 21 #define BF_OFB_LEN (8*(BF_BLOCK)) |
16 | 22 |
17 typedef union { | 23 typedef union { |
18 long_u ul[2]; | 24 uint32_t ul[2]; |
19 char_u uc[8]; | 25 char_u uc[8]; |
20 } block8; | 26 } block8; |
21 | 27 |
22 #ifdef __BORLANDC__ | 28 #ifdef WIN3264 |
23 # define LITTLE_ENDIAN | 29 /* MS-Windows is always little endian */ |
24 #else | 30 #else |
25 # if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) | 31 # ifdef HAVE_CONFIG_H |
26 # if (('1234' >> 24) == '1') | 32 /* in configure.in AC_C_BIGENDIAN() defines WORDS_BIGENDIAN when needed */ |
27 # define LITTLE_ENDIAN 1 | 33 # else |
28 # else | 34 error! |
29 # if (('4321' >> 24) == '1') | 35 Please change this code to define WORDS_BIGENDIAN for big-endian machines. |
30 # define BIG_ENDIAN 1 | |
31 # endif | |
32 # endif | |
33 # endif | 36 # endif |
34 #endif | 37 #endif |
35 | 38 |
36 static void bf_e_block __ARGS((long_u *p_xl, long_u *p_xr)); | 39 static void bf_e_block __ARGS((uint32_t *p_xl, uint32_t *p_xr)); |
37 static void bf_e_cblock __ARGS((char_u *block)); | 40 static void bf_e_cblock __ARGS((char_u *block)); |
38 static int bf_check_tables __ARGS((long_u ipa[18], long_u sbi[4][256], long_u val)); | 41 static int bf_check_tables __ARGS((uint32_t ipa[18], uint32_t sbi[4][256], uint32_t val)); |
39 static int bf_self_test __ARGS((void)); | 42 static int bf_self_test __ARGS((void)); |
40 | 43 |
41 // Blowfish code | 44 // Blowfish code |
42 static long_u pax[18]; | 45 static uint32_t pax[18]; |
43 static long_u ipa[18] = { | 46 static uint32_t ipa[18] = { |
44 0x243f6a88u, 0x85a308d3u, 0x13198a2eu, | 47 0x243f6a88u, 0x85a308d3u, 0x13198a2eu, |
45 0x03707344u, 0xa4093822u, 0x299f31d0u, | 48 0x03707344u, 0xa4093822u, 0x299f31d0u, |
46 0x082efa98u, 0xec4e6c89u, 0x452821e6u, | 49 0x082efa98u, 0xec4e6c89u, 0x452821e6u, |
47 0x38d01377u, 0xbe5466cfu, 0x34e90c6cu, | 50 0x38d01377u, 0xbe5466cfu, 0x34e90c6cu, |
48 0xc0ac29b7u, 0xc97c50ddu, 0x3f84d5b5u, | 51 0xc0ac29b7u, 0xc97c50ddu, 0x3f84d5b5u, |
49 0xb5470917u, 0x9216d5d9u, 0x8979fb1bu | 52 0xb5470917u, 0x9216d5d9u, 0x8979fb1bu |
50 }; | 53 }; |
51 | 54 |
52 static long_u sbx[4][256]; | 55 static uint32_t sbx[4][256]; |
53 static long_u sbi[4][256] = { | 56 static uint32_t sbi[4][256] = { |
54 {0xd1310ba6u, 0x98dfb5acu, 0x2ffd72dbu, 0xd01adfb7u, | 57 {0xd1310ba6u, 0x98dfb5acu, 0x2ffd72dbu, 0xd01adfb7u, |
55 0xb8e1afedu, 0x6a267e96u, 0xba7c9045u, 0xf12c7f99u, | 58 0xb8e1afedu, 0x6a267e96u, 0xba7c9045u, 0xf12c7f99u, |
56 0x24a19947u, 0xb3916cf7u, 0x0801f2e2u, 0x858efc16u, | 59 0x24a19947u, 0xb3916cf7u, 0x0801f2e2u, 0x858efc16u, |
57 0x636920d8u, 0x71574e69u, 0xa458fea3u, 0xf4933d7eu, | 60 0x636920d8u, 0x71574e69u, 0xa458fea3u, 0xf4933d7eu, |
58 0x0d95748fu, 0x728eb658u, 0x718bcd58u, 0x82154aeeu, | 61 0x0d95748fu, 0x728eb658u, 0x718bcd58u, 0x82154aeeu, |
326 sbx[3][xr&0xFF]; | 329 sbx[3][xr&0xFF]; |
327 | 330 |
328 | 331 |
329 static void | 332 static void |
330 bf_e_block(p_xl, p_xr) | 333 bf_e_block(p_xl, p_xr) |
331 long_u *p_xl; | 334 uint32_t *p_xl; |
332 long_u *p_xr; | 335 uint32_t *p_xr; |
333 { | 336 { |
334 long_u temp, xl = *p_xl, xr = *p_xr; | 337 uint32_t temp, xl = *p_xl, xr = *p_xr; |
335 | 338 |
336 F1(0) F2(1) F1(2) F2(3) F1(4) F2(5) F1(6) F2(7) | 339 F1(0) F2(1) F1(2) F2(3) F1(4) F2(5) F1(6) F2(7) |
337 F1(8) F2(9) F1(10) F2(11) F1(12) F2(13) F1(14) F2(15) | 340 F1(8) F2(9) F1(10) F2(11) F1(12) F2(13) F1(14) F2(15) |
338 xl ^= pax[16]; xr ^= pax[17]; | 341 xl ^= pax[16]; xr ^= pax[17]; |
339 temp = xl; xl = xr; xr = temp; | 342 temp = xl; xl = xr; xr = temp; |
341 } | 344 } |
342 | 345 |
343 #if 0 /* not used */ | 346 #if 0 /* not used */ |
344 static void | 347 static void |
345 bf_d_block(p_xl, p_xr) | 348 bf_d_block(p_xl, p_xr) |
346 long_u *p_xl; | 349 uint32_t *p_xl; |
347 long_u *p_xr; | 350 uint32_t *p_xr; |
348 { | 351 { |
349 long_u temp, xl = *p_xl, xr = *p_xr; | 352 uint32_t temp, xl = *p_xl, xr = *p_xr; |
350 F1(17) F2(16) F1(15) F2(14) F1(13) F2(12) F1(11) F2(10) | 353 F1(17) F2(16) F1(15) F2(14) F1(13) F2(12) F1(11) F2(10) |
351 F1(9) F2(8) F1(7) F2(6) F1(5) F2(4) F1(3) F2(2) | 354 F1(9) F2(8) F1(7) F2(6) F1(5) F2(4) F1(3) F2(2) |
352 xl ^= pax[1]; | 355 xl ^= pax[1]; |
353 xr ^= pax[0]; | 356 xr ^= pax[0]; |
354 temp = xl; xl = xr; xr = temp; | 357 temp = xl; xl = xr; xr = temp; |
355 *p_xl = xl; *p_xr = xr; | 358 *p_xl = xl; *p_xr = xr; |
356 } | 359 } |
357 #endif | 360 #endif |
358 | 361 |
359 | 362 |
360 #ifdef BIG_ENDIAN | 363 #ifdef WORDS_BIGENDIAN |
361 # define htonl2(x) \ | 364 # define htonl2(x) \ |
362 x = ((((x) & 0xffL) << 24) | (((x) & 0xff00L) << 8) | \ | 365 x = ((((x) & 0xffL) << 24) | (((x) & 0xff00L) << 8) | \ |
363 (((x) & 0xff0000L) >> 8) | (((x) & 0xff000000L) >> 24)) | 366 (((x) & 0xff0000L) >> 8) | (((x) & 0xff000000L) >> 24)) |
364 #else | 367 #else |
365 # define htonl2(x) | 368 # define htonl2(x) |
395 | 398 |
396 void | 399 void |
397 bf_key_init(password) | 400 bf_key_init(password) |
398 char_u *password; | 401 char_u *password; |
399 { | 402 { |
400 int i, j, keypos = 0; | 403 int i, j, keypos = 0; |
401 long_u val, data_l, data_r; | 404 uint32_t val, data_l, data_r; |
402 char_u *key; | 405 char_u *key; |
403 int keylen; | 406 int keylen; |
404 | 407 |
405 key = sha256_key(password); | 408 key = sha256_key(password); |
406 keylen = STRLEN(key); | 409 keylen = STRLEN(key); |
407 for (i = 0; i < 256; ++i) | 410 for (i = 0; i < 256; ++i) |
408 { | 411 { |
442 /* | 445 /* |
443 * BF Self test for corrupted tables or instructions | 446 * BF Self test for corrupted tables or instructions |
444 */ | 447 */ |
445 static int | 448 static int |
446 bf_check_tables(ipa, sbi, val) | 449 bf_check_tables(ipa, sbi, val) |
447 long_u ipa[18]; | 450 uint32_t ipa[18]; |
448 long_u sbi[4][256]; | 451 uint32_t sbi[4][256]; |
449 long_u val; | 452 uint32_t val; |
450 { | 453 { |
451 int i, j; | 454 int i, j; |
452 long_u c = 0; | 455 uint32_t c = 0; |
453 | 456 |
454 for (i = 0; i < 18; i++) | 457 for (i = 0; i < 18; i++) |
455 c ^= ipa[i]; | 458 c ^= ipa[i]; |
456 for (i = 0; i < 4; i++) | 459 for (i = 0; i < 4; i++) |
457 for (j = 0; j < 256; j++) | 460 for (j = 0; j < 256; j++) |
458 c ^= sbi[i][j]; | 461 c ^= sbi[i][j]; |
459 return c == val; | 462 return c == val; |
460 } | 463 } |
461 | 464 |
462 typedef struct { | 465 typedef struct { |
463 char_u password[64]; | 466 char_u password[64]; |
464 char_u plaintxt[8]; | 467 char_u plaintxt[8]; |
465 char_u cryptxt[8]; | 468 char_u cryptxt[8]; |
466 long_u keysum; | 469 char_u badcryptxt[8]; /* cryptxt when big/little endian is wrong */ |
470 uint32_t keysum; | |
467 } struct_bf_test_data; | 471 } struct_bf_test_data; |
468 | 472 |
469 // Assert bf(password, plaintxt) is cryptxt. | 473 // Assert bf(password, plaintxt) is cryptxt. |
470 // Assert csum(pax sbx(password)) is keysum. | 474 // Assert csum(pax sbx(password)) is keysum. |
471 static struct_bf_test_data bf_test_data[] = { | 475 static struct_bf_test_data bf_test_data[] = { |
472 { | 476 { |
473 "password", | 477 "password", |
474 "plaintxt", | 478 "plaintxt", |
475 #if 0 /* This value doesn't work, why??? */ | |
476 "\x55\xca\x56\x3a\xef\xe1\x9c\x73", /* cryptxt */ | 479 "\x55\xca\x56\x3a\xef\xe1\x9c\x73", /* cryptxt */ |
477 #else | 480 "\x47\xd9\x67\x49\x91\xc5\x9a\x95", /* badcryptxt */ |
478 "\x47\xd9\x67\x49\x91\xc5\x9a\x95", /* cryptxt */ | |
479 #endif | |
480 0x5de01bdbu, /* keysum */ | 481 0x5de01bdbu, /* keysum */ |
481 }, | 482 }, |
482 }; | 483 }; |
483 | 484 |
484 /* | 485 /* |
503 | 504 |
504 /* Don't modify bf_test_data[i].plaintxt, self test is idempotent. */ | 505 /* Don't modify bf_test_data[i].plaintxt, self test is idempotent. */ |
505 memcpy(bk.uc, bf_test_data[i].plaintxt, 8); | 506 memcpy(bk.uc, bf_test_data[i].plaintxt, 8); |
506 bf_e_cblock(bk.uc); | 507 bf_e_cblock(bk.uc); |
507 if (memcmp(bk.uc, bf_test_data[i].cryptxt, 8) != 0) | 508 if (memcmp(bk.uc, bf_test_data[i].cryptxt, 8) != 0) |
509 { | |
510 if (err == 0 && memcmp(bk.uc, bf_test_data[i].badcryptxt, 8) == 0) | |
511 EMSG(_("E817: Blowfish big/little endian use wrong")); | |
508 err++; | 512 err++; |
513 } | |
509 } | 514 } |
510 | 515 |
511 return err > 0 ? FAIL : OK; | 516 return err > 0 ? FAIL : OK; |
512 } | 517 } |
513 | 518 |
565 int | 570 int |
566 blowfish_self_test() | 571 blowfish_self_test() |
567 { | 572 { |
568 if (sha256_self_test() == FAIL) | 573 if (sha256_self_test() == FAIL) |
569 { | 574 { |
570 EMSG2(_("E000: sha256 test failed"),""); | 575 EMSG(_("E818: sha256 test failed")); |
571 return FAIL; | 576 return FAIL; |
572 } | 577 } |
573 if (bf_self_test() == FAIL) | 578 if (bf_self_test() == FAIL) |
574 { | 579 { |
575 EMSG2(_("E000: Blowfish test failed"),""); | 580 EMSG(_("E819: Blowfish test failed")); |
576 return FAIL; | 581 return FAIL; |
577 } | 582 } |
578 return OK; | 583 return OK; |
579 } | 584 } |
580 | 585 |