1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 
11 #include "tomcrypt_private.h"
12 
13 #ifdef LTC_RC4_STREAM
14 
15 /**
16    Initialize an RC4 context (only the key)
17    @param st        [out] The destination of the RC4 state
18    @param key       The secret key
19    @param keylen    The length of the secret key (8 - 256 bytes)
20    @return CRYPT_OK if successful
21 */
rc4_stream_setup(rc4_state * st,const unsigned char * key,unsigned long keylen)22 int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen)
23 {
24    unsigned char tmp, *s;
25    int x, y;
26    unsigned long j;
27 
28    LTC_ARGCHK(st  != NULL);
29    LTC_ARGCHK(key != NULL);
30    LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */
31 
32    s = st->buf;
33    for (x = 0; x < 256; x++) {
34       s[x] = x;
35    }
36 
37    for (j = x = y = 0; x < 256; x++) {
38       y = (y + s[x] + key[j++]) & 255;
39       if (j == keylen) {
40          j = 0;
41       }
42       tmp = s[x]; s[x] = s[y]; s[y] = tmp;
43    }
44    st->x = 0;
45    st->y = 0;
46 
47    return CRYPT_OK;
48 }
49 
50 /**
51    Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4
52    @param st      The RC4 state
53    @param in      The plaintext (or ciphertext)
54    @param inlen   The length of the input (octets)
55    @param out     [out] The ciphertext (or plaintext), length inlen
56    @return CRYPT_OK if successful
57 */
rc4_stream_crypt(rc4_state * st,const unsigned char * in,unsigned long inlen,unsigned char * out)58 int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
59 {
60    unsigned char x, y, *s, tmp;
61 
62    LTC_ARGCHK(st  != NULL);
63    LTC_ARGCHK(in  != NULL);
64    LTC_ARGCHK(out != NULL);
65 
66    x = st->x;
67    y = st->y;
68    s = st->buf;
69    while (inlen--) {
70       x = (x + 1) & 255;
71       y = (y + s[x]) & 255;
72       tmp = s[x]; s[x] = s[y]; s[y] = tmp;
73       tmp = (s[x] + s[y]) & 255;
74       *out++ = *in++ ^ s[tmp];
75    }
76    st->x = x;
77    st->y = y;
78    return CRYPT_OK;
79 }
80 
81 /**
82   Generate a stream of random bytes via RC4
83   @param st      The RC420 state
84   @param out     [out] The output buffer
85   @param outlen  The output length
86   @return CRYPT_OK on success
87  */
rc4_stream_keystream(rc4_state * st,unsigned char * out,unsigned long outlen)88 int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen)
89 {
90    if (outlen == 0) return CRYPT_OK; /* nothing to do */
91    LTC_ARGCHK(out != NULL);
92    XMEMSET(out, 0, outlen);
93    return rc4_stream_crypt(st, out, outlen, out);
94 }
95 
96 /**
97   Terminate and clear RC4 state
98   @param st      The RC4 state
99   @return CRYPT_OK on success
100 */
rc4_stream_done(rc4_state * st)101 int rc4_stream_done(rc4_state *st)
102 {
103    LTC_ARGCHK(st != NULL);
104    XMEMSET(st, 0, sizeof(rc4_state));
105    return CRYPT_OK;
106 }
107 
108 #endif
109 
110 /* ref:         $Format:%D$ */
111 /* git commit:  $Format:%H$ */
112 /* commit time: $Format:%ai$ */
113