cifs: fork arc4 and create a separate module for it for cifs and other users
authorRonnie Sahlberg <lsahlber@redhat.com>
Thu, 19 Aug 2021 10:34:59 +0000 (20:34 +1000)
committerSteve French <stfrench@microsoft.com>
Wed, 25 Aug 2021 20:47:57 +0000 (15:47 -0500)
We can not drop ARC4 and basically destroy CIFS connectivity for
almost all CIFS users so create a new forked ARC4 module that CIFS and other
subsystems that have a hard dependency on ARC4 can use.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/Kconfig
fs/Makefile
fs/cifs/Kconfig
fs/cifs/cifsencrypt.c
fs/cifs_common/Makefile [new file with mode: 0644]
fs/cifs_common/arc4.h [new file with mode: 0644]
fs/cifs_common/cifs_arc4.c [new file with mode: 0644]

index a7749c1..6d719f2 100644 (file)
@@ -358,7 +358,14 @@ config NFS_V4_2_SSC_HELPER
 
 source "net/sunrpc/Kconfig"
 source "fs/ceph/Kconfig"
+
 source "fs/cifs/Kconfig"
+
+config CIFS_COMMON
+       tristate
+       default y if CIFS=y
+       default m if CIFS=m
+
 source "fs/coda/Kconfig"
 source "fs/afs/Kconfig"
 source "fs/9p/Kconfig"
index f98f3e6..77b0e79 100644 (file)
@@ -96,6 +96,7 @@ obj-$(CONFIG_LOCKD)           += lockd/
 obj-$(CONFIG_NLS)              += nls/
 obj-$(CONFIG_UNICODE)          += unicode/
 obj-$(CONFIG_SYSV_FS)          += sysv/
+obj-$(CONFIG_CIFS_COMMON)      += cifs_common/
 obj-$(CONFIG_CIFS)             += cifs/
 obj-$(CONFIG_HPFS_FS)          += hpfs/
 obj-$(CONFIG_NTFS_FS)          += ntfs/
index 2e8b132..aa4457d 100644 (file)
@@ -10,7 +10,6 @@ config CIFS
        select CRYPTO_SHA512
        select CRYPTO_CMAC
        select CRYPTO_HMAC
-       select CRYPTO_LIB_ARC4
        select CRYPTO_AEAD2
        select CRYPTO_CCM
        select CRYPTO_GCM
index 7680e0a..6679e07 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/random.h>
 #include <linux/highmem.h>
 #include <linux/fips.h>
-#include <crypto/arc4.h>
+#include "../cifs_common/arc4.h"
 #include <crypto/aead.h>
 
 int __cifs_calc_signature(struct smb_rqst *rqst,
@@ -699,9 +699,9 @@ calc_seckey(struct cifs_ses *ses)
                return -ENOMEM;
        }
 
-       arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
-       arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
-                  CIFS_CPHTXT_SIZE);
+       cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
+       cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
+                       CIFS_CPHTXT_SIZE);
 
        /* make secondary_key/nonce as session key */
        memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
diff --git a/fs/cifs_common/Makefile b/fs/cifs_common/Makefile
new file mode 100644 (file)
index 0000000..2fc9b40
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for Linux filesystem routines that are shared by client and server.
+#
+
+obj-$(CONFIG_CIFS_COMMON) += cifs_arc4.o
diff --git a/fs/cifs_common/arc4.h b/fs/cifs_common/arc4.h
new file mode 100644 (file)
index 0000000..12e71ec
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Common values for ARC4 Cipher Algorithm
+ */
+
+#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 cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len);
+void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len);
+
+#endif /* _CRYPTO_ARC4_H */
diff --git a/fs/cifs_common/cifs_arc4.c b/fs/cifs_common/cifs_arc4.c
new file mode 100644 (file)
index 0000000..b964cc6
--- /dev/null
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Cryptographic API
+ *
+ * ARC4 Cipher Algorithm
+ *
+ * Jon Oberheide <jon@oberheide.org>
+ */
+
+#include <linux/module.h>
+#include "arc4.h"
+
+MODULE_LICENSE("GPL");
+
+int cifs_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_GPL(cifs_arc4_setkey);
+
+void cifs_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_GPL(cifs_arc4_crypt);
+
+static int __init
+init_cifs_common(void)
+{
+       return 0;
+}
+static void __init
+exit_cifs_common(void)
+{
+}
+
+module_init(init_cifs_common)
+module_exit(exit_cifs_common)