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.
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>
30 const kripto_stream_desc
*desc
;
36 static void improved_setup
52 for(i
= 0; i
< 256; i
++) s
->p
[i
] = i
;
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;
64 s
->p
[s
->i
] = s
->p
[s
->j
];
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;
81 s
->p
[s
->i
] = s
->p
[s
->j
];
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;
97 s
->p
[s
->i
] = s
->p
[s
->j
];
105 s
->i
= s
->j
; /* original RC4: s->i = s->j = 0; */
108 static uint8_t rc4(kripto_stream
*s
)
113 s
->j
= s
->j
+ s
->p
[s
->i
];
116 s
->p
[s
->i
] = s
->p
[s
->j
];
119 return(s
->p
[(uint8_t)(s
->p
[s
->i
] + s
->p
[s
->j
])]);
122 static void rc4_crypt
132 for(i
= 0; i
< len
; i
++)
133 U8(out
)[i
] = CU8(in
)[i
] ^ rc4(s
);
145 for(i
= 0; i
< len
; i
++)
149 static kripto_stream
*rc4i_recreate
154 unsigned int key_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
);
169 static kripto_stream
*rc4_recreate
174 unsigned int key_len
,
181 assert(key_len
+ iv_len
<= 256);
183 improved_setup(s
, key
, key_len
, iv
, iv_len
, 256);
188 for(i
= 0; i
< r
; i
++) (void)rc4(s
);
193 static kripto_stream
*rc4i_create
195 const kripto_stream_desc
*desc
,
198 unsigned int key_len
,
207 s
= malloc(sizeof(kripto_stream
));
210 s
->desc
= kripto_stream_rc4i
;
211 (void)rc4i_recreate(s
, r
, key
, key_len
, iv
, iv_len
);
216 static kripto_stream
*rc4_create
218 const kripto_stream_desc
*desc
,
221 unsigned int key_len
,
229 s
= rc4i_create(desc
, 256, key
, key_len
, iv
, iv_len
);
232 s
->desc
= kripto_stream_rc4
;
237 for(i
= 0; i
< r
; i
++) (void)rc4(s
);
242 static void rc4_destroy(kripto_stream
*s
)
244 kripto_memwipe(s
, sizeof(kripto_stream
));
249 static const struct kripto_stream_desc rc4_desc
=
262 const kripto_stream_desc
*const kripto_stream_rc4
= &rc4_desc
;
265 static const struct kripto_stream_desc rc4i
=
278 const kripto_stream_desc
*const kripto_stream_rc4i
= &rc4i
;