| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | #include <linux/module.h> | 
|  | 15 | #include <linux/init.h> | 
|  | 16 | #include <linux/crypto.h> | 
|  | 17 |  | 
|  | 18 | #define ARC4_MIN_KEY_SIZE	1 | 
|  | 19 | #define ARC4_MAX_KEY_SIZE	256 | 
|  | 20 | #define ARC4_BLOCK_SIZE		1 | 
|  | 21 |  | 
|  | 22 | struct arc4_ctx { | 
|  | 23 | u8 S[256]; | 
|  | 24 | u8 x, y; | 
|  | 25 | }; | 
|  | 26 |  | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 27 | static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, | 
| Herbert Xu | 560c06a | 2006-08-13 14:16:39 +1000 | [diff] [blame] | 28 | unsigned int key_len) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 29 | { | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 30 | struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 31 | int i, j = 0, k = 0; | 
|  | 32 |  | 
|  | 33 | ctx->x = 1; | 
|  | 34 | ctx->y = 0; | 
|  | 35 |  | 
|  | 36 | for(i = 0; i < 256; i++) | 
|  | 37 | ctx->S[i] = i; | 
|  | 38 |  | 
|  | 39 | for(i = 0; i < 256; i++) | 
|  | 40 | { | 
|  | 41 | u8 a = ctx->S[i]; | 
|  | 42 | j = (j + in_key[k] + a) & 0xff; | 
|  | 43 | ctx->S[i] = ctx->S[j]; | 
|  | 44 | ctx->S[j] = a; | 
|  | 45 | if(++k >= key_len) | 
|  | 46 | k = 0; | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | return 0; | 
|  | 50 | } | 
|  | 51 |  | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 52 | static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 53 | { | 
| Herbert Xu | 6c2bb98 | 2006-05-16 22:09:29 +1000 | [diff] [blame] | 54 | struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 55 |  | 
|  | 56 | u8 *const S = ctx->S; | 
|  | 57 | u8 x = ctx->x; | 
|  | 58 | u8 y = ctx->y; | 
|  | 59 | u8 a, b; | 
|  | 60 |  | 
|  | 61 | a = S[x]; | 
|  | 62 | y = (y + a) & 0xff; | 
|  | 63 | b = S[y]; | 
|  | 64 | S[x] = b; | 
|  | 65 | S[y] = a; | 
|  | 66 | x = (x + 1) & 0xff; | 
|  | 67 | *out++ = *in ^ S[(a + b) & 0xff]; | 
|  | 68 |  | 
|  | 69 | ctx->x = x; | 
|  | 70 | ctx->y = y; | 
|  | 71 | } | 
|  | 72 |  | 
|  | 73 | static struct crypto_alg arc4_alg = { | 
|  | 74 | .cra_name		=	"arc4", | 
|  | 75 | .cra_flags		=	CRYPTO_ALG_TYPE_CIPHER, | 
|  | 76 | .cra_blocksize		=	ARC4_BLOCK_SIZE, | 
|  | 77 | .cra_ctxsize		=	sizeof(struct arc4_ctx), | 
|  | 78 | .cra_module		=	THIS_MODULE, | 
|  | 79 | .cra_list		=	LIST_HEAD_INIT(arc4_alg.cra_list), | 
|  | 80 | .cra_u			=	{ .cipher = { | 
|  | 81 | .cia_min_keysize	=	ARC4_MIN_KEY_SIZE, | 
|  | 82 | .cia_max_keysize	=	ARC4_MAX_KEY_SIZE, | 
|  | 83 | .cia_setkey	   	= 	arc4_set_key, | 
|  | 84 | .cia_encrypt	 	=	arc4_crypt, | 
|  | 85 | .cia_decrypt	  	=	arc4_crypt } } | 
|  | 86 | }; | 
|  | 87 |  | 
|  | 88 | static int __init arc4_init(void) | 
|  | 89 | { | 
|  | 90 | return crypto_register_alg(&arc4_alg); | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 |  | 
|  | 94 | static void __exit arc4_exit(void) | 
|  | 95 | { | 
|  | 96 | crypto_unregister_alg(&arc4_alg); | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | module_init(arc4_init); | 
|  | 100 | module_exit(arc4_exit); | 
|  | 101 |  | 
|  | 102 | MODULE_LICENSE("GPL"); | 
|  | 103 | MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); | 
|  | 104 | MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>"); |