]>
git.saurik.com Git - apple/security.git/blob - AppleCSP/open_ssl/misc/rc4_enc.c
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
19 /* crypto/rc4/rc4_enc.c */
20 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
21 * All rights reserved.
23 * This package is an SSL implementation written
24 * by Eric Young (eay@cryptsoft.com).
25 * The implementation was written so as to conform with Netscapes SSL.
27 * This library is free for commercial and non-commercial use as long as
28 * the following conditions are aheared to. The following conditions
29 * apply to all code found in this distribution, be it the RC4, RSA,
30 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
31 * included with this distribution is covered by the same copyright terms
32 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
34 * Copyright remains Eric Young's, and as such any Copyright notices in
35 * the code are not to be removed.
36 * If this package is used in a product, Eric Young should be given attribution
37 * as the author of the parts of the library used.
38 * This can be in the form of a textual message at program startup or
39 * in documentation (online or textual) provided with the package.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * "This product includes cryptographic software written by
52 * Eric Young (eay@cryptsoft.com)"
53 * The word 'cryptographic' can be left out if the rouines from the library
54 * being used are not cryptographic related :-).
55 * 4. If you include any Windows specific code (or a derivative thereof) from
56 * the apps directory (application code) you must include an acknowledgement:
57 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
59 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * The licence and distribution terms for any publically available version or
72 * derivative of this code cannot be changed. i.e. this code cannot simply be
73 * copied and put under another distribution licence
74 * [including the GNU Public Licence.]
77 #include <openssl/rc4.h>
79 /* RC4 as implemented from a posting from
80 * Newsgroups: sci.crypt
81 * From: sterndark@netcom.com (David Sterndark)
82 * Subject: RC4 Algorithm revealed.
83 * Message-ID: <sternCvKL4B.Hyy@netcom.com>
84 * Date: Wed, 14 Sep 1994 06:35:31 GMT
87 void RC4(RC4_KEY
*key
, unsigned long len
, const unsigned char *indata
,
88 unsigned char *outdata
)
91 register RC4_INT x
,y
,tx
,ty
;
98 #if defined(RC4_CHUNK)
100 * The original reason for implementing this(*) was the fact that
101 * pre-21164a Alpha CPUs don't have byte load/store instructions
102 * and e.g. a byte store has to be done with 64-bit load, shift,
103 * and, or and finally 64-bit store. Peaking data and operating
104 * at natural word size made it possible to reduce amount of
105 * instructions as well as to perform early read-ahead without
106 * suffering from RAW (read-after-write) hazard. This resulted
107 * in ~40%(**) performance improvement on 21064 box with gcc.
108 * But it's not only Alpha users who win here:-) Thanks to the
109 * early-n-wide read-ahead this implementation also exhibits
110 * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending
111 * on sizeof(RC4_INT)).
113 * (*) "this" means code which recognizes the case when input
114 * and output pointers appear to be aligned at natural CPU
116 * (**) i.e. according to 'apps/openssl speed rc4' benchmark,
117 * crypto/rc4/rc4speed.c exhibits almost 70% speed-up...
121 * - RC4_CHUNK="unsigned long long" should be a #1 choice for
122 * UltraSPARC. Unfortunately gcc generates very slow code
123 * (2.5-3 times slower than one generated by Sun's WorkShop
124 * C) and therefore gcc (at least 2.95 and earlier) should
125 * always be told that RC4_CHUNK="unsigned long".
127 * <appro@fy.chalmers.se>
130 # define RC4_STEP ( \
137 (RC4_CHUNK)d[(tx+ty)&0xff]\
140 if ( ( ((unsigned long)indata
& (sizeof(RC4_CHUNK
)-1)) |
141 ((unsigned long)outdata
& (sizeof(RC4_CHUNK
)-1)) ) == 0 )
143 RC4_CHUNK ichunk
,otp
;
144 const union { long one
; char little
; } is_endian
= {1};
147 * I reckon we can afford to implement both endian
148 * cases and to decide which way to take at run-time
149 * because the machine code appears to be very compact
150 * and redundant 1-2KB is perfectly tolerable (i.e.
151 * in case the compiler fails to eliminate it:-). By
152 * suggestion from Terrel Larson <terr@terralogic.net>
153 * who also stands for the is_endian union:-)
157 * - is_endian is declared automatic as doing otherwise
158 * (declaring static) prevents gcc from eliminating
159 * the redundant code;
160 * - compilers (those I've tried) don't seem to have
161 * problems eliminating either the operators guarded
162 * by "if (sizeof(RC4_CHUNK)==8)" or the condition
163 * expressions themselves so I've got 'em to replace
164 * corresponding #ifdefs from the previous version;
165 * - I chose to let the redundant switch cases when
166 * sizeof(RC4_CHUNK)!=8 be (were also #ifdefed
168 * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in
169 * [LB]ESHFT guards against "shift is out of range"
170 * warnings when sizeof(RC4_CHUNK)!=8
172 * <appro@fy.chalmers.se>
174 if (!is_endian
.little
)
175 { /* BIG-ENDIAN CASE */
176 # define BESHFT(c) (((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1))
177 for (;len
&-sizeof(RC4_CHUNK
);len
-=sizeof(RC4_CHUNK
))
179 ichunk
= *(RC4_CHUNK
*)indata
;
180 otp
= RC4_STEP
<<BESHFT(0);
181 otp
|= RC4_STEP
<<BESHFT(1);
182 otp
|= RC4_STEP
<<BESHFT(2);
183 otp
|= RC4_STEP
<<BESHFT(3);
184 if (sizeof(RC4_CHUNK
)==8)
186 otp
|= RC4_STEP
<<BESHFT(4);
187 otp
|= RC4_STEP
<<BESHFT(5);
188 otp
|= RC4_STEP
<<BESHFT(6);
189 otp
|= RC4_STEP
<<BESHFT(7);
191 *(RC4_CHUNK
*)outdata
= otp
^ichunk
;
192 indata
+= sizeof(RC4_CHUNK
);
193 outdata
+= sizeof(RC4_CHUNK
);
197 RC4_CHUNK mask
=(RC4_CHUNK
)-1, ochunk
;
199 ichunk
= *(RC4_CHUNK
*)indata
;
200 ochunk
= *(RC4_CHUNK
*)outdata
;
203 mask
<<= (sizeof(RC4_CHUNK
)-len
)<<3;
204 switch (len
&(sizeof(RC4_CHUNK
)-1))
206 case 7: otp
= RC4_STEP
<<i
, i
-=8;
207 case 6: otp
|= RC4_STEP
<<i
, i
-=8;
208 case 5: otp
|= RC4_STEP
<<i
, i
-=8;
209 case 4: otp
|= RC4_STEP
<<i
, i
-=8;
210 case 3: otp
|= RC4_STEP
<<i
, i
-=8;
211 case 2: otp
|= RC4_STEP
<<i
, i
-=8;
212 case 1: otp
|= RC4_STEP
<<i
, i
-=8;
214 * it's never the case,
215 * but it has to be here
220 ochunk
|= (otp
^ichunk
) & mask
;
221 *(RC4_CHUNK
*)outdata
= ochunk
;
228 { /* LITTLE-ENDIAN CASE */
229 # define LESHFT(c) (((c)*8)&(sizeof(RC4_CHUNK)*8-1))
230 for (;len
&-sizeof(RC4_CHUNK
);len
-=sizeof(RC4_CHUNK
))
232 ichunk
= *(RC4_CHUNK
*)indata
;
237 if (sizeof(RC4_CHUNK
)==8)
239 otp
|= RC4_STEP
<<LESHFT(4);
240 otp
|= RC4_STEP
<<LESHFT(5);
241 otp
|= RC4_STEP
<<LESHFT(6);
242 otp
|= RC4_STEP
<<LESHFT(7);
244 *(RC4_CHUNK
*)outdata
= otp
^ichunk
;
245 indata
+= sizeof(RC4_CHUNK
);
246 outdata
+= sizeof(RC4_CHUNK
);
250 RC4_CHUNK mask
=(RC4_CHUNK
)-1, ochunk
;
252 ichunk
= *(RC4_CHUNK
*)indata
;
253 ochunk
= *(RC4_CHUNK
*)outdata
;
256 mask
>>= (sizeof(RC4_CHUNK
)-len
)<<3;
257 switch (len
&(sizeof(RC4_CHUNK
)-1))
259 case 7: otp
= RC4_STEP
, i
+=8;
260 case 6: otp
|= RC4_STEP
<<i
, i
+=8;
261 case 5: otp
|= RC4_STEP
<<i
, i
+=8;
262 case 4: otp
|= RC4_STEP
<<i
, i
+=8;
263 case 3: otp
|= RC4_STEP
<<i
, i
+=8;
264 case 2: otp
|= RC4_STEP
<<i
, i
+=8;
265 case 1: otp
|= RC4_STEP
<<i
, i
+=8;
267 * it's never the case,
268 * but it has to be here
273 ochunk
|= (otp
^ichunk
) & mask
;
274 *(RC4_CHUNK
*)outdata
= ochunk
;
279 } /* little-endian */
282 #define LOOP(in,out) \
288 (out) = d[(tx+ty)&0xff]^ (in);
291 #define RC4_LOOP(a,b,i) LOOP(*((a)++),*((b)++))
293 #define RC4_LOOP(a,b,i) LOOP(a[i],b[i])
301 RC4_LOOP(indata
,outdata
,0);
302 RC4_LOOP(indata
,outdata
,1);
303 RC4_LOOP(indata
,outdata
,2);
304 RC4_LOOP(indata
,outdata
,3);
305 RC4_LOOP(indata
,outdata
,4);
306 RC4_LOOP(indata
,outdata
,5);
307 RC4_LOOP(indata
,outdata
,6);
308 RC4_LOOP(indata
,outdata
,7);
321 RC4_LOOP(indata
,outdata
,0); if (--i
== 0) break;
322 RC4_LOOP(indata
,outdata
,1); if (--i
== 0) break;
323 RC4_LOOP(indata
,outdata
,2); if (--i
== 0) break;
324 RC4_LOOP(indata
,outdata
,3); if (--i
== 0) break;
325 RC4_LOOP(indata
,outdata
,4); if (--i
== 0) break;
326 RC4_LOOP(indata
,outdata
,5); if (--i
== 0) break;
327 RC4_LOOP(indata
,outdata
,6); if (--i
== 0) break;