arcfour_crypt.c revision 416:6f98fe688e7b
1168404Spjd/*
2168404Spjd * CDDL HEADER START
3168404Spjd *
4168404Spjd * The contents of this file are subject to the terms of the
5168404Spjd * Common Development and Distribution License, Version 1.0 only
6168404Spjd * (the "License").  You may not use this file except in compliance
7168404Spjd * with the License.
8168404Spjd *
9168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10168404Spjd * or http://www.opensolaris.org/os/licensing.
11168404Spjd * See the License for the specific language governing permissions
12168404Spjd * and limitations under the License.
13168404Spjd *
14168404Spjd * When distributing Covered Code, include this CDDL HEADER in each
15168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16168404Spjd * If applicable, add the following below this CDDL HEADER, with the
17168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying
18168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
19168404Spjd *
20168404Spjd * CDDL HEADER END
21263406Sdelphij */
22168404Spjd/*
23205199Sdelphij * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24168404Spjd * Use is subject to license terms.
25263406Sdelphij */
26168404Spjd
27168404Spjd#pragma ident	"%Z%%M%	%I%	%E% SMI"
28168404Spjd
29168404Spjd#include "arcfour.h"
30168404Spjd
31168404Spjd/* Initialize the key stream 'key' using the key value */
32168404Spjdvoid
33168404Spjdarcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen)
34168404Spjd{
35168404Spjd/* EXPORT DELETE START */
36168404Spjd
37168404Spjd	uchar_t ext_keyval[256];
38168404Spjd	uchar_t tmp;
39168404Spjd	int i, j;
40168404Spjd
41168404Spjd	for (i = j = 0; i < 256; i++, j++) {
42168404Spjd		if (j == keyvallen)
43185029Spjd			j = 0;
44185029Spjd
45185029Spjd		ext_keyval[i] = keyval[j];
46205199Sdelphij	}
47219089Spjd	for (i = 0; i < 256; i++)
48231946Smm		key->arr[i] = (uchar_t)i;
49263406Sdelphij
50185029Spjd	j = 0;
51185029Spjd	for (i = 0; i < 256; i++) {
52205199Sdelphij		j = (j + key->arr[i] + ext_keyval[i]) % 256;
53168404Spjd		tmp = key->arr[i];
54168404Spjd		key->arr[i] = key->arr[j];
55231946Smm		key->arr[j] = tmp;
56168404Spjd	}
57168404Spjd	key->i = 0;
58168404Spjd	key->j = 0;
59168404Spjd
60168404Spjd/* EXPORT DELETE END */
61168404Spjd}
62
63
64/*
65 * Encipher 'in' using 'key.
66 * in and out can point to the same location
67 */
68void
69arcfour_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