xref: /illumos-gate/usr/src/common/crypto/arcfour/arcfour_crypt.c (revision bfed486ad8de8b8ebc6345a8e10accae08bf2f45)
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