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	"%Z%%M%	%I%	%E% 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 }
133