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