Print this page
5007142 Add ntohll and htonll to sys/byteorder.h
6717509 Need to use bswap/bswapq for byte swap of 64-bit integer on x32/x64
PSARC 2008/474


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 /*
  29  * Blowfish encryption/decryption and keyschedule code.
  30  */
  31 
  32 #include <sys/types.h>
  33 #include <sys/systm.h>
  34 #include <sys/ddi.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/strsun.h>
  37 #include <sys/note.h>
  38 #include <sys/byteorder.h>
  39 #include <sys/crypto/spi.h>
  40 #include <modes/modes.h>
  41 #include <sys/crypto/common.h>
  42 #include "blowfish_impl.h"
  43 
  44 #ifdef _KERNEL
  45 
  46 #define BLOWFISH_ASSERT(x)      ASSERT(x)
  47 
  48 #else /* !_KERNEL */
  49 
  50 #include <strings.h>
  51 #include <stdlib.h>
  52 #define BLOWFISH_ASSERT(x)
  53 
  54 #endif /* _KERNEL */
  55 





  56 /* EXPORT DELETE START */
  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,


 373  */
 374 /* ARGSUSED */
 375 int
 376 blowfish_encrypt_block(const void *cookie, const uint8_t *block,
 377     uint8_t *out_block)
 378 {
 379 /* EXPORT DELETE START */
 380         keysched_t *ksch = (keysched_t *)cookie;
 381 
 382         uint32_t left, right, tmp;
 383         uint32_t *P = ksch->ksch_P;
 384         uint32_t *S = ksch->ksch_S;
 385 #ifdef _BIG_ENDIAN
 386         uint32_t *b32;
 387 
 388         if (IS_P2ALIGNED(block, sizeof (uint32_t))) {
 389                 /* LINTED:  pointer alignment */
 390                 b32 = (uint32_t *)block;
 391                 left = b32[0];
 392                 right = b32[1];
 393         } else {
 394 #endif

 395         /*
 396          * Read input block and place in left/right in big-endian order.
 397          */




 398         left = ((uint32_t)block[0] << 24)
 399             | ((uint32_t)block[1] << 16)
 400             | ((uint32_t)block[2] << 8)
 401             | (uint32_t)block[3];
 402         right = ((uint32_t)block[4] << 24)
 403             | ((uint32_t)block[5] << 16)
 404             | ((uint32_t)block[6] << 8)
 405             | (uint32_t)block[7];
 406 #ifdef _BIG_ENDIAN
 407         }
 408 #endif
 409 
 410         ROUND(left, right, 0);
 411         ROUND(left, right, 1);
 412         ROUND(left, right, 2);
 413         ROUND(left, right, 3);
 414         ROUND(left, right, 4);
 415         ROUND(left, right, 5);
 416         ROUND(left, right, 6);
 417         ROUND(left, right, 7);
 418         ROUND(left, right, 8);
 419         ROUND(left, right, 9);
 420         ROUND(left, right, 10);
 421         ROUND(left, right, 11);
 422         ROUND(left, right, 12);
 423         ROUND(left, right, 13);
 424         ROUND(left, right, 14);
 425         ROUND(left, right, 15);
 426 
 427         tmp = left;
 428         left = right;
 429         right = tmp;
 430         right ^= P[16];
 431         left ^= P[17];
 432 
 433 #ifdef _BIG_ENDIAN
 434         if (IS_P2ALIGNED(out_block, sizeof (uint32_t))) {
 435                 /* LINTED:  pointer alignment */
 436                 b32 = (uint32_t *)out_block;
 437                 b32[0] = left;
 438                 b32[1] = right;
 439         } else {
 440 #endif

 441         /* Put the block back into the user's block with final swap */




 442         out_block[0] = left >> 24;
 443         out_block[1] = left >> 16;
 444         out_block[2] = left >> 8;
 445         out_block[3] = left;
 446         out_block[4] = right >> 24;
 447         out_block[5] = right >> 16;
 448         out_block[6] = right >> 8;
 449         out_block[7] = right;
 450 #ifdef _BIG_ENDIAN
 451         }
 452 #endif
 453 /* EXPORT DELETE END */
 454         return (CRYPTO_SUCCESS);
 455 }
 456 
 457 /*
 458  * Decrypt a block of data.  Because of addition operations, convert blocks
 459  * to their big-endian representation, even on Intel boxen.
 460  * It should look like the blowfish_encrypt_block() operation
 461  * except for the order in which the S/P boxes are accessed.
 462  */
 463 /* ARGSUSED */
 464 int
 465 blowfish_decrypt_block(const void *cookie, const uint8_t *block,
 466     uint8_t *out_block)
 467 {
 468 /* EXPORT DELETE START */
 469         keysched_t *ksch = (keysched_t *)cookie;
 470 
 471         uint32_t left, right, tmp;
 472         uint32_t *P = ksch->ksch_P;
 473         uint32_t *S = ksch->ksch_S;
 474 #ifdef _BIG_ENDIAN
 475         uint32_t *b32;
 476 
 477         if (IS_P2ALIGNED(block, sizeof (uint32_t))) {
 478                 /* LINTED:  pointer alignment */
 479                 b32 = (uint32_t *)block;
 480                 left = b32[0];
 481                 right = b32[1];
 482         } else {
 483 #endif

 484         /*
 485          * Read input block and place in left/right in big-endian order.
 486          */




 487         left = ((uint32_t)block[0] << 24)
 488             | ((uint32_t)block[1] << 16)
 489             | ((uint32_t)block[2] << 8)
 490             | (uint32_t)block[3];
 491         right = ((uint32_t)block[4] << 24)
 492             | ((uint32_t)block[5] << 16)
 493             | ((uint32_t)block[6] << 8)
 494             | (uint32_t)block[7];
 495 #ifdef _BIG_ENDIAN
 496         }
 497 #endif
 498 
 499         ROUND(left, right, 17);
 500         ROUND(left, right, 16);
 501         ROUND(left, right, 15);
 502         ROUND(left, right, 14);
 503         ROUND(left, right, 13);
 504         ROUND(left, right, 12);
 505         ROUND(left, right, 11);
 506         ROUND(left, right, 10);
 507         ROUND(left, right, 9);
 508         ROUND(left, right, 8);
 509         ROUND(left, right, 7);
 510         ROUND(left, right, 6);
 511         ROUND(left, right, 5);
 512         ROUND(left, right, 4);
 513         ROUND(left, right, 3);
 514         ROUND(left, right, 2);
 515 
 516         tmp = left;
 517         left = right;
 518         right = tmp;
 519         right ^= P[1];
 520         left ^= P[0];
 521 
 522 #ifdef _BIG_ENDIAN
 523         if (IS_P2ALIGNED(out_block, sizeof (uint32_t))) {
 524                 /* LINTED:  pointer alignment */
 525                 b32 = (uint32_t *)out_block;
 526                 b32[0] = left;
 527                 b32[1] = right;
 528         } else {
 529 #endif

 530         /* Put the block back into the user's block with final swap */




 531         out_block[0] = left >> 24;
 532         out_block[1] = left >> 16;
 533         out_block[2] = left >> 8;
 534         out_block[3] = left;
 535         out_block[4] = right >> 24;
 536         out_block[5] = right >> 16;
 537         out_block[6] = right >> 8;
 538         out_block[7] = right;
 539 #ifdef _BIG_ENDIAN
 540         }
 541 #endif
 542 /* EXPORT DELETE END */
 543         return (CRYPTO_SUCCESS);
 544 }
 545 
 546 static void
 547 bitrepeat(uint8_t *pattern, uint_t len_bytes, uint_t len_bits, uint8_t *dst,
 548     uint_t dst_len_bytes)
 549 {
 550 /* EXPORT DELETE START */
 551         uint8_t *current = dst;
 552         uint_t bitsleft = dst_len_bytes << 3;
 553         uint_t bitoffset = 0;
 554         uint_t currentbits;
 555         int i;
 556 
 557         BLOWFISH_ASSERT(((len_bits + 7) >> 3) == len_bytes);
 558 
 559         bzero(dst, dst_len_bytes);
 560 
 561         while (bitsleft != 0) {




   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 


  26 /*
  27  * Blowfish encryption/decryption and keyschedule code.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/systm.h>
  32 #include <sys/ddi.h>
  33 #include <sys/sysmacros.h>
  34 #include <sys/strsun.h>
  35 #include <sys/note.h>
  36 #include <sys/byteorder.h>
  37 #include <sys/crypto/spi.h>
  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,


 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
 402         left = htonl(*(uint32_t *)&block[0]);
 403         right = htonl(*(uint32_t *)&block[4]);
 404 #else
 405         left = ((uint32_t)block[0] << 24)
 406             | ((uint32_t)block[1] << 16)
 407             | ((uint32_t)block[2] << 8)
 408             | (uint32_t)block[3];
 409         right = ((uint32_t)block[4] << 24)
 410             | ((uint32_t)block[5] << 16)
 411             | ((uint32_t)block[6] << 8)
 412             | (uint32_t)block[7];
 413 #endif  /* UNALIGNED_POINTERS_PERMITTED */
 414         }

 415 
 416         ROUND(left, right, 0);
 417         ROUND(left, right, 1);
 418         ROUND(left, right, 2);
 419         ROUND(left, right, 3);
 420         ROUND(left, right, 4);
 421         ROUND(left, right, 5);
 422         ROUND(left, right, 6);
 423         ROUND(left, right, 7);
 424         ROUND(left, right, 8);
 425         ROUND(left, right, 9);
 426         ROUND(left, right, 10);
 427         ROUND(left, right, 11);
 428         ROUND(left, right, 12);
 429         ROUND(left, right, 13);
 430         ROUND(left, right, 14);
 431         ROUND(left, right, 15);
 432 
 433         tmp = left;
 434         left = right;
 435         right = tmp;
 436         right ^= P[16];
 437         left ^= P[17];
 438 
 439 #ifdef _BIG_ENDIAN
 440         if (IS_P2ALIGNED(out_block, sizeof (uint32_t))) {
 441                 /* LINTED:  pointer alignment */
 442                 b32 = (uint32_t *)out_block;
 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 *)&out_block[0] = htonl(left);
 451                 *(uint32_t *)&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
 499         left = htonl(*(uint32_t *)&block[0]);
 500         right = htonl(*(uint32_t *)&block[4]);
 501 #else
 502         left = ((uint32_t)block[0] << 24)
 503             | ((uint32_t)block[1] << 16)
 504             | ((uint32_t)block[2] << 8)
 505             | (uint32_t)block[3];
 506         right = ((uint32_t)block[4] << 24)
 507             | ((uint32_t)block[5] << 16)
 508             | ((uint32_t)block[6] << 8)
 509             | (uint32_t)block[7];
 510 #endif  /* UNALIGNED_POINTERS_PERMITTED */
 511         }

 512 
 513         ROUND(left, right, 17);
 514         ROUND(left, right, 16);
 515         ROUND(left, right, 15);
 516         ROUND(left, right, 14);
 517         ROUND(left, right, 13);
 518         ROUND(left, right, 12);
 519         ROUND(left, right, 11);
 520         ROUND(left, right, 10);
 521         ROUND(left, right, 9);
 522         ROUND(left, right, 8);
 523         ROUND(left, right, 7);
 524         ROUND(left, right, 6);
 525         ROUND(left, right, 5);
 526         ROUND(left, right, 4);
 527         ROUND(left, right, 3);
 528         ROUND(left, right, 2);
 529 
 530         tmp = left;
 531         left = right;
 532         right = tmp;
 533         right ^= P[1];
 534         left ^= P[0];
 535 
 536 #ifdef _BIG_ENDIAN
 537         if (IS_P2ALIGNED(out_block, sizeof (uint32_t))) {
 538                 /* LINTED:  pointer alignment */
 539                 b32 = (uint32_t *)out_block;
 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 *)&out_block[0] = htonl(left);
 548                 *(uint32_t *)&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 = dst_len_bytes << 3;
 571         uint_t bitoffset = 0;
 572         uint_t currentbits;
 573         int i;
 574 
 575         BLOWFISH_ASSERT(((len_bits + 7) >> 3) == len_bytes);
 576 
 577         bzero(dst, dst_len_bytes);
 578 
 579         while (bitsleft != 0) {