38 #include <modes/modes.h>
39 #include <sys/crypto/common.h>
40 #include "blowfish_impl.h"
41
42 #ifdef _KERNEL
43
44 #define BLOWFISH_ASSERT(x) ASSERT(x)
45
46 #else /* !_KERNEL */
47
48 #include <strings.h>
49 #include <stdlib.h>
50 #define BLOWFISH_ASSERT(x)
51 #endif /* _KERNEL */
52
53 #if defined(__i386) || defined(__amd64)
54 #include <sys/byteorder.h>
55 #define UNALIGNED_POINTERS_PERMITTED
56 #endif
57
58 /* EXPORT DELETE START */
59
60 /*
61 * Blowfish initial P box and S boxes, derived from the hex digits of PI.
62 *
63 * NOTE: S boxes are placed into one large array.
64 */
65 static const uint32_t init_P[] = {
66 0x243f6a88U, 0x85a308d3U, 0x13198a2eU,
67 0x03707344U, 0xa4093822U, 0x299f31d0U,
68 0x082efa98U, 0xec4e6c89U, 0x452821e6U,
69 0x38d01377U, 0xbe5466cfU, 0x34e90c6cU,
70 0xc0ac29b7U, 0xc97c50ddU, 0x3f84d5b5U,
71 0xb5470917U, 0x9216d5d9U, 0x8979fb1bU
72 };
73
74 static const uint32_t init_S[] = {
75 /* S-Box 0. */
76 0xd1310ba6U, 0x98dfb5acU, 0x2ffd72dbU, 0xd01adfb7U,
77 0xb8e1afedU, 0x6a267e96U, 0xba7c9045U, 0xf12c7f99U,
78 0x24a19947U, 0xb3916cf7U, 0x0801f2e2U, 0x858efc16U,
79 0x636920d8U, 0x71574e69U, 0xa458fea3U, 0xf4933d7eU,
350 * uint32_t *P;
351 * uint32_t *S;
352 * uint32_t tmp;
353 *
354 *
355 * And to Microsoft interview survivors out there, perhaps I should do the
356 * XOR swap trick, or at least #ifdef (__i386) the tmp = ... = tmp; stuff.
357 */
358
359 #define F(word) \
360 (((S[(word >> 24) & 0xff] + S[256 + ((word >> 16) & 0xff)]) ^ \
361 S[512 + ((word >> 8) & 0xff)]) + S[768 + (word & 0xff)])
362
363 #define ROUND(left, right, i) \
364 (left) ^= P[i]; \
365 (right) ^= F((left)); \
366 tmp = (left); \
367 (left) = (right); \
368 (right) = tmp;
369
370 /* EXPORT DELETE END */
371
372 /*
373 * Encrypt a block of data. Because of addition operations, convert blocks
374 * to their big-endian representation, even on Intel boxen.
375 */
376 /* ARGSUSED */
377 int
378 blowfish_encrypt_block(const void *cookie, const uint8_t *block,
379 uint8_t *out_block)
380 {
381 /* EXPORT DELETE START */
382 keysched_t *ksch = (keysched_t *)cookie;
383
384 uint32_t left, right, tmp;
385 uint32_t *P = ksch->ksch_P;
386 uint32_t *S = ksch->ksch_S;
387 #ifdef _BIG_ENDIAN
388 uint32_t *b32;
389
390 if (IS_P2ALIGNED(block, sizeof (uint32_t))) {
391 /* LINTED: pointer alignment */
392 b32 = (uint32_t *)block;
393 left = b32[0];
394 right = b32[1];
395 } else
396 #endif
397 {
398 /*
399 * Read input block and place in left/right in big-endian order.
400 */
401 #ifdef UNALIGNED_POINTERS_PERMITTED
443 b32[0] = left;
444 b32[1] = right;
445 } else
446 #endif
447 {
448 /* Put the block back into the user's block with final swap */
449 #ifdef UNALIGNED_POINTERS_PERMITTED
450 *(uint32_t *)(void *)&out_block[0] = htonl(left);
451 *(uint32_t *)(void *)&out_block[4] = htonl(right);
452 #else
453 out_block[0] = left >> 24;
454 out_block[1] = left >> 16;
455 out_block[2] = left >> 8;
456 out_block[3] = left;
457 out_block[4] = right >> 24;
458 out_block[5] = right >> 16;
459 out_block[6] = right >> 8;
460 out_block[7] = right;
461 #endif /* UNALIGNED_POINTERS_PERMITTED */
462 }
463 /* EXPORT DELETE END */
464 return (CRYPTO_SUCCESS);
465 }
466
467 /*
468 * Decrypt a block of data. Because of addition operations, convert blocks
469 * to their big-endian representation, even on Intel boxen.
470 * It should look like the blowfish_encrypt_block() operation
471 * except for the order in which the S/P boxes are accessed.
472 */
473 /* ARGSUSED */
474 int
475 blowfish_decrypt_block(const void *cookie, const uint8_t *block,
476 uint8_t *out_block)
477 {
478 /* EXPORT DELETE START */
479 keysched_t *ksch = (keysched_t *)cookie;
480
481 uint32_t left, right, tmp;
482 uint32_t *P = ksch->ksch_P;
483 uint32_t *S = ksch->ksch_S;
484 #ifdef _BIG_ENDIAN
485 uint32_t *b32;
486
487 if (IS_P2ALIGNED(block, sizeof (uint32_t))) {
488 /* LINTED: pointer alignment */
489 b32 = (uint32_t *)block;
490 left = b32[0];
491 right = b32[1];
492 } else
493 #endif
494 {
495 /*
496 * Read input block and place in left/right in big-endian order.
497 */
498 #ifdef UNALIGNED_POINTERS_PERMITTED
540 b32[0] = left;
541 b32[1] = right;
542 } else
543 #endif
544 {
545 /* Put the block back into the user's block with final swap */
546 #ifdef UNALIGNED_POINTERS_PERMITTED
547 *(uint32_t *)(void *)&out_block[0] = htonl(left);
548 *(uint32_t *)(void *)&out_block[4] = htonl(right);
549 #else
550 out_block[0] = left >> 24;
551 out_block[1] = left >> 16;
552 out_block[2] = left >> 8;
553 out_block[3] = left;
554 out_block[4] = right >> 24;
555 out_block[5] = right >> 16;
556 out_block[6] = right >> 8;
557 out_block[7] = right;
558 #endif /* UNALIGNED_POINTERS_PERMITTED */
559 }
560 /* EXPORT DELETE END */
561 return (CRYPTO_SUCCESS);
562 }
563
564 static void
565 bitrepeat(uint8_t *pattern, uint_t len_bytes, uint_t len_bits, uint8_t *dst,
566 uint_t dst_len_bytes)
567 {
568 /* EXPORT DELETE START */
569 uint8_t *current = dst;
570 uint_t bitsleft = CRYPTO_BYTES2BITS(dst_len_bytes);
571 uint_t bitoffset = 0;
572 uint_t currentbits;
573 int i;
574
575 BLOWFISH_ASSERT(CRYPTO_BITS2BYTES(len_bits) == len_bytes);
576
577 bzero(dst, dst_len_bytes);
578
579 while (bitsleft != 0) {
580 if (bitsleft >= len_bits) {
581 currentbits = len_bits;
582
583 for (i = 0; i < len_bytes; i++) {
584 if (currentbits >= 8) {
585 *current++ |= pattern[i] >> bitoffset;
586 *current |= pattern[i] << 8 - bitoffset;
587 currentbits -= 8;
588 } else {
600 for (i = 0; i < len_bytes && bitsleft != 0; i++) {
601 if (currentbits >= 8 &&
602 current < dst + dst_len_bytes) {
603 *current++ |= pattern[i] >> bitoffset;
604 *current |= pattern[i] << 8 - bitoffset;
605 currentbits -= 8;
606 bitsleft -= 8;
607 } else {
608 *current |= pattern[i] >> bitoffset;
609 bitsleft -= bitoffset;
610 bitoffset = bitoffset + currentbits;
611 bitoffset &= 0x7;
612 if (bitoffset == 0)
613 current++;
614 currentbits = 0;
615 }
616 }
617 bitsleft = 0;
618 }
619 }
620 /* EXPORT DELETE END */
621 }
622
623 /*
624 * Initialize key schedules for Blowfish.
625 */
626 void
627 blowfish_init_keysched(uint8_t *key, uint_t bits, void *keysched)
628 {
629 /* EXPORT DELETE START */
630 keysched_t *newbie = keysched;
631 uint32_t *P = newbie->ksch_P;
632 uint32_t *S = newbie->ksch_S;
633 uint32_t *initp;
634 uint32_t tmpblock[] = {0, 0};
635 uint8_t *rawkeybytes = (uint8_t *)P;
636 int i, slop, copylen;
637 uintptr_t bytesleft;
638 uint_t len;
639
640 len = CRYPTO_BITS2BYTES(bits);
641
642 if ((bits & 0x7) != 0) {
643 /*
644 * Really slow case, bits aren't on a byte boundary.
645 * Keep track of individual bits copied over. :-P
646 */
647 bitrepeat(key, len, bits, rawkeybytes, 72);
648 } else {
649 slop = 72 % len;
668 * When initializing P and S boxes, store the results of a single
669 * encrypt-block operation in "host order", which on little-endian
670 * means byte-swapping. Fortunately, the ntohl() function does this
671 * quite nicely, and it a NOP on big-endian machine.
672 */
673 initp = P;
674 for (i = 0; i < 9; i++) {
675 (void) blowfish_encrypt_block(newbie, (uint8_t *)tmpblock,
676 (uint8_t *)tmpblock);
677 *initp++ = ntohl(tmpblock[0]);
678 *initp++ = ntohl(tmpblock[1]);
679 }
680
681 initp = S;
682 for (i = 0; i < 512; i++) {
683 (void) blowfish_encrypt_block(newbie, (uint8_t *)tmpblock,
684 (uint8_t *)tmpblock);
685 *initp++ = ntohl(tmpblock[0]);
686 *initp++ = ntohl(tmpblock[1]);
687 }
688 /* EXPORT DELETE END */
689 }
690
691 /*
692 * Allocate key schedule for Blowfish.
693 */
694 /* ARGSUSED */
695 void *
696 blowfish_alloc_keysched(size_t *size, int kmflag)
697 {
698 /* EXPORT DELETE START */
699 keysched_t *keysched;
700
701 #ifdef _KERNEL
702 keysched = (keysched_t *)kmem_alloc(sizeof (keysched_t), kmflag);
703 #else
704 keysched = (keysched_t *)malloc(sizeof (keysched_t));
705 #endif /* _KERNEL */
706 if (keysched != NULL) {
707 *size = sizeof (keysched_t);
708 return (keysched);
709 }
710 /* EXPORT DELETE END */
711
712 return (NULL);
713 }
714
715 void
716 blowfish_copy_block(uint8_t *in, uint8_t *out)
717 {
718 if (IS_P2ALIGNED(in, sizeof (uint32_t)) &&
719 IS_P2ALIGNED(out, sizeof (uint32_t))) {
720 /* LINTED: pointer alignment */
721 *(uint32_t *)&out[0] = *(uint32_t *)&in[0];
722 /* LINTED: pointer alignment */
723 *(uint32_t *)&out[4] = *(uint32_t *)&in[4];
724 } else {
725 BLOWFISH_COPY_BLOCK(in, out);
726 }
727 }
728
729 /* XOR block of data into dest */
730 void
|
38 #include <modes/modes.h>
39 #include <sys/crypto/common.h>
40 #include "blowfish_impl.h"
41
42 #ifdef _KERNEL
43
44 #define BLOWFISH_ASSERT(x) ASSERT(x)
45
46 #else /* !_KERNEL */
47
48 #include <strings.h>
49 #include <stdlib.h>
50 #define BLOWFISH_ASSERT(x)
51 #endif /* _KERNEL */
52
53 #if defined(__i386) || defined(__amd64)
54 #include <sys/byteorder.h>
55 #define UNALIGNED_POINTERS_PERMITTED
56 #endif
57
58 /*
59 * Blowfish initial P box and S boxes, derived from the hex digits of PI.
60 *
61 * NOTE: S boxes are placed into one large array.
62 */
63 static const uint32_t init_P[] = {
64 0x243f6a88U, 0x85a308d3U, 0x13198a2eU,
65 0x03707344U, 0xa4093822U, 0x299f31d0U,
66 0x082efa98U, 0xec4e6c89U, 0x452821e6U,
67 0x38d01377U, 0xbe5466cfU, 0x34e90c6cU,
68 0xc0ac29b7U, 0xc97c50ddU, 0x3f84d5b5U,
69 0xb5470917U, 0x9216d5d9U, 0x8979fb1bU
70 };
71
72 static const uint32_t init_S[] = {
73 /* S-Box 0. */
74 0xd1310ba6U, 0x98dfb5acU, 0x2ffd72dbU, 0xd01adfb7U,
75 0xb8e1afedU, 0x6a267e96U, 0xba7c9045U, 0xf12c7f99U,
76 0x24a19947U, 0xb3916cf7U, 0x0801f2e2U, 0x858efc16U,
77 0x636920d8U, 0x71574e69U, 0xa458fea3U, 0xf4933d7eU,
348 * uint32_t *P;
349 * uint32_t *S;
350 * uint32_t tmp;
351 *
352 *
353 * And to Microsoft interview survivors out there, perhaps I should do the
354 * XOR swap trick, or at least #ifdef (__i386) the tmp = ... = tmp; stuff.
355 */
356
357 #define F(word) \
358 (((S[(word >> 24) & 0xff] + S[256 + ((word >> 16) & 0xff)]) ^ \
359 S[512 + ((word >> 8) & 0xff)]) + S[768 + (word & 0xff)])
360
361 #define ROUND(left, right, i) \
362 (left) ^= P[i]; \
363 (right) ^= F((left)); \
364 tmp = (left); \
365 (left) = (right); \
366 (right) = tmp;
367
368 /*
369 * Encrypt a block of data. Because of addition operations, convert blocks
370 * to their big-endian representation, even on Intel boxen.
371 */
372 /* ARGSUSED */
373 int
374 blowfish_encrypt_block(const void *cookie, const uint8_t *block,
375 uint8_t *out_block)
376 {
377 keysched_t *ksch = (keysched_t *)cookie;
378
379 uint32_t left, right, tmp;
380 uint32_t *P = ksch->ksch_P;
381 uint32_t *S = ksch->ksch_S;
382 #ifdef _BIG_ENDIAN
383 uint32_t *b32;
384
385 if (IS_P2ALIGNED(block, sizeof (uint32_t))) {
386 /* LINTED: pointer alignment */
387 b32 = (uint32_t *)block;
388 left = b32[0];
389 right = b32[1];
390 } else
391 #endif
392 {
393 /*
394 * Read input block and place in left/right in big-endian order.
395 */
396 #ifdef UNALIGNED_POINTERS_PERMITTED
438 b32[0] = left;
439 b32[1] = right;
440 } else
441 #endif
442 {
443 /* Put the block back into the user's block with final swap */
444 #ifdef UNALIGNED_POINTERS_PERMITTED
445 *(uint32_t *)(void *)&out_block[0] = htonl(left);
446 *(uint32_t *)(void *)&out_block[4] = htonl(right);
447 #else
448 out_block[0] = left >> 24;
449 out_block[1] = left >> 16;
450 out_block[2] = left >> 8;
451 out_block[3] = left;
452 out_block[4] = right >> 24;
453 out_block[5] = right >> 16;
454 out_block[6] = right >> 8;
455 out_block[7] = right;
456 #endif /* UNALIGNED_POINTERS_PERMITTED */
457 }
458 return (CRYPTO_SUCCESS);
459 }
460
461 /*
462 * Decrypt a block of data. Because of addition operations, convert blocks
463 * to their big-endian representation, even on Intel boxen.
464 * It should look like the blowfish_encrypt_block() operation
465 * except for the order in which the S/P boxes are accessed.
466 */
467 /* ARGSUSED */
468 int
469 blowfish_decrypt_block(const void *cookie, const uint8_t *block,
470 uint8_t *out_block)
471 {
472 keysched_t *ksch = (keysched_t *)cookie;
473
474 uint32_t left, right, tmp;
475 uint32_t *P = ksch->ksch_P;
476 uint32_t *S = ksch->ksch_S;
477 #ifdef _BIG_ENDIAN
478 uint32_t *b32;
479
480 if (IS_P2ALIGNED(block, sizeof (uint32_t))) {
481 /* LINTED: pointer alignment */
482 b32 = (uint32_t *)block;
483 left = b32[0];
484 right = b32[1];
485 } else
486 #endif
487 {
488 /*
489 * Read input block and place in left/right in big-endian order.
490 */
491 #ifdef UNALIGNED_POINTERS_PERMITTED
533 b32[0] = left;
534 b32[1] = right;
535 } else
536 #endif
537 {
538 /* Put the block back into the user's block with final swap */
539 #ifdef UNALIGNED_POINTERS_PERMITTED
540 *(uint32_t *)(void *)&out_block[0] = htonl(left);
541 *(uint32_t *)(void *)&out_block[4] = htonl(right);
542 #else
543 out_block[0] = left >> 24;
544 out_block[1] = left >> 16;
545 out_block[2] = left >> 8;
546 out_block[3] = left;
547 out_block[4] = right >> 24;
548 out_block[5] = right >> 16;
549 out_block[6] = right >> 8;
550 out_block[7] = right;
551 #endif /* UNALIGNED_POINTERS_PERMITTED */
552 }
553 return (CRYPTO_SUCCESS);
554 }
555
556 static void
557 bitrepeat(uint8_t *pattern, uint_t len_bytes, uint_t len_bits, uint8_t *dst,
558 uint_t dst_len_bytes)
559 {
560 uint8_t *current = dst;
561 uint_t bitsleft = CRYPTO_BYTES2BITS(dst_len_bytes);
562 uint_t bitoffset = 0;
563 uint_t currentbits;
564 int i;
565
566 BLOWFISH_ASSERT(CRYPTO_BITS2BYTES(len_bits) == len_bytes);
567
568 bzero(dst, dst_len_bytes);
569
570 while (bitsleft != 0) {
571 if (bitsleft >= len_bits) {
572 currentbits = len_bits;
573
574 for (i = 0; i < len_bytes; i++) {
575 if (currentbits >= 8) {
576 *current++ |= pattern[i] >> bitoffset;
577 *current |= pattern[i] << 8 - bitoffset;
578 currentbits -= 8;
579 } else {
591 for (i = 0; i < len_bytes && bitsleft != 0; i++) {
592 if (currentbits >= 8 &&
593 current < dst + dst_len_bytes) {
594 *current++ |= pattern[i] >> bitoffset;
595 *current |= pattern[i] << 8 - bitoffset;
596 currentbits -= 8;
597 bitsleft -= 8;
598 } else {
599 *current |= pattern[i] >> bitoffset;
600 bitsleft -= bitoffset;
601 bitoffset = bitoffset + currentbits;
602 bitoffset &= 0x7;
603 if (bitoffset == 0)
604 current++;
605 currentbits = 0;
606 }
607 }
608 bitsleft = 0;
609 }
610 }
611 }
612
613 /*
614 * Initialize key schedules for Blowfish.
615 */
616 void
617 blowfish_init_keysched(uint8_t *key, uint_t bits, void *keysched)
618 {
619 keysched_t *newbie = keysched;
620 uint32_t *P = newbie->ksch_P;
621 uint32_t *S = newbie->ksch_S;
622 uint32_t *initp;
623 uint32_t tmpblock[] = {0, 0};
624 uint8_t *rawkeybytes = (uint8_t *)P;
625 int i, slop, copylen;
626 uintptr_t bytesleft;
627 uint_t len;
628
629 len = CRYPTO_BITS2BYTES(bits);
630
631 if ((bits & 0x7) != 0) {
632 /*
633 * Really slow case, bits aren't on a byte boundary.
634 * Keep track of individual bits copied over. :-P
635 */
636 bitrepeat(key, len, bits, rawkeybytes, 72);
637 } else {
638 slop = 72 % len;
657 * When initializing P and S boxes, store the results of a single
658 * encrypt-block operation in "host order", which on little-endian
659 * means byte-swapping. Fortunately, the ntohl() function does this
660 * quite nicely, and it a NOP on big-endian machine.
661 */
662 initp = P;
663 for (i = 0; i < 9; i++) {
664 (void) blowfish_encrypt_block(newbie, (uint8_t *)tmpblock,
665 (uint8_t *)tmpblock);
666 *initp++ = ntohl(tmpblock[0]);
667 *initp++ = ntohl(tmpblock[1]);
668 }
669
670 initp = S;
671 for (i = 0; i < 512; i++) {
672 (void) blowfish_encrypt_block(newbie, (uint8_t *)tmpblock,
673 (uint8_t *)tmpblock);
674 *initp++ = ntohl(tmpblock[0]);
675 *initp++ = ntohl(tmpblock[1]);
676 }
677 }
678
679 /*
680 * Allocate key schedule for Blowfish.
681 */
682 /* ARGSUSED */
683 void *
684 blowfish_alloc_keysched(size_t *size, int kmflag)
685 {
686 keysched_t *keysched;
687
688 #ifdef _KERNEL
689 keysched = (keysched_t *)kmem_alloc(sizeof (keysched_t), kmflag);
690 #else
691 keysched = (keysched_t *)malloc(sizeof (keysched_t));
692 #endif /* _KERNEL */
693 if (keysched != NULL) {
694 *size = sizeof (keysched_t);
695 return (keysched);
696 }
697
698 return (NULL);
699 }
700
701 void
702 blowfish_copy_block(uint8_t *in, uint8_t *out)
703 {
704 if (IS_P2ALIGNED(in, sizeof (uint32_t)) &&
705 IS_P2ALIGNED(out, sizeof (uint32_t))) {
706 /* LINTED: pointer alignment */
707 *(uint32_t *)&out[0] = *(uint32_t *)&in[0];
708 /* LINTED: pointer alignment */
709 *(uint32_t *)&out[4] = *(uint32_t *)&in[4];
710 } else {
711 BLOWFISH_COPY_BLOCK(in, out);
712 }
713 }
714
715 /* XOR block of data into dest */
716 void
|