linux/crypto/arc4.c
<<
>>
Prefs
   1/*
   2 * Cryptographic API
   3 *
   4 * ARC4 Cipher Algorithm
   5 *
   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 *
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/init.h>
  17#include <linux/crypto.h>
  18#include <crypto/algapi.h>
  19
  20#define ARC4_MIN_KEY_SIZE       1
  21#define ARC4_MAX_KEY_SIZE       256
  22#define ARC4_BLOCK_SIZE         1
  23
  24struct arc4_ctx {
  25        u32 S[256];
  26        u32 x, y;
  27};
  28
  29static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
  30                        unsigned int key_len)
  31{
  32        struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
  33        int i, j = 0, k = 0;
  34
  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;
  51}
  52
  53static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in,
  54                       unsigned int len)
  55{
  56        u32 *const S = ctx->S;
  57        u32 x, y, a, b;
  58        u32 ty, ta, tb;
  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);
  85
  86        ctx->x = x;
  87        ctx->y = y;
  88}
  89
  90static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in)
  91{
  92        arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1);
  93}
  94
  95static int ecb_arc4_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  96                          struct scatterlist *src, unsigned int nbytes)
  97{
  98        struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  99        struct blkcipher_walk walk;
 100        int err;
 101
 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;
 116}
 117
 118static struct crypto_alg arc4_algs[2] = { {
 119        .cra_name               =       "arc4",
 120        .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
 121        .cra_blocksize          =       ARC4_BLOCK_SIZE,
 122        .cra_ctxsize            =       sizeof(struct arc4_ctx),
 123        .cra_module             =       THIS_MODULE,
 124        .cra_u                  =       {
 125                .cipher = {
 126                        .cia_min_keysize        =       ARC4_MIN_KEY_SIZE,
 127                        .cia_max_keysize        =       ARC4_MAX_KEY_SIZE,
 128                        .cia_setkey             =       arc4_set_key,
 129                        .cia_encrypt            =       arc4_crypt_one,
 130                        .cia_decrypt            =       arc4_crypt_one,
 131                },
 132        },
 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} };
 152
 153static int __init arc4_init(void)
 154{
 155        return crypto_register_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
 156}
 157
 158static void __exit arc4_exit(void)
 159{
 160        crypto_unregister_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
 161}
 162
 163module_init(arc4_init);
 164module_exit(arc4_exit);
 165
 166MODULE_LICENSE("GPL");
 167MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
 168MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
 169MODULE_ALIAS_CRYPTO("arc4");
 170