1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   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   "@(#)arcfour_crypt.c    1.6     08/01/02 SMI"
  27 
  28 #include "arcfour.h"
  29 
  30 #if defined(__amd64)
  31 /*
  32  * Use hand-tuned, processor-specific assembly version of arcfour_crypt()
  33  * for 64-bit x86:
  34  */
  35 #define USE_PSR_VERSION_OF_ARCFOUR_CRYPT
  36 #endif /* __amd64 */
  37 
  38 /* Initialize the key stream 'key' using the key value */
  39 void
  40 arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen)
  41 {
  42 /* EXPORT DELETE START */
  43 
  44         uchar_t ext_keyval[256];
  45         uchar_t tmp;
  46         int i, j;
  47 
  48         for (i = j = 0; i < 256; i++, j++) {
  49                 if (j == keyvallen)
  50                         j = 0;
  51 
  52                 ext_keyval[i] = keyval[j];
  53         }
  54         for (i = 0; i < 256; i++)
  55                 key->arr[i] = (uchar_t)i;
  56 
  57         j = 0;
  58         for (i = 0; i < 256; i++) {
  59                 j = (j + key->arr[i] + ext_keyval[i]) % 256;
  60                 tmp = key->arr[i];
  61                 key->arr[i] = key->arr[j];
  62                 key->arr[j] = tmp;
  63         }
  64         key->i = 0;
  65         key->j = 0;
  66 
  67 /* EXPORT DELETE END */
  68 }
  69 
  70 
  71 #if !defined(USE_PSR_VERSION_OF_ARCFOUR_CRYPT)
  72 /*
  73  * Encipher 'in' using 'key'.
  74  * in and out can point to the same location
  75  */
  76 void
  77 arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len)
  78 {
  79         size_t ii;
  80         uchar_t tmp, i, j;
  81 
  82 /* EXPORT DELETE START */
  83 
  84         /*
  85          * The sun4u has a version of arcfour_crypt_aligned() hand-tuned for
  86          * the cases where the input and output  buffers are aligned on
  87          * a multiple of 8-byte boundary.
  88          */
  89 #ifdef  sun4u
  90         int index;
  91 
  92         index = (((uint64_t)(uintptr_t)in) & 0x7);
  93 
  94         /* Get the 'in' on an 8-byte alignment */
  95         if (index > 0) {
  96                 i = key->i;
  97                 j = key->j;
  98                 for (index = 8 - (uint64_t)(uintptr_t)in & 0x7;
  99                     (index-- > 0) && len > 0;
 100                     len--, in++, out++) {
 101                         i = i + 1;
 102                         j = j + key->arr[i];
 103                         tmp = key->arr[i];
 104                         key->arr[i] = key->arr[j];
 105                         key->arr[j] = tmp;
 106                         tmp = key->arr[i] + key->arr[j];
 107                         *out = *in ^ key->arr[tmp];
 108                 }
 109                 key->i = i;
 110                 key->j = j;
 111 
 112         }
 113         if (len == 0)
 114                 return;
 115 
 116         /* See if we're fortunate and 'out' got aligned as well */
 117 
 118         if ((((uint64_t)(uintptr_t)out) & 7) != 0) {
 119 #endif  /* sun4u */
 120                 i = key->i;
 121                 j = key->j;
 122                 for (ii = 0; ii < len; ii++) {
 123                         i = i + 1;
 124                         j = j + key->arr[i];
 125                         tmp = key->arr[i];
 126                         key->arr[i] = key->arr[j];
 127                         key->arr[j] = tmp;
 128                         tmp = key->arr[i] + key->arr[j];
 129                         out[ii] = in[ii] ^ key->arr[tmp];
 130                 }
 131                 key->i = i;
 132                 key->j = j;
 133 #ifdef  sun4u
 134         } else {
 135                 arcfour_crypt_aligned(key, len, in, out);
 136         }
 137 #endif  /* sun4u */
 138 
 139 /* EXPORT DELETE END */
 140 }
 141 #endif  /* !USE_PSR_VERSION_OF_ARCFOUR_CRYPT */