/* arcfour.c - the arc four algorithm. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND #include"stubs.h" #endif
#include"prerr.h" #include"secerr.h"
#include"prtypes.h" #include"blapi.h"
/* Architecture-dependent defines */
#ifdefined(SOLARIS) || defined(HPUX) || defined(NSS_X86) || \ defined(_WIN64) /* Convert the byte-stream to a word-stream */ #define CONVERT_TO_WORDS #endif
#ifdefined(AIX) || defined(NSS_BEVAND_ARCFOUR) /* Treat array variables as words, not bytes, on CPUs that take * much longer to write bytes than to write words, or when using * assembler code that required it.
*/ #define USE_WORD #endif
/* verify the key length. */
PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE); if (len == 0 || len >= ARCFOUR_STATE_SIZE) {
PORT_SetError(SEC_ERROR_BAD_KEY); return SECFailure;
} if (cx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
} /* Initialize the state using array indices. */
memcpy(cx->S, Kinit, sizeof cx->S); /* Fill in K repeatedly with values from key. */
L = K; for (i = sizeof K; i > len; i -= len) {
memcpy(L, key, len);
L += len;
}
memcpy(L, key, i); /* Stir the state of the generator. At this point it is assumed * that the key is the size of the state buffer. If this is not * the case, the key bytes are repeated to fill the buffer.
*/
j = 0; #define ARCFOUR_STATE_STIR(ii) \
j = j + cx->S[ii] + K[ii]; \
SWAP(cx->S[ii], cx->S[j]); for (i = 0; i < ARCFOUR_STATE_SIZE; i++) {
ARCFOUR_STATE_STIR(i);
}
cx->i = 0;
cx->j = 0; return SECSuccess;
}
/* * Initialize a new generator.
*/
RC4Context *
RC4_CreateContext(constunsignedchar *key, int len)
{
RC4Context *cx = RC4_AllocateContext(); if (cx) {
SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0); if (rv != SECSuccess) {
PORT_ZFree(cx, sizeof(*cx));
cx = NULL;
}
} return cx;
}
PORT_Assert(maxOutputLen >= inputLen); if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN); 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 = (const WORD *)(input - inOffset);
pOutWord = (WORD *)(output - outOffset); 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) { unsignedint byteCount = WORDSIZE - outOffset; for (i = 0; i < byteCount; i++) {
ARCFOUR_NEXT_BYTE();
output[i] = cx->S[t] ^ input[i];
} /* Consumed byteCount bytes of input */
inputLen -= byteCount;
pInWord++;
/* move to next word of output */
pOutWord++;
/* If buffers are relatively misaligned, shift the bytes in inWord * to be aligned to the output buffer.
*/ if (inOffset < outOffset) { /* The first input word (which may be partial) has more bytes * than needed. Copy the remainder to inWord.
*/ unsignedint shift = LEFTMOST_BYTE_SHIFT;
inWord = 0; for (i = 0; i < outOffset - inOffset; i++) {
inWord |= (WORD)input[byteCount + i] << shift;
shift = NEXT_BYTE_SHIFT(shift);
}
} elseif (inOffset > outOffset) { /* Consumed some bytes in the second input word. Copy the * remainder to inWord.
*/
inWord = *pInWord++;
inWord = inWord LSH invBufShift;
} else {
inWord = 0;
}
} else { /* output is word-aligned */ 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.
*/ unsignedint shift = LEFTMOST_BYTE_SHIFT;
inWord = 0; for (i = 0; i < WORDSIZE - inOffset; i++) {
inWord |= (WORD)input[i] << shift;
shift = NEXT_BYTE_SHIFT(shift);
}
pInWord++;
} 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;
}
} /*****************************************************************/ /* 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 (bufShift) { /* preloadedByteCount is the number of input bytes pre-loaded * in inWord.
*/ unsignedint preloadedByteCount = bufShift / 8; for (; inputLen >= preloadedByteCount + 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;
}
finalIn = (constunsignedchar *)pInWord - preloadedByteCount;
} 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;
}
finalIn = (constunsignedchar *)pInWord;
} /*****************************************************************/ /* Step 3: */ /* Do the remaining partial word of input one byte at a time. */ /*****************************************************************/
finalOut = (unsignedchar *)pOutWord; for (i = 0; i < inputLen; i++) {
ARCFOUR_NEXT_BYTE();
finalOut[i] = cx->S[t] ^ finalIn[i];
}
cx->i = tmpi;
cx->j = tmpj; return SECSuccess;
} #endif #endif/* NSS_BEVAND_ARCFOUR */
SECStatus
RC4_Encrypt(RC4Context *cx, unsignedchar *output, unsignedint *outputLen, unsignedint maxOutputLen, constunsignedchar *input, unsignedint inputLen)
{
PORT_Assert(maxOutputLen >= inputLen); if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN); return SECFailure;
} #ifdefined(NSS_BEVAND_ARCFOUR)
ARCFOUR(cx, inputLen, input, output);
*outputLen = inputLen; return SECSuccess; #elifdefined(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, unsignedchar *output, unsignedint *outputLen, unsignedint maxOutputLen, constunsignedchar *input, unsignedint inputLen)
{
PORT_Assert(maxOutputLen >= inputLen); if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN); return SECFailure;
} /* decrypt and encrypt are same operation. */ #ifdefined(NSS_BEVAND_ARCFOUR)
ARCFOUR(cx, inputLen, input, output);
*outputLen = inputLen; return SECSuccess; #elifdefined(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_WORD
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-06)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.