1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Cryptographic API
4 *
5 * ARC4 Cipher Algorithm
6 *
7 * Jon Oberheide <jon@oberheide.org>
8 */
9
10#include <linux/module.h>
11#include "arc4.h"
12
13MODULE_LICENSE("GPL");
14
15int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
16{
17	int i, j = 0, k = 0;
18
19	ctx->x = 1;
20	ctx->y = 0;
21
22	for (i = 0; i < 256; i++)
23		ctx->S[i] = i;
24
25	for (i = 0; i < 256; i++) {
26		u32 a = ctx->S[i];
27
28		j = (j + in_key[k] + a) & 0xff;
29		ctx->S[i] = ctx->S[j];
30		ctx->S[j] = a;
31		if (++k >= key_len)
32			k = 0;
33	}
34
35	return 0;
36}
37EXPORT_SYMBOL_GPL(cifs_arc4_setkey);
38
39void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
40{
41	u32 *const S = ctx->S;
42	u32 x, y, a, b;
43	u32 ty, ta, tb;
44
45	if (len == 0)
46		return;
47
48	x = ctx->x;
49	y = ctx->y;
50
51	a = S[x];
52	y = (y + a) & 0xff;
53	b = S[y];
54
55	do {
56		S[y] = a;
57		a = (a + b) & 0xff;
58		S[x] = b;
59		x = (x + 1) & 0xff;
60		ta = S[x];
61		ty = (y + ta) & 0xff;
62		tb = S[ty];
63		*out++ = *in++ ^ S[a];
64		if (--len == 0)
65			break;
66		y = ty;
67		a = ta;
68		b = tb;
69	} while (true);
70
71	ctx->x = x;
72	ctx->y = y;
73}
74EXPORT_SYMBOL_GPL(cifs_arc4_crypt);
75