xref: /openbsd-src/sys/crypto/arc4.c (revision 753dd0db73c7ec9c639cb6ccdbeb9ecb87962a71)
1*753dd0dbSdjm /*	$OpenBSD: arc4.c,v 1.3 2007/09/11 12:07:05 djm Exp $	*/
238553144Smarkus /*
338553144Smarkus  * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
438553144Smarkus  *
538553144Smarkus  * Permission to use, copy, modify, and distribute this software for any
638553144Smarkus  * purpose with or without fee is hereby granted, provided that the above
738553144Smarkus  * copyright notice and this permission notice appear in all copies.
838553144Smarkus  *
938553144Smarkus  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1038553144Smarkus  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1138553144Smarkus  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1238553144Smarkus  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1338553144Smarkus  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1438553144Smarkus  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1538553144Smarkus  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1638553144Smarkus  */
1738553144Smarkus 
1838553144Smarkus #include <sys/types.h>
1938553144Smarkus 
2038553144Smarkus #include <crypto/arc4.h>
2138553144Smarkus 
2238553144Smarkus #define RC4SWAP(x,y) \
2338553144Smarkus 	do { \
2438553144Smarkus 		u_int8_t t = ctx->state[x];  \
2538553144Smarkus 		ctx->state[x] = ctx->state[y]; \
2638553144Smarkus 		ctx->state[y] = t; \
2738553144Smarkus 	} while(0)
2838553144Smarkus 
2938553144Smarkus void
rc4_keysetup(struct rc4_ctx * ctx,u_char * key,u_int32_t klen)3038553144Smarkus rc4_keysetup(struct rc4_ctx *ctx, u_char *key, u_int32_t klen)
3138553144Smarkus {
3238553144Smarkus 	u_int8_t x, y;
3338553144Smarkus 	u_int32_t i;
3438553144Smarkus 
3538553144Smarkus 	x = y = 0;
3638553144Smarkus 	for (i = 0; i < RC4STATE; i++)
3738553144Smarkus 		ctx->state[i] = i;
3838553144Smarkus 	for (i = 0; i < RC4STATE; i++) {
39*753dd0dbSdjm 		y = (key[x] + ctx->state[i] + y) & (RC4STATE - 1);
4038553144Smarkus 		RC4SWAP(i, y);
4138553144Smarkus 		x = (x + 1) % klen;
4238553144Smarkus 	}
4338553144Smarkus 	ctx->x = ctx->y = 0;
4438553144Smarkus }
4538553144Smarkus 
4638553144Smarkus void
rc4_crypt(struct rc4_ctx * ctx,u_char * src,u_char * dst,u_int32_t len)4738553144Smarkus rc4_crypt(struct rc4_ctx *ctx, u_char *src, u_char *dst,
4838553144Smarkus     u_int32_t len)
4938553144Smarkus {
5038553144Smarkus 	u_int32_t i;
5138553144Smarkus 
5238553144Smarkus 	for (i = 0; i < len; i++) {
53*753dd0dbSdjm 		ctx->x = (ctx->x + 1) & (RC4STATE - 1);
54*753dd0dbSdjm 		ctx->y = (ctx->state[ctx->x] + ctx->y) & (RC4STATE - 1);
5538553144Smarkus 		RC4SWAP(ctx->x, ctx->y);
5638553144Smarkus 		dst[i] = src[i] ^ ctx->state[
57*753dd0dbSdjm 		   (ctx->state[ctx->x] + ctx->state[ctx->y]) & (RC4STATE - 1)];
58*753dd0dbSdjm 	}
59*753dd0dbSdjm }
60*753dd0dbSdjm 
61*753dd0dbSdjm void
rc4_getbytes(struct rc4_ctx * ctx,u_char * dst,u_int32_t len)62*753dd0dbSdjm rc4_getbytes(struct rc4_ctx *ctx, u_char *dst, u_int32_t len)
63*753dd0dbSdjm {
64*753dd0dbSdjm 	u_int32_t i;
65*753dd0dbSdjm 
66*753dd0dbSdjm 	for (i = 0; i < len; i++) {
67*753dd0dbSdjm 		ctx->x = (ctx->x + 1) & (RC4STATE - 1);
68*753dd0dbSdjm 		ctx->y = (ctx->state[ctx->x] + ctx->y) & (RC4STATE - 1);
69*753dd0dbSdjm 		RC4SWAP(ctx->x, ctx->y);
70*753dd0dbSdjm 		dst[i] = ctx->state[
71*753dd0dbSdjm 		   (ctx->state[ctx->x] + ctx->state[ctx->y]) & (RC4STATE - 1)];
7238553144Smarkus 	}
7338553144Smarkus }
74c5823ff2Sdamien 
75c5823ff2Sdamien void
rc4_skip(struct rc4_ctx * ctx,u_int32_t len)76c5823ff2Sdamien rc4_skip(struct rc4_ctx *ctx, u_int32_t len)
77c5823ff2Sdamien {
78c5823ff2Sdamien 	for (; len > 0; len--) {
79*753dd0dbSdjm 		ctx->x = (ctx->x + 1) & (RC4STATE - 1);
80*753dd0dbSdjm 		ctx->y = (ctx->state[ctx->x] + ctx->y) & (RC4STATE - 1);
81c5823ff2Sdamien 		RC4SWAP(ctx->x, ctx->y);
82c5823ff2Sdamien 	}
83c5823ff2Sdamien }
84