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 + -
显示快捷键?