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, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "@(#)arcfour_crypt.c    1.5     05/08/23 SMI"
  28 
  29 #include "arcfour.h"
  30 
  31 /* Initialize the key stream 'key' using the key value */
  32 void
  33 arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen)
  34 {
  35 /* EXPORT DELETE START */
  36 
  37         uchar_t ext_keyval[256];
  38         uchar_t tmp;
  39         int i, j;
  40 
  41         for (i = j = 0; i < 256; i++, j++) {
  42                 if (j == keyvallen)
  43                         j = 0;
  44 
  45                 ext_keyval[i] = keyval[j];
  46         }
  47         for (i = 0; i < 256; i++)
  48                 key->arr[i] = (uchar_t)i;
  49 
  50         j = 0;
  51         for (i = 0; i < 256; i++) {
  52                 j = (j + key->arr[i] + ext_keyval[i]) % 256;
  53                 tmp = key->arr[i];
  54                 key->arr[i] = key->arr[j];
  55                 key->arr[j] = tmp;
  56         }
  57         key->i = 0;
  58         key->j = 0;
  59 
  60 /* EXPORT DELETE END */
  61 }
  62 
  63 
  64 /*
  65  * Encipher 'in' using 'key.
  66  * in and out can point to the same location
  67  */
  68 void
  69 arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len)
  70 {
  71         size_t ii;
  72         uchar_t tmp, i, j;
  73 
  74 /* EXPORT DELETE START */
  75 
  76         /*
  77          * The sun4u has a version of arcfour_crypt_aligned() hand-tuned for
  78          * the cases where the input and output  buffers are aligned on
  79          * a multiple of 8-byte boundary.
  80          */
  81 #ifdef  sun4u
  82         int index;
  83 
  84         index = (((uint64_t)(uintptr_t)in) & 0x7);
  85 
  86         /* Get the 'in' on an 8-byte alignment */
  87         if (index > 0) {
  88                 i = key->i;
  89                 j = key->j;
  90                 for (index = 8 - (uint64_t)(uintptr_t)in & 0x7;
  91                     (index-- > 0) && len > 0;
  92                     len--, in++, out++) {
  93                         i = i + 1;
  94                         j = j + key->arr[i];
  95                         tmp = key->arr[i];
  96                         key->arr[i] = key->arr[j];
  97                         key->arr[j] = tmp;
  98                         tmp = key->arr[i] + key->arr[j];
  99                         *out = *in ^ key->arr[tmp];
 100                 }
 101                 key->i = i;
 102                 key->j = j;
 103 
 104         }
 105         if (len == 0)
 106                 return;
 107 
 108         /* See if we're fortunate and 'out' got aligned as well */
 109 
 110         if ((((uint64_t)(uintptr_t)out) & 7) != 0) {
 111 #endif  /* sun4u */
 112                 i = key->i;
 113                 j = key->j;
 114                 for (ii = 0; ii < len; ii++) {
 115                         i = i + 1;
 116                         j = j + key->arr[i];
 117                         tmp = key->arr[i];
 118                         key->arr[i] = key->arr[j];
 119                         key->arr[j] = tmp;
 120                         tmp = key->arr[i] + key->arr[j];
 121                         out[ii] = in[ii] ^ key->arr[tmp];
 122                 }
 123                 key->i = i;
 124                 key->j = j;
 125 #ifdef  sun4u
 126         } else {
 127                 arcfour_crypt_aligned(key, len, in, out);
 128         }
 129 #endif  /* sun4u */
 130 
 131 /* EXPORT DELETE END */
 132 }