1189251Ssam/*
2189251Ssam * RC4 stream cipher
3189251Ssam * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam */
8189251Ssam
9189251Ssam#include "includes.h"
10189251Ssam
11189251Ssam#include "common.h"
12214734Srpaulo#include "crypto.h"
13189251Ssam
14189251Ssam#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
15189251Ssam
16214734Srpauloint rc4_skip(const u8 *key, size_t keylen, size_t skip,
17214734Srpaulo	     u8 *data, size_t data_len)
18189251Ssam{
19189251Ssam	u32 i, j, k;
20189251Ssam	u8 S[256], *pos;
21189251Ssam	size_t kpos;
22189251Ssam
23189251Ssam	/* Setup RC4 state */
24189251Ssam	for (i = 0; i < 256; i++)
25189251Ssam		S[i] = i;
26189251Ssam	j = 0;
27189251Ssam	kpos = 0;
28189251Ssam	for (i = 0; i < 256; i++) {
29189251Ssam		j = (j + S[i] + key[kpos]) & 0xff;
30189251Ssam		kpos++;
31189251Ssam		if (kpos >= keylen)
32189251Ssam			kpos = 0;
33189251Ssam		S_SWAP(i, j);
34189251Ssam	}
35189251Ssam
36189251Ssam	/* Skip the start of the stream */
37189251Ssam	i = j = 0;
38189251Ssam	for (k = 0; k < skip; k++) {
39189251Ssam		i = (i + 1) & 0xff;
40189251Ssam		j = (j + S[i]) & 0xff;
41189251Ssam		S_SWAP(i, j);
42189251Ssam	}
43189251Ssam
44189251Ssam	/* Apply RC4 to data */
45189251Ssam	pos = data;
46189251Ssam	for (k = 0; k < data_len; k++) {
47189251Ssam		i = (i + 1) & 0xff;
48189251Ssam		j = (j + S[i]) & 0xff;
49189251Ssam		S_SWAP(i, j);
50189251Ssam		*pos++ ^= S[(S[i] + S[j]) & 0xff];
51189251Ssam	}
52214734Srpaulo
53214734Srpaulo	return 0;
54189251Ssam}
55