Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/freebl/arcfour.c
Line
Count
Source (jump to first uncovered line)
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
0
#define ARCFOUR_STATE_SIZE 256
47
48
#define MASK1BYTE (WORD)(0xff)
49
50
#define SWAP(a, b) \
51
0
    tmp = a;       \
52
0
    a = b;         \
53
0
    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
0
{
111
0
    return PORT_ZNew(RC4Context);
112
0
}
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
0
{
119
0
    unsigned int i;
120
0
    PRUint8 j, tmp;
121
0
    PRUint8 K[256];
122
0
    PRUint8 *L;
123
124
    /* verify the key length. */
125
0
    PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
126
0
    if (len == 0 || len >= ARCFOUR_STATE_SIZE) {
127
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
128
0
        return SECFailure;
129
0
    }
130
0
    if (cx == NULL) {
131
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
132
0
        return SECFailure;
133
0
    }
134
    /* Initialize the state using array indices. */
135
0
    memcpy(cx->S, Kinit, sizeof cx->S);
136
    /* Fill in K repeatedly with values from key. */
137
0
    L = K;
138
0
    for (i = sizeof K; i > len; i -= len) {
139
0
        memcpy(L, key, len);
140
0
        L += len;
141
0
    }
142
0
    memcpy(L, key, i);
143
    /* Stir the state of the generator.  At this point it is assumed
144
     * that the key is the size of the state buffer.  If this is not
145
     * the case, the key bytes are repeated to fill the buffer.
146
     */
147
0
    j = 0;
148
0
#define ARCFOUR_STATE_STIR(ii) \
149
0
    j = j + cx->S[ii] + K[ii]; \
150
0
    SWAP(cx->S[ii], cx->S[j]);
151
0
    for (i = 0; i < ARCFOUR_STATE_SIZE; i++) {
152
0
        ARCFOUR_STATE_STIR(i);
153
0
    }
154
0
    cx->i = 0;
155
0
    cx->j = 0;
156
0
    return SECSuccess;
157
0
}
158
159
/*
160
 * Initialize a new generator.
161
 */
162
RC4Context *
163
RC4_CreateContext(const unsigned char *key, int len)
164
0
{
165
0
    RC4Context *cx = RC4_AllocateContext();
166
0
    if (cx) {
167
0
        SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0);
168
0
        if (rv != SECSuccess) {
169
0
            PORT_ZFree(cx, sizeof(*cx));
170
0
            cx = NULL;
171
0
        }
172
0
    }
173
0
    return cx;
174
0
}
175
176
void
177
RC4_DestroyContext(RC4Context *cx, PRBool freeit)
178
0
{
179
0
    if (freeit)
180
0
        PORT_ZFree(cx, sizeof(*cx));
181
0
}
182
183
#if defined(NSS_BEVAND_ARCFOUR)
184
extern void ARCFOUR(RC4Context *cx, WORD inputLen,
185
                    const unsigned char *input, unsigned char *output);
186
#else
187
/*
188
 * Generate the next byte in the stream.
189
 */
190
#define ARCFOUR_NEXT_BYTE() \
191
    tmpSi = cx->S[++tmpi];  \
192
    tmpj += tmpSi;          \
193
    tmpSj = cx->S[tmpj];    \
194
    cx->S[tmpi] = tmpSj;    \
195
    cx->S[tmpj] = tmpSi;    \
196
    t = tmpSi + tmpSj;
197
198
#ifdef CONVERT_TO_WORDS
199
/*
200
 * Straight ARCFOUR op.  No optimization.
201
 */
202
static SECStatus
203
rc4_no_opt(RC4Context *cx, unsigned char *output,
204
           unsigned int *outputLen, unsigned int maxOutputLen,
205
           const unsigned char *input, unsigned int inputLen)
