3 * $Id: blowfish.c,v 1.3 1997/08/07 09:42:58 mdw Exp $
5 * Blowfish encryption routines
7 * (c) 1997 Mark Wooding
10 /*----- Licencing notice --------------------------------------------------*
12 * This file is part of `become'
14 * `Become' is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * `Become' is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with `become'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Revision history --------------------------------------------------*
31 * $Log: blowfish.c,v $
32 * Revision 1.3 1997/08/07 09:42:58 mdw
33 * Fix address of the FSF.
35 * Revision 1.2 1997/08/04 10:24:20 mdw
36 * Sources placed under CVS control.
38 * Revision 1.1 1997/07/21 13:47:53 mdw
43 /*----- Header files ------------------------------------------------------*/
45 /* --- ANSI headers --- */
49 /* --- Local headers --- */
55 /*----- Define the initial S-box values -----------------------------------*/
57 #include "blowfish-sbox.h"
59 /*----- Useful macros -----------------------------------------------------*/
61 /* --- The Blowfish round function --- *
63 * This is why I like this cipher. The round function is microscopic. And
67 #define ROUND(L, R, K) \
69 (R) ^= ((((k->s0[((L) >> 24) & 0xFF]) + \
70 k->s1[((L) >> 16) & 0xFF]) ^ \
71 k->s2[((L) >> 8) & 0xFF]) + \
72 k->s3[((L) >> 0) & 0xFF]))
74 /*----- Main code ---------------------------------------------------------*/
76 /* --- @blowfish_encrypt@ --- *
78 * Arguments: @const blowfish_key *k@ = pointer to key block
79 * @const void *from@ = block to encrypt from
80 * @void *to@ = block to encrypt to
84 * Use: Encrypts a block using the Blowfish algorithm.
87 void blowfish_encrypt(const blowfish_key
*k
, const void *from
, void *to
)
90 const unsigned char *f
= from
;
91 unsigned char *t
= to
;
93 /* --- Extract left and right block halves --- */
98 /* --- Now run the round function on these values --- */
117 /* --- Final transformation --- */
122 /* --- Store the encrypted value --- */
128 /* --- @blowfish_decrypt@ --- *
130 * Arguments: @const blowfish_key *k@ = pointer to key block
131 * @const void *from@ = block to decrypt from
132 * @void *to@ = block to decrypt to
136 * Use: Decrypts a block using the Blowfish algorithm.
139 void blowfish_decrypt(const blowfish_key
*k
, const void *from
, void *to
)
142 const unsigned char *f
= from
;
143 unsigned char *t
= to
;
145 /* --- Extract left and right block halves --- */
150 /* --- Now run the round function on these values --- */
169 /* --- Final transformation --- */
174 /* --- Store the decrypted value --- */
180 /* --- @blowfish__qcrypt@ --- *
182 * Arguments: @const blowfish_key *k@ = pointer to a key block
183 * @uint_32 *p@ = pointer to block to mangle
187 * Use: Mangles a block using the Blowfish algorithm.
190 static void blowfish__qcrypt(blowfish_key
*k
, uint_32
*p
)
192 uint_32 l
= p
[0], r
= p
[1];
194 /* --- Run the round function --- */
213 /* --- Output transformation --- */
218 /* --- Store the new values --- */
224 /* --- @blowfish__buildKey@ --- *
226 * Arguments: @blowfish_key *k@ = pointer to a key block to set up
230 * Use: Sets up the P-array and S-boxes once a key has been mixed
231 * into the P-array. Use a local copy of the Blowfish
232 * encryption routine, to avoid penalising the main code too
233 * much with having to veneer onto a general args-in-words
234 * function, and to avoid me messing about with transforming
235 * values backwards and forwards between char arrays and
239 static void blowfish__buildKey(blowfish_key
*k
)
241 uint_32 b
[2] = { 0, 0 };
244 /* --- First, run through the P-array --- */
246 for (i
= 0; i
< 18; i
+= 2) {
247 blowfish__qcrypt(k
, b
);
252 /* --- Now do the S-boxes --- */
254 for (i
= 0; i
< 256; i
+= 2) {
255 blowfish__qcrypt(k
, b
);
260 for (i
= 0; i
< 256; i
+= 2) {
261 blowfish__qcrypt(k
, b
);
266 for (i
= 0; i
< 256; i
+= 2) {
267 blowfish__qcrypt(k
, b
);
272 for (i
= 0; i
< 256; i
+= 2) {
273 blowfish__qcrypt(k
, b
);
279 /* --- @blowfish_setKey@ --- *
281 * Arguments: @blowfish_key *kb@ = pointer to key block to fill
282 * @void *k@ = pointer to key data
283 * @size_t sz@ = length of data in bytes
287 * Use: Expands a key which isn't represented as a number of whole
288 * words. This is a nonstandard extension, although it can be
289 * used to support 40-bit keys, which some governments might
290 * find more palatable than 160-bit (or 448-bit!) keys.
293 void blowfish_setKey(blowfish_key
*kb
, const void *k
, size_t sz
)
296 const unsigned char *p
= k
;
299 memcpy(kb
, &blowfish__init
, sizeof(blowfish__init
));
302 for (i
= 0; i
< 18; i
++) {
304 for (l
= 0; l
< 4; l
++) {
313 blowfish__buildKey(kb
);
316 /*----- Test rig ----------------------------------------------------------*/
322 /* --- Stage one: ECB tests --- */
330 { { 0x00000000u
, 0x00000000u
},
331 { 0x00000000u
, 0x00000000u
},
332 { 0x4EF99745u
, 0x6198DD78u
} },
334 { { 0xFFFFFFFFu
, 0xFFFFFFFFu
},
335 { 0xFFFFFFFFu
, 0xFFFFFFFFu
},
336 { 0x51866FD5u
, 0xB85ECB8Au
} },
338 { { 0x30000000u
, 0x00000000u
},
339 { 0x10000000u
, 0x00000001u
},
340 { 0x7D856F9Au
, 0x613063F2u
} },
342 { { 0x11111111u
, 0x11111111u
},
343 { 0x11111111u
, 0x11111111u
},
344 { 0x2466DD87u
, 0x8B963C9Du
} },
346 { { 0x01234567u
, 0x89ABCDEFu
},
347 { 0x11111111u
, 0x11111111u
},
348 { 0x61F9C380u
, 0x2281B096u
} },
350 { { 0x11111111u
, 0x11111111u
},
351 { 0x01234567u
, 0x89ABCDEFu
},
352 { 0x7D0CC630u
, 0xAFDA1EC7u
} },
354 { { 0x00000000u
, 0x00000000u
},
355 { 0x00000000u
, 0x00000000u
},
356 { 0x4EF99745u
, 0x6198DD78u
} },
358 { { 0xFEDCBA98u
, 0x76543210u
},
359 { 0x01234567u
, 0x89ABCDEFu
},
360 { 0x0ACEAB0Fu
, 0xC6A0A28Du
} },
362 { { 0x7CA11045u
, 0x4A1A6E57u
},
363 { 0x01A1D6D0u
, 0x39776742u
},
364 { 0x59C68245u
, 0xEB05282Bu
} },
366 { { 0x0131D961u
, 0x9DC1376Eu
},
367 { 0x5CD54CA8u
, 0x3DEF57DAu
},
368 { 0xB1B8CC0Bu
, 0x250F09A0u
} },
370 { { 0x07A1133Eu
, 0x4A0B2686u
},
371 { 0x0248D438u
, 0x06F67172u
},
372 { 0x1730E577u
, 0x8BEA1DA4u
} },
374 { { 0x3849674Cu
, 0x2602319Eu
},
375 { 0x51454B58u
, 0x2DDF440Au
},
376 { 0xA25E7856u
, 0xCF2651EBu
} },
378 { { 0x04B915BAu
, 0x43FEB5B6u
},
379 { 0x42FD4430u
, 0x59577FA2u
},
380 { 0x353882B1u
, 0x09CE8F1Au
} },
382 { { 0x0113B970u
, 0xFD34F2CEu
},
383 { 0x059B5E08u
, 0x51CF143Au
},
384 { 0x48F4D088u
, 0x4C379918u
} },
386 { { 0x0170F175u
, 0x468FB5E6u
},
387 { 0x0756D8E0u
, 0x774761D2u
},
388 { 0x432193B7u
, 0x8951FC98u
} },
390 { { 0x43297FADu
, 0x38E373FEu
},
391 { 0x762514B8u
, 0x29BF486Au
},
392 { 0x13F04154u
, 0xD69D1AE5u
} },
394 { { 0x07A71370u
, 0x45DA2A16u
},
395 { 0x3BDD1190u
, 0x49372802u
},
396 { 0x2EEDDA93u
, 0xFFD39C79u
} },
398 { { 0x04689104u
, 0xC2FD3B2Fu
},
399 { 0x26955F68u
, 0x35AF609Au
},
400 { 0xD887E039u
, 0x3C2DA6E3u
} },
402 { { 0x37D06BB5u
, 0x16CB7546u
},
403 { 0x164D5E40u
, 0x4F275232u
},
404 { 0x5F99D04Fu
, 0x5B163969u
} },
406 { { 0x1F08260Du
, 0x1AC2465Eu
},
407 { 0x6B056E18u
, 0x759F5CCAu
},
408 { 0x4A057A3Bu
, 0x24D3977Bu
} },
410 { { 0x58402364u
, 0x1ABA6176u
},
411 { 0x004BD6EFu
, 0x09176062u
},
412 { 0x452031C1u
, 0xE4FADA8Eu
} },
414 { { 0x02581616u
, 0x4629B007u
},
415 { 0x480D3900u
, 0x6EE762F2u
},
416 { 0x7555AE39u
, 0xF59B87BDu
} },
418 { { 0x49793EBCu
, 0x79B3258Fu
},
419 { 0x437540C8u
, 0x698F3CFAu
},
420 { 0x53C55F9Cu
, 0xB49FC019u
} },
422 { { 0x4FB05E15u
, 0x15AB73A7u
},
423 { 0x072D43A0u
, 0x77075292u
},
424 { 0x7A8E7BFAu
, 0x937E89A3u
} },
426 { { 0x49E95D6Du
, 0x4CA229BFu
},
427 { 0x02FE5577u
, 0x8117F12Au
},
428 { 0xCF9C5D7Au
, 0x4986ADB5u
} },
430 { { 0x018310DCu
, 0x409B26D6u
},
431 { 0x1D9D5C50u
, 0x18F728C2u
},
432 { 0xD1ABB290u
, 0x658BC778u
} },
434 { { 0x1C587F1Cu
, 0x13924FEFu
},
435 { 0x30553228u
, 0x6D6F295Au
},
436 { 0x55CB3774u
, 0xD13EF201u
} },
438 { { 0x01010101u
, 0x01010101u
},
439 { 0x01234567u
, 0x89ABCDEFu
},
440 { 0xFA34EC48u
, 0x47B268B2u
} },
442 { { 0x1F1F1F1Fu
, 0x0E0E0E0Eu
},
443 { 0x01234567u
, 0x89ABCDEFu
},
444 { 0xA7907951u
, 0x08EA3CAEu
} },
446 { { 0xE0FEE0FEu
, 0xF1FEF1FEu
},
447 { 0x01234567u
, 0x89ABCDEFu
},
448 { 0xC39E072Du
, 0x9FAC631Du
} },
450 { { 0x00000000u
, 0x00000000u
},
451 { 0xFFFFFFFFu
, 0xFFFFFFFFu
},
452 { 0x014933E0u
, 0xCDAFF6E4u
} },
454 { { 0xFFFFFFFFu
, 0xFFFFFFFFu
},
455 { 0x00000000u
, 0x00000000u
},
456 { 0xF21E9A77u
, 0xB71C49BCu
} },
458 { { 0x01234567u
, 0x89ABCDEFu
},
459 { 0x00000000u
, 0x00000000u
},
460 { 0x24594688u
, 0x5754369Au
} },
462 { { 0xFEDCBA98u
, 0x76543210u
},
463 { 0xFFFFFFFFu
, 0xFFFFFFFFu
},
464 { 0x6B5C5A9Cu
, 0x5D9E0A5Au
} }
470 printf("*** stage one: ");
473 for (i
= 0; i
< sizeof(table
) / sizeof(table
[0]); i
++) {
474 char kb
[8], p
[8], c
[8];
477 store32(kb
+ 0, table
[i
].k
[0]);
478 store32(kb
+ 4, table
[i
].k
[1]);
479 blowfish_setKey(&k
, kb
, 8);
481 store32(p
+ 0, table
[i
].p
[0]);
482 store32(p
+ 4, table
[i
].p
[1]);
483 blowfish_encrypt(&k
, p
, c
);
485 if (load32(c
+ 0) != table
[i
].c
[0] ||
486 load32(c
+ 4) != table
[i
].c
[1]) {
488 "!!! bad encryption\n"
489 " key = %08lx-%08lx\n"
490 " plaintext = %08lx-%08lx\n"
491 " expected ciphertext = %08lx-%08lx\n"
492 " calculated ciphertext = %08lx-%08lx\n",
493 (unsigned long)table
[i
].k
[0],
494 (unsigned long)table
[i
].k
[1],
495 (unsigned long)table
[i
].p
[0],
496 (unsigned long)table
[i
].p
[1],
497 (unsigned long)table
[i
].c
[0],
498 (unsigned long)table
[i
].c
[1],
499 (unsigned long)load32(c
+ 0),
500 (unsigned long)load32(c
+ 4));
504 blowfish_decrypt(&k
, c
, p
);
505 if (load32(p
+ 0) != table
[i
].p
[0] ||
506 load32(p
+ 4) != table
[i
].p
[1]) {
508 "!!! bad decryption\n"
509 " key = %08lx-%08lx\n"
510 " ciphertext = %08lx-%08lx\n"
511 " expected plaintext = %08lx-%08lx\n"
512 " calculated plaintext = %08lx-%08lx\n",
513 (unsigned long)table
[i
].k
[0],
514 (unsigned long)table
[i
].k
[1],
515 (unsigned long)table
[i
].c
[0],
516 (unsigned long)table
[i
].c
[1],
517 (unsigned long)table
[i
].p
[0],
518 (unsigned long)table
[i
].p
[1],
519 (unsigned long)load32(p
+ 0),
520 (unsigned long)load32(p
+ 4));
529 printf("*** stage one ok\n");
532 /* --- Stage 2: key scheduling --- */
538 {{ 0xF9AD597Cu
, 0x49DB005Eu
}},
539 {{ 0xE91D21C1u
, 0xD961A6D6u
}},
540 {{ 0xE9C2B70Au
, 0x1BC65CF3u
}},
541 {{ 0xBE1E6394u
, 0x08640F05u
}},
542 {{ 0xB39E4448u
, 0x1BDB1E6Eu
}},
543 {{ 0x9457AA83u
, 0xB1928C0Du
}},
544 {{ 0x8BB77032u
, 0xF960629Du
}},
545 {{ 0xE87A244Eu
, 0x2CC85E82u
}},
546 {{ 0x15750E7Au
, 0x4F4EC577u
}},
547 {{ 0x122BA70Bu
, 0x3AB64AE0u
}},
548 {{ 0x3A833C9Au
, 0xFFC537F6u
}},
549 {{ 0x9409DA87u
, 0xA90F6BF2u
}},
550 {{ 0x884F8062u
, 0x5060B8B4u
}},
551 {{ 0x1F85031Cu
, 0x19E11968u
}},
552 {{ 0x79D9373Au
, 0x714CA34Fu
}},
553 {{ 0x93142887u
, 0xEE3BE15Cu
}},
554 {{ 0x03429E83u
, 0x8CE2D14Bu
}},
555 {{ 0xA4299E27u
, 0x469FF67Bu
}},
556 {{ 0xAFD5AED1u
, 0xC1BC96A8u
}},
557 {{ 0x10851C0Eu
, 0x3858DA9Fu
}},
558 {{ 0xE6F51ED7u
, 0x9B9DB21Fu
}},
559 {{ 0x64A6E14Au
, 0xFD36B46Fu
}},
560 {{ 0x80C7D7D4u
, 0x5A5479ADu
}},
561 {{ 0x05044B62u
, 0xFA52D080u
}},
564 unsigned char kk
[] = {
565 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
566 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,
567 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
573 printf("*** stage two: ");
576 for (i
= 0; i
< sizeof(kk
); i
++) {
578 unsigned char p
[8] = { 0xFE, 0xDC, 0xBA, 0x98,
579 0x76, 0x54, 0x32, 0x10 };
581 blowfish_setKey(&k
, kk
, i
+ 1);
582 blowfish_encrypt(&k
, p
, p
);
584 if (load32(p
+ 0) != table
[i
].c
[0] ||
585 load32(p
+ 4) != table
[i
].c
[1]) {
586 printf("!!! bad encryption\n"
588 " expected = %08lx-%08lx\n"
589 " calculated = %08lx-%08lx\n",
591 (unsigned long)table
[i
].c
[0],
592 (unsigned long)table
[i
].c
[1],
593 (unsigned long)load32(p
+ 0),
594 (unsigned long)load32(p
+ 4));
605 printf("*** stage two ok\n");
614 /*----- That's all, folks -------------------------------------------------*/