keccak stream ciphers added
[rofl0r-kripto.git] / lib / stream / rc4.c
blobda5f59e6f3cdd6cf51c548fcae27a903bed9cc33
1 /*
2 * Copyright (C) 2011 Gregor Pintar <grpintar@gmail.com>
4 * Permission is granted to deal in this work without any restriction,
5 * including unlimited rights to use, publicly perform, publish,
6 * reproduce, relicence, modify, merge, and/or distribute in any form,
7 * for any purpose, with or without fee, and by any means.
9 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind,
10 * to the utmost extent permitted by applicable law. In no event
11 * shall a licensor, author or contributor be held liable for any
12 * issues arising in any way out of dealing in the work.
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <limits.h>
18 #include <assert.h>
20 #include <kripto/cast.h>
21 #include <kripto/memwipe.h>
22 #include <kripto/stream.h>
23 #include <kripto/desc/stream.h>
25 #include <kripto/stream/rc4.h>
26 #include <kripto/stream/rc4i.h>
28 struct kripto_stream
30 const kripto_stream_desc *desc;
31 uint8_t p[256];
32 uint8_t i;
33 uint8_t j;
36 static void improved_setup
38 kripto_stream *s,
39 const void *key,
40 unsigned int key_len,
41 const void *iv,
42 unsigned int iv_len,
43 unsigned int rounds
46 unsigned int i;
47 unsigned int j;
48 uint8_t t;
50 s->i = s->j = 0;
52 for(i = 0; i < 256; i++) s->p[i] = i;
54 /* key */
55 if(key && key_len)
57 j = 0;
58 for(i = 0; i < rounds; i++)
60 s->j = s->j + s->p[s->i] + CU8(key)[j++];
61 if(j == key_len) j = 0;
63 t = s->p[s->i];
64 s->p[s->i] = s->p[s->j];
65 s->p[s->j] = t;
67 s->i++;
71 /* iv */
72 if(iv && iv_len)
74 j = 0;
75 for(i = 0; i < rounds; i++)
77 s->j = s->j + s->p[s->i] + CU8(iv)[j++];
78 if(j == iv_len) j = 0;
80 t = s->p[s->i];
81 s->p[s->i] = s->p[s->j];
82 s->p[s->j] = t;
84 s->i++;
87 /* key */
88 if(key && key_len)
90 j = 0;
91 for(i = 0; i < rounds; i++)
93 s->j = s->j + s->p[s->i] + CU8(key)[j++];
94 if(j == key_len) j = 0;
96 t = s->p[s->i];
97 s->p[s->i] = s->p[s->j];
98 s->p[s->j] = t;
100 s->i++;
105 s->i = s->j; /* original RC4: s->i = s->j = 0; */
108 static uint8_t rc4(kripto_stream *s)
110 uint8_t t;
112 s->i++;
113 s->j = s->j + s->p[s->i];
115 t = s->p[s->i];
116 s->p[s->i] = s->p[s->j];
117 s->p[s->j] = t;
119 return(s->p[(uint8_t)(s->p[s->i] + s->p[s->j])]);
122 static void rc4_crypt
124 kripto_stream *s,
125 const void *in,
126 void *out,
127 size_t len
130 size_t i;
132 for(i = 0; i < len; i++)
133 U8(out)[i] = CU8(in)[i] ^ rc4(s);
136 static void rc4_prng
138 kripto_stream *s,
139 void *out,
140 size_t len
143 size_t i;
145 for(i = 0; i < len; i++)
146 U8(out)[i] = rc4(s);
149 static kripto_stream *rc4i_recreate
151 kripto_stream *s,
152 unsigned int r,
153 const void *key,
154 unsigned int key_len,
155 const void *iv,
156 unsigned int iv_len
159 unsigned int rounds = r;
161 assert(key_len + iv_len <= 256);
162 if(!rounds) rounds = 512;
164 improved_setup(s, key, key_len, iv, iv_len, r);
166 return s;
169 static kripto_stream *rc4_recreate
171 kripto_stream *s,
172 unsigned int r,
173 const void *key,
174 unsigned int key_len,
175 const void *iv,
176 unsigned int iv_len
179 unsigned int i;
181 assert(key_len + iv_len <= 256);
183 improved_setup(s, key, key_len, iv, iv_len, 256);
185 s->i = s->j = 0;
187 /* drop ? */
188 for(i = 0; i < r; i++) (void)rc4(s);
190 return s;
193 static kripto_stream *rc4i_create
195 const kripto_stream_desc *desc,
196 unsigned int r,
197 const void *key,
198 unsigned int key_len,
199 const void *iv,
200 unsigned int iv_len
203 kripto_stream *s;
205 (void)desc;
207 s = malloc(sizeof(kripto_stream));
208 if(!s) return 0;
210 s->desc = kripto_stream_rc4i;
211 (void)rc4i_recreate(s, r, key, key_len, iv, iv_len);
213 return s;
216 static kripto_stream *rc4_create
218 const kripto_stream_desc *desc,
219 unsigned int r,
220 const void *key,
221 unsigned int key_len,
222 const void *iv,
223 unsigned int iv_len
226 kripto_stream *s;
227 unsigned int i;
229 s = rc4i_create(desc, 256, key, key_len, iv, iv_len);
230 if(!s) return 0;
232 s->desc = kripto_stream_rc4;
234 s->i = s->j = 0;
236 /* drop ? */
237 for(i = 0; i < r; i++) (void)rc4(s);
239 return s;
242 static void rc4_destroy(kripto_stream *s)
244 kripto_memwipe(s, sizeof(kripto_stream));
245 free(s);
248 /* RC4 */
249 static const struct kripto_stream_desc rc4_desc =
251 &rc4_create,
252 &rc4_recreate,
253 &rc4_crypt,
254 &rc4_crypt,
255 &rc4_prng,
256 &rc4_destroy,
258 256, /* max key */
259 0 /* max iv */
262 const kripto_stream_desc *const kripto_stream_rc4 = &rc4_desc;
264 /* RC4i */
265 static const struct kripto_stream_desc rc4i =
267 &rc4i_create,
268 &rc4i_recreate,
269 &rc4_crypt,
270 &rc4_crypt,
271 &rc4_prng,
272 &rc4_destroy,
274 256, /* max key */
275 256 /* max iv */
278 const kripto_stream_desc *const kripto_stream_rc4i = &rc4i;