206
{
207
    PRUint8 t;
208
    Stype tmpSi, tmpSj;
209
    register PRUint8 tmpi = cx->i;
210
    register PRUint8 tmpj = cx->j;
211
    unsigned int index;
212
    PORT_Assert(maxOutputLen >= inputLen);
213
    if (maxOutputLen < inputLen) {
214
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
215
        return SECFailure;
216
    }
217
    for (index = 0; index < inputLen; index++) {
218
        /* Generate next byte from stream. */
219
        ARCFOUR_NEXT_BYTE();
220
        /* output = next stream byte XOR next input byte */
221
        output[index] = cx->S[t] ^ input[index];
222
    }
223
    *outputLen = inputLen;
224
    cx->i = tmpi;
225
    cx->j = tmpj;
226
    return SECSuccess;
227
}
228
229
#else
230
/* !CONVERT_TO_WORDS */
231
232
/*
233
 * Byte-at-a-time ARCFOUR, unrolling the loop into 8 pieces.
234
 */
235
static SECStatus
236
rc4_unrolled(RC4Context *cx, unsigned char *output,
237
             unsigned int *outputLen, unsigned int maxOutputLen,
238
             const unsigned char *input, unsigned int inputLen)
239
{
240
    PRUint8 t;
241
    Stype tmpSi, tmpSj;
242
    register PRUint8 tmpi = cx->i;
243
    register PRUint8 tmpj = cx->j;
244
    int index;
245
    PORT_Assert(maxOutputLen >= inputLen);
246
    if (maxOutputLen < inputLen) {
247
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
248
        return SECFailure;
249
    }
250
    for (index = inputLen / 8; index-- > 0; input += 8, output += 8) {
251
        ARCFOUR_NEXT_BYTE();
252
        output[0] = cx->S[t] ^ input[0];
253
        ARCFOUR_NEXT_BYTE();
254
        output[1] = cx->S[t] ^ input[1];
255
        ARCFOUR_NEXT_BYTE();
256
        output[2] = cx->S[t] ^ input[2];
257
        ARCFOUR_NEXT_BYTE();
258
        output[3] = cx->S[t] ^ input[3];
259
        ARCFOUR_NEXT_BYTE();
260
        output[4] = cx->S[t] ^ input[4];
261
        ARCFOUR_NEXT_BYTE();
262
        output[5] = cx->S[t] ^ input[5];
263
        ARCFOUR_NEXT_BYTE();
264
        output[6] = cx->S[t] ^ input[6];
265
        ARCFOUR_NEXT_BYTE();
266
        output[7] = cx->S[t] ^ input[7];
267
    }
268
    index = inputLen % 8;
269
    if (index) {
270
        input += index;
271
        output += index;
272
        switch (index) {
273
            case 7:
274
                ARCFOUR_NEXT_BYTE();
275
                output[-7] = cx->S[t] ^ input[-7]; /* FALLTHRU */
276
            case 6:
277
                ARCFOUR_NEXT_BYTE();
278
                output[-6] = cx->S[t] ^ input[-6]; /* FALLTHRU */
279
            case 5:
280
                ARCFOUR_NEXT_BYTE();
281
                output[-5] = cx->S[t] ^ input[-5]; /* FALLTHRU */
282
            case 4:
283
                ARCFOUR_NEXT_BYTE();
284
                output[-4] = cx->S[t] ^ input[-4]; /* FALLTHRU */
285
            case 3:
286
                ARCFOUR_NEXT_BYTE();
287
                output[-3] = cx->S[t] ^ input[-3]; /* FALLTHRU */
288
            case 2:
289
                ARCFOUR_NEXT_BYTE();
290
                output[-2] = cx->S[t] ^ input[-2]; /* FALLTHRU */
291
            case 1:
292
                ARCFOUR_NEXT_BYTE();
293
                output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */
294
            default:
295
                /* FALLTHRU */
296
                ; /* hp-ux build breaks without this */
297
        }
298
    }
299
    cx->i = tmpi;
300
    cx->j = tmpj;
301
    *outputLen = inputLen;
302
    return SECSuccess;
303
}
304
#endif
305
306
#ifdef IS_LITTLE_ENDIAN
307
#define ARCFOUR_NEXT4BYTES_L(n)               \
308
    ARCFOUR_NEXT_BYTE();                      \
