1
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
3
* LibTomCrypt is a library that provides various cryptographic
4
* algorithms in a highly modular and flexible manner.
6
* The library is free for all purposes without any express
9
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
15
RC4 PRNG, Tom St Denis
20
const struct ltc_prng_descriptor rc4_desc =
35
@param prng [out] The PRNG state to initialize
36
@return CRYPT_OK if successful
38
int rc4_start(prng_state *prng)
40
LTC_ARGCHK(prng != NULL);
42
/* set keysize to zero */
49
Add entropy to the PRNG state
50
@param in The data to add
51
@param inlen Length of the data to add
52
@param prng PRNG state to update
53
@return CRYPT_OK if successful
55
int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
57
LTC_ARGCHK(in != NULL);
58
LTC_ARGCHK(prng != NULL);
60
/* trim as required */
61
if (prng->rc4.x + inlen > 256) {
62
if (prng->rc4.x == 256) {
63
/* I can't possibly accept another byte, ok maybe a mint wafer... */
66
/* only accept part of it */
67
inlen = 256 - prng->rc4.x;
72
prng->rc4.buf[prng->rc4.x++] = *in++;
80
Make the PRNG ready to read from
81
@param prng The PRNG to make active
82
@return CRYPT_OK if successful
84
int rc4_ready(prng_state *prng)
86
unsigned char key[256], tmp, *s;
89
LTC_ARGCHK(prng != NULL);
96
/* make RC4 perm and shuffle */
97
for (x = 0; x < 256; x++) {
101
for (j = x = y = 0; x < 256; x++) {
102
y = (y + prng->rc4.buf[x] + key[j++]) & 255;
106
tmp = s[x]; s[x] = s[y]; s[y] = tmp;
111
#ifdef LTC_CLEAN_STACK
112
zeromem(key, sizeof(key));
120
@param out Destination
121
@param outlen Length of output
122
@param prng The active PRNG to read from
123
@return Number of octets read
125
unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng)
127
unsigned char x, y, *s, tmp;
130
LTC_ARGCHK(out != NULL);
131
LTC_ARGCHK(prng != NULL);
139
y = (y + s[x]) & 255;
140
tmp = s[x]; s[x] = s[y]; s[y] = tmp;
141
tmp = (s[x] + s[y]) & 255;
151
@param prng The PRNG to terminate
152
@return CRYPT_OK if successful
154
int rc4_done(prng_state *prng)
156
LTC_ARGCHK(prng != NULL);
161
Export the PRNG state
162
@param out [out] Destination
163
@param outlen [in/out] Max size and resulting size of the state
164
@param prng The PRNG to export
165
@return CRYPT_OK if successful
167
int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
169
LTC_ARGCHK(outlen != NULL);
170
LTC_ARGCHK(out != NULL);
171
LTC_ARGCHK(prng != NULL);
174
return CRYPT_BUFFER_OVERFLOW;
177
if (rc4_read(out, 32, prng) != 32) {
178
return CRYPT_ERROR_READPRNG;
187
@param in The PRNG state
188
@param inlen Size of the state
189
@param prng The PRNG to import
190
@return CRYPT_OK if successful
192
int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
195
LTC_ARGCHK(in != NULL);
196
LTC_ARGCHK(prng != NULL);
199
return CRYPT_INVALID_ARG;
202
if ((err = rc4_start(prng)) != CRYPT_OK) {
205
return rc4_add_entropy(in, 32, prng);
210
@return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
217
static const struct {
218
unsigned char key[8], pt[8], ct[8];
221
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
222
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
223
{ 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }
227
unsigned char dst[8];
230
for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
231
if ((err = rc4_start(&prng)) != CRYPT_OK) {
234
if ((err = rc4_add_entropy(tests[x].key, 8, &prng)) != CRYPT_OK) {
237
if ((err = rc4_ready(&prng)) != CRYPT_OK) {
240
XMEMCPY(dst, tests[x].pt, 8);
241
if (rc4_read(dst, 8, &prng) != 8) {
242
return CRYPT_ERROR_READPRNG;
245
if (memcmp(dst, tests[x].ct, 8)) {
248
printf("\n\nRC4 failed, I got:\n");
249
for (y = 0; y < 8; y++) printf("%02x ", dst[y]);
252
return CRYPT_FAIL_TESTVECTOR;
262
/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rc4.c,v $ */
263
/* $Revision: 1.3 $ */
264
/* $Date: 2005/05/05 14:35:59 $ */