Mercurial > dropbear
comparison rc4.c @ 143:5d99163f7e32 libtomcrypt-orig
import of libtomcrypt 0.99
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 19 Dec 2004 11:34:45 +0000 |
parents | 7faae8f46238 |
children |
comparison
equal
deleted
inserted
replaced
15:6362d3854bb4 | 143:5d99163f7e32 |
---|---|
12 | 12 |
13 #ifdef RC4 | 13 #ifdef RC4 |
14 | 14 |
15 const struct _prng_descriptor rc4_desc = | 15 const struct _prng_descriptor rc4_desc = |
16 { | 16 { |
17 "rc4", | 17 "rc4", 32, |
18 &rc4_start, | 18 &rc4_start, |
19 &rc4_add_entropy, | 19 &rc4_add_entropy, |
20 &rc4_ready, | 20 &rc4_ready, |
21 &rc4_read | 21 &rc4_read, |
22 &rc4_done, | |
23 &rc4_export, | |
24 &rc4_import, | |
25 &rc4_test | |
22 }; | 26 }; |
23 | 27 |
24 int rc4_start(prng_state *prng) | 28 int rc4_start(prng_state *prng) |
25 { | 29 { |
26 _ARGCHK(prng != NULL); | 30 _ARGCHK(prng != NULL); |
31 return CRYPT_OK; | 35 return CRYPT_OK; |
32 } | 36 } |
33 | 37 |
34 int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) | 38 int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) |
35 { | 39 { |
36 _ARGCHK(buf != NULL); | 40 _ARGCHK(buf != NULL); |
37 _ARGCHK(prng != NULL); | 41 _ARGCHK(prng != NULL); |
38 | 42 |
43 /* trim as required */ | |
39 if (prng->rc4.x + len > 256) { | 44 if (prng->rc4.x + len > 256) { |
40 return CRYPT_INVALID_KEYSIZE; | 45 if (prng->rc4.x == 256) { |
46 /* I can't possibly accept another byte, ok maybe a mint wafer... */ | |
47 return CRYPT_OK; | |
48 } else { | |
49 /* only accept part of it */ | |
50 len = 256 - prng->rc4.x; | |
51 } | |
41 } | 52 } |
42 | 53 |
43 while (len--) { | 54 while (len--) { |
44 prng->rc4.buf[prng->rc4.x++] = *buf++; | 55 prng->rc4.buf[prng->rc4.x++] = *buf++; |
45 } | 56 } |
48 | 59 |
49 } | 60 } |
50 | 61 |
51 int rc4_ready(prng_state *prng) | 62 int rc4_ready(prng_state *prng) |
52 { | 63 { |
53 unsigned char key[256], tmp; | 64 unsigned char key[256], tmp, *s; |
54 int keylen, x, y; | 65 int keylen, x, y, j; |
55 | 66 |
56 _ARGCHK(prng != NULL); | 67 _ARGCHK(prng != NULL); |
57 | 68 |
58 /* extract the key */ | 69 /* extract the key */ |
59 memcpy(key, prng->rc4.buf, 256); | 70 s = prng->rc4.buf; |
71 XMEMCPY(key, s, 256); | |
60 keylen = prng->rc4.x; | 72 keylen = prng->rc4.x; |
61 | 73 |
62 /* make RC4 perm and shuffle */ | 74 /* make RC4 perm and shuffle */ |
63 for (x = 0; x < 256; x++) { | 75 for (x = 0; x < 256; x++) { |
64 prng->rc4.buf[x] = x; | 76 s[x] = x; |
65 } | 77 } |
66 | 78 |
67 for (x = y = 0; x < 256; x++) { | 79 for (j = x = y = 0; x < 256; x++) { |
68 y = (y + prng->rc4.buf[x] + key[x % keylen]) & 255; | 80 y = (y + prng->rc4.buf[x] + key[j++]) & 255; |
69 tmp = prng->rc4.buf[x]; prng->rc4.buf[x] = prng->rc4.buf[y]; prng->rc4.buf[y] = tmp; | 81 if (j == keylen) { |
70 } | 82 j = 0; |
71 prng->rc4.x = x; | 83 } |
72 prng->rc4.y = y; | 84 tmp = s[x]; s[x] = s[y]; s[y] = tmp; |
85 } | |
86 prng->rc4.x = 0; | |
87 prng->rc4.y = 0; | |
73 | 88 |
74 #ifdef CLEAN_STACK | 89 #ifdef CLEAN_STACK |
75 zeromem(key, sizeof(key)); | 90 zeromem(key, sizeof(key)); |
76 #endif | 91 #endif |
77 | 92 |
78 return CRYPT_OK; | 93 return CRYPT_OK; |
79 } | 94 } |
80 | 95 |
81 unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng) | 96 unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng) |
82 { | 97 { |
83 int x, y; | 98 unsigned char x, y, *s, tmp; |
84 unsigned char *s, tmp; | |
85 unsigned long n; | 99 unsigned long n; |
86 | 100 |
87 _ARGCHK(buf != NULL); | 101 _ARGCHK(buf != NULL); |
88 _ARGCHK(prng != NULL); | 102 _ARGCHK(prng != NULL); |
89 | 103 |
101 prng->rc4.x = x; | 115 prng->rc4.x = x; |
102 prng->rc4.y = y; | 116 prng->rc4.y = y; |
103 return n; | 117 return n; |
104 } | 118 } |
105 | 119 |
106 #endif | 120 int rc4_done(prng_state *prng) |
107 | 121 { |
122 _ARGCHK(prng != NULL); | |
123 return CRYPT_OK; | |
124 } | |
125 | |
126 int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | |
127 { | |
128 _ARGCHK(outlen != NULL); | |
129 _ARGCHK(out != NULL); | |
130 _ARGCHK(prng != NULL); | |
131 | |
132 if (*outlen < 32) { | |
133 return CRYPT_BUFFER_OVERFLOW; | |
134 } | |
135 | |
136 if (rc4_read(out, 32, prng) != 32) { | |
137 return CRYPT_ERROR_READPRNG; | |
138 } | |
139 *outlen = 32; | |
140 | |
141 return CRYPT_OK; | |
142 } | |
143 | |
144 int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
145 { | |
146 int err; | |
147 _ARGCHK(in != NULL); | |
148 _ARGCHK(prng != NULL); | |
149 | |
150 if (inlen != 32) { | |
151 return CRYPT_INVALID_ARG; | |
152 } | |
153 | |
154 if ((err = rc4_start(prng)) != CRYPT_OK) { | |
155 return err; | |
156 } | |
157 return rc4_add_entropy(in, 32, prng); | |
158 } | |
159 | |
160 int rc4_test(void) | |
161 { | |
162 #ifndef LTC_TEST | |
163 return CRYPT_NOP; | |
164 #else | |
165 static const struct { | |
166 unsigned char key[8], pt[8], ct[8]; | |
167 } tests[] = { | |
168 { | |
169 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, | |
170 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, | |
171 { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 } | |
172 } | |
173 }; | |
174 prng_state prng; | |
175 unsigned char dst[8]; | |
176 int err, x; | |
177 | |
178 for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { | |
179 if ((err = rc4_start(&prng)) != CRYPT_OK) { | |
180 return err; | |
181 } | |
182 if ((err = rc4_add_entropy(tests[x].key, 8, &prng)) != CRYPT_OK) { | |
183 return err; | |
184 } | |
185 if ((err = rc4_ready(&prng)) != CRYPT_OK) { | |
186 return err; | |
187 } | |
188 XMEMCPY(dst, tests[x].pt, 8); | |
189 if (rc4_read(dst, 8, &prng) != 8) { | |
190 return CRYPT_ERROR_READPRNG; | |
191 } | |
192 rc4_done(&prng); | |
193 if (memcmp(dst, tests[x].ct, 8)) { | |
194 #if 0 | |
195 int y; | |
196 printf("\n\nRC4 failed, I got:\n"); | |
197 for (y = 0; y < 8; y++) printf("%02x ", dst[y]); | |
198 printf("\n"); | |
199 #endif | |
200 return CRYPT_FAIL_TESTVECTOR; | |
201 } | |
202 } | |
203 return CRYPT_OK; | |
204 #endif | |
205 } | |
206 | |
207 #endif | |
208 |