309
    streamWord |= (WORD)cx->S[t] << (n);      \
310
    ARCFOUR_NEXT_BYTE();                      \
311
    streamWord |= (WORD)cx->S[t] << (n + 8);  \
312
    ARCFOUR_NEXT_BYTE();                      \
313
    streamWord |= (WORD)cx->S[t] << (n + 16); \
314
    ARCFOUR_NEXT_BYTE();                      \
315
    streamWord |= (WORD)cx->S[t] << (n + 24);
316
#else
317
#define ARCFOUR_NEXT4BYTES_B(n)               \
318
    ARCFOUR_NEXT_BYTE();                      \
319
    streamWord |= (WORD)cx->S[t] << (n + 24); \
320
    ARCFOUR_NEXT_BYTE();                      \
321
    streamWord |= (WORD)cx->S[t] << (n + 16); \
322
    ARCFOUR_NEXT_BYTE();                      \
323
    streamWord |= (WORD)cx->S[t] << (n + 8);  \
324
    ARCFOUR_NEXT_BYTE();                      \
325
    streamWord |= (WORD)cx->S[t] << (n);
326
#endif
327
328
#if (defined(IS_64) && !defined(__sparc)) || defined(NSS_USE_64)
329
/* 64-bit wordsize */
330
#ifdef IS_LITTLE_ENDIAN
331
#define ARCFOUR_NEXT_WORD()       \
332
    {                             \
333
        streamWord = 0;           \
334
        ARCFOUR_NEXT4BYTES_L(0);  \
335
        ARCFOUR_NEXT4BYTES_L(32); \
336
    }
337
#else
338
#define ARCFOUR_NEXT_WORD()       \
339
    {                             \
340
        streamWord = 0;           \
341
        ARCFOUR_NEXT4BYTES_B(32); \
342
        ARCFOUR_NEXT4BYTES_B(0);  \
343
    }
344
#endif
345
#else
346
/* 32-bit wordsize */
347
#ifdef IS_LITTLE_ENDIAN
348
#define ARCFOUR_NEXT_WORD()      \
349
    {                            \
350
        streamWord = 0;          \
351
        ARCFOUR_NEXT4BYTES_L(0); \
352
    }
353
#else
354
#define ARCFOUR_NEXT_WORD()      \
355
    {                            \
356
        streamWord = 0;          \
357
        ARCFOUR_NEXT4BYTES_B(0); \
358
    }
359
#endif
360
#endif
361
362
#ifdef IS_LITTLE_ENDIAN
363
#define RSH <<
364
#define LSH >>
365
#else
366
#define RSH >>
367
#define LSH <<
368
#endif
369
370
#ifdef IS_LITTLE_ENDIAN
371
#define LEFTMOST_BYTE_SHIFT 0
372
#define NEXT_BYTE_SHIFT(shift) shift + 8
373
#else
374
#define LEFTMOST_BYTE_SHIFT 8 * (WORDSIZE - 1)
375
#define NEXT_BYTE_SHIFT(shift) shift - 8
376
#endif
377
378
#ifdef CONVERT_TO_WORDS
379
static SECStatus
380
rc4_wordconv(RC4Context *cx, unsigned char *output,
381
             unsigned int *outputLen, unsigned int maxOutputLen,
382
             const unsigned char *input, unsigned int inputLen)
383
{
384
    PR_STATIC_ASSERT(sizeof(PRUword) == sizeof(ptrdiff_t));
385
    unsigned int inOffset = (PRUword)input % WORDSIZE;
386
    unsigned int outOffset = (PRUword)output % WORDSIZE;
387
    register WORD streamWord;
388
    register const WORD *pInWord;
389
    register WORD *pOutWord;
390
    register WORD inWord, nextInWord;
391
    PRUint8 t;
392
    register Stype tmpSi, tmpSj;
393
    register PRUint8 tmpi = cx->i;
394
    register PRUint8 tmpj = cx->j;
395
    unsigned int bufShift, invBufShift;
396
    unsigned int i;
397
    const unsigned char *finalIn;
398
    unsigned char *finalOut;
399
400
    PORT_Assert(maxOutputLen >= inputLen);
401
    if (maxOutputLen < inputLen) {
402
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
403
        return SECFailure;
404
    }
405
    if (inputLen < 2 * WORDSIZE) {
406
        /* Ignore word conversion, do byte-at-a-time */
407
        return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);
408
    }
