xref: /onnv-gate/usr/src/common/crypto/arcfour/arcfour_crypt.c (revision 6281:abaa1bb4fbe5)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55764Sda73024  * Common Development and Distribution License (the "License").
65764Sda73024  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
225764Sda73024  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include "arcfour.h"
290Sstevel@tonic-gate 
305764Sda73024 #if defined(__amd64)
31*6281Sda73024 #ifdef _KERNEL
32*6281Sda73024 #include <sys/x86_archext.h>
33*6281Sda73024 #include <sys/cpuvar.h>
345764Sda73024 
35*6281Sda73024 #else
36*6281Sda73024 #include <sys/auxv.h>
37*6281Sda73024 #endif	/* _KERNEL */
38*6281Sda73024 #endif	/* __amd64 */
39*6281Sda73024 
40*6281Sda73024 #if !defined(__amd64)
410Sstevel@tonic-gate /* Initialize the key stream 'key' using the key value */
420Sstevel@tonic-gate void
430Sstevel@tonic-gate arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen)
440Sstevel@tonic-gate {
450Sstevel@tonic-gate /* EXPORT DELETE START */
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 	uchar_t ext_keyval[256];
480Sstevel@tonic-gate 	uchar_t tmp;
490Sstevel@tonic-gate 	int i, j;
500Sstevel@tonic-gate 
51*6281Sda73024 	/* Normalize key length to 256 */
520Sstevel@tonic-gate 	for (i = j = 0; i < 256; i++, j++) {
530Sstevel@tonic-gate 		if (j == keyvallen)
540Sstevel@tonic-gate 			j = 0;
550Sstevel@tonic-gate 		ext_keyval[i] = keyval[j];
560Sstevel@tonic-gate 	}
57*6281Sda73024 
580Sstevel@tonic-gate 	for (i = 0; i < 256; i++)
590Sstevel@tonic-gate 		key->arr[i] = (uchar_t)i;
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	j = 0;
620Sstevel@tonic-gate 	for (i = 0; i < 256; i++) {
630Sstevel@tonic-gate 		j = (j + key->arr[i] + ext_keyval[i]) % 256;
640Sstevel@tonic-gate 		tmp = key->arr[i];
650Sstevel@tonic-gate 		key->arr[i] = key->arr[j];
660Sstevel@tonic-gate 		key->arr[j] = tmp;
670Sstevel@tonic-gate 	}
680Sstevel@tonic-gate 	key->i = 0;
690Sstevel@tonic-gate 	key->j = 0;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate /* EXPORT DELETE END */
720Sstevel@tonic-gate }
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 
750Sstevel@tonic-gate /*
765764Sda73024  * Encipher 'in' using 'key'.
770Sstevel@tonic-gate  * in and out can point to the same location
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate void
800Sstevel@tonic-gate arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len)
810Sstevel@tonic-gate {
820Sstevel@tonic-gate 	size_t ii;
830Sstevel@tonic-gate 	uchar_t tmp, i, j;
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /* EXPORT DELETE START */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	/*
880Sstevel@tonic-gate 	 * The sun4u has a version of arcfour_crypt_aligned() hand-tuned for
890Sstevel@tonic-gate 	 * the cases where the input and output  buffers are aligned on
900Sstevel@tonic-gate 	 * a multiple of 8-byte boundary.
910Sstevel@tonic-gate 	 */
920Sstevel@tonic-gate #ifdef	sun4u
930Sstevel@tonic-gate 	int index;
940Sstevel@tonic-gate 
95416Skrishna 	index = (((uint64_t)(uintptr_t)in) & 0x7);
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	/* Get the 'in' on an 8-byte alignment */
980Sstevel@tonic-gate 	if (index > 0) {
990Sstevel@tonic-gate 		i = key->i;
1000Sstevel@tonic-gate 		j = key->j;
101416Skrishna 		for (index = 8 - (uint64_t)(uintptr_t)in & 0x7;
102416Skrishna 		    (index-- > 0) && len > 0;
1030Sstevel@tonic-gate 		    len--, in++, out++) {
1040Sstevel@tonic-gate 			i = i + 1;
1050Sstevel@tonic-gate 			j = j + key->arr[i];
1060Sstevel@tonic-gate 			tmp = key->arr[i];
1070Sstevel@tonic-gate 			key->arr[i] = key->arr[j];
1080Sstevel@tonic-gate 			key->arr[j] = tmp;
1090Sstevel@tonic-gate 			tmp = key->arr[i] + key->arr[j];
1100Sstevel@tonic-gate 			*out = *in ^ key->arr[tmp];
1110Sstevel@tonic-gate 		}
1120Sstevel@tonic-gate 		key->i = i;
1130Sstevel@tonic-gate 		key->j = j;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 	if (len == 0)
1170Sstevel@tonic-gate 		return;
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	/* See if we're fortunate and 'out' got aligned as well */
1200Sstevel@tonic-gate 
121416Skrishna 	if ((((uint64_t)(uintptr_t)out) & 7) != 0) {
1220Sstevel@tonic-gate #endif	/* sun4u */
1230Sstevel@tonic-gate 		i = key->i;
1240Sstevel@tonic-gate 		j = key->j;
1250Sstevel@tonic-gate 		for (ii = 0; ii < len; ii++) {
1260Sstevel@tonic-gate 			i = i + 1;
1270Sstevel@tonic-gate 			j = j + key->arr[i];
1280Sstevel@tonic-gate 			tmp = key->arr[i];
1290Sstevel@tonic-gate 			key->arr[i] = key->arr[j];
1300Sstevel@tonic-gate 			key->arr[j] = tmp;
1310Sstevel@tonic-gate 			tmp = key->arr[i] + key->arr[j];
1320Sstevel@tonic-gate 			out[ii] = in[ii] ^ key->arr[tmp];
1330Sstevel@tonic-gate 		}
1340Sstevel@tonic-gate 		key->i = i;
1350Sstevel@tonic-gate 		key->j = j;
1360Sstevel@tonic-gate #ifdef	sun4u
1370Sstevel@tonic-gate 	} else {
1380Sstevel@tonic-gate 		arcfour_crypt_aligned(key, len, in, out);
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate #endif	/* sun4u */
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /* EXPORT DELETE END */
1430Sstevel@tonic-gate }
144*6281Sda73024 
145*6281Sda73024 #else
146*6281Sda73024 
147*6281Sda73024 /*
148*6281Sda73024  * Return 1 if executing on Intel, otherwise 0 (e.g., AMD64).
149*6281Sda73024  */
150*6281Sda73024 int
151*6281Sda73024 arcfour_crypt_on_intel(void)
152*6281Sda73024 {
153*6281Sda73024 #ifdef _KERNEL
154*6281Sda73024 	return (cpuid_getvendor(CPU) == X86_VENDOR_Intel);
155*6281Sda73024 #else
156*6281Sda73024 	uint_t	ui;
157*6281Sda73024 	(void) getisax(&ui, 1);
158*6281Sda73024 	return ((ui & AV_386_AMD_MMX) == 0);
159*6281Sda73024 #endif	/* _KERNEL */
160*6281Sda73024 }
161*6281Sda73024 #endif	/* !__amd64 */
162