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
13 MODULE_LICENSE("GPL");
14
cifs_arc4_setkey(struct arc4_ctx * ctx,const u8 * in_key,unsigned int key_len)15 int 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 }
37 EXPORT_SYMBOL_GPL(cifs_arc4_setkey);
38
cifs_arc4_crypt(struct arc4_ctx * ctx,u8 * out,const u8 * in,unsigned int len)39 void 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 }
74 EXPORT_SYMBOL_GPL(cifs_arc4_crypt);
75