Refactor the core rc4 handling so we can move most users to a library
interface, permitting us to drop the cipher interface entirely in a
future patch. This is part of an effort to simplify the crypto API
and improve its robustness against incorrect use.

Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
---
 MAINTAINERS           |  1 +
 crypto/Kconfig        |  4 ++
 crypto/arc4.c         | 60 +---------------
 include/crypto/arc4.h | 10 +++
 lib/Makefile          |  2 +-
 lib/crypto/Makefile   |  4 ++
 lib/crypto/arc4.c     | 72 ++++++++++++++++++++
 7 files changed, 93 insertions(+), 60 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 57f496cff999..112f21066141 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4241,6 +4241,7 @@ F:        crypto/
 F:     drivers/crypto/
 F:     include/crypto/
 F:     include/linux/crypto*
+F:     lib/crypto/
 
 CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
 M:     Neil Horman <nhor...@tuxdriver.com>
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 3d056e7da65f..5114b35ef3b4 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1230,9 +1230,13 @@ config CRYPTO_ANUBIS
          <https://www.cosic.esat.kuleuven.be/nessie/reports/>
          <http://www.larc.usp.br/~pbarreto/AnubisPage.html>
 
+config CRYPTO_LIB_ARC4
+       tristate
+
 config CRYPTO_ARC4
        tristate "ARC4 cipher algorithm"
        select CRYPTO_BLKCIPHER
+       select CRYPTO_LIB_ARC4
        help
          ARC4 cipher algorithm.
 
diff --git a/crypto/arc4.c b/crypto/arc4.c
index a2120e06bf84..6974dba1b7b9 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -13,33 +13,12 @@
 #include <linux/init.h>
 #include <linux/module.h>
 
-struct arc4_ctx {
-       u32 S[256];
-       u32 x, y;
-};
-
 static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                        unsigned int key_len)
 {
        struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
-       int i, j = 0, k = 0;
-
-       ctx->x = 1;
-       ctx->y = 0;
 
-       for (i = 0; i < 256; i++)
-               ctx->S[i] = i;
-
-       for (i = 0; i < 256; i++) {
-               u32 a = ctx->S[i];
-               j = (j + in_key[k] + a) & 0xff;
-               ctx->S[i] = ctx->S[j];
-               ctx->S[j] = a;
-               if (++k >= key_len)
-                       k = 0;
-       }
-
-       return 0;
+       return arc4_setkey(ctx, in_key, key_len);
 }
 
 static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key,
@@ -48,43 +27,6 @@ static int arc4_set_key_skcipher(struct crypto_skcipher 
*tfm, const u8 *in_key,
        return arc4_set_key(&tfm->base, in_key, key_len);
 }
 
-static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in,
-                      unsigned int len)
-{
-       u32 *const S = ctx->S;
-       u32 x, y, a, b;
-       u32 ty, ta, tb;
-
-       if (len == 0)
-               return;
-
-       x = ctx->x;
-       y = ctx->y;
-
-       a = S[x];
-       y = (y + a) & 0xff;
-       b = S[y];
-
-       do {
-               S[y] = a;
-               a = (a + b) & 0xff;
-               S[x] = b;
-               x = (x + 1) & 0xff;
-               ta = S[x];
-               ty = (y + ta) & 0xff;
-               tb = S[ty];
-               *out++ = *in++ ^ S[a];
-               if (--len == 0)
-                       break;
-               y = ty;
-               a = ta;
-               b = tb;
-       } while (true);
-
-       ctx->x = x;
-       ctx->y = y;
-}
-
 static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
        arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1);
diff --git a/include/crypto/arc4.h b/include/crypto/arc4.h
index 5b2c24ab0139..f3c22fe01704 100644
--- a/include/crypto/arc4.h
+++ b/include/crypto/arc4.h
@@ -6,8 +6,18 @@
 #ifndef _CRYPTO_ARC4_H
 #define _CRYPTO_ARC4_H
 
+#include <linux/types.h>
+
 #define ARC4_MIN_KEY_SIZE      1
 #define ARC4_MAX_KEY_SIZE      256
 #define ARC4_BLOCK_SIZE                1
 
+struct arc4_ctx {
+       u32 S[256];
+       u32 x, y;
+};
+
+int arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len);
+void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len);
+
 #endif /* _CRYPTO_ARC4_H */
diff --git a/lib/Makefile b/lib/Makefile
index fb7697031a79..d3daedf93c5a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -102,7 +102,7 @@ endif
 obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o
 CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any)
 
-obj-y += math/
+obj-y += math/ crypto/
 
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
 obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
new file mode 100644
index 000000000000..88195c34932d
--- /dev/null
+++ b/lib/crypto/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_CRYPTO_LIB_ARC4) += libarc4.o
+libarc4-y := arc4.o
diff --git a/lib/crypto/arc4.c b/lib/crypto/arc4.c
new file mode 100644
index 000000000000..fa589eba3d50
--- /dev/null
+++ b/lib/crypto/arc4.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Cryptographic API
+ *
+ * ARC4 Cipher Algorithm
+ *
+ * Jon Oberheide <j...@oberheide.org>
+ */
+
+#include <crypto/arc4.h>
+#include <linux/module.h>
+
+int arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
+{
+       int i, j = 0, k = 0;
+
+       ctx->x = 1;
+       ctx->y = 0;
+
+       for (i = 0; i < 256; i++)
+               ctx->S[i] = i;
+
+       for (i = 0; i < 256; i++) {
+               u32 a = ctx->S[i];
+
+               j = (j + in_key[k] + a) & 0xff;
+               ctx->S[i] = ctx->S[j];
+               ctx->S[j] = a;
+               if (++k >= key_len)
+                       k = 0;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(arc4_setkey);
+
+void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
+{
+       u32 *const S = ctx->S;
+       u32 x, y, a, b;
+       u32 ty, ta, tb;
+
+       if (len == 0)
+               return;
+
+       x = ctx->x;
+       y = ctx->y;
+
+       a = S[x];
+       y = (y + a) & 0xff;
+       b = S[y];
+
+       do {
+               S[y] = a;
+               a = (a + b) & 0xff;
+               S[x] = b;
+               x = (x + 1) & 0xff;
+               ta = S[x];
+               ty = (y + ta) & 0xff;
+               tb = S[ty];
+               *out++ = *in++ ^ S[a];
+               if (--len == 0)
+                       break;
+               y = ty;
+               a = ta;
+               b = tb;
+       } while (true);
+
+       ctx->x = x;
+       ctx->y = y;
+}
+EXPORT_SYMBOL(arc4_crypt);
-- 
2.20.1

Reply via email to