409
    *outputLen = inputLen;
410
    pInWord = (const WORD *)(input - inOffset);
411
    pOutWord = (WORD *)(output - outOffset);
412
    if (inOffset <= outOffset) {
413
        bufShift = 8 * (outOffset - inOffset);
414
        invBufShift = 8 * WORDSIZE - bufShift;
415
    } else {
416
        invBufShift = 8 * (inOffset - outOffset);
417
        bufShift = 8 * WORDSIZE - invBufShift;
418
    }
419
    /*****************************************************************/
420
    /* Step 1:                                                       */
421
    /* If the first output word is partial, consume the bytes in the */
422
    /* first partial output word by loading one or two words of      */
423
    /* input and shifting them accordingly.  Otherwise, just load    */
424
    /* in the first word of input.  At the end of this block, at     */
425
    /* least one partial word of input should ALWAYS be loaded.      */
426
    /*****************************************************************/
427
    if (outOffset) {
428
        unsigned int byteCount = WORDSIZE - outOffset;
429
        for (i = 0; i < byteCount; i++) {
430
            ARCFOUR_NEXT_BYTE();
431
            output[i] = cx->S[t] ^ input[i];
432
        }
433
        /* Consumed byteCount bytes of input */
434
        inputLen -= byteCount;
435
        pInWord++;
436
437
        /* move to next word of output */
438
        pOutWord++;
439
440
        /* If buffers are relatively misaligned, shift the bytes in inWord
441
         * to be aligned to the output buffer.
442
         */
443
        if (inOffset < outOffset) {
444
            /* The first input word (which may be partial) has more bytes
445
             * than needed.  Copy the remainder to inWord.
446
             */
447
            unsigned int shift = LEFTMOST_BYTE_SHIFT;
448
            inWord = 0;
449
            for (i = 0; i < outOffset - inOffset; i++) {
450
                inWord |= (WORD)input[byteCount + i] << shift;
451
                shift = NEXT_BYTE_SHIFT(shift);
452
            }
453
        } else if (inOffset > outOffset) {
454
            /* Consumed some bytes in the second input word.  Copy the
455
             * remainder to inWord.
456
             */
457
            inWord = *pInWord++;
458
            inWord = inWord LSH invBufShift;
459
        } else {
460
            inWord = 0;
461
        }
462
    } else {
463
        /* output is word-aligned */
464
        if (inOffset) {
465
            /* Input is not word-aligned.  The first word load of input
466
             * will not produce a full word of input bytes, so one word
467
             * must be pre-loaded.  The main loop below will load in the
468
             * next input word and shift some of its bytes into inWord
469
             * in order to create a full input word.  Note that the main
470
             * loop must execute at least once because the input must
471
             * be at least two words.
472
             */
473
            unsigned int shift = LEFTMOST_BYTE_SHIFT;
474
            inWord = 0;
475
            for (i = 0; i < WORDSIZE - inOffset; i++) {
476
                inWord |= (WORD)input[i] << shift;
477
                shift = NEXT_BYTE_SHIFT(shift);
478
            }
479
            pInWord++;
480
        } else {
481
            /* Input is word-aligned.  The first word load of input
482
             * will produce a full word of input bytes, so nothing
483
             * needs to be loaded here.
484
             */
485
            inWord = 0;
486
        }
487
    }
488
    /*****************************************************************/
489
    /* Step 2: main loop                                             */
490
    /* At this point the output buffer is word-aligned.  Any unused  */
491
    /* bytes from above will be in inWord (shifted correctly).  If   */
492
    /* the input buffer is unaligned relative to the output buffer,  */
