1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * RC4 stream cipher
3e5b75505Sopenharmony_ci * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#include "common.h"
12e5b75505Sopenharmony_ci#include "crypto.h"
13e5b75505Sopenharmony_ci
14e5b75505Sopenharmony_ci#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
15e5b75505Sopenharmony_ci
16e5b75505Sopenharmony_ciint rc4_skip(const u8 *key, size_t keylen, size_t skip,
17e5b75505Sopenharmony_ci	     u8 *data, size_t data_len)
18e5b75505Sopenharmony_ci{
19e5b75505Sopenharmony_ci	u32 i, j, k;
20e5b75505Sopenharmony_ci	u8 S[256], *pos;
21e5b75505Sopenharmony_ci	size_t kpos;
22e5b75505Sopenharmony_ci
23e5b75505Sopenharmony_ci	/* Setup RC4 state */
24e5b75505Sopenharmony_ci	for (i = 0; i < 256; i++)
25e5b75505Sopenharmony_ci		S[i] = i;
26e5b75505Sopenharmony_ci	j = 0;
27e5b75505Sopenharmony_ci	kpos = 0;
28e5b75505Sopenharmony_ci	for (i = 0; i < 256; i++) {
29e5b75505Sopenharmony_ci		j = (j + S[i] + key[kpos]) & 0xff;
30e5b75505Sopenharmony_ci		kpos++;
31e5b75505Sopenharmony_ci		if (kpos >= keylen)
32e5b75505Sopenharmony_ci			kpos = 0;
33e5b75505Sopenharmony_ci		S_SWAP(i, j);
34e5b75505Sopenharmony_ci	}
35e5b75505Sopenharmony_ci
36e5b75505Sopenharmony_ci	/* Skip the start of the stream */
37e5b75505Sopenharmony_ci	i = j = 0;
38e5b75505Sopenharmony_ci	for (k = 0; k < skip; k++) {
39e5b75505Sopenharmony_ci		i = (i + 1) & 0xff;
40e5b75505Sopenharmony_ci		j = (j + S[i]) & 0xff;
41e5b75505Sopenharmony_ci		S_SWAP(i, j);
42e5b75505Sopenharmony_ci	}
43e5b75505Sopenharmony_ci
44e5b75505Sopenharmony_ci	/* Apply RC4 to data */
45e5b75505Sopenharmony_ci	pos = data;
46e5b75505Sopenharmony_ci	for (k = 0; k < data_len; k++) {
47e5b75505Sopenharmony_ci		i = (i + 1) & 0xff;
48e5b75505Sopenharmony_ci		j = (j + S[i]) & 0xff;
49e5b75505Sopenharmony_ci		S_SWAP(i, j);
50e5b75505Sopenharmony_ci		*pos++ ^= S[(S[i] + S[j]) & 0xff];
51e5b75505Sopenharmony_ci	}
52e5b75505Sopenharmony_ci
53e5b75505Sopenharmony_ci	return 0;
54e5b75505Sopenharmony_ci}
55