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 "%Z%%M% %I% %E% 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 */ 142