xref: /linux/fs/smb/common/cifs_arc4.c (revision 89be4025b0db42db830d72d532437248774cba49)
138c8a9a5SSteve French // SPDX-License-Identifier: GPL-2.0-or-later
238c8a9a5SSteve French /*
338c8a9a5SSteve French  * Cryptographic API
438c8a9a5SSteve French  *
538c8a9a5SSteve French  * ARC4 Cipher Algorithm
638c8a9a5SSteve French  *
738c8a9a5SSteve French  * Jon Oberheide <jon@oberheide.org>
838c8a9a5SSteve French  */
938c8a9a5SSteve French 
1038c8a9a5SSteve French #include <linux/module.h>
1138c8a9a5SSteve French #include "arc4.h"
1238c8a9a5SSteve French 
13*9ee267a2SJeff Johnson MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
1438c8a9a5SSteve French MODULE_LICENSE("GPL");
1538c8a9a5SSteve French 
cifs_arc4_setkey(struct arc4_ctx * ctx,const u8 * in_key,unsigned int key_len)1638c8a9a5SSteve French int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
1738c8a9a5SSteve French {
1838c8a9a5SSteve French 	int i, j = 0, k = 0;
1938c8a9a5SSteve French 
2038c8a9a5SSteve French 	ctx->x = 1;
2138c8a9a5SSteve French 	ctx->y = 0;
2238c8a9a5SSteve French 
2338c8a9a5SSteve French 	for (i = 0; i < 256; i++)
2438c8a9a5SSteve French 		ctx->S[i] = i;
2538c8a9a5SSteve French 
2638c8a9a5SSteve French 	for (i = 0; i < 256; i++) {
2738c8a9a5SSteve French 		u32 a = ctx->S[i];
2838c8a9a5SSteve French 
2938c8a9a5SSteve French 		j = (j + in_key[k] + a) & 0xff;
3038c8a9a5SSteve French 		ctx->S[i] = ctx->S[j];
3138c8a9a5SSteve French 		ctx->S[j] = a;
3238c8a9a5SSteve French 		if (++k >= key_len)
3338c8a9a5SSteve French 			k = 0;
3438c8a9a5SSteve French 	}
3538c8a9a5SSteve French 
3638c8a9a5SSteve French 	return 0;
3738c8a9a5SSteve French }
3838c8a9a5SSteve French EXPORT_SYMBOL_GPL(cifs_arc4_setkey);
3938c8a9a5SSteve French 
cifs_arc4_crypt(struct arc4_ctx * ctx,u8 * out,const u8 * in,unsigned int len)4038c8a9a5SSteve French void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
4138c8a9a5SSteve French {
4238c8a9a5SSteve French 	u32 *const S = ctx->S;
4338c8a9a5SSteve French 	u32 x, y, a, b;
4438c8a9a5SSteve French 	u32 ty, ta, tb;
4538c8a9a5SSteve French 
4638c8a9a5SSteve French 	if (len == 0)
4738c8a9a5SSteve French 		return;
4838c8a9a5SSteve French 
4938c8a9a5SSteve French 	x = ctx->x;
5038c8a9a5SSteve French 	y = ctx->y;
5138c8a9a5SSteve French 
5238c8a9a5SSteve French 	a = S[x];
5338c8a9a5SSteve French 	y = (y + a) & 0xff;
5438c8a9a5SSteve French 	b = S[y];
5538c8a9a5SSteve French 
5638c8a9a5SSteve French 	do {
5738c8a9a5SSteve French 		S[y] = a;
5838c8a9a5SSteve French 		a = (a + b) & 0xff;
5938c8a9a5SSteve French 		S[x] = b;
6038c8a9a5SSteve French 		x = (x + 1) & 0xff;
6138c8a9a5SSteve French 		ta = S[x];
6238c8a9a5SSteve French 		ty = (y + ta) & 0xff;
6338c8a9a5SSteve French 		tb = S[ty];
6438c8a9a5SSteve French 		*out++ = *in++ ^ S[a];
6538c8a9a5SSteve French 		if (--len == 0)
6638c8a9a5SSteve French 			break;
6738c8a9a5SSteve French 		y = ty;
6838c8a9a5SSteve French 		a = ta;
6938c8a9a5SSteve French 		b = tb;
7038c8a9a5SSteve French 	} while (true);
7138c8a9a5SSteve French 
7238c8a9a5SSteve French 	ctx->x = x;
7338c8a9a5SSteve French 	ctx->y = y;
7438c8a9a5SSteve French }
7538c8a9a5SSteve French EXPORT_SYMBOL_GPL(cifs_arc4_crypt);
76