• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
24  struct arc4_ctx {
25  	u32 S[256];
26  	u32 x, y;
27  };
28  
arc4_set_key(struct crypto_tfm * tfm,const u8 * in_key,unsigned int key_len)29  static 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  
arc4_crypt(struct arc4_ctx * ctx,u8 * out,const u8 * in,unsigned int len)53  static 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  
arc4_crypt_one(struct crypto_tfm * tfm,u8 * out,const u8 * in)90  static 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  
ecb_arc4_crypt(struct blkcipher_desc * desc,struct scatterlist * dst,struct scatterlist * src,unsigned int nbytes)95  static 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  
118  static 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  
arc4_init(void)153  static int __init arc4_init(void)
154  {
155  	return crypto_register_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
156  }
157  
arc4_exit(void)158  static void __exit arc4_exit(void)
159  {
160  	crypto_unregister_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
161  }
162  
163  module_init(arc4_init);
164  module_exit(arc4_exit);
165  
166  MODULE_LICENSE("GPL");
167  MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
168  MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
169  MODULE_ALIAS_CRYPTO("arc4");
170