1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* 3 * Cryptographic API 2 * Cryptographic API 4 * 3 * 5 * ARC4 Cipher Algorithm 4 * ARC4 Cipher Algorithm 6 * 5 * 7 * Jon Oberheide <jon@oberheide.org> 6 * Jon Oberheide <jon@oberheide.org> >> 7 * >> 8 * This program is free software; you can redistribute it and/or modify >> 9 * it under the terms of the GNU General Public License as published by >> 10 * the Free Software Foundation; either version 2 of the License, or >> 11 * (at your option) any later version. >> 12 * 8 */ 13 */ 9 14 >> 15 #include <crypto/algapi.h> 10 #include <crypto/arc4.h> 16 #include <crypto/arc4.h> 11 #include <crypto/internal/skcipher.h> 17 #include <crypto/internal/skcipher.h> 12 #include <linux/init.h> 18 #include <linux/init.h> 13 #include <linux/kernel.h> << 14 #include <linux/module.h> 19 #include <linux/module.h> 15 #include <linux/sched.h> << 16 20 17 #define ARC4_ALIGN __alignof__(struct arc4_ctx !! 21 struct arc4_ctx { >> 22 u32 S[256]; >> 23 u32 x, y; >> 24 }; 18 25 19 static int crypto_arc4_setkey(struct crypto_ls !! 26 static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, 20 unsigned int key !! 27 unsigned int key_len) 21 { 28 { 22 struct arc4_ctx *ctx = crypto_lskciphe !! 29 struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); >> 30 int i, j = 0, k = 0; >> 31 >> 32 ctx->x = 1; >> 33 ctx->y = 0; 23 34 24 return arc4_setkey(ctx, in_key, key_le !! 35 for (i = 0; i < 256; i++) >> 36 ctx->S[i] = i; >> 37 >> 38 for (i = 0; i < 256; i++) { >> 39 u32 a = ctx->S[i]; >> 40 j = (j + in_key[k] + a) & 0xff; >> 41 ctx->S[i] = ctx->S[j]; >> 42 ctx->S[j] = a; >> 43 if (++k >= key_len) >> 44 k = 0; >> 45 } >> 46 >> 47 return 0; 25 } 48 } 26 49 27 static int crypto_arc4_crypt(struct crypto_lsk !! 50 static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key, 28 u8 *dst, unsigned !! 51 unsigned int key_len) 29 { 52 { 30 struct arc4_ctx *ctx = crypto_lskciphe !! 53 return arc4_set_key(&tfm->base, in_key, key_len); >> 54 } 31 55 32 if (!(flags & CRYPTO_LSKCIPHER_FLAG_CO !! 56 static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, 33 memcpy(siv, ctx, sizeof(*ctx)) !! 57 unsigned int len) >> 58 { >> 59 u32 *const S = ctx->S; >> 60 u32 x, y, a, b; >> 61 u32 ty, ta, tb; >> 62 >> 63 if (len == 0) >> 64 return; >> 65 >> 66 x = ctx->x; >> 67 y = ctx->y; >> 68 >> 69 a = S[x]; >> 70 y = (y + a) & 0xff; >> 71 b = S[y]; >> 72 >> 73 do { >> 74 S[y] = a; >> 75 a = (a + b) & 0xff; >> 76 S[x] = b; >> 77 x = (x + 1) & 0xff; >> 78 ta = S[x]; >> 79 ty = (y + ta) & 0xff; >> 80 tb = S[ty]; >> 81 *out++ = *in++ ^ S[a]; >> 82 if (--len == 0) >> 83 break; >> 84 y = ty; >> 85 a = ta; >> 86 b = tb; >> 87 } while (true); 34 88 35 ctx = (struct arc4_ctx *)siv; !! 89 ctx->x = x; >> 90 ctx->y = y; >> 91 } 36 92 37 arc4_crypt(ctx, dst, src, nbytes); !! 93 static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in) 38 return 0; !! 94 { >> 95 arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1); 39 } 96 } 40 97 41 static int crypto_arc4_init(struct crypto_lskc !! 98 static int ecb_arc4_crypt(struct skcipher_request *req) 42 { 99 { 43 pr_warn_ratelimited("\"%s\" (%ld) uses !! 100 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 44 current->comm, (un !! 101 struct arc4_ctx *ctx = crypto_skcipher_ctx(tfm); >> 102 struct skcipher_walk walk; >> 103 int err; >> 104 >> 105 err = skcipher_walk_virt(&walk, req, false); >> 106 >> 107 while (walk.nbytes > 0) { >> 108 arc4_crypt(ctx, walk.dst.virt.addr, walk.src.virt.addr, >> 109 walk.nbytes); >> 110 err = skcipher_walk_done(&walk, 0); >> 111 } 45 112 46 return 0; !! 113 return err; 47 } 114 } 48 115 49 static struct lskcipher_alg arc4_alg = { !! 116 static struct crypto_alg arc4_cipher = { 50 .co.base.cra_name = !! 117 .cra_name = "arc4", 51 .co.base.cra_driver_name = !! 118 .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 52 .co.base.cra_priority = !! 119 .cra_blocksize = ARC4_BLOCK_SIZE, 53 .co.base.cra_blocksize = !! 120 .cra_ctxsize = sizeof(struct arc4_ctx), 54 .co.base.cra_ctxsize = !! 121 .cra_module = THIS_MODULE, 55 .co.base.cra_alignmask = !! 122 .cra_u = { 56 .co.base.cra_module = !! 123 .cipher = { 57 .co.min_keysize = !! 124 .cia_min_keysize = ARC4_MIN_KEY_SIZE, 58 .co.max_keysize = !! 125 .cia_max_keysize = ARC4_MAX_KEY_SIZE, 59 .co.statesize = !! 126 .cia_setkey = arc4_set_key, 60 .setkey = !! 127 .cia_encrypt = arc4_crypt_one, 61 .encrypt = !! 128 .cia_decrypt = arc4_crypt_one, 62 .decrypt = !! 129 }, 63 .init = !! 130 }, >> 131 }; >> 132 >> 133 static struct skcipher_alg arc4_skcipher = { >> 134 .base.cra_name = "ecb(arc4)", >> 135 .base.cra_priority = 100, >> 136 .base.cra_blocksize = ARC4_BLOCK_SIZE, >> 137 .base.cra_ctxsize = sizeof(struct arc4_ctx), >> 138 .base.cra_module = THIS_MODULE, >> 139 .min_keysize = ARC4_MIN_KEY_SIZE, >> 140 .max_keysize = ARC4_MAX_KEY_SIZE, >> 141 .setkey = arc4_set_key_skcipher, >> 142 .encrypt = ecb_arc4_crypt, >> 143 .decrypt = ecb_arc4_crypt, 64 }; 144 }; 65 145 66 static int __init arc4_init(void) 146 static int __init arc4_init(void) 67 { 147 { 68 return crypto_register_lskcipher(&arc4 !! 148 int err; >> 149 >> 150 err = crypto_register_alg(&arc4_cipher); >> 151 if (err) >> 152 return err; >> 153 >> 154 err = crypto_register_skcipher(&arc4_skcipher); >> 155 if (err) >> 156 crypto_unregister_alg(&arc4_cipher); >> 157 return err; 69 } 158 } 70 159 71 static void __exit arc4_exit(void) 160 static void __exit arc4_exit(void) 72 { 161 { 73 crypto_unregister_lskcipher(&arc4_alg) !! 162 crypto_unregister_alg(&arc4_cipher); >> 163 crypto_unregister_skcipher(&arc4_skcipher); 74 } 164 } 75 165 76 subsys_initcall(arc4_init); !! 166 module_init(arc4_init); 77 module_exit(arc4_exit); 167 module_exit(arc4_exit); 78 168 79 MODULE_LICENSE("GPL"); 169 MODULE_LICENSE("GPL"); 80 MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); 170 MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); 81 MODULE_AUTHOR("Jon Oberheide <jon@oberheide.or 171 MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>"); 82 MODULE_ALIAS_CRYPTO("ecb(arc4)"); !! 172 MODULE_ALIAS_CRYPTO("arc4"); 83 173
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.