rc4_enc.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:10k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* crypto/rc4/rc4_enc.c */
  2. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  3.  * All rights reserved.
  4.  *
  5.  * This package is an SSL implementation written
  6.  * by Eric Young (eay@cryptsoft.com).
  7.  * The implementation was written so as to conform with Netscapes SSL.
  8.  * 
  9.  * This library is free for commercial and non-commercial use as long as
  10.  * the following conditions are aheared to.  The following conditions
  11.  * apply to all code found in this distribution, be it the RC4, RSA,
  12.  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  13.  * included with this distribution is covered by the same copyright terms
  14.  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15.  * 
  16.  * Copyright remains Eric Young's, and as such any Copyright notices in
  17.  * the code are not to be removed.
  18.  * If this package is used in a product, Eric Young should be given attribution
  19.  * as the author of the parts of the library used.
  20.  * This can be in the form of a textual message at program startup or
  21.  * in documentation (online or textual) provided with the package.
  22.  * 
  23.  * Redistribution and use in source and binary forms, with or without
  24.  * modification, are permitted provided that the following conditions
  25.  * are met:
  26.  * 1. Redistributions of source code must retain the copyright
  27.  *    notice, this list of conditions and the following disclaimer.
  28.  * 2. Redistributions in binary form must reproduce the above copyright
  29.  *    notice, this list of conditions and the following disclaimer in the
  30.  *    documentation and/or other materials provided with the distribution.
  31.  * 3. All advertising materials mentioning features or use of this software
  32.  *    must display the following acknowledgement:
  33.  *    "This product includes cryptographic software written by
  34.  *     Eric Young (eay@cryptsoft.com)"
  35.  *    The word 'cryptographic' can be left out if the rouines from the library
  36.  *    being used are not cryptographic related :-).
  37.  * 4. If you include any Windows specific code (or a derivative thereof) from 
  38.  *    the apps directory (application code) you must include an acknowledgement:
  39.  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40.  * 
  41.  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51.  * SUCH DAMAGE.
  52.  * 
  53.  * The licence and distribution terms for any publically available version or
  54.  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  55.  * copied and put under another distribution licence
  56.  * [including the GNU Public Licence.]
  57.  */
  58. #include <openssl/rc4.h>
  59. #include "rc4_locl.h"
  60. /* RC4 as implemented from a posting from
  61.  * Newsgroups: sci.crypt
  62.  * From: sterndark@netcom.com (David Sterndark)
  63.  * Subject: RC4 Algorithm revealed.
  64.  * Message-ID: <sternCvKL4B.Hyy@netcom.com>
  65.  * Date: Wed, 14 Sep 1994 06:35:31 GMT
  66.  */
  67. void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,
  68.      unsigned char *outdata)
  69. {
  70.         register RC4_INT *d;
  71.         register RC4_INT x,y,tx,ty;
  72. int i;
  73.         
  74.         x=key->x;     
  75.         y=key->y;     
  76.         d=key->data; 
  77. #if defined(RC4_CHUNK)
  78. /*
  79.  * The original reason for implementing this(*) was the fact that
  80.  * pre-21164a Alpha CPUs don't have byte load/store instructions
  81.  * and e.g. a byte store has to be done with 64-bit load, shift,
  82.  * and, or and finally 64-bit store. Peaking data and operating
  83.  * at natural word size made it possible to reduce amount of
  84.  * instructions as well as to perform early read-ahead without
  85.  * suffering from RAW (read-after-write) hazard. This resulted
  86.  * in ~40%(**) performance improvement on 21064 box with gcc.
  87.  * But it's not only Alpha users who win here:-) Thanks to the
  88.  * early-n-wide read-ahead this implementation also exhibits
  89.  * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending
  90.  * on sizeof(RC4_INT)).
  91.  *
  92.  * (*) "this" means code which recognizes the case when input
  93.  * and output pointers appear to be aligned at natural CPU
  94.  * word boundary
  95.  * (**) i.e. according to 'apps/openssl speed rc4' benchmark,
  96.  * crypto/rc4/rc4speed.c exhibits almost 70% speed-up...
  97.  *
  98.  * Cavets.
  99.  *
  100.  * - RC4_CHUNK="unsigned long long" should be a #1 choice for
  101.  *   UltraSPARC. Unfortunately gcc generates very slow code
  102.  *   (2.5-3 times slower than one generated by Sun's WorkShop
  103.  *   C) and therefore gcc (at least 2.95 and earlier) should
  104.  *   always be told that RC4_CHUNK="unsigned long".
  105.  *
  106.  * <appro@fy.chalmers.se>
  107.  */
  108. # define RC4_STEP ( 
  109. x=(x+1) &0xff,
  110. tx=d[x],
  111. y=(tx+y)&0xff,
  112. ty=d[y],
  113. d[y]=tx,
  114. d[x]=ty,
  115. (RC4_CHUNK)d[(tx+ty)&0xff]
  116. )
  117. if ( ( ((unsigned long)indata  & (sizeof(RC4_CHUNK)-1)) | 
  118.        ((unsigned long)outdata & (sizeof(RC4_CHUNK)-1)) ) == 0 )
  119. {
  120. RC4_CHUNK ichunk,otp;
  121. const union { long one; char little; } is_endian = {1};
  122. /*
  123.  * I reckon we can afford to implement both endian
  124.  * cases and to decide which way to take at run-time
  125.  * because the machine code appears to be very compact
  126.  * and redundant 1-2KB is perfectly tolerable (i.e.
  127.  * in case the compiler fails to eliminate it:-). By
  128.  * suggestion from Terrel Larson <terr@terralogic.net>
  129.  * who also stands for the is_endian union:-)
  130.  *
  131.  * Special notes.
  132.  *
  133.  * - is_endian is declared automatic as doing otherwise
  134.  *   (declaring static) prevents gcc from eliminating
  135.  *   the redundant code;
  136.  * - compilers (those I've tried) don't seem to have
  137.  *   problems eliminating either the operators guarded
  138.  *   by "if (sizeof(RC4_CHUNK)==8)" or the condition
  139.  *   expressions themselves so I've got 'em to replace
  140.  *   corresponding #ifdefs from the previous version;
  141.  * - I chose to let the redundant switch cases when
  142.  *   sizeof(RC4_CHUNK)!=8 be (were also #ifdefed
  143.  *   before);
  144.  * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in
  145.  *   [LB]ESHFT guards against "shift is out of range"
  146.  *   warnings when sizeof(RC4_CHUNK)!=8 
  147.  *
  148.  * <appro@fy.chalmers.se>
  149.  */
  150. if (!is_endian.little)
  151. { /* BIG-ENDIAN CASE */
  152. # define BESHFT(c) (((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1))
  153. for (;len&~(sizeof(RC4_CHUNK)-1);len-=sizeof(RC4_CHUNK))
  154. {
  155. ichunk  = *(RC4_CHUNK *)indata;
  156. otp  = RC4_STEP<<BESHFT(0);
  157. otp |= RC4_STEP<<BESHFT(1);
  158. otp |= RC4_STEP<<BESHFT(2);
  159. otp |= RC4_STEP<<BESHFT(3);
  160. if (sizeof(RC4_CHUNK)==8)
  161. {
  162. otp |= RC4_STEP<<BESHFT(4);
  163. otp |= RC4_STEP<<BESHFT(5);
  164. otp |= RC4_STEP<<BESHFT(6);
  165. otp |= RC4_STEP<<BESHFT(7);
  166. }
  167. *(RC4_CHUNK *)outdata = otp^ichunk;
  168. indata  += sizeof(RC4_CHUNK);
  169. outdata += sizeof(RC4_CHUNK);
  170. }
  171. if (len)
  172. {
  173. RC4_CHUNK mask=(RC4_CHUNK)-1, ochunk;
  174. ichunk = *(RC4_CHUNK *)indata;
  175. ochunk = *(RC4_CHUNK *)outdata;
  176. otp = 0;
  177. i = BESHFT(0);
  178. mask <<= (sizeof(RC4_CHUNK)-len)<<3;
  179. switch (len&(sizeof(RC4_CHUNK)-1))
  180. {
  181. case 7: otp  = RC4_STEP<<i, i-=8;
  182. case 6: otp |= RC4_STEP<<i, i-=8;
  183. case 5: otp |= RC4_STEP<<i, i-=8;
  184. case 4: otp |= RC4_STEP<<i, i-=8;
  185. case 3: otp |= RC4_STEP<<i, i-=8;
  186. case 2: otp |= RC4_STEP<<i, i-=8;
  187. case 1: otp |= RC4_STEP<<i, i-=8;
  188. case 0: ; /*
  189.    * it's never the case,
  190.    * but it has to be here
  191.    * for ultrix?
  192.    */
  193. }
  194. ochunk &= ~mask;
  195. ochunk |= (otp^ichunk) & mask;
  196. *(RC4_CHUNK *)outdata = ochunk;
  197. }
  198. key->x=x;     
  199. key->y=y;
  200. return;
  201. }
  202. else
  203. { /* LITTLE-ENDIAN CASE */
  204. # define LESHFT(c) (((c)*8)&(sizeof(RC4_CHUNK)*8-1))
  205. for (;len&~(sizeof(RC4_CHUNK)-1);len-=sizeof(RC4_CHUNK))
  206. {
  207. ichunk  = *(RC4_CHUNK *)indata;
  208. otp  = RC4_STEP;
  209. otp |= RC4_STEP<<8;
  210. otp |= RC4_STEP<<16;
  211. otp |= RC4_STEP<<24;
  212. if (sizeof(RC4_CHUNK)==8)
  213. {
  214. otp |= RC4_STEP<<LESHFT(4);
  215. otp |= RC4_STEP<<LESHFT(5);
  216. otp |= RC4_STEP<<LESHFT(6);
  217. otp |= RC4_STEP<<LESHFT(7);
  218. }
  219. *(RC4_CHUNK *)outdata = otp^ichunk;
  220. indata  += sizeof(RC4_CHUNK);
  221. outdata += sizeof(RC4_CHUNK);
  222. }
  223. if (len)
  224. {
  225. RC4_CHUNK mask=(RC4_CHUNK)-1, ochunk;
  226. ichunk = *(RC4_CHUNK *)indata;
  227. ochunk = *(RC4_CHUNK *)outdata;
  228. otp = 0;
  229. i   = 0;
  230. mask >>= (sizeof(RC4_CHUNK)-len)<<3;
  231. switch (len&(sizeof(RC4_CHUNK)-1))
  232. {
  233. case 7: otp  = RC4_STEP,    i+=8;
  234. case 6: otp |= RC4_STEP<<i, i+=8;
  235. case 5: otp |= RC4_STEP<<i, i+=8;
  236. case 4: otp |= RC4_STEP<<i, i+=8;
  237. case 3: otp |= RC4_STEP<<i, i+=8;
  238. case 2: otp |= RC4_STEP<<i, i+=8;
  239. case 1: otp |= RC4_STEP<<i, i+=8;
  240. case 0: ; /*
  241.    * it's never the case,
  242.    * but it has to be here
  243.    * for ultrix?
  244.    */
  245. }
  246. ochunk &= ~mask;
  247. ochunk |= (otp^ichunk) & mask;
  248. *(RC4_CHUNK *)outdata = ochunk;
  249. }
  250. key->x=x;     
  251. key->y=y;
  252. return;
  253. }
  254. }
  255. #endif
  256. #define LOOP(in,out) 
  257. x=((x+1)&0xff); 
  258. tx=d[x]; 
  259. y=(tx+y)&0xff; 
  260. d[x]=ty=d[y]; 
  261. d[y]=tx; 
  262. (out) = d[(tx+ty)&0xff]^ (in);
  263. #ifndef RC4_INDEX
  264. #define RC4_LOOP(a,b,i) LOOP(*((a)++),*((b)++))
  265. #else
  266. #define RC4_LOOP(a,b,i) LOOP(a[i],b[i])
  267. #endif
  268. i=(int)(len>>3L);
  269. if (i)
  270. {
  271. for (;;)
  272. {
  273. RC4_LOOP(indata,outdata,0);
  274. RC4_LOOP(indata,outdata,1);
  275. RC4_LOOP(indata,outdata,2);
  276. RC4_LOOP(indata,outdata,3);
  277. RC4_LOOP(indata,outdata,4);
  278. RC4_LOOP(indata,outdata,5);
  279. RC4_LOOP(indata,outdata,6);
  280. RC4_LOOP(indata,outdata,7);
  281. #ifdef RC4_INDEX
  282. indata+=8;
  283. outdata+=8;
  284. #endif
  285. if (--i == 0) break;
  286. }
  287. }
  288. i=(int)len&0x07;
  289. if (i)
  290. {
  291. for (;;)
  292. {
  293. RC4_LOOP(indata,outdata,0); if (--i == 0) break;
  294. RC4_LOOP(indata,outdata,1); if (--i == 0) break;
  295. RC4_LOOP(indata,outdata,2); if (--i == 0) break;
  296. RC4_LOOP(indata,outdata,3); if (--i == 0) break;
  297. RC4_LOOP(indata,outdata,4); if (--i == 0) break;
  298. RC4_LOOP(indata,outdata,5); if (--i == 0) break;
  299. RC4_LOOP(indata,outdata,6); if (--i == 0) break;
  300. }
  301. }               
  302. key->x=x;     
  303. key->y=y;
  304. }