Coverage Report

Created: 2025-07-11 07:04

/src/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
    if (len == 0 || len >= ARCFOUR_STATE_SIZE) {
126
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
127
0
        return SECFailure;
128
0
    }
129
0
    if (cx == NULL) {
130
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
131
0
        return SECFailure;
132
0
    }
133
    /* Initialize the state using array indices. */
134
0
    memcpy(cx->S, Kinit, sizeof cx->S);
135
    /* Fill in K repeatedly with values from key. */
136
0
    L = K;
137
0
    for (i = sizeof K; i > len; i -= len) {
138
0
        memcpy(L, key, len);
139
0
        L += len;
140
0
    }
141
0
    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
0
    j = 0;
147
0
#define ARCFOUR_STATE_STIR(ii) \
148
0
    j = j + cx->S[ii] + K[ii]; \
149
0
    SWAP(cx->S[ii], cx->S[j]);
150
0
    for (i = 0; i < ARCFOUR_STATE_SIZE; i++) {
151
0
        ARCFOUR_STATE_STIR(i);
152
0
    }
153
0
    cx->i = 0;
154
0
    cx->j = 0;
155
0
    return SECSuccess;
156
0
}
157
158
/*
159
 * Initialize a new generator.
160
 */
161
RC4Context *
162
RC4_CreateContext(const unsigned char *key, int len)
163
0
{
164
0
    RC4Context *cx = RC4_AllocateContext();
165
0
    if (cx) {
166
0
        SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0);
167
0
        if (rv != SECSuccess) {
168
0
            PORT_ZFree(cx, sizeof(*cx));
169
0
            cx = NULL;
170
0
        }
171
0
    }
172
0
    return cx;
173
0
}
174
175
void
176
RC4_DestroyContext(RC4Context *cx, PRBool freeit)
177
0
{
178
0
    if (freeit)
179
0
        PORT_ZFree(cx, sizeof(*cx));
180
0
}
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
0
{
550
0
    PORT_Assert(maxOutputLen >= inputLen);
551
0
    if (maxOutputLen < inputLen) {
552
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
553
0
        return SECFailure;
554
0
    }
555
0
#if defined(NSS_BEVAND_ARCFOUR)
556
0
    ARCFOUR(cx, inputLen, input, output);
557
0
    *outputLen = inputLen;
558
0
    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
0
}
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
0
{
573
0
    PORT_Assert(maxOutputLen >= inputLen);
574
0
    if (maxOutputLen < inputLen) {
575
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
576
0
        return SECFailure;
577
0
    }
578
/* decrypt and encrypt are same operation. */
579
0
#if defined(NSS_BEVAND_ARCFOUR)
580
0
    ARCFOUR(cx, inputLen, input, output);
581
0
    *outputLen = inputLen;
582
0
    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
0
}
591
592
#undef CONVERT_TO_WORDS
593
#undef USE_WORD