arcfour.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 562 行 · 第 1/2 页

C
562
字号
			output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */		default:			/* FALLTHRU */			; /* hp-ux build breaks without this */		}	}	cx->i = tmpi;	cx->j = tmpj;	*outputLen = inputLen;	return SECSuccess;}#ifdef IS_LITTLE_ENDIAN#define ARCFOUR_NEXT4BYTES_L(n) \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n     ); \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n +  8); \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24);#else#define ARCFOUR_NEXT4BYTES_B(n) \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24); \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n +  8); \	ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n     );#endif#ifdef NSS_USE_64/* 64-bit wordsize */#ifdef IS_LITTLE_ENDIAN#define ARCFOUR_NEXT_WORD() \	{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); ARCFOUR_NEXT4BYTES_L(32); }#else#define ARCFOUR_NEXT_WORD() \	{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(32); ARCFOUR_NEXT4BYTES_B(0); }#endif#else/* 32-bit wordsize */#ifdef IS_LITTLE_ENDIAN#define ARCFOUR_NEXT_WORD() \	{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); }#else#define ARCFOUR_NEXT_WORD() \	{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(0); }#endif#endif#ifdef IS_LITTLE_ENDIAN#define RSH <<#define LSH >>#else#define RSH >>#define LSH <<#endif/* * Convert input and output buffers to words before performing * RC4 operations. */SECStatus rc4_wordconv(RC4Context *cx, unsigned char *output,             unsigned int *outputLen, unsigned int maxOutputLen,             const unsigned char *input, unsigned int inputLen){	ptrdiff_t inOffset = (ptrdiff_t)input % WORDSIZE;	ptrdiff_t outOffset = (ptrdiff_t)output % WORDSIZE;	register WORD streamWord, mask;	register WORD *pInWord, *pOutWord;	register WORD inWord, nextInWord;	PRUint8 t;	register Stype tmpSi, tmpSj;	register PRUint8 tmpi = cx->i;	register PRUint8 tmpj = cx->j;	unsigned int byteCount;	unsigned int bufShift, invBufShift;	int i;	PORT_Assert(maxOutputLen >= inputLen);	if (maxOutputLen < inputLen) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}	if (inputLen < 2*WORDSIZE) {		/* Ignore word conversion, do byte-at-a-time */		return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);	}	*outputLen = inputLen;	pInWord = (WORD *)(input - inOffset);	if (inOffset < outOffset) {		bufShift = 8*(outOffset - inOffset);		invBufShift = 8*WORDSIZE - bufShift;	} else {		invBufShift = 8*(inOffset - outOffset);		bufShift = 8*WORDSIZE - invBufShift;	}	/*****************************************************************/	/* Step 1:                                                       */	/* If the first output word is partial, consume the bytes in the */	/* first partial output word by loading one or two words of      */	/* input and shifting them accordingly.  Otherwise, just load    */	/* in the first word of input.  At the end of this block, at     */	/* least one partial word of input should ALWAYS be loaded.      */	/*****************************************************************/	if (outOffset) {		/* Generate input and stream words aligned relative to the		 * partial output buffer.		 */		byteCount = WORDSIZE - outOffset; 		pOutWord = (WORD *)(output - outOffset);		mask = streamWord = 0;#ifdef IS_LITTLE_ENDIAN		for (i = WORDSIZE - byteCount; i < WORDSIZE; i++) {#else		for (i = byteCount - 1; i >= 0; --i) {#endif			ARCFOUR_NEXT_BYTE();			streamWord |= (WORD)(cx->S[t]) << 8*i;			mask |= 0xff << 8*i;		}		inWord = *pInWord++;		/* If buffers are relatively misaligned, shift the bytes in inWord		 * to be aligned to the output buffer.		 */		if (inOffset < outOffset) {			/* Have more bytes than needed, shift remainder into nextInWord */			nextInWord = inWord LSH 8*(inOffset + byteCount);			inWord = inWord RSH bufShift;		} else if (inOffset > outOffset) {			/* Didn't get enough bytes from current input word, load another			 * word and then shift remainder into nextInWord.			 */			nextInWord = *pInWord++;			inWord = (inWord LSH invBufShift) | 			         (nextInWord RSH bufShift);			nextInWord = nextInWord LSH invBufShift;		}		/* Store output of first partial word */		*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);		/* Consumed byteCount bytes of input */		inputLen -= byteCount;		/* move to next word of output */		pOutWord++;		/* inWord has been consumed, but there may be bytes in nextInWord */		if (inOffset == outOffset)			inWord = 0;		else			inWord = nextInWord;	} else {		/* output is word-aligned */		pOutWord = (WORD *)output;		if (inOffset) {			/* Input is not word-aligned.  The first word load of input 			 * will not produce a full word of input bytes, so one word			 * must be pre-loaded.  The main loop below will load in the			 * next input word and shift some of its bytes into inWord			 * in order to create a full input word.  Note that the main			 * loop must execute at least once because the input must			 * be at least two words.			 */			inWord = *pInWord++;			inWord = inWord LSH invBufShift;		} else {			/* Input is word-aligned.  The first word load of input 			 * will produce a full word of input bytes, so nothing			 * needs to be loaded here.			 */			inWord = 0;		}	}	/* Output buffer is aligned, inOffset is now measured relative to	 * outOffset (and not a word boundary).	 */	inOffset = (inOffset + WORDSIZE - outOffset) % WORDSIZE;	/*****************************************************************/	/* Step 2: main loop                                             */	/* At this point the output buffer is word-aligned.  Any unused  */	/* bytes from above will be in inWord (shifted correctly).  If   */	/* the input buffer is unaligned relative to the output buffer,  */	/* shifting has to be done.                                      */	/*****************************************************************/	if (inOffset) {		for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {			nextInWord = *pInWord++;			inWord |= nextInWord RSH bufShift;			nextInWord = nextInWord LSH invBufShift;			ARCFOUR_NEXT_WORD();			*pOutWord++ = inWord ^ streamWord;			inWord = nextInWord;		}		if (inputLen == 0) {			/* Nothing left to do. */			cx->i = tmpi;			cx->j = tmpj;			return SECSuccess;		}		/* If the amount of remaining input is greater than the amount		 * bytes pulled from the current input word, need to do another		 * word load.  What's left in inWord will be consumed in step 3.		 */		if (inputLen > WORDSIZE - inOffset)			inWord |= *pInWord RSH bufShift;	} else {		for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {			inWord = *pInWord++;			ARCFOUR_NEXT_WORD();			*pOutWord++ = inWord ^ streamWord;		}		if (inputLen == 0) {			/* Nothing left to do. */			cx->i = tmpi;			cx->j = tmpj;			return SECSuccess;		} else {			/* A partial input word remains at the tail.  Load it.  The			 * relevant bytes will be consumed in step 3.			 */			inWord = *pInWord;		}	}	/*****************************************************************/	/* Step 3:                                                       */	/* A partial word of input remains, and it is already loaded     */	/* into nextInWord.  Shift appropriately and consume the bytes   */	/* used in the partial word.                                     */	/*****************************************************************/	mask = streamWord = 0;#ifdef IS_LITTLE_ENDIAN	for (i = 0; i < inputLen; ++i) {#else	for (i = WORDSIZE - 1; i >= WORDSIZE - inputLen; --i) {#endif		ARCFOUR_NEXT_BYTE();		streamWord |= (WORD)(cx->S[t]) << 8*i;		mask |= 0xff << 8*i;	}	*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);	cx->i = tmpi;	cx->j = tmpj;	return SECSuccess;}SECStatus RC4_Encrypt(RC4Context *cx, unsigned char *output,            unsigned int *outputLen, unsigned int maxOutputLen,            const unsigned char *input, unsigned int inputLen){	PORT_Assert(maxOutputLen >= inputLen);	if (maxOutputLen < inputLen) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}#ifdef CONVERT_TO_WORDS	/* Convert the byte-stream to a word-stream */	return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);#else	/* Operate on bytes, but unroll the main loop */	return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);#endif}SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,                      unsigned int *outputLen, unsigned int maxOutputLen,                      const unsigned char *input, unsigned int inputLen){	PORT_Assert(maxOutputLen >= inputLen);	if (maxOutputLen < inputLen) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}	/* decrypt and encrypt are same operation. */#ifdef CONVERT_TO_WORDS	/* Convert the byte-stream to a word-stream */	return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);#else	/* Operate on bytes, but unroll the main loop */	return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);#endif}#undef CONVERT_TO_WORDS#undef USE_LONG

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?