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