arc4.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. #include <crypto/algapi.h>
  18. #define ARC4_MIN_KEY_SIZE 1
  19. #define ARC4_MAX_KEY_SIZE 256
  20. #define ARC4_BLOCK_SIZE 1
  21. struct arc4_ctx {
  22. u32 S[256];
  23. u32 x, y;
  24. };
  25. static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
  26. unsigned int key_len)
  27. {
  28. struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
  29. int i, j = 0, k = 0;
  30. ctx->x = 1;
  31. ctx->y = 0;
  32. for (i = 0; i < 256; i++)
  33. ctx->S[i] = i;
  34. for (i = 0; i < 256; i++) {
  35. u32 a = ctx->S[i];
  36. j = (j + in_key[k] + a) & 0xff;
  37. ctx->S[i] = ctx->S[j];
  38. ctx->S[j] = a;
  39. if (++k >= key_len)
  40. k = 0;
  41. }
  42. return 0;
  43. }
  44. static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in,
  45. unsigned int len)
  46. {
  47. u32 *const S = ctx->S;
  48. u32 x, y, a, b;
  49. u32 ty, ta, tb;
  50. if (len == 0)
  51. return;
  52. x = ctx->x;
  53. y = ctx->y;
  54. a = S[x];
  55. y = (y + a) & 0xff;
  56. b = S[y];
  57. do {
  58. S[y] = a;
  59. a = (a + b) & 0xff;
  60. S[x] = b;
  61. x = (x + 1) & 0xff;
  62. ta = S[x];
  63. ty = (y + ta) & 0xff;
  64. tb = S[ty];
  65. *out++ = *in++ ^ S[a];
  66. if (--len == 0)
  67. break;
  68. y = ty;
  69. a = ta;
  70. b = tb;
  71. } while (true);
  72. ctx->x = x;
  73. ctx->y = y;
  74. }
  75. static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in)
  76. {
  77. arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1);
  78. }
  79. static int ecb_arc4_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  80. struct scatterlist *src, unsigned int nbytes)
  81. {
  82. struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  83. struct blkcipher_walk walk;
  84. int err;
  85. blkcipher_walk_init(&walk, dst, src, nbytes);
  86. err = blkcipher_walk_virt(desc, &walk);
  87. while (walk.nbytes > 0) {
  88. u8 *wsrc = walk.src.virt.addr;
  89. u8 *wdst = walk.dst.virt.addr;
  90. arc4_crypt(ctx, wdst, wsrc, walk.nbytes);
  91. err = blkcipher_walk_done(desc, &walk, 0);
  92. }
  93. return err;
  94. }
  95. static struct crypto_alg arc4_algs[2] = { {
  96. .cra_name = "arc4",
  97. .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
  98. .cra_blocksize = ARC4_BLOCK_SIZE,
  99. .cra_ctxsize = sizeof(struct arc4_ctx),
  100. .cra_module = THIS_MODULE,
  101. .cra_u = {
  102. .cipher = {
  103. .cia_min_keysize = ARC4_MIN_KEY_SIZE,
  104. .cia_max_keysize = ARC4_MAX_KEY_SIZE,
  105. .cia_setkey = arc4_set_key,
  106. .cia_encrypt = arc4_crypt_one,
  107. .cia_decrypt = arc4_crypt_one,
  108. },
  109. },
  110. }, {
  111. .cra_name = "ecb(arc4)",
  112. .cra_priority = 100,
  113. .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
  114. .cra_blocksize = ARC4_BLOCK_SIZE,
  115. .cra_ctxsize = sizeof(struct arc4_ctx),
  116. .cra_alignmask = 0,
  117. .cra_type = &crypto_blkcipher_type,
  118. .cra_module = THIS_MODULE,
  119. .cra_u = {
  120. .blkcipher = {
  121. .min_keysize = ARC4_MIN_KEY_SIZE,
  122. .max_keysize = ARC4_MAX_KEY_SIZE,
  123. .setkey = arc4_set_key,
  124. .encrypt = ecb_arc4_crypt,
  125. .decrypt = ecb_arc4_crypt,
  126. },
  127. },
  128. } };
  129. static int __init arc4_init(void)
  130. {
  131. return crypto_register_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
  132. }
  133. static void __exit arc4_exit(void)
  134. {
  135. crypto_unregister_algs(arc4_algs, ARRAY_SIZE(arc4_algs));
  136. }
  137. module_init(arc4_init);
  138. module_exit(arc4_exit);
  139. MODULE_LICENSE("GPL");
  140. MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
  141. MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
  142. MODULE_ALIAS_CRYPTO("arc4");