493
    /* shifting has to be done.                                      */
494
    /*****************************************************************/
495
    if (bufShift) {
496
        /* preloadedByteCount is the number of input bytes pre-loaded
497
         * in inWord.
498
         */
499
        unsigned int preloadedByteCount = bufShift / 8;
500
        for (; inputLen >= preloadedByteCount + WORDSIZE;
501
             inputLen -= WORDSIZE) {
502
            nextInWord = *pInWord++;
503
            inWord |= nextInWord RSH bufShift;
504
            nextInWord = nextInWord LSH invBufShift;
505
            ARCFOUR_NEXT_WORD();
506
            *pOutWord++ = inWord ^ streamWord;
507
            inWord = nextInWord;
508
        }
509
        if (inputLen == 0) {
510
            /* Nothing left to do. */
511
            cx->i = tmpi;
512
            cx->j = tmpj;
513
            return SECSuccess;
514
        }
515
        finalIn = (const unsigned char *)pInWord - preloadedByteCount;
516
    } else {
517
        for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
518
            inWord = *pInWord++;
519
            ARCFOUR_NEXT_WORD();
520
            *pOutWord++ = inWord ^ streamWord;
521
        }
522
        if (inputLen == 0) {
523
            /* Nothing left to do. */
524
            cx->i = tmpi;
525
            cx->j = tmpj;
526
            return SECSuccess;
527
        }
528
        finalIn = (const unsigned char *)pInWord;
529
    }
530
    /*****************************************************************/
531
    /* Step 3:                                                       */
532
    /* Do the remaining partial word of input one byte at a time.    */
533
    /*****************************************************************/
534
    finalOut = (unsigned char *)pOutWord;
535
    for (i = 0; i < inputLen; i++) {
536
        ARCFOUR_NEXT_BYTE();
537
        finalOut[i] = cx->S[t] ^ finalIn[i];
538
    }
539
    cx->i = tmpi;
540
    cx->j = tmpj;
541
    return SECSuccess;
542
}
543
#endif
544
#endif /* NSS_BEVAND_ARCFOUR */
545
546
SECStatus
547
RC4_Encrypt(RC4Context *cx, unsigned char *output,
548
            unsigned int *outputLen, unsigned int maxOutputLen,
549
            const unsigned char *input, unsigned int inputLen)
550
0
{
551
0
    PORT_Assert(maxOutputLen >= inputLen);
552
0
    if (maxOutputLen < inputLen) {
553
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
554
0
        return SECFailure;
555
0
    }
556
0
#if defined(NSS_BEVAND_ARCFOUR)
557
0
    ARCFOUR(cx, inputLen, input, output);
558
0
    *outputLen = inputLen;
559
0
    return SECSuccess;
560
#elif defined(CONVERT_TO_WORDS)
561
    /* Convert the byte-stream to a word-stream */
562
    return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
563
#else
564
    /* Operate on bytes, but unroll the main loop */
565
    return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
566
#endif
567
0
}
568
569
SECStatus
570
RC4_Decrypt(RC4Context *cx, unsigned char *output,
571
            unsigned int *outputLen, unsigned int maxOutputLen,
572
            const unsigned char *input, unsigned int inputLen)
573
0
{
574
0
    PORT_Assert(maxOutputLen >= inputLen);
575
0
    if (maxOutputLen < inputLen) {
576
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
577
0
        return SECFailure;
578
0
    }
579
/* decrypt and encrypt are same operation. */
580
0
#if defined(NSS_BEVAND_ARCFOUR)
581
0
    ARCFOUR(cx, inputLen, input, output);
582
0
    *outputLen = inputLen;
583
0
    return SECSuccess;
584
#elif defined(CONVERT_TO_WORDS)
585
    /* Convert the byte-stream to a word-stream */
586
    return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
587
#else
588
    /* Operate on bytes, but unroll the main loop */
589
    return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
590
#endif
591
0
}
592
593
#undef CONVERT_TO_WORDS
594
#undef USE_WORD