xref: /linux/fs/smb/common/cifs_arc4.c (revision ea77850e98410987525eb392c229949c87779835)
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 
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 
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