security/nss/lib/freebl/arcfour.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* arcfour.c - the arc four algorithm.
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifdef FREEBL_NO_DEPEND
     8 #include "stubs.h"
     9 #endif
    11 #include "prerr.h"
    12 #include "secerr.h"
    14 #include "prtypes.h"
    15 #include "blapi.h"
    17 /* Architecture-dependent defines */
    19 #if defined(SOLARIS) || defined(HPUX) || defined(NSS_X86) || \
    20     defined(_WIN64)
    21 /* Convert the byte-stream to a word-stream */
    22 #define CONVERT_TO_WORDS
    23 #endif
    25 #if defined(AIX) || defined(OSF1) || defined(NSS_BEVAND_ARCFOUR)
    26 /* Treat array variables as words, not bytes, on CPUs that take 
    27  * much longer to write bytes than to write words, or when using 
    28  * assembler code that required it.
    29  */
    30 #define USE_WORD
    31 #endif
    33 #if defined(IS_64) || defined(NSS_BEVAND_ARCFOUR)
    34 typedef PRUint64 WORD;
    35 #else
    36 typedef PRUint32 WORD;
    37 #endif
    38 #define WORDSIZE sizeof(WORD)
    40 #if defined(USE_WORD)
    41 typedef WORD Stype;
    42 #else
    43 typedef PRUint8 Stype;
    44 #endif
    46 #define ARCFOUR_STATE_SIZE 256
    48 #define MASK1BYTE (WORD)(0xff)
    50 #define SWAP(a, b) \
    51 	tmp = a; \
    52 	a = b; \
    53 	b = tmp;
    55 /*
    56  * State information for stream cipher.
    57  */
    58 struct RC4ContextStr
    59 {
    60 #if defined(NSS_ARCFOUR_IJ_B4_S) || defined(NSS_BEVAND_ARCFOUR)
    61 	Stype i;
    62 	Stype j;
    63 	Stype S[ARCFOUR_STATE_SIZE];
    64 #else
    65 	Stype S[ARCFOUR_STATE_SIZE];
    66 	Stype i;
    67 	Stype j;
    68 #endif
    69 };
    71 /*
    72  * array indices [0..255] to initialize cx->S array (faster than loop).
    73  */
    74 static const Stype Kinit[256] = {
    75 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    76 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    77 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    78 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    79 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    80 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    81 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    82 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
    83 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
    84 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
    85 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
    86 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
    87 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
    88 	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
    89 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
    90 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
    91 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
    92 	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
    93 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
    94 	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
    95 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
    96 	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
    97 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
    98 	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
    99 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
   100 	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
   101 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
   102 	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
   103 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
   104 	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
   105 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
   106 	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
   107 };
   109 RC4Context *
   110 RC4_AllocateContext(void)
   111 {
   112     return PORT_ZNew(RC4Context);
   113 }
   115 SECStatus   
   116 RC4_InitContext(RC4Context *cx, const unsigned char *key, unsigned int len,
   117 	        const unsigned char * unused1, int unused2, 
   118 		unsigned int unused3, unsigned int unused4)
   119 {
   120 	unsigned int i;
   121 	PRUint8 j, tmp;
   122 	PRUint8 K[256];
   123 	PRUint8 *L;
   125 	/* verify the key length. */
   126 	PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
   127 	if (len == 0 || len >= ARCFOUR_STATE_SIZE) {
   128 		PORT_SetError(SEC_ERROR_BAD_KEY);
   129 		return SECFailure;
   130 	}
   131 	if (cx == NULL) {
   132 	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
   133 	    return SECFailure;
   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 SECSuccess;
   158 }
   161 /*
   162  * Initialize a new generator.
   163  */
   164 RC4Context *
   165 RC4_CreateContext(const unsigned char *key, int len)
   166 {
   167     RC4Context *cx = RC4_AllocateContext();
   168     if (cx) {
   169 	SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0);
   170 	if (rv != SECSuccess) {
   171 	    PORT_ZFree(cx, sizeof(*cx));
   172 	    cx = NULL;
   173 	}
   174     }
   175     return cx;
   176 }
   178 void 
   179 RC4_DestroyContext(RC4Context *cx, PRBool freeit)
   180 {
   181 	if (freeit)
   182 		PORT_ZFree(cx, sizeof(*cx));
   183 }
   185 #if defined(NSS_BEVAND_ARCFOUR)
   186 extern void ARCFOUR(RC4Context *cx, WORD inputLen, 
   187 	const unsigned char *input, unsigned char *output);
   188 #else
   189 /*
   190  * Generate the next byte in the stream.
   191  */
   192 #define ARCFOUR_NEXT_BYTE() \
   193 	tmpSi = cx->S[++tmpi]; \
   194 	tmpj += tmpSi; \
   195 	tmpSj = cx->S[tmpj]; \
   196 	cx->S[tmpi] = tmpSj; \
   197 	cx->S[tmpj] = tmpSi; \
   198 	t = tmpSi + tmpSj;
   200 #ifdef CONVERT_TO_WORDS
   201 /*
   202  * Straight ARCFOUR op.  No optimization.
   203  */
   204 static SECStatus 
   205 rc4_no_opt(RC4Context *cx, unsigned char *output,
   206            unsigned int *outputLen, unsigned int maxOutputLen,
   207            const unsigned char *input, unsigned int inputLen)
   208 {
   209     PRUint8 t;
   210 	Stype tmpSi, tmpSj;
   211 	register PRUint8 tmpi = cx->i;
   212 	register PRUint8 tmpj = cx->j;
   213 	unsigned int index;
   214 	PORT_Assert(maxOutputLen >= inputLen);
   215 	if (maxOutputLen < inputLen) {
   216 		PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   217 		return SECFailure;
   218 	}
   219 	for (index=0; index < inputLen; index++) {
   220 		/* Generate next byte from stream. */
   221 		ARCFOUR_NEXT_BYTE();
   222 		/* output = next stream byte XOR next input byte */
   223 		output[index] = cx->S[t] ^ input[index];
   224 	}
   225 	*outputLen = inputLen;
   226 	cx->i = tmpi;
   227 	cx->j = tmpj;
   228 	return SECSuccess;
   229 }
   231 #else
   232 /* !CONVERT_TO_WORDS */
   234 /*
   235  * Byte-at-a-time ARCFOUR, unrolling the loop into 8 pieces.
   236  */
   237 static SECStatus 
   238 rc4_unrolled(RC4Context *cx, unsigned char *output,
   239              unsigned int *outputLen, unsigned int maxOutputLen,
   240              const unsigned char *input, unsigned int inputLen)
   241 {
   242 	PRUint8 t;
   243 	Stype tmpSi, tmpSj;
   244 	register PRUint8 tmpi = cx->i;
   245 	register PRUint8 tmpj = cx->j;
   246 	int index;
   247 	PORT_Assert(maxOutputLen >= inputLen);
   248 	if (maxOutputLen < inputLen) {
   249 		PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   250 		return SECFailure;
   251 	}
   252 	for (index = inputLen / 8; index-- > 0; input += 8, output += 8) {
   253 		ARCFOUR_NEXT_BYTE();
   254 		output[0] = cx->S[t] ^ input[0];
   255 		ARCFOUR_NEXT_BYTE();
   256 		output[1] = cx->S[t] ^ input[1];
   257 		ARCFOUR_NEXT_BYTE();
   258 		output[2] = cx->S[t] ^ input[2];
   259 		ARCFOUR_NEXT_BYTE();
   260 		output[3] = cx->S[t] ^ input[3];
   261 		ARCFOUR_NEXT_BYTE();
   262 		output[4] = cx->S[t] ^ input[4];
   263 		ARCFOUR_NEXT_BYTE();
   264 		output[5] = cx->S[t] ^ input[5];
   265 		ARCFOUR_NEXT_BYTE();
   266 		output[6] = cx->S[t] ^ input[6];
   267 		ARCFOUR_NEXT_BYTE();
   268 		output[7] = cx->S[t] ^ input[7];
   269 	}
   270 	index = inputLen % 8;
   271 	if (index) {
   272 		input += index;
   273 		output += index;
   274 		switch (index) {
   275 		case 7:
   276 			ARCFOUR_NEXT_BYTE();
   277 			output[-7] = cx->S[t] ^ input[-7]; /* FALLTHRU */
   278 		case 6:
   279 			ARCFOUR_NEXT_BYTE();
   280 			output[-6] = cx->S[t] ^ input[-6]; /* FALLTHRU */
   281 		case 5:
   282 			ARCFOUR_NEXT_BYTE();
   283 			output[-5] = cx->S[t] ^ input[-5]; /* FALLTHRU */
   284 		case 4:
   285 			ARCFOUR_NEXT_BYTE();
   286 			output[-4] = cx->S[t] ^ input[-4]; /* FALLTHRU */
   287 		case 3:
   288 			ARCFOUR_NEXT_BYTE();
   289 			output[-3] = cx->S[t] ^ input[-3]; /* FALLTHRU */
   290 		case 2:
   291 			ARCFOUR_NEXT_BYTE();
   292 			output[-2] = cx->S[t] ^ input[-2]; /* FALLTHRU */
   293 		case 1:
   294 			ARCFOUR_NEXT_BYTE();
   295 			output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */
   296 		default:
   297 			/* FALLTHRU */
   298 			; /* hp-ux build breaks without this */
   299 		}
   300 	}
   301 	cx->i = tmpi;
   302 	cx->j = tmpj;
   303 	*outputLen = inputLen;
   304 	return SECSuccess;
   305 }
   306 #endif
   308 #ifdef IS_LITTLE_ENDIAN
   309 #define ARCFOUR_NEXT4BYTES_L(n) \
   310 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n     ); \
   311 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n +  8); \
   312 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
   313 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24);
   314 #else
   315 #define ARCFOUR_NEXT4BYTES_B(n) \
   316 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24); \
   317 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
   318 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n +  8); \
   319 	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n     );
   320 #endif
   322 #if (defined(IS_64) && !defined(__sparc)) || defined(NSS_USE_64)
   323 /* 64-bit wordsize */
   324 #ifdef IS_LITTLE_ENDIAN
   325 #define ARCFOUR_NEXT_WORD() \
   326 	{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); ARCFOUR_NEXT4BYTES_L(32); }
   327 #else
   328 #define ARCFOUR_NEXT_WORD() \
   329 	{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(32); ARCFOUR_NEXT4BYTES_B(0); }
   330 #endif
   331 #else
   332 /* 32-bit wordsize */
   333 #ifdef IS_LITTLE_ENDIAN
   334 #define ARCFOUR_NEXT_WORD() \
   335 	{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); }
   336 #else
   337 #define ARCFOUR_NEXT_WORD() \
   338 	{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(0); }
   339 #endif
   340 #endif
   342 #ifdef IS_LITTLE_ENDIAN
   343 #define RSH <<
   344 #define LSH >>
   345 #else
   346 #define RSH >>
   347 #define LSH <<
   348 #endif
   350 #ifdef IS_LITTLE_ENDIAN
   351 #define LEFTMOST_BYTE_SHIFT 0
   352 #define NEXT_BYTE_SHIFT(shift) shift + 8
   353 #else
   354 #define LEFTMOST_BYTE_SHIFT 8*(WORDSIZE - 1)
   355 #define NEXT_BYTE_SHIFT(shift) shift - 8
   356 #endif
   358 #ifdef CONVERT_TO_WORDS
   359 static SECStatus 
   360 rc4_wordconv(RC4Context *cx, unsigned char *output,
   361              unsigned int *outputLen, unsigned int maxOutputLen,
   362              const unsigned char *input, unsigned int inputLen)
   363 {
   364 	PR_STATIC_ASSERT(sizeof(PRUword) == sizeof(ptrdiff_t));
   365 	unsigned int inOffset = (PRUword)input % WORDSIZE;
   366 	unsigned int outOffset = (PRUword)output % WORDSIZE;
   367 	register WORD streamWord;
   368 	register const WORD *pInWord;
   369 	register WORD *pOutWord;
   370 	register WORD inWord, nextInWord;
   371 	PRUint8 t;
   372 	register Stype tmpSi, tmpSj;
   373 	register PRUint8 tmpi = cx->i;
   374 	register PRUint8 tmpj = cx->j;
   375 	unsigned int bufShift, invBufShift;
   376 	unsigned int i;
   377 	const unsigned char *finalIn;
   378 	unsigned char *finalOut;
   380 	PORT_Assert(maxOutputLen >= inputLen);
   381 	if (maxOutputLen < inputLen) {
   382 		PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   383 		return SECFailure;
   384 	}
   385 	if (inputLen < 2*WORDSIZE) {
   386 		/* Ignore word conversion, do byte-at-a-time */
   387 		return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);
   388 	}
   389 	*outputLen = inputLen;
   390 	pInWord = (const WORD *)(input - inOffset);
   391 	pOutWord = (WORD *)(output - outOffset);
   392 	if (inOffset <= outOffset) {
   393 		bufShift = 8*(outOffset - inOffset);
   394 		invBufShift = 8*WORDSIZE - bufShift;
   395 	} else {
   396 		invBufShift = 8*(inOffset - outOffset);
   397 		bufShift = 8*WORDSIZE - invBufShift;
   398 	}
   399 	/*****************************************************************/
   400 	/* Step 1:                                                       */
   401 	/* If the first output word is partial, consume the bytes in the */
   402 	/* first partial output word by loading one or two words of      */
   403 	/* input and shifting them accordingly.  Otherwise, just load    */
   404 	/* in the first word of input.  At the end of this block, at     */
   405 	/* least one partial word of input should ALWAYS be loaded.      */
   406 	/*****************************************************************/
   407 	if (outOffset) {
   408 		unsigned int byteCount = WORDSIZE - outOffset; 
   409 		for (i = 0; i < byteCount; i++) {
   410 			ARCFOUR_NEXT_BYTE();
   411 			output[i] = cx->S[t] ^ input[i];
   412 		}
   413 		/* Consumed byteCount bytes of input */
   414 		inputLen -= byteCount;
   415 		pInWord++;
   417 		/* move to next word of output */
   418 		pOutWord++;
   420 		/* If buffers are relatively misaligned, shift the bytes in inWord
   421 		 * to be aligned to the output buffer.
   422 		 */
   423 		if (inOffset < outOffset) {
   424 			/* The first input word (which may be partial) has more bytes
   425 			 * than needed.  Copy the remainder to inWord.
   426 			 */
   427 			unsigned int shift = LEFTMOST_BYTE_SHIFT;
   428 			inWord = 0;
   429 			for (i = 0; i < outOffset - inOffset; i++) {
   430 				inWord |= (WORD)input[byteCount + i] << shift;
   431 				shift = NEXT_BYTE_SHIFT(shift);
   432 			}
   433 		} else if (inOffset > outOffset) {
   434 			/* Consumed some bytes in the second input word.  Copy the
   435 			 * remainder to inWord.
   436 			 */
   437 			inWord = *pInWord++;
   438 			inWord = inWord LSH invBufShift;
   439 		} else {
   440 			inWord = 0;
   441 		}
   442 	} else {
   443 		/* output is word-aligned */
   444 		if (inOffset) {
   445 			/* Input is not word-aligned.  The first word load of input 
   446 			 * will not produce a full word of input bytes, so one word
   447 			 * must be pre-loaded.  The main loop below will load in the
   448 			 * next input word and shift some of its bytes into inWord
   449 			 * in order to create a full input word.  Note that the main
   450 			 * loop must execute at least once because the input must
   451 			 * be at least two words.
   452 			 */
   453 			unsigned int shift = LEFTMOST_BYTE_SHIFT;
   454 			inWord = 0;
   455 			for (i = 0; i < WORDSIZE - inOffset; i++) {
   456 				inWord |= (WORD)input[i] << shift;
   457 				shift = NEXT_BYTE_SHIFT(shift);
   458 			}
   459 			pInWord++;
   460 		} else {
   461 			/* Input is word-aligned.  The first word load of input 
   462 			 * will produce a full word of input bytes, so nothing
   463 			 * needs to be loaded here.
   464 			 */
   465 			inWord = 0;
   466 		}
   467 	}
   468 	/*****************************************************************/
   469 	/* Step 2: main loop                                             */
   470 	/* At this point the output buffer is word-aligned.  Any unused  */
   471 	/* bytes from above will be in inWord (shifted correctly).  If   */
   472 	/* the input buffer is unaligned relative to the output buffer,  */
   473 	/* shifting has to be done.                                      */
   474 	/*****************************************************************/
   475 	if (bufShift) {
   476 		/* preloadedByteCount is the number of input bytes pre-loaded
   477 		 * in inWord.
   478 		 */
   479 		unsigned int preloadedByteCount = bufShift/8;
   480 		for (; inputLen >= preloadedByteCount + WORDSIZE;
   481 		     inputLen -= WORDSIZE) {
   482 			nextInWord = *pInWord++;
   483 			inWord |= nextInWord RSH bufShift;
   484 			nextInWord = nextInWord LSH invBufShift;
   485 			ARCFOUR_NEXT_WORD();
   486 			*pOutWord++ = inWord ^ streamWord;
   487 			inWord = nextInWord;
   488 		}
   489 		if (inputLen == 0) {
   490 			/* Nothing left to do. */
   491 			cx->i = tmpi;
   492 			cx->j = tmpj;
   493 			return SECSuccess;
   494 		}
   495 		finalIn = (const unsigned char *)pInWord - preloadedByteCount;
   496 	} else {
   497 		for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
   498 			inWord = *pInWord++;
   499 			ARCFOUR_NEXT_WORD();
   500 			*pOutWord++ = inWord ^ streamWord;
   501 		}
   502 		if (inputLen == 0) {
   503 			/* Nothing left to do. */
   504 			cx->i = tmpi;
   505 			cx->j = tmpj;
   506 			return SECSuccess;
   507 		}
   508 		finalIn = (const unsigned char *)pInWord;
   509 	}
   510 	/*****************************************************************/
   511 	/* Step 3:                                                       */
   512 	/* Do the remaining partial word of input one byte at a time.    */
   513 	/*****************************************************************/
   514 	finalOut = (unsigned char *)pOutWord;
   515 	for (i = 0; i < inputLen; i++) {
   516 		ARCFOUR_NEXT_BYTE();
   517 		finalOut[i] = cx->S[t] ^ finalIn[i];
   518 	}
   519 	cx->i = tmpi;
   520 	cx->j = tmpj;
   521 	return SECSuccess;
   522 }
   523 #endif
   524 #endif /* NSS_BEVAND_ARCFOUR */
   526 SECStatus 
   527 RC4_Encrypt(RC4Context *cx, unsigned char *output,
   528             unsigned int *outputLen, unsigned int maxOutputLen,
   529             const unsigned char *input, unsigned int inputLen)
   530 {
   531 	PORT_Assert(maxOutputLen >= inputLen);
   532 	if (maxOutputLen < inputLen) {
   533 		PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   534 		return SECFailure;
   535 	}
   536 #if defined(NSS_BEVAND_ARCFOUR)
   537 	ARCFOUR(cx, inputLen, input, output);
   538         *outputLen = inputLen;
   539 	return SECSuccess;
   540 #elif defined( CONVERT_TO_WORDS )
   541 	/* Convert the byte-stream to a word-stream */
   542 	return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
   543 #else
   544 	/* Operate on bytes, but unroll the main loop */
   545 	return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
   546 #endif
   547 }
   549 SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,
   550                       unsigned int *outputLen, unsigned int maxOutputLen,
   551                       const unsigned char *input, unsigned int inputLen)
   552 {
   553 	PORT_Assert(maxOutputLen >= inputLen);
   554 	if (maxOutputLen < inputLen) {
   555 		PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   556 		return SECFailure;
   557 	}
   558 	/* decrypt and encrypt are same operation. */
   559 #if defined(NSS_BEVAND_ARCFOUR)
   560 	ARCFOUR(cx, inputLen, input, output);
   561         *outputLen = inputLen;
   562 	return SECSuccess;
   563 #elif defined( CONVERT_TO_WORDS )
   564 	/* Convert the byte-stream to a word-stream */
   565 	return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
   566 #else
   567 	/* Operate on bytes, but unroll the main loop */
   568 	return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
   569 #endif
   570 }
   572 #undef CONVERT_TO_WORDS
   573 #undef USE_WORD

mercurial