xref: /titanic_50/usr/src/common/crypto/arcfour/sun4v/arcfour_crypt.c (revision 694c35faa87b858ecdadfe4fc592615f4eefbb07)
1554ff184Skais /*
2554ff184Skais  * CDDL HEADER START
3554ff184Skais  *
4554ff184Skais  * The contents of this file are subject to the terms of the
5b6c3f786Sbubbva  * Common Development and Distribution License (the "License").
6b6c3f786Sbubbva  * You may not use this file except in compliance with the License.
7554ff184Skais  *
8554ff184Skais  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9554ff184Skais  * or http://www.opensolaris.org/os/licensing.
10554ff184Skais  * See the License for the specific language governing permissions
11554ff184Skais  * and limitations under the License.
12554ff184Skais  *
13554ff184Skais  * When distributing Covered Code, include this CDDL HEADER in each
14554ff184Skais  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15554ff184Skais  * If applicable, add the following below this CDDL HEADER, with the
16554ff184Skais  * fields enclosed by brackets "[]" replaced with your own identifying
17554ff184Skais  * information: Portions Copyright [yyyy] [name of copyright owner]
18554ff184Skais  *
19554ff184Skais  * CDDL HEADER END
20554ff184Skais  */
21*726fad2aSDina K Nimeh 
22554ff184Skais /*
23*726fad2aSDina K Nimeh  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24554ff184Skais  */
25554ff184Skais 
26554ff184Skais #include "../arcfour.h"
27554ff184Skais 
28554ff184Skais /* Initialize the key stream 'key' using the key value */
29554ff184Skais void
arcfour_key_init(ARCFour_key * key,uchar_t * keyval,int keyvallen)30554ff184Skais arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen)
31554ff184Skais {
32554ff184Skais 	uchar_t ext_keyval[256];
33554ff184Skais 	uchar_t tmp;
34554ff184Skais 	int i, j;
35554ff184Skais 
36554ff184Skais 	for (i = j = 0; i < 256; i++, j++) {
37554ff184Skais 		if (j == keyvallen)
38554ff184Skais 			j = 0;
39554ff184Skais 
40554ff184Skais 		ext_keyval[i] = keyval[j];
41554ff184Skais 	}
42554ff184Skais 	for (i = 0; i < 256; i++)
43554ff184Skais 		key->arr[i] = (uchar_t)i;
44554ff184Skais 
45554ff184Skais 	j = 0;
46554ff184Skais 	for (i = 0; i < 256; i++) {
47554ff184Skais 		j = (j + key->arr[i] + ext_keyval[i]) % 256;
48554ff184Skais 		tmp = key->arr[i];
49554ff184Skais 		key->arr[i] = key->arr[j];
50554ff184Skais 		key->arr[j] = tmp;
51554ff184Skais 	}
52554ff184Skais 	key->i = 0;
53554ff184Skais 	key->j = 0;
54554ff184Skais }
55554ff184Skais 
56554ff184Skais 
57554ff184Skais /*
58554ff184Skais  * Encipher 'in' using 'key.
59554ff184Skais  * in and out can point to the same location
60554ff184Skais  */
61554ff184Skais void
arcfour_crypt(ARCFour_key * key,uchar_t * in,uchar_t * out,size_t len)62554ff184Skais arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len)
63554ff184Skais {
6471269a22SAnthony Scarpino 	size_t ii;
6571269a22SAnthony Scarpino 	unsigned long long in0, merge = 0, merge0 = 0, merge1, mask = 0;
66554ff184Skais 	uchar_t i, j, *base, jj, *base1, tmp;
6771269a22SAnthony Scarpino 	unsigned int tmp0, tmp1, i_accum, shift = 0, i1;
68554ff184Skais 
69554ff184Skais 	int index;
70554ff184Skais 
71554ff184Skais 	base = key->arr;
72554ff184Skais 
73b6c3f786Sbubbva 	index = (((uintptr_t)in) & 0x7);
74554ff184Skais 
75554ff184Skais 	/* Get the 'in' on an 8-byte alignment */
76554ff184Skais 	if (index > 0) {
77554ff184Skais 		i = key->i;
78554ff184Skais 		j = key->j;
79b6c3f786Sbubbva 
80b6c3f786Sbubbva 		for (index = 8 - index; (index-- > 0) && len > 0;
81554ff184Skais 		    len--, in++, out++) {
82b6c3f786Sbubbva 
83554ff184Skais 			i = i + 1;
84554ff184Skais 			j = j + key->arr[i];
85554ff184Skais 			tmp = key->arr[i];
86554ff184Skais 			key->arr[i] = key->arr[j];
87554ff184Skais 			key->arr[j] = tmp;
88554ff184Skais 			tmp = key->arr[i] + key->arr[j];
89554ff184Skais 			*out = *in ^ key->arr[tmp];
90554ff184Skais 		}
91554ff184Skais 		key->i = i;
92554ff184Skais 		key->j = j;
93554ff184Skais 
94554ff184Skais 	}
95554ff184Skais 	if (len == 0)
96554ff184Skais 		return;
97554ff184Skais 
98554ff184Skais 	/* See if we're fortunate and 'out' got aligned as well */
99554ff184Skais 
100554ff184Skais 
101554ff184Skais 	/*
102554ff184Skais 	 * Niagara optimized version for
103554ff184Skais 	 * the cases where the input and output  buffers are aligned on
104554ff184Skais 	 * a multiple of 8-byte boundary.
105554ff184Skais 	 */
106554ff184Skais #ifdef	sun4v
107b6c3f786Sbubbva 	if ((((uintptr_t)out) & 7) != 0) {
108554ff184Skais #endif	/* sun4v */
109554ff184Skais 		i = key->i;
110554ff184Skais 		j = key->j;
111554ff184Skais 		for (ii = 0; ii < len; ii++) {
112554ff184Skais 			i = i + 1;
113554ff184Skais 			tmp0 = base[i];
114554ff184Skais 			j = j + tmp0;
115554ff184Skais 			tmp1 = base[j];
116*726fad2aSDina K Nimeh 			base[i] = (uchar_t)tmp1;
117*726fad2aSDina K Nimeh 			base[j] = (uchar_t)tmp0;
118554ff184Skais 			tmp0 += tmp1;
119554ff184Skais 			tmp0 = tmp0 & 0xff;
120554ff184Skais 			out[ii] = in[ii] ^ base[tmp0];
121554ff184Skais 		}
122554ff184Skais 		key->i = i;
123554ff184Skais 		key->j = j;
124554ff184Skais #ifdef	sun4v
125554ff184Skais 	} else {
126554ff184Skais 		i = key->i;
127554ff184Skais 		j = key->j;
128554ff184Skais 
129554ff184Skais 		/*
130554ff184Skais 		 * Want to align base[i] on a 2B boundary -- allows updates
131554ff184Skais 		 * via [i] to be performed in 2B chunks (reducing # of stores).
132554ff184Skais 		 * Requires appropriate alias detection.
133554ff184Skais 		 */
134554ff184Skais 
135554ff184Skais 		if (((i+1) % 2) != 0) {
136554ff184Skais 			i = i + 1;
137554ff184Skais 			tmp0 = base[i];
138554ff184Skais 			j = j + tmp0;
139554ff184Skais 			tmp1 = base[j];
140554ff184Skais 
141*726fad2aSDina K Nimeh 			base[i] = (uchar_t)tmp1;
142*726fad2aSDina K Nimeh 			base[j] = (uchar_t)tmp0;
143554ff184Skais 
144554ff184Skais 			tmp0 += tmp1;
145554ff184Skais 			tmp0 = tmp0 & 0xff;
146554ff184Skais 
147554ff184Skais 			merge0 = (unsigned long long)(base[tmp0]) << 56;
148554ff184Skais 			shift = 8; mask = 0xff;
149554ff184Skais 		}
150554ff184Skais 
151554ff184Skais 		/*
152554ff184Skais 		 * Note - in and out may now be misaligned -
153554ff184Skais 		 * as updating [out] in 8B chunks need to handle this
154554ff184Skais 		 * possibility. Also could have a 1B overrun.
155554ff184Skais 		 * Need to drop out of loop early as a result.
156554ff184Skais 		 */
157554ff184Skais 
158554ff184Skais 		for (ii = 0, i1 = i; ii < ((len-1)  & (~7));
159554ff184Skais 		    ii += 8, i1 = i1&0xff) {
160554ff184Skais 
161554ff184Skais 			/*
162554ff184Skais 			 * If i < less than 248, know wont wrap around
163554ff184Skais 			 * (i % 256), so don't need to bother with masking i
164554ff184Skais 			 * after each increment
165554ff184Skais 			 */
166554ff184Skais 			if (i1 < 248) {
167554ff184Skais 
168554ff184Skais 				/* BYTE 0 */
169554ff184Skais 				i1 = (i1 + 1);
170554ff184Skais 
171554ff184Skais 				/*
172554ff184Skais 				 * Creating this base pointer reduces subsequent
173554ff184Skais 				 * arihmetic ops required to load [i]
174554ff184Skais 				 *
175554ff184Skais 				 * N.B. don't need to check if [j] aliases.
176554ff184Skais 				 * [i] and [j] end up with the same values
177554ff184Skais 				 * anyway.
178554ff184Skais 				 */
179554ff184Skais 				base1 = &base[i1];
180554ff184Skais 
181554ff184Skais 				tmp0 = base1[0];
182554ff184Skais 				j = j + tmp0;
183554ff184Skais 
184554ff184Skais 				tmp1 = base[j];
185554ff184Skais 				/*
186554ff184Skais 				 * Don't store [i] yet
187554ff184Skais 				 */
188554ff184Skais 				i_accum = tmp1;
189*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
190554ff184Skais 
191554ff184Skais 				tmp0 += tmp1;
192554ff184Skais 				tmp0 = tmp0 & 0xff;
193554ff184Skais 
194554ff184Skais 				/*
195554ff184Skais 				 * Check [tmp0] doesn't alias with [i]
196554ff184Skais 				 */
197554ff184Skais 
198554ff184Skais 				/*
199554ff184Skais 				 * Updating [out] in 8B chunks
200554ff184Skais 				 */
201554ff184Skais 				if (i1 == tmp0) {
202554ff184Skais 					merge =
203554ff184Skais 					    (unsigned long long)(i_accum) << 56;
204554ff184Skais 				} else {
205554ff184Skais 					merge =
206554ff184Skais 					    (unsigned long long)(base[tmp0]) <<
207554ff184Skais 					    56;
208554ff184Skais 				}
209554ff184Skais 
210554ff184Skais 				/* BYTE 1 */
211554ff184Skais 				tmp0 = base1[1];
212554ff184Skais 
213554ff184Skais 				j = j + tmp0;
214554ff184Skais 
215554ff184Skais 				/*
216554ff184Skais 				 * [j] can now alias with [i] and [i-1]
217554ff184Skais 				 * If alias abort speculation
218554ff184Skais 				 */
219554ff184Skais 				if ((i1 ^ j) < 2) {
220*726fad2aSDina K Nimeh 					base1[0] = (uchar_t)i_accum;
221554ff184Skais 
222554ff184Skais 					tmp1 = base[j];
223554ff184Skais 
224*726fad2aSDina K Nimeh 					base1[1] = (uchar_t)tmp1;
225*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
226554ff184Skais 
227554ff184Skais 					tmp0 += tmp1;
228554ff184Skais 					tmp0 = tmp0 & 0xff;
229554ff184Skais 
230554ff184Skais 					merge |= (unsigned long long)
231554ff184Skais 					    (base[tmp0]) << 48;
232554ff184Skais 				} else {
233554ff184Skais 
234554ff184Skais 					tmp1 = base[j];
235554ff184Skais 
236554ff184Skais 					i_accum = i_accum << 8;
237554ff184Skais 					i_accum |= tmp1;
238554ff184Skais 
239*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
240554ff184Skais 
241554ff184Skais 					tmp0 += tmp1;
242554ff184Skais 					tmp0 = tmp0 & 0xff;
243554ff184Skais 
244554ff184Skais 					/*
245554ff184Skais 					 * Speculation suceeded! Update [i]
246554ff184Skais 					 * in 2B chunk
247554ff184Skais 					 */
24871269a22SAnthony Scarpino 					/* LINTED E_BAD_PTR_CAST_ALIGN */
249554ff184Skais 					*((unsigned short *) &base[i1]) =
250554ff184Skais 					    i_accum;
251554ff184Skais 
252554ff184Skais 					merge |=
253554ff184Skais 					    (unsigned long long)(base[tmp0]) <<
254554ff184Skais 					    48;
255554ff184Skais 				}
256554ff184Skais 
257554ff184Skais 
258554ff184Skais 				/*
259554ff184Skais 				 * Too expensive to perform [i] speculation for
260554ff184Skais 				 * every byte. Just need to reduce frequency
261554ff184Skais 				 * of stores until store buffer full stalls
262554ff184Skais 				 * are not the bottleneck.
263554ff184Skais 				 */
264554ff184Skais 
265554ff184Skais 				/* BYTE 2 */
266554ff184Skais 				tmp0 = base1[2];
267554ff184Skais 				j = j + tmp0;
268554ff184Skais 				tmp1 = base[j];
269*726fad2aSDina K Nimeh 				base1[2] = (uchar_t)tmp1;
270*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
271554ff184Skais 				tmp1 += tmp0;
272554ff184Skais 				tmp1 = tmp1 & 0xff;
273554ff184Skais 				merge |= (unsigned long long)(base[tmp1]) << 40;
274554ff184Skais 
275554ff184Skais 				/* BYTE 3 */
276554ff184Skais 				tmp0 = base1[3];
277554ff184Skais 				j = j + tmp0;
278554ff184Skais 				tmp1 = base[j];
279*726fad2aSDina K Nimeh 				base1[3] = (uchar_t)tmp1;
280*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
281554ff184Skais 				tmp0 += tmp1;
282554ff184Skais 				tmp0 = tmp0 & 0xff;
283554ff184Skais 				merge |= (unsigned long long)(base[tmp0]) << 32;
284554ff184Skais 
285554ff184Skais 				/* BYTE 4 */
286554ff184Skais 				tmp0 = base1[4];
287554ff184Skais 				j = j + tmp0;
288554ff184Skais 				tmp1 = base[j];
289*726fad2aSDina K Nimeh 				base1[4] = (uchar_t)tmp1;
290*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
291554ff184Skais 				tmp0 += tmp1;
292554ff184Skais 				tmp0 = tmp0 & 0xff;
293554ff184Skais 				merge |= (unsigned long long)(base[tmp0]) << 24;
294554ff184Skais 
295554ff184Skais 				/* BYTE 5 */
296554ff184Skais 				tmp0 = base1[5];
297554ff184Skais 				j = j + tmp0;
298554ff184Skais 				tmp1 = base[j];
299*726fad2aSDina K Nimeh 				base1[5] = (uchar_t)tmp1;
300*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
301554ff184Skais 				tmp0 += tmp1;
302554ff184Skais 				tmp0 = tmp0 & 0xff;
303554ff184Skais 				merge |= (unsigned long long)(base[tmp0]) << 16;
304554ff184Skais 
305554ff184Skais 				/* BYTE 6 */
306554ff184Skais 				i1 = (i1+6);
307554ff184Skais 				tmp0 = base1[6];
308554ff184Skais 				j = j + tmp0;
309554ff184Skais 				tmp1 = base[j];
310554ff184Skais 				i_accum = tmp1;
311*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
312554ff184Skais 
313554ff184Skais 				tmp0 += tmp1;
314554ff184Skais 				tmp0 = tmp0 & 0xff;
315554ff184Skais 
316554ff184Skais 				if (i1 == tmp0) {
317554ff184Skais 					merge |=
318554ff184Skais 					    (unsigned long long)(i_accum) << 8;
319554ff184Skais 				} else {
320554ff184Skais 					merge |=
321554ff184Skais 					    (unsigned long long)(base[tmp0]) <<
322554ff184Skais 					    8;
323554ff184Skais 				}
324554ff184Skais 
325554ff184Skais 				/* BYTE 7 */
326554ff184Skais 				tmp0 = base1[7];
327554ff184Skais 
328554ff184Skais 				/*
329554ff184Skais 				 * Perform [i] speculation again. Indentical
330554ff184Skais 				 * to that performed for BYTE0 and BYTE1.
331554ff184Skais 				 */
332554ff184Skais 				j = j + tmp0;
333554ff184Skais 				if ((i1 ^ j) < 2) {
334*726fad2aSDina K Nimeh 					base1[6] = (uchar_t)i_accum;
335554ff184Skais 					tmp1 = base[j];
336554ff184Skais 
337*726fad2aSDina K Nimeh 					base1[7] = (uchar_t)tmp1;
338*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
339554ff184Skais 
340554ff184Skais 					tmp0 += tmp1;
341554ff184Skais 					tmp0 = tmp0 & 0xff;
342554ff184Skais 
343554ff184Skais 					merge |=
344554ff184Skais 					    (unsigned long long)(base[tmp0]);
345554ff184Skais 
346554ff184Skais 				} else {
347554ff184Skais 					tmp1 = base[j];
348554ff184Skais 
349554ff184Skais 					i_accum = i_accum << 8;
350554ff184Skais 					i_accum |= tmp1;
351554ff184Skais 
352*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
353554ff184Skais 
354554ff184Skais 					tmp0 += tmp1;
355554ff184Skais 					tmp0 = tmp0 & 0xff;
356554ff184Skais 
35771269a22SAnthony Scarpino 					/* LINTED E_BAD_PTR_CAST_ALIGN */
358554ff184Skais 					*((unsigned short *) &base[i1]) =
359554ff184Skais 					    i_accum;
360554ff184Skais 
361554ff184Skais 					merge |=
362554ff184Skais 					    (unsigned long long)(base[tmp0]);
363554ff184Skais 				}
364554ff184Skais 				i1++;
365554ff184Skais 			} else {
366554ff184Skais 				/*
367554ff184Skais 				 * i is too close to wrap-around to allow
368554ff184Skais 				 * masking to be disregarded
369554ff184Skais 				 */
370554ff184Skais 
371554ff184Skais 				/*
372554ff184Skais 				 * Same old speculation for BYTE 0 and BYTE 1
373554ff184Skais 				 */
374554ff184Skais 
375554ff184Skais 				/* BYTE 0 */
376554ff184Skais 				i1 = (i1 + 1) & 0xff;
377*726fad2aSDina K Nimeh 				jj = (uchar_t)i1;
378554ff184Skais 
379554ff184Skais 				tmp0 = base[i1];
380554ff184Skais 				j = j + tmp0;
381554ff184Skais 
382554ff184Skais 				tmp1 = base[j];
383554ff184Skais 				i_accum = tmp1;
384*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
385554ff184Skais 
386554ff184Skais 				tmp0 += tmp1;
387554ff184Skais 				tmp0 = tmp0 & 0xff;
388554ff184Skais 
389554ff184Skais 				if (i1 == tmp0) {
390554ff184Skais 					merge =
391554ff184Skais 					    (unsigned long long)(i_accum) << 56;
392554ff184Skais 				} else {
393554ff184Skais 					merge =
394554ff184Skais 					    (unsigned long long)(base[tmp0]) <<
395554ff184Skais 					    56;
396554ff184Skais 				}
397554ff184Skais 
398554ff184Skais 				/* BYTE 1 */
399554ff184Skais 				tmp0 = base[i1+1];
400554ff184Skais 
401554ff184Skais 				j = j + tmp0;
402554ff184Skais 
403554ff184Skais 				if ((jj ^ j) < 2) {
404*726fad2aSDina K Nimeh 					base[jj] = (uchar_t)i_accum;
405554ff184Skais 
406554ff184Skais 					tmp1 = base[j];
407554ff184Skais 
408*726fad2aSDina K Nimeh 					base[i1+1] = (uchar_t)tmp1;
409*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
410554ff184Skais 
411554ff184Skais 					tmp0 += tmp1;
412554ff184Skais 					tmp0 = tmp0 & 0xff;
413554ff184Skais 
414554ff184Skais 					merge |=
415554ff184Skais 					    (unsigned long long)(base[tmp0]) <<
416554ff184Skais 					    48;
417554ff184Skais 				} else {
418554ff184Skais 
419554ff184Skais 					tmp1 = base[j];
420554ff184Skais 
421554ff184Skais 					i_accum = i_accum << 8;
422554ff184Skais 					i_accum |= tmp1;
423554ff184Skais 
424*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
425554ff184Skais 
426554ff184Skais 					tmp0 += tmp1;
427554ff184Skais 					tmp0 = tmp0 & 0xff;
428554ff184Skais 
42971269a22SAnthony Scarpino 					/* LINTED E_BAD_PTR_CAST_ALIGN */
430554ff184Skais 					*((unsigned short *) &base[jj]) =
431554ff184Skais 					    i_accum;
432554ff184Skais 
433554ff184Skais 					merge |=
434554ff184Skais 					    (unsigned long long)(base[tmp0]) <<
435554ff184Skais 					    48;
436554ff184Skais 				}
437554ff184Skais 
438554ff184Skais 				/* BYTE 2 */
439554ff184Skais 				/*
440554ff184Skais 				 * As know i must be even when enter loop (to
441554ff184Skais 				 * satisfy alignment), can only wrap around
442554ff184Skais 				 * on the even bytes. So just need to perform
443554ff184Skais 				 * mask every 2nd byte
444554ff184Skais 				 */
445554ff184Skais 				i1 = (i1 + 2) & 0xff;
446554ff184Skais 				tmp0 = base[i1];
447554ff184Skais 				j = j + tmp0;
448554ff184Skais 				tmp1 = base[j];
449*726fad2aSDina K Nimeh 				base[i1] = (uchar_t)tmp1;
450*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
451554ff184Skais 				tmp0 += tmp1;
452554ff184Skais 				tmp0 = tmp0 & 0xff;
453554ff184Skais 				merge |= (unsigned long long)(base[tmp0]) << 40;
454554ff184Skais 
455554ff184Skais 				/* BYTE 3 */
456554ff184Skais 				tmp0 = base[i1+1];
457554ff184Skais 				j = j + tmp0;
458554ff184Skais 				tmp1 = base[j];
459*726fad2aSDina K Nimeh 				base[i1+1] = (uchar_t)tmp1;
460*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
461554ff184Skais 				tmp0 += tmp1;
462554ff184Skais 				tmp0 = tmp0 & 0xff;
463554ff184Skais 				merge |= (unsigned long long)(base[tmp0]) << 32;
464554ff184Skais 
465554ff184Skais 				/* BYTE 4 */
466554ff184Skais 				i1 = (i1 + 2) & 0xff;
467554ff184Skais 				tmp0 = base[i1];
468554ff184Skais 				j = j + tmp0;
469554ff184Skais 				tmp1 = base[j];
470*726fad2aSDina K Nimeh 				base[i1] = (uchar_t)tmp1;
471*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
472554ff184Skais 				tmp0 += tmp1;
473554ff184Skais 				tmp0 = tmp0 & 0xff;
474554ff184Skais 				merge |= (unsigned long long)(base[tmp0]) << 24;
475554ff184Skais 
476554ff184Skais 				/* BYTE 5 */
477554ff184Skais 				tmp0 = base[i1+1];
478554ff184Skais 				j = j + tmp0;
479554ff184Skais 				tmp1 = base[j];
480*726fad2aSDina K Nimeh 				base[i1+1] = (uchar_t)tmp1;
481*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
482554ff184Skais 				tmp0 += tmp1;
483554ff184Skais 				tmp0 = tmp0 & 0xff;
484554ff184Skais 				merge |= (unsigned long long)(base[tmp0]) << 16;
485554ff184Skais 
486554ff184Skais 				/* BYTE 6 */
487554ff184Skais 				i1 = (i1+2) &0xff;
488*726fad2aSDina K Nimeh 				jj = (uchar_t)i1;
489554ff184Skais 				tmp0 = base[i1];
490554ff184Skais 
491554ff184Skais 				j = j + tmp0;
492554ff184Skais 
493554ff184Skais 				tmp1 = base[j];
494554ff184Skais 				i_accum = tmp1;
495*726fad2aSDina K Nimeh 				base[j] = (uchar_t)tmp0;
496554ff184Skais 
497554ff184Skais 
498554ff184Skais 				tmp0 += tmp1;
499554ff184Skais 				tmp0 = tmp0 & 0xff;
500554ff184Skais 
501554ff184Skais 				if (i1 == tmp0) {
502554ff184Skais 					merge |=
503554ff184Skais 					    (unsigned long long)(i_accum) << 8;
504554ff184Skais 				} else {
505554ff184Skais 					merge |=
506554ff184Skais 					    (unsigned long long)(base[tmp0]) <<
507554ff184Skais 					    8;
508554ff184Skais 				}
509554ff184Skais 
510554ff184Skais 				/* BYTE 7 */
511554ff184Skais 				i1++;
512554ff184Skais 				tmp0 = base[i1];
513554ff184Skais 
514554ff184Skais 				j = j + tmp0;
515554ff184Skais 				if ((jj ^ j) < 2) {
516*726fad2aSDina K Nimeh 					base[jj] = (uchar_t)i_accum;
517554ff184Skais 					tmp1 = base[j];
518554ff184Skais 
519*726fad2aSDina K Nimeh 					base[i1] = (uchar_t)tmp1;
520*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
521554ff184Skais 
522554ff184Skais 					tmp0 += tmp1;
523554ff184Skais 					tmp0 = tmp0 & 0xff;
524554ff184Skais 
525554ff184Skais 					merge |=
526554ff184Skais 					    (unsigned long long)(base[tmp0]);
527554ff184Skais 
528554ff184Skais 				} else {
52971269a22SAnthony Scarpino 
530554ff184Skais 					tmp1 = base[j];
531554ff184Skais 
532554ff184Skais 					i_accum = i_accum << 8;
533554ff184Skais 					i_accum |= tmp1;
534554ff184Skais 
535*726fad2aSDina K Nimeh 					base[j] = (uchar_t)tmp0;
536554ff184Skais 
537554ff184Skais 					tmp0 += tmp1;
538554ff184Skais 					tmp0 = tmp0 & 0xff;
539554ff184Skais 
54071269a22SAnthony Scarpino 					/* LINTED E_BAD_PTR_CAST_ALIGN */
541554ff184Skais 					*((unsigned short *) &base[jj]) =
542554ff184Skais 					    i_accum;
543554ff184Skais 
544554ff184Skais 					merge |=
545554ff184Skais 					    (unsigned long long)(base[tmp0]);
546554ff184Skais 				}
547554ff184Skais 			}
548554ff184Skais 
549554ff184Skais 			/*
550554ff184Skais 			 * Perform update to [out]
551554ff184Skais 			 * Remember could be alignment issues
552554ff184Skais 			 */
55371269a22SAnthony Scarpino 			/* LINTED E_BAD_PTR_CAST_ALIGN */
554554ff184Skais 			in0 = *((unsigned long long *) (&in[ii]));
555554ff184Skais 
556554ff184Skais 			merge1 = merge0 | (merge >> shift);
557554ff184Skais 
558554ff184Skais 			merge0 = (merge & mask) << 56;
559554ff184Skais 
560554ff184Skais 			in0 = in0 ^ merge1;
561554ff184Skais 
56271269a22SAnthony Scarpino 			/* LINTED E_BAD_PTR_CAST_ALIGN */
563554ff184Skais 			*((unsigned long long *) (&out[ii])) = in0;
564554ff184Skais 		}
565554ff184Skais 
566*726fad2aSDina K Nimeh 		i = (uchar_t)i1;
567554ff184Skais 
568554ff184Skais 		/*
569554ff184Skais 		 * Handle any overrun
570554ff184Skais 		 */
571554ff184Skais 		if (shift) {
572554ff184Skais 			out[ii] = in[ii] ^ (merge0 >> 56);
573554ff184Skais 			ii++;
574554ff184Skais 		}
575554ff184Skais 
576554ff184Skais 		/*
577554ff184Skais 		 * Handle final few bytes
578554ff184Skais 		 */
579554ff184Skais 		for (; ii < len; ii++) {
580554ff184Skais 			i = i + 1;
581554ff184Skais 			tmp0 = base[i];
582554ff184Skais 			j = j + tmp0;
583554ff184Skais 			tmp1 = base[j];
584554ff184Skais 
585*726fad2aSDina K Nimeh 			base[i] = (uchar_t)tmp1;
586*726fad2aSDina K Nimeh 			base[j] = (uchar_t)tmp0;
587554ff184Skais 
588554ff184Skais 			tmp0 += tmp1;
589554ff184Skais 			tmp0 = tmp0 & 0xff;
590554ff184Skais 			out[ii] = in[ii] ^ base[tmp0];
591554ff184Skais 		}
592554ff184Skais 		key->i = i;
593554ff184Skais 		key->j = j;
594554ff184Skais 	}
595554ff184Skais #endif /* sun4v */
596554ff184Skais }
597