arcfour.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:17k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation. Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above. If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #include "prerr.h"
  34. #include "secerr.h"
  35. #include "prtypes.h"
  36. #include "blapi.h"
  37. /* Architecture-dependent defines */
  38. #if defined(SOLARIS) || defined(HPUX) || defined(i386) || defined(IRIX)
  39. /* Convert the byte-stream to a word-stream */
  40. #define CONVERT_TO_WORDS
  41. #endif
  42. /* this case is failing for 3.1.  See bug #55234.  */
  43. #if (defined(SOLARIS) || defined(HPUX)) && defined(NSS_USE_64)
  44. #undef CONVERT_TO_WORDS
  45. #endif
  46. #if defined(AIX) || defined(OSF1)
  47. /* Treat array variables as longs, not bytes */
  48. #define USE_LONG
  49. #endif
  50. #ifdef NSS_USE_64
  51. typedef unsigned long long WORD;
  52. #else
  53. typedef unsigned long WORD;
  54. #endif
  55. #define WORDSIZE sizeof(WORD)
  56. #ifdef USE_LONG
  57. typedef unsigned long Stype;
  58. #else
  59. typedef PRUint8 Stype;
  60. #endif
  61. #define ARCFOUR_STATE_SIZE 256
  62. #define SWAP(a, b) 
  63. tmp = a; 
  64. a = b; 
  65. b = tmp;
  66. /*
  67.  * State information for stream cipher.
  68.  */
  69. struct RC4ContextStr
  70. {
  71. Stype S[ARCFOUR_STATE_SIZE];
  72. PRUint8 i;
  73. PRUint8 j;
  74. };
  75. /*
  76.  * array indices [0..255] to initialize cx->S array (faster than loop).
  77.  */
  78. static const Stype Kinit[256] = {
  79. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  80. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  81. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  82. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  83. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  84. 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  85. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  86. 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  87. 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
  88. 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
  89. 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
  90. 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
  91. 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  92. 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
  93. 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
  94. 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
  95. 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  96. 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
  97. 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
  98. 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
  99. 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  100. 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
  101. 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
  102. 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
  103. 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  104. 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
  105. 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  106. 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
  107. 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
  108. 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
  109. 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  110. 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
  111. };
  112. /*
  113.  * Initialize a new generator.
  114.  */
  115. RC4Context *
  116. RC4_CreateContext(unsigned char *key, int len)
  117. {
  118. int i;
  119. PRUint8 j, tmp;
  120. RC4Context *cx;
  121. PRUint8 K[256];
  122. PRUint8 *L;
  123. /* verify the key length. */
  124. PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
  125. if (len < 0 || len >= ARCFOUR_STATE_SIZE) {
  126. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  127. return NULL;
  128. }
  129. /* Create space for the context. */
  130. cx = (RC4Context *)PORT_ZAlloc(sizeof(RC4Context));
  131. if (cx == NULL) {
  132. PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
  133. return NULL;
  134. }
  135. /* Initialize the state using array indices. */
  136. memcpy(cx->S, Kinit, sizeof cx->S);
  137. /* Fill in K repeatedly with values from key. */
  138. L = K;
  139. for (i = sizeof K; i > len; i-= len) {
  140. memcpy(L, key, len);
  141. L += len;
  142. }
  143. memcpy(L, key, i);
  144. /* Stir the state of the generator.  At this point it is assumed
  145.  * that the key is the size of the state buffer.  If this is not
  146.  * the case, the key bytes are repeated to fill the buffer.
  147.  */
  148. j = 0;
  149. #define ARCFOUR_STATE_STIR(ii) 
  150. j = j + cx->S[ii] + K[ii]; 
  151. SWAP(cx->S[ii], cx->S[j]);
  152. for (i=0; i<ARCFOUR_STATE_SIZE; i++) {
  153. ARCFOUR_STATE_STIR(i);
  154. }
  155. cx->i = 0;
  156. cx->j = 0;
  157. return cx;
  158. }
  159. void 
  160. RC4_DestroyContext(RC4Context *cx, PRBool freeit)
  161. {
  162. if (freeit)
  163. PORT_ZFree(cx, sizeof(*cx));
  164. }
  165. /*
  166.  * Generate the next byte in the stream.
  167.  */
  168. #define ARCFOUR_NEXT_BYTE() 
  169. tmpSi = cx->S[++tmpi]; 
  170. tmpj += tmpSi; 
  171. tmpSj = cx->S[tmpj]; 
  172. cx->S[tmpi] = tmpSj; 
  173. cx->S[tmpj] = tmpSi; 
  174. t = tmpSi + tmpSj;
  175. /*
  176.  * Straight RC4 op.  No optimization.
  177.  */
  178. SECStatus 
  179. rc4_no_opt(RC4Context *cx, unsigned char *output,
  180.            unsigned int *outputLen, unsigned int maxOutputLen,
  181.            const unsigned char *input, unsigned int inputLen)
  182. {
  183.     PRUint8 t;
  184. Stype tmpSi, tmpSj;
  185. register PRUint8 tmpi = cx->i;
  186. register PRUint8 tmpj = cx->j;
  187. int index;
  188. PORT_Assert(maxOutputLen >= inputLen);
  189. if (maxOutputLen < inputLen) {
  190. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  191. return SECFailure;
  192. }
  193. for (index=0; index < inputLen; index++) {
  194. /* Generate next byte from stream. */
  195. ARCFOUR_NEXT_BYTE();
  196. /* output = next stream byte XOR next input byte */
  197. output[index] = cx->S[t] ^ input[index];
  198. }
  199. *outputLen = inputLen;
  200. cx->i = tmpi;
  201. cx->j = tmpj;
  202. return SECSuccess;
  203. }
  204. /*
  205.  * Byte-at-a-time RC4, unrolling the loop into 8 pieces.
  206.  */
  207. SECStatus 
  208. rc4_unrolled(RC4Context *cx, unsigned char *output,
  209.              unsigned int *outputLen, unsigned int maxOutputLen,
  210.              const unsigned char *input, unsigned int inputLen)
  211. {
  212. PRUint8 t;
  213. Stype tmpSi, tmpSj;
  214. register PRUint8 tmpi = cx->i;
  215. register PRUint8 tmpj = cx->j;
  216. int index;
  217. PORT_Assert(maxOutputLen >= inputLen);
  218. if (maxOutputLen < inputLen) {
  219. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  220. return SECFailure;
  221. }
  222. for (index = inputLen / 8; index-- > 0; input += 8, output += 8) {
  223. ARCFOUR_NEXT_BYTE();
  224. output[0] = cx->S[t] ^ input[0];
  225. ARCFOUR_NEXT_BYTE();
  226. output[1] = cx->S[t] ^ input[1];
  227. ARCFOUR_NEXT_BYTE();
  228. output[2] = cx->S[t] ^ input[2];
  229. ARCFOUR_NEXT_BYTE();
  230. output[3] = cx->S[t] ^ input[3];
  231. ARCFOUR_NEXT_BYTE();
  232. output[4] = cx->S[t] ^ input[4];
  233. ARCFOUR_NEXT_BYTE();
  234. output[5] = cx->S[t] ^ input[5];
  235. ARCFOUR_NEXT_BYTE();
  236. output[6] = cx->S[t] ^ input[6];
  237. ARCFOUR_NEXT_BYTE();
  238. output[7] = cx->S[t] ^ input[7];
  239. }
  240. index = inputLen % 8;
  241. if (index) {
  242. input += index;
  243. output += index;
  244. switch (index) {
  245. case 7:
  246. ARCFOUR_NEXT_BYTE();
  247. output[-7] = cx->S[t] ^ input[-7]; /* FALLTHRU */
  248. case 6:
  249. ARCFOUR_NEXT_BYTE();
  250. output[-6] = cx->S[t] ^ input[-6]; /* FALLTHRU */
  251. case 5:
  252. ARCFOUR_NEXT_BYTE();
  253. output[-5] = cx->S[t] ^ input[-5]; /* FALLTHRU */
  254. case 4:
  255. ARCFOUR_NEXT_BYTE();
  256. output[-4] = cx->S[t] ^ input[-4]; /* FALLTHRU */
  257. case 3:
  258. ARCFOUR_NEXT_BYTE();
  259. output[-3] = cx->S[t] ^ input[-3]; /* FALLTHRU */
  260. case 2:
  261. ARCFOUR_NEXT_BYTE();
  262. output[-2] = cx->S[t] ^ input[-2]; /* FALLTHRU */
  263. case 1:
  264. ARCFOUR_NEXT_BYTE();
  265. output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */
  266. default:
  267. /* FALLTHRU */
  268. ; /* hp-ux build breaks without this */
  269. }
  270. }
  271. cx->i = tmpi;
  272. cx->j = tmpj;
  273. *outputLen = inputLen;
  274. return SECSuccess;
  275. }
  276. #ifdef IS_LITTLE_ENDIAN
  277. #define ARCFOUR_NEXT4BYTES_L(n) 
  278. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n     ); 
  279. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n +  8); 
  280. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); 
  281. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24);
  282. #else
  283. #define ARCFOUR_NEXT4BYTES_B(n) 
  284. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24); 
  285. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); 
  286. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n +  8); 
  287. ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n     );
  288. #endif
  289. #ifdef NSS_USE_64
  290. /* 64-bit wordsize */
  291. #ifdef IS_LITTLE_ENDIAN
  292. #define ARCFOUR_NEXT_WORD() 
  293. { streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); ARCFOUR_NEXT4BYTES_L(32); }
  294. #else
  295. #define ARCFOUR_NEXT_WORD() 
  296. { streamWord = 0; ARCFOUR_NEXT4BYTES_B(32); ARCFOUR_NEXT4BYTES_B(0); }
  297. #endif
  298. #else
  299. /* 32-bit wordsize */
  300. #ifdef IS_LITTLE_ENDIAN
  301. #define ARCFOUR_NEXT_WORD() 
  302. { streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); }
  303. #else
  304. #define ARCFOUR_NEXT_WORD() 
  305. { streamWord = 0; ARCFOUR_NEXT4BYTES_B(0); }
  306. #endif
  307. #endif
  308. #ifdef IS_LITTLE_ENDIAN
  309. #define RSH <<
  310. #define LSH >>
  311. #else
  312. #define RSH >>
  313. #define LSH <<
  314. #endif
  315. /*
  316.  * Convert input and output buffers to words before performing
  317.  * RC4 operations.
  318.  */
  319. SECStatus 
  320. rc4_wordconv(RC4Context *cx, unsigned char *output,
  321.              unsigned int *outputLen, unsigned int maxOutputLen,
  322.              const unsigned char *input, unsigned int inputLen)
  323. {
  324. ptrdiff_t inOffset = (ptrdiff_t)input % WORDSIZE;
  325. ptrdiff_t outOffset = (ptrdiff_t)output % WORDSIZE;
  326. register WORD streamWord, mask;
  327. register WORD *pInWord, *pOutWord;
  328. register WORD inWord, nextInWord;
  329. PRUint8 t;
  330. register Stype tmpSi, tmpSj;
  331. register PRUint8 tmpi = cx->i;
  332. register PRUint8 tmpj = cx->j;
  333. unsigned int byteCount;
  334. unsigned int bufShift, invBufShift;
  335. int i;
  336. PORT_Assert(maxOutputLen >= inputLen);
  337. if (maxOutputLen < inputLen) {
  338. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  339. return SECFailure;
  340. }
  341. if (inputLen < 2*WORDSIZE) {
  342. /* Ignore word conversion, do byte-at-a-time */
  343. return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);
  344. }
  345. *outputLen = inputLen;
  346. pInWord = (WORD *)(input - inOffset);
  347. if (inOffset < outOffset) {
  348. bufShift = 8*(outOffset - inOffset);
  349. invBufShift = 8*WORDSIZE - bufShift;
  350. } else {
  351. invBufShift = 8*(inOffset - outOffset);
  352. bufShift = 8*WORDSIZE - invBufShift;
  353. }
  354. /*****************************************************************/
  355. /* Step 1:                                                       */
  356. /* If the first output word is partial, consume the bytes in the */
  357. /* first partial output word by loading one or two words of      */
  358. /* input and shifting them accordingly.  Otherwise, just load    */
  359. /* in the first word of input.  At the end of this block, at     */
  360. /* least one partial word of input should ALWAYS be loaded.      */
  361. /*****************************************************************/
  362. if (outOffset) {
  363. /* Generate input and stream words aligned relative to the
  364.  * partial output buffer.
  365.  */
  366. byteCount = WORDSIZE - outOffset; 
  367. pOutWord = (WORD *)(output - outOffset);
  368. mask = streamWord = 0;
  369. #ifdef IS_LITTLE_ENDIAN
  370. for (i = WORDSIZE - byteCount; i < WORDSIZE; i++) {
  371. #else
  372. for (i = byteCount - 1; i >= 0; --i) {
  373. #endif
  374. ARCFOUR_NEXT_BYTE();
  375. streamWord |= (WORD)(cx->S[t]) << 8*i;
  376. mask |= 0xff << 8*i;
  377. }
  378. inWord = *pInWord++;
  379. /* If buffers are relatively misaligned, shift the bytes in inWord
  380.  * to be aligned to the output buffer.
  381.  */
  382. if (inOffset < outOffset) {
  383. /* Have more bytes than needed, shift remainder into nextInWord */
  384. nextInWord = inWord LSH 8*(inOffset + byteCount);
  385. inWord = inWord RSH bufShift;
  386. } else if (inOffset > outOffset) {
  387. /* Didn't get enough bytes from current input word, load another
  388.  * word and then shift remainder into nextInWord.
  389.  */
  390. nextInWord = *pInWord++;
  391. inWord = (inWord LSH invBufShift) | 
  392.          (nextInWord RSH bufShift);
  393. nextInWord = nextInWord LSH invBufShift;
  394. }
  395. /* Store output of first partial word */
  396. *pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
  397. /* Consumed byteCount bytes of input */
  398. inputLen -= byteCount;
  399. /* move to next word of output */
  400. pOutWord++;
  401. /* inWord has been consumed, but there may be bytes in nextInWord */
  402. if (inOffset == outOffset)
  403. inWord = 0;
  404. else
  405. inWord = nextInWord;
  406. } else {
  407. /* output is word-aligned */
  408. pOutWord = (WORD *)output;
  409. if (inOffset) {
  410. /* Input is not word-aligned.  The first word load of input 
  411.  * will not produce a full word of input bytes, so one word
  412.  * must be pre-loaded.  The main loop below will load in the
  413.  * next input word and shift some of its bytes into inWord
  414.  * in order to create a full input word.  Note that the main
  415.  * loop must execute at least once because the input must
  416.  * be at least two words.
  417.  */
  418. inWord = *pInWord++;
  419. inWord = inWord LSH invBufShift;
  420. } else {
  421. /* Input is word-aligned.  The first word load of input 
  422.  * will produce a full word of input bytes, so nothing
  423.  * needs to be loaded here.
  424.  */
  425. inWord = 0;
  426. }
  427. }
  428. /* Output buffer is aligned, inOffset is now measured relative to
  429.  * outOffset (and not a word boundary).
  430.  */
  431. inOffset = (inOffset + WORDSIZE - outOffset) % WORDSIZE;
  432. /*****************************************************************/
  433. /* Step 2: main loop                                             */
  434. /* At this point the output buffer is word-aligned.  Any unused  */
  435. /* bytes from above will be in inWord (shifted correctly).  If   */
  436. /* the input buffer is unaligned relative to the output buffer,  */
  437. /* shifting has to be done.                                      */
  438. /*****************************************************************/
  439. if (inOffset) {
  440. for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
  441. nextInWord = *pInWord++;
  442. inWord |= nextInWord RSH bufShift;
  443. nextInWord = nextInWord LSH invBufShift;
  444. ARCFOUR_NEXT_WORD();
  445. *pOutWord++ = inWord ^ streamWord;
  446. inWord = nextInWord;
  447. }
  448. if (inputLen == 0) {
  449. /* Nothing left to do. */
  450. cx->i = tmpi;
  451. cx->j = tmpj;
  452. return SECSuccess;
  453. }
  454. /* If the amount of remaining input is greater than the amount
  455.  * bytes pulled from the current input word, need to do another
  456.  * word load.  What's left in inWord will be consumed in step 3.
  457.  */
  458. if (inputLen > WORDSIZE - inOffset)
  459. inWord |= *pInWord RSH bufShift;
  460. } else {
  461. for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
  462. inWord = *pInWord++;
  463. ARCFOUR_NEXT_WORD();
  464. *pOutWord++ = inWord ^ streamWord;
  465. }
  466. if (inputLen == 0) {
  467. /* Nothing left to do. */
  468. cx->i = tmpi;
  469. cx->j = tmpj;
  470. return SECSuccess;
  471. } else {
  472. /* A partial input word remains at the tail.  Load it.  The
  473.  * relevant bytes will be consumed in step 3.
  474.  */
  475. inWord = *pInWord;
  476. }
  477. }
  478. /*****************************************************************/
  479. /* Step 3:                                                       */
  480. /* A partial word of input remains, and it is already loaded     */
  481. /* into nextInWord.  Shift appropriately and consume the bytes   */
  482. /* used in the partial word.                                     */
  483. /*****************************************************************/
  484. mask = streamWord = 0;
  485. #ifdef IS_LITTLE_ENDIAN
  486. for (i = 0; i < inputLen; ++i) {
  487. #else
  488. for (i = WORDSIZE - 1; i >= WORDSIZE - inputLen; --i) {
  489. #endif
  490. ARCFOUR_NEXT_BYTE();
  491. streamWord |= (WORD)(cx->S[t]) << 8*i;
  492. mask |= 0xff << 8*i;
  493. }
  494. *pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
  495. cx->i = tmpi;
  496. cx->j = tmpj;
  497. return SECSuccess;
  498. }
  499. SECStatus 
  500. RC4_Encrypt(RC4Context *cx, unsigned char *output,
  501.             unsigned int *outputLen, unsigned int maxOutputLen,
  502.             const unsigned char *input, unsigned int inputLen)
  503. {
  504. PORT_Assert(maxOutputLen >= inputLen);
  505. if (maxOutputLen < inputLen) {
  506. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  507. return SECFailure;
  508. }
  509. #ifdef CONVERT_TO_WORDS
  510. /* Convert the byte-stream to a word-stream */
  511. return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
  512. #else
  513. /* Operate on bytes, but unroll the main loop */
  514. return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
  515. #endif
  516. }
  517. SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,
  518.                       unsigned int *outputLen, unsigned int maxOutputLen,
  519.                       const unsigned char *input, unsigned int inputLen)
  520. {
  521. PORT_Assert(maxOutputLen >= inputLen);
  522. if (maxOutputLen < inputLen) {
  523. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  524. return SECFailure;
  525. }
  526. /* decrypt and encrypt are same operation. */
  527. #ifdef CONVERT_TO_WORDS
  528. /* Convert the byte-stream to a word-stream */
  529. return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
  530. #else
  531. /* Operate on bytes, but unroll the main loop */
  532. return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
  533. #endif
  534. }
  535. #undef CONVERT_TO_WORDS
  536. #undef USE_LONG