11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Cryptographic API 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * ARC4 Cipher Algorithm 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Jon Oberheide <jon@oberheide.org> 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 91da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 101da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 111da177e4SLinus Torvalds * (at your option) any later version. 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds */ 14ce6dd368SJussi Kivilinna 151da177e4SLinus Torvalds #include <linux/module.h> 161da177e4SLinus Torvalds #include <linux/init.h> 171da177e4SLinus Torvalds #include <linux/crypto.h> 18ce6dd368SJussi Kivilinna #include <crypto/algapi.h> 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #define ARC4_MIN_KEY_SIZE 1 211da177e4SLinus Torvalds #define ARC4_MAX_KEY_SIZE 256 221da177e4SLinus Torvalds #define ARC4_BLOCK_SIZE 1 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds struct arc4_ctx { 25d366db60SJussi Kivilinna u32 S[256]; 26d366db60SJussi Kivilinna u32 x, y; 271da177e4SLinus Torvalds }; 281da177e4SLinus Torvalds 296c2bb98bSHerbert Xu static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, 30560c06aeSHerbert Xu unsigned int key_len) 311da177e4SLinus Torvalds { 326c2bb98bSHerbert Xu struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); 331da177e4SLinus Torvalds int i, j = 0, k = 0; 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds ctx->x = 1; 361da177e4SLinus Torvalds ctx->y = 0; 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds for (i = 0; i < 256; i++) 391da177e4SLinus Torvalds ctx->S[i] = i; 401da177e4SLinus Torvalds 41cfa2b54eSMati Vait for (i = 0; i < 256; i++) { 42d366db60SJussi Kivilinna u32 a = ctx->S[i]; 431da177e4SLinus Torvalds j = (j + in_key[k] + a) & 0xff; 441da177e4SLinus Torvalds ctx->S[i] = ctx->S[j]; 451da177e4SLinus Torvalds ctx->S[j] = a; 461da177e4SLinus Torvalds if (++k >= key_len) 471da177e4SLinus Torvalds k = 0; 481da177e4SLinus Torvalds } 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds return 0; 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 53ce6dd368SJussi Kivilinna static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, 54ce6dd368SJussi Kivilinna unsigned int len) 551da177e4SLinus Torvalds { 56d366db60SJussi Kivilinna u32 *const S = ctx->S; 57d366db60SJussi Kivilinna u32 x, y, a, b; 58d366db60SJussi Kivilinna u32 ty, ta, tb; 59ce6dd368SJussi Kivilinna 60ce6dd368SJussi Kivilinna if (len == 0) 61ce6dd368SJussi Kivilinna return; 62ce6dd368SJussi Kivilinna 63ce6dd368SJussi Kivilinna x = ctx->x; 64ce6dd368SJussi Kivilinna y = ctx->y; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds a = S[x]; 671da177e4SLinus Torvalds y = (y + a) & 0xff; 681da177e4SLinus Torvalds b = S[y]; 69ce6dd368SJussi Kivilinna 70ce6dd368SJussi Kivilinna do { 711da177e4SLinus Torvalds S[y] = a; 72ce6dd368SJussi Kivilinna a = (a + b) & 0xff; 73ce6dd368SJussi Kivilinna S[x] = b; 741da177e4SLinus Torvalds x = (x + 1) & 0xff; 75ce6dd368SJussi Kivilinna ta = S[x]; 76ce6dd368SJussi Kivilinna ty = (y + ta) & 0xff; 77ce6dd368SJussi Kivilinna tb = S[ty]; 78ce6dd368SJussi Kivilinna *out++ = *in++ ^ S[a]; 79ce6dd368SJussi Kivilinna if (--len == 0) 80ce6dd368SJussi Kivilinna break; 81ce6dd368SJussi Kivilinna y = ty; 82ce6dd368SJussi Kivilinna a = ta; 83ce6dd368SJussi Kivilinna b = tb; 84ce6dd368SJussi Kivilinna } while (true); 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds ctx->x = x; 871da177e4SLinus Torvalds ctx->y = y; 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds 90ce6dd368SJussi Kivilinna static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in) 91ce6dd368SJussi Kivilinna { 92ce6dd368SJussi Kivilinna arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1); 93ce6dd368SJussi Kivilinna } 94ce6dd368SJussi Kivilinna 95ce6dd368SJussi Kivilinna static int ecb_arc4_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, 96ce6dd368SJussi Kivilinna struct scatterlist *src, unsigned int nbytes) 97ce6dd368SJussi Kivilinna { 98ce6dd368SJussi Kivilinna struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 99ce6dd368SJussi Kivilinna struct blkcipher_walk walk; 100ce6dd368SJussi Kivilinna int err; 101ce6dd368SJussi Kivilinna 102ce6dd368SJussi Kivilinna blkcipher_walk_init(&walk, dst, src, nbytes); 103ce6dd368SJussi Kivilinna 104ce6dd368SJussi Kivilinna err = blkcipher_walk_virt(desc, &walk); 105ce6dd368SJussi Kivilinna 106ce6dd368SJussi Kivilinna while (walk.nbytes > 0) { 107ce6dd368SJussi Kivilinna u8 *wsrc = walk.src.virt.addr; 108ce6dd368SJussi Kivilinna u8 *wdst = walk.dst.virt.addr; 109ce6dd368SJussi Kivilinna 110ce6dd368SJussi Kivilinna arc4_crypt(ctx, wdst, wsrc, walk.nbytes); 111ce6dd368SJussi Kivilinna 112ce6dd368SJussi Kivilinna err = blkcipher_walk_done(desc, &walk, 0); 113ce6dd368SJussi Kivilinna } 114ce6dd368SJussi Kivilinna 115ce6dd368SJussi Kivilinna return err; 116ce6dd368SJussi Kivilinna } 117ce6dd368SJussi Kivilinna 118ce6dd368SJussi Kivilinna static struct crypto_alg arc4_algs[2] = { { 1191da177e4SLinus Torvalds .cra_name = "arc4", 1201da177e4SLinus Torvalds .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 1211da177e4SLinus Torvalds .cra_blocksize = ARC4_BLOCK_SIZE, 1221da177e4SLinus Torvalds .cra_ctxsize = sizeof(struct arc4_ctx), 1231da177e4SLinus Torvalds .cra_module = THIS_MODULE, 124ce6dd368SJussi Kivilinna .cra_u = { 125ce6dd368SJussi Kivilinna .cipher = { 1261da177e4SLinus Torvalds .cia_min_keysize = ARC4_MIN_KEY_SIZE, 1271da177e4SLinus Torvalds .cia_max_keysize = ARC4_MAX_KEY_SIZE, 1281da177e4SLinus Torvalds .cia_setkey = arc4_set_key, 129ce6dd368SJussi Kivilinna .cia_encrypt = arc4_crypt_one, 130ce6dd368SJussi Kivilinna .cia_decrypt = arc4_crypt_one, 131ce6dd368SJussi Kivilinna }, 132ce6dd368SJussi Kivilinna }, 133ce6dd368SJussi Kivilinna }, { 134ce6dd368SJussi Kivilinna .cra_name = "ecb(arc4)", 135ce6dd368SJussi Kivilinna .cra_priority = 100, 136ce6dd368SJussi Kivilinna .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 137ce6dd368SJussi Kivilinna .cra_blocksize = ARC4_BLOCK_SIZE, 138ce6dd368SJussi Kivilinna .cra_ctxsize = sizeof(struct arc4_ctx), 139ce6dd368SJussi Kivilinna .cra_alignmask = 0, 140ce6dd368SJussi Kivilinna .cra_type = &crypto_blkcipher_type, 141ce6dd368SJussi Kivilinna .cra_module = THIS_MODULE, 142ce6dd368SJussi Kivilinna .cra_u = { 143ce6dd368SJussi Kivilinna .blkcipher = { 144ce6dd368SJussi Kivilinna .min_keysize = ARC4_MIN_KEY_SIZE, 145ce6dd368SJussi Kivilinna .max_keysize = ARC4_MAX_KEY_SIZE, 146ce6dd368SJussi Kivilinna .setkey = arc4_set_key, 147ce6dd368SJussi Kivilinna .encrypt = ecb_arc4_crypt, 148ce6dd368SJussi Kivilinna .decrypt = ecb_arc4_crypt, 149ce6dd368SJussi Kivilinna }, 150ce6dd368SJussi Kivilinna }, 151ce6dd368SJussi Kivilinna } }; 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds static int __init arc4_init(void) 1541da177e4SLinus Torvalds { 155ce6dd368SJussi Kivilinna return crypto_register_algs(arc4_algs, ARRAY_SIZE(arc4_algs)); 1561da177e4SLinus Torvalds } 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds static void __exit arc4_exit(void) 1591da177e4SLinus Torvalds { 160ce6dd368SJussi Kivilinna crypto_unregister_algs(arc4_algs, ARRAY_SIZE(arc4_algs)); 1611da177e4SLinus Torvalds } 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds module_init(arc4_init); 1641da177e4SLinus Torvalds module_exit(arc4_exit); 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 1671da177e4SLinus Torvalds MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); 1681da177e4SLinus Torvalds MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>"); 169*5d26a105SKees Cook MODULE_ALIAS_CRYPTO("arc4"); 170