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