159108Sarchie/*
259108Sarchie * rc4.c
359108Sarchie *
459108Sarchie * Copyright (c) 1996-2000 Whistle Communications, Inc.
559108Sarchie * All rights reserved.
659108Sarchie *
759108Sarchie * Subject to the following obligations and disclaimer of warranty, use and
859108Sarchie * redistribution of this software, in source or object code forms, with or
959108Sarchie * without modifications are expressly permitted by Whistle Communications;
1059108Sarchie * provided, however, that:
1159108Sarchie * 1. Any and all reproductions of the source or object code must include the
1259108Sarchie *    copyright notice above and the following disclaimer of warranties; and
1359108Sarchie * 2. No rights are granted, in any manner or form, to use Whistle
1459108Sarchie *    Communications, Inc. trademarks, including the mark "WHISTLE
1559108Sarchie *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
1659108Sarchie *    such appears in the above copyright notice or in the software.
1759108Sarchie *
1859108Sarchie * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
1959108Sarchie * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
2059108Sarchie * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
2159108Sarchie * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
2259108Sarchie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
2359108Sarchie * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
2459108Sarchie * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
2559108Sarchie * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
2659108Sarchie * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
2759108Sarchie * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
2859108Sarchie * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
2959108Sarchie * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
3059108Sarchie * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
3159108Sarchie * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3259108Sarchie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3359108Sarchie * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
3459108Sarchie * OF SUCH DAMAGE.
3559108Sarchie */
3659108Sarchie
37116174Sobrien#include <sys/cdefs.h>
38116174Sobrien__FBSDID("$FreeBSD$");
39116174Sobrien
40109318Ssam#include <sys/param.h>
41109318Ssam#include <sys/kernel.h>
42109318Ssam#include <sys/module.h>
4359108Sarchie#include <sys/types.h>
4459108Sarchie#include <crypto/rc4/rc4.h>
4559108Sarchie
4659108Sarchiestatic __inline void
4759108Sarchieswap_bytes(u_char *a, u_char *b)
4859108Sarchie{
4959108Sarchie	u_char temp;
5059108Sarchie
5159108Sarchie	temp = *a;
5259108Sarchie	*a = *b;
5359108Sarchie	*b = temp;
5459108Sarchie}
5559108Sarchie
5659108Sarchie/*
5759108Sarchie * Initialize an RC4 state buffer using the supplied key,
5859108Sarchie * which can have arbitrary length.
5959108Sarchie */
6059108Sarchievoid
6159108Sarchierc4_init(struct rc4_state *const state, const u_char *key, int keylen)
6259108Sarchie{
6359108Sarchie	u_char j;
64186179Smav	int i, k;
6559108Sarchie
6659108Sarchie	/* Initialize state with identity permutation */
6759108Sarchie	for (i = 0; i < 256; i++)
6859108Sarchie		state->perm[i] = (u_char)i;
6959108Sarchie	state->index1 = 0;
7059108Sarchie	state->index2 = 0;
7159108Sarchie
7259108Sarchie	/* Randomize the permutation using key data */
73186179Smav	for (j = i = k = 0; i < 256; i++) {
74186179Smav		j += state->perm[i] + key[k];
7559108Sarchie		swap_bytes(&state->perm[i], &state->perm[j]);
76186179Smav		if (++k >= keylen)
77186179Smav			k = 0;
7859108Sarchie	}
7959108Sarchie}
8059108Sarchie
8159108Sarchie/*
8259108Sarchie * Encrypt some data using the supplied RC4 state buffer.
8359108Sarchie * The input and output buffers may be the same buffer.
8459108Sarchie * Since RC4 is a stream cypher, this function is used
8559108Sarchie * for both encryption and decryption.
8659108Sarchie */
8759108Sarchievoid
8859108Sarchierc4_crypt(struct rc4_state *const state,
8959108Sarchie	const u_char *inbuf, u_char *outbuf, int buflen)
9059108Sarchie{
9159108Sarchie	int i;
9259108Sarchie	u_char j;
9359108Sarchie
9459108Sarchie	for (i = 0; i < buflen; i++) {
9559108Sarchie
9659108Sarchie		/* Update modification indicies */
9759108Sarchie		state->index1++;
9859108Sarchie		state->index2 += state->perm[state->index1];
9959108Sarchie
10059108Sarchie		/* Modify permutation */
10159108Sarchie		swap_bytes(&state->perm[state->index1],
10259108Sarchie		    &state->perm[state->index2]);
10359108Sarchie
10459108Sarchie		/* Encrypt/decrypt next byte */
10559108Sarchie		j = state->perm[state->index1] + state->perm[state->index2];
10659108Sarchie		outbuf[i] = inbuf[i] ^ state->perm[j];
10759108Sarchie	}
10859108Sarchie}
10959108Sarchie
110109318Ssamstatic int
111109318Ssamrc4_modevent(module_t mod, int type, void *unused)
112109318Ssam{
113109318Ssam	switch (type) {
114109318Ssam	case MOD_LOAD:
115109318Ssam		return 0;
116109318Ssam	case MOD_UNLOAD:
117109318Ssam		return 0;
118109318Ssam	}
119109318Ssam	return EINVAL;
120109318Ssam}
121109318Ssam
122109318Ssamstatic moduledata_t rc4_mod = {
123109318Ssam	"rc4",
124109318Ssam	rc4_modevent,
125241394Skevlo	0
126109318Ssam};
127109318SsamDECLARE_MODULE(rc4, rc4_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
128109318SsamMODULE_VERSION(rc4, 1);
129