Back to home page

LXR

 
 

    


0001 /*
0002  * Cryptographic API
0003  *
0004  * ARC4 Cipher Algorithm
0005  *
0006  * Jon Oberheide <jon@oberheide.org>
0007  *
0008  * This program is free software; you can redistribute it and/or modify
0009  * it under the terms of the GNU General Public License as published by
0010  * the Free Software Foundation; either version 2 of the License, or
0011  * (at your option) any later version.
0012  *
0013  */
0014 
0015 #include <linux/module.h>
0016 #include <linux/init.h>
0017 #include <linux/crypto.h>
0018 #include <crypto/algapi.h>
0019 
0020 #define ARC4_MIN_KEY_SIZE   1
0021 #define ARC4_MAX_KEY_SIZE   256
0022 #define ARC4_BLOCK_SIZE     1
0023 
0024 struct arc4_ctx {
0025     u32 S[256];
0026     u32 x, y;
0027 };
0028 
0029 static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
0030             unsigned int key_len)
0031 {
0032     struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
0033     int i, j = 0, k = 0;
0034 
0035     ctx->x = 1;
0036     ctx->y = 0;
0037 
0038     for (i = 0; i < 256; i++)
0039         ctx->S[i] = i;
0040 
0041     for (i = 0; i < 256; i++) {
0042         u32 a = ctx->S[i];
0043         j = (j + in_key[k] + a) & 0xff;
0044         ctx->S[i] = ctx->S[j];
0045         ctx->S[j] = a;
0046         if (++k >= key_len)
0047             k = 0;
0048     }
0049 
0050     return 0;
0051 }
0052 
0053 static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in,
0054                unsigned int len)
0055 {
0056     u32 *const S = ctx->S;
0057     u32 x, y, a, b;
0058     u32 ty, ta, tb;
0059 
0060     if (len == 0)
0061         return;
0062 
0063     x = ctx->x;
0064     y = ctx->y;
0065 
0066     a = S[x];
0067     y = (y + a) & 0xff;
0068     b = S[y];
0069 
0070     do {
0071         S[y] = a;
0072         a = (a + b) & 0xff;
0073         S[x] = b;
0074         x = (x + 1) & 0xff;
0075         ta = S[x];
0076         ty = (y + ta) & 0xff;
0077         tb = S[ty];
0078         *out++ = *in++ ^ S[a];
0079         if (--len == 0)
0080             break;
0081         y = ty;
0082         a = ta;
0083         b = tb;
0084     } while (true);
0085 
0086     ctx->x = x;
0087     ctx->y = y;
0088 }
0089 
0090 static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in)
0091 {
0092     arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1);
0093 }
0094 
0095 static int ecb_arc4_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
0096               struct scatterlist *src, unsigned int nbytes)
0097 {
0098     struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
0099     struct blkcipher_walk walk;
0100     int err;
0101 
0102     blkcipher_walk_init(&walk, dst, src, nbytes);
0103 
0104     err = blkcipher_walk_virt(desc, &walk);
0105 
0106     while (walk.nbytes > 0) {
0107         u8 *wsrc = walk.src.virt.addr;
0108         u8 *wdst = walk.dst.virt.addr;
0109 
0110         arc4_crypt(ctx, wdst, wsrc, walk.nbytes);
0111 
0112         err = blkcipher_walk_done(desc, &walk, 0);
0113     }
0114 
0115     return err;
0116 }
0117 
0118 static struct crypto_alg arc4_algs[2] = { {
0119     .cra_name       =   "arc4",
0120     .cra_flags      =   CRYPTO_ALG_TYPE_CIPHER,
0121     .cra_blocksize      =   ARC4_BLOCK_SIZE,
0122     .cra_ctxsize        =   sizeof(struct arc4_ctx),
0123     .cra_module     =   THIS_MODULE,
0124     .cra_u          =   {
0125         .cipher = {
0126             .cia_min_keysize    =   ARC4_MIN_KEY_SIZE,
0127             .cia_max_keysize    =   ARC4_MAX_KEY_SIZE,
0128             .cia_setkey     =   arc4_set_key,
0129             .cia_encrypt        =   arc4_crypt_one,
0130             .cia_decrypt        =   arc4_crypt_one,
0131         },
0132     },
0133 }, {
0134     .cra_name       =   "ecb(arc4)",
0135     .cra_priority       =   100,
0136     .cra_flags      =   CRYPTO_ALG_TYPE_BLKCIPHER,
0137     .cra_blocksize      =   ARC4_BLOCK_SIZE,
0138     .cra_ctxsize        =   sizeof(struct arc4_ctx),
0139     .cra_alignmask      =   0,
0140     .cra_type       =   &crypto_blkcipher_type,
0141     .cra_module     =   THIS_MODULE,
0142     .cra_u          =   {
0143         .blkcipher = {
0144             .min_keysize    =   ARC4_MIN_KEY_SIZE,
0145             .max_keysize    =   ARC4_MAX_KEY_SIZE,
0146             .setkey     =   arc4_set_key,
0147             .encrypt    =   ecb_arc4_crypt,
0148             .decrypt    =   ecb_arc4_crypt,
0149         },
0150     },
0151 } };
0152 
0153 static int __init arc4_init(void)
0154 {
0155     return crypto_register_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
0156 }
0157 
0158 static void __exit arc4_exit(void)
0159 {
0160     crypto_unregister_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
0161 }
0162 
0163 module_init(arc4_init);
0164 module_exit(arc4_exit);
0165 
0166 MODULE_LICENSE("GPL");
0167 MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
0168 MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
0169 MODULE_ALIAS_CRYPTO("arc4");