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