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 #ifdef _KERNEL 32 #include <sys/x86_archext.h> 33 #include <sys/cpuvar.h> 34 35 #else 36 #include <sys/auxv.h> 37 #endif /* _KERNEL */ 38 #endif /* __amd64 */ 39 40 #if !defined(__amd64) 41 /* Initialize the key stream 'key' using the key value */ 42 void 43 arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen) 44 { 45 /* EXPORT DELETE START */ 46 47 uchar_t ext_keyval[256]; 48 uchar_t tmp; 49 int i, j; 50 51 /* Normalize key length to 256 */ 52 for (i = j = 0; i < 256; i++, j++) { 53 if (j == keyvallen) 54 j = 0; 55 ext_keyval[i] = keyval[j]; 56 } 57 58 for (i = 0; i < 256; i++) 59 key->arr[i] = (uchar_t)i; 60 61 j = 0; 62 for (i = 0; i < 256; i++) { 63 j = (j + key->arr[i] + ext_keyval[i]) % 256; 64 tmp = key->arr[i]; 65 key->arr[i] = key->arr[j]; 66 key->arr[j] = tmp; 67 } 68 key->i = 0; 69 key->j = 0; 70 71 /* EXPORT DELETE END */ 72 } 73 74 75 /* 76 * Encipher 'in' using 'key'. 77 * in and out can point to the same location 78 */ 79 void 80 arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len) 81 { 82 size_t ii; 83 uchar_t tmp, i, j; 84 85 /* EXPORT DELETE START */ 86 87 /* 88 * The sun4u has a version of arcfour_crypt_aligned() hand-tuned for 89 * the cases where the input and output buffers are aligned on 90 * a multiple of 8-byte boundary. 91 */ 92 #ifdef sun4u 93 int index; 94 95 index = (((uint64_t)(uintptr_t)in) & 0x7); 96 97 /* Get the 'in' on an 8-byte alignment */ 98 if (index > 0) { 99 i = key->i; 100 j = key->j; 101 for (index = 8 - (uint64_t)(uintptr_t)in & 0x7; 102 (index-- > 0) && len > 0; 103 len--, in++, out++) { 104 i = i + 1; 105 j = j + key->arr[i]; 106 tmp = key->arr[i]; 107 key->arr[i] = key->arr[j]; 108 key->arr[j] = tmp; 109 tmp = key->arr[i] + key->arr[j]; 110 *out = *in ^ key->arr[tmp]; 111 } 112 key->i = i; 113 key->j = j; 114 115 } 116 if (len == 0) 117 return; 118 119 /* See if we're fortunate and 'out' got aligned as well */ 120 121 if ((((uint64_t)(uintptr_t)out) & 7) != 0) { 122 #endif /* sun4u */ 123 i = key->i; 124 j = key->j; 125 for (ii = 0; ii < len; ii++) { 126 i = i + 1; 127 j = j + key->arr[i]; 128 tmp = key->arr[i]; 129 key->arr[i] = key->arr[j]; 130 key->arr[j] = tmp; 131 tmp = key->arr[i] + key->arr[j]; 132 out[ii] = in[ii] ^ key->arr[tmp]; 133 } 134 key->i = i; 135 key->j = j; 136 #ifdef sun4u 137 } else { 138 arcfour_crypt_aligned(key, len, in, out); 139 } 140 #endif /* sun4u */ 141 142 /* EXPORT DELETE END */ 143 } 144 145 #else 146 147 /* 148 * Return 1 if executing on Intel, otherwise 0 (e.g., AMD64). 149 */ 150 int 151 arcfour_crypt_on_intel(void) 152 { 153 #ifdef _KERNEL 154 return (cpuid_getvendor(CPU) == X86_VENDOR_Intel); 155 #else 156 uint_t ui; 157 (void) getisax(&ui, 1); 158 return ((ui & AV_386_AMD_MMX) == 0); 159 #endif /* _KERNEL */ 160 } 161 #endif /* !__amd64 */ 162