162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Cryptographic API 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * ARC4 Cipher Algorithm 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Jon Oberheide <jon@oberheide.org> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include "arc4.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciint cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci int i, j = 0, k = 0; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci ctx->x = 1; 2062306a36Sopenharmony_ci ctx->y = 0; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci for (i = 0; i < 256; i++) 2362306a36Sopenharmony_ci ctx->S[i] = i; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci for (i = 0; i < 256; i++) { 2662306a36Sopenharmony_ci u32 a = ctx->S[i]; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci j = (j + in_key[k] + a) & 0xff; 2962306a36Sopenharmony_ci ctx->S[i] = ctx->S[j]; 3062306a36Sopenharmony_ci ctx->S[j] = a; 3162306a36Sopenharmony_ci if (++k >= key_len) 3262306a36Sopenharmony_ci k = 0; 3362306a36Sopenharmony_ci } 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci return 0; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cifs_arc4_setkey); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_civoid cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci u32 *const S = ctx->S; 4262306a36Sopenharmony_ci u32 x, y, a, b; 4362306a36Sopenharmony_ci u32 ty, ta, tb; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (len == 0) 4662306a36Sopenharmony_ci return; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci x = ctx->x; 4962306a36Sopenharmony_ci y = ctx->y; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci a = S[x]; 5262306a36Sopenharmony_ci y = (y + a) & 0xff; 5362306a36Sopenharmony_ci b = S[y]; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci do { 5662306a36Sopenharmony_ci S[y] = a; 5762306a36Sopenharmony_ci a = (a + b) & 0xff; 5862306a36Sopenharmony_ci S[x] = b; 5962306a36Sopenharmony_ci x = (x + 1) & 0xff; 6062306a36Sopenharmony_ci ta = S[x]; 6162306a36Sopenharmony_ci ty = (y + ta) & 0xff; 6262306a36Sopenharmony_ci tb = S[ty]; 6362306a36Sopenharmony_ci *out++ = *in++ ^ S[a]; 6462306a36Sopenharmony_ci if (--len == 0) 6562306a36Sopenharmony_ci break; 6662306a36Sopenharmony_ci y = ty; 6762306a36Sopenharmony_ci a = ta; 6862306a36Sopenharmony_ci b = tb; 6962306a36Sopenharmony_ci } while (true); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci ctx->x = x; 7262306a36Sopenharmony_ci ctx->y = y; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cifs_arc4_crypt); 75