tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

arcfour.c (19061B)


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