1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Cryptographic API 4 * 5 * ARC4 Cipher Algorithm 6 * 7 * Jon Oberheide <jon@oberheide.org> 8 */ 9 10 #include <crypto/algapi.h> 11 #include <crypto/arc4.h> 12 #include <crypto/internal/skcipher.h> 13 #include <linux/init.h> 14 #include <linux/module.h> 15 16 struct arc4_ctx { 17 u32 S[256]; 18 u32 x, y; 19 }; 20 21 static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, 22 unsigned int key_len) 23 { 24 struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); 25 int i, j = 0, k = 0; 26 27 ctx->x = 1; 28 ctx->y = 0; 29 30 for (i = 0; i < 256; i++) 31 ctx->S[i] = i; 32 33 for (i = 0; i < 256; i++) { 34 u32 a = ctx->S[i]; 35 j = (j + in_key[k] + a) & 0xff; 36 ctx->S[i] = ctx->S[j]; 37 ctx->S[j] = a; 38 if (++k >= key_len) 39 k = 0; 40 } 41 42 return 0; 43 } 44 45 static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key, 46 unsigned int key_len) 47 { 48 return arc4_set_key(&tfm->base, in_key, key_len); 49 } 50 51 static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, 52 unsigned int len) 53 { 54 u32 *const S = ctx->S; 55 u32 x, y, a, b; 56 u32 ty, ta, tb; 57 58 if (len == 0) 59 return; 60 61 x = ctx->x; 62 y = ctx->y; 63 64 a = S[x]; 65 y = (y + a) & 0xff; 66 b = S[y]; 67 68 do { 69 S[y] = a; 70 a = (a + b) & 0xff; 71 S[x] = b; 72 x = (x + 1) & 0xff; 73 ta = S[x]; 74 ty = (y + ta) & 0xff; 75 tb = S[ty]; 76 *out++ = *in++ ^ S[a]; 77 if (--len == 0) 78 break; 79 y = ty; 80 a = ta; 81 b = tb; 82 } while (true); 83 84 ctx->x = x; 85 ctx->y = y; 86 } 87 88 static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in) 89 { 90 arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1); 91 } 92 93 static int ecb_arc4_crypt(struct skcipher_request *req) 94 { 95 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 96 struct arc4_ctx *ctx = crypto_skcipher_ctx(tfm); 97 struct skcipher_walk walk; 98 int err; 99 100 err = skcipher_walk_virt(&walk, req, false); 101 102 while (walk.nbytes > 0) { 103 arc4_crypt(ctx, walk.dst.virt.addr, walk.src.virt.addr, 104 walk.nbytes); 105 err = skcipher_walk_done(&walk, 0); 106 } 107 108 return err; 109 } 110 111 static struct crypto_alg arc4_cipher = { 112 .cra_name = "arc4", 113 .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 114 .cra_blocksize = ARC4_BLOCK_SIZE, 115 .cra_ctxsize = sizeof(struct arc4_ctx), 116 .cra_module = THIS_MODULE, 117 .cra_u = { 118 .cipher = { 119 .cia_min_keysize = ARC4_MIN_KEY_SIZE, 120 .cia_max_keysize = ARC4_MAX_KEY_SIZE, 121 .cia_setkey = arc4_set_key, 122 .cia_encrypt = arc4_crypt_one, 123 .cia_decrypt = arc4_crypt_one, 124 }, 125 }, 126 }; 127 128 static struct skcipher_alg arc4_skcipher = { 129 .base.cra_name = "ecb(arc4)", 130 .base.cra_priority = 100, 131 .base.cra_blocksize = ARC4_BLOCK_SIZE, 132 .base.cra_ctxsize = sizeof(struct arc4_ctx), 133 .base.cra_module = THIS_MODULE, 134 .min_keysize = ARC4_MIN_KEY_SIZE, 135 .max_keysize = ARC4_MAX_KEY_SIZE, 136 .setkey = arc4_set_key_skcipher, 137 .encrypt = ecb_arc4_crypt, 138 .decrypt = ecb_arc4_crypt, 139 }; 140 141 static int __init arc4_init(void) 142 { 143 int err; 144 145 err = crypto_register_alg(&arc4_cipher); 146 if (err) 147 return err; 148 149 err = crypto_register_skcipher(&arc4_skcipher); 150 if (err) 151 crypto_unregister_alg(&arc4_cipher); 152 return err; 153 } 154 155 static void __exit arc4_exit(void) 156 { 157 crypto_unregister_alg(&arc4_cipher); 158 crypto_unregister_skcipher(&arc4_skcipher); 159 } 160 161 subsys_initcall(arc4_init); 162 module_exit(arc4_exit); 163 164 MODULE_LICENSE("GPL"); 165 MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); 166 MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>"); 167 MODULE_ALIAS_CRYPTO("arc4"); 168