1189251Ssam/*
2189251Ssam * RC4 stream cipher
3189251Ssam * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4189251Ssam *
5189251Ssam * This program is free software; you can redistribute it and/or modify
6189251Ssam * it under the terms of the GNU General Public License version 2 as
7189251Ssam * published by the Free Software Foundation.
8189251Ssam *
9189251Ssam * Alternatively, this software may be distributed under the terms of BSD
10189251Ssam * license.
11189251Ssam *
12189251Ssam * See README and COPYING for more details.
13189251Ssam */
14189251Ssam
15189251Ssam#include "includes.h"
16189251Ssam
17189251Ssam#include "common.h"
18214734Srpaulo#include "crypto.h"
19189251Ssam
20189251Ssam#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
21189251Ssam
22214734Srpauloint rc4_skip(const u8 *key, size_t keylen, size_t skip,
23214734Srpaulo	     u8 *data, size_t data_len)
24189251Ssam{
25189251Ssam	u32 i, j, k;
26189251Ssam	u8 S[256], *pos;
27189251Ssam	size_t kpos;
28189251Ssam
29189251Ssam	/* Setup RC4 state */
30189251Ssam	for (i = 0; i < 256; i++)
31189251Ssam		S[i] = i;
32189251Ssam	j = 0;
33189251Ssam	kpos = 0;
34189251Ssam	for (i = 0; i < 256; i++) {
35189251Ssam		j = (j + S[i] + key[kpos]) & 0xff;
36189251Ssam		kpos++;
37189251Ssam		if (kpos >= keylen)
38189251Ssam			kpos = 0;
39189251Ssam		S_SWAP(i, j);
40189251Ssam	}
41189251Ssam
42189251Ssam	/* Skip the start of the stream */
43189251Ssam	i = j = 0;
44189251Ssam	for (k = 0; k < skip; k++) {
45189251Ssam		i = (i + 1) & 0xff;
46189251Ssam		j = (j + S[i]) & 0xff;
47189251Ssam		S_SWAP(i, j);
48189251Ssam	}
49189251Ssam
50189251Ssam	/* Apply RC4 to data */
51189251Ssam	pos = data;
52189251Ssam	for (k = 0; k < data_len; k++) {
53189251Ssam		i = (i + 1) & 0xff;
54189251Ssam		j = (j + S[i]) & 0xff;
55189251Ssam		S_SWAP(i, j);
56189251Ssam		*pos++ ^= S[(S[i] + S[j]) & 0xff];
57189251Ssam	}
58214734Srpaulo
59214734Srpaulo	return 0;
60189251Ssam}
61