18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Cryptographic API
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * ARC4 Cipher Algorithm
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Jon Oberheide <jon@oberheide.org>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <crypto/arc4.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ciint arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	int i, j = 0, k = 0;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	ctx->x = 1;
188c2ecf20Sopenharmony_ci	ctx->y = 0;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i++)
218c2ecf20Sopenharmony_ci		ctx->S[i] = i;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i++) {
248c2ecf20Sopenharmony_ci		u32 a = ctx->S[i];
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci		j = (j + in_key[k] + a) & 0xff;
278c2ecf20Sopenharmony_ci		ctx->S[i] = ctx->S[j];
288c2ecf20Sopenharmony_ci		ctx->S[j] = a;
298c2ecf20Sopenharmony_ci		if (++k >= key_len)
308c2ecf20Sopenharmony_ci			k = 0;
318c2ecf20Sopenharmony_ci	}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	return 0;
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(arc4_setkey);
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_civoid arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	u32 *const S = ctx->S;
408c2ecf20Sopenharmony_ci	u32 x, y, a, b;
418c2ecf20Sopenharmony_ci	u32 ty, ta, tb;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (len == 0)
448c2ecf20Sopenharmony_ci		return;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	x = ctx->x;
478c2ecf20Sopenharmony_ci	y = ctx->y;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	a = S[x];
508c2ecf20Sopenharmony_ci	y = (y + a) & 0xff;
518c2ecf20Sopenharmony_ci	b = S[y];
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	do {
548c2ecf20Sopenharmony_ci		S[y] = a;
558c2ecf20Sopenharmony_ci		a = (a + b) & 0xff;
568c2ecf20Sopenharmony_ci		S[x] = b;
578c2ecf20Sopenharmony_ci		x = (x + 1) & 0xff;
588c2ecf20Sopenharmony_ci		ta = S[x];
598c2ecf20Sopenharmony_ci		ty = (y + ta) & 0xff;
608c2ecf20Sopenharmony_ci		tb = S[ty];
618c2ecf20Sopenharmony_ci		*out++ = *in++ ^ S[a];
628c2ecf20Sopenharmony_ci		if (--len == 0)
638c2ecf20Sopenharmony_ci			break;
648c2ecf20Sopenharmony_ci		y = ty;
658c2ecf20Sopenharmony_ci		a = ta;
668c2ecf20Sopenharmony_ci		b = tb;
678c2ecf20Sopenharmony_ci	} while (true);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	ctx->x = x;
708c2ecf20Sopenharmony_ci	ctx->y = y;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(arc4_crypt);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
75