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