* [PATCH] cifs: create a MD4 module and switch cifs.ko to use it
@ 2021-08-19 23:32 Ronnie Sahlberg
2021-08-24 16:50 ` Steve French
0 siblings, 1 reply; 2+ messages in thread
From: Ronnie Sahlberg @ 2021-08-19 23:32 UTC (permalink / raw)
To: linux-cifs; +Cc: Steve French
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
fs/cifs/Kconfig | 1 -
fs/cifs/cifsfs.c | 1 -
fs/cifs/smbencrypt.c | 24 ++---
fs/cifs_common/Makefile | 1 +
fs/cifs_common/cifs_md4.c | 201 ++++++++++++++++++++++++++++++++++++++
fs/cifs_common/md4.h | 27 +++++
6 files changed, 239 insertions(+), 16 deletions(-)
create mode 100644 fs/cifs_common/cifs_md4.c
create mode 100644 fs/cifs_common/md4.h
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index aa4457d72392..3b7e3b9e4fd2 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -4,7 +4,6 @@ config CIFS
depends on INET
select NLS
select CRYPTO
- select CRYPTO_MD4
select CRYPTO_MD5
select CRYPTO_SHA256
select CRYPTO_SHA512
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 85c884db909d..c5ba42d75bc2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -1749,7 +1749,6 @@ MODULE_DESCRIPTION
MODULE_VERSION(CIFS_VERSION);
MODULE_SOFTDEP("ecb");
MODULE_SOFTDEP("hmac");
-MODULE_SOFTDEP("md4");
MODULE_SOFTDEP("md5");
MODULE_SOFTDEP("nls");
MODULE_SOFTDEP("aes");
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 5da7eea3323f..c4b0bf239073 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -24,6 +24,7 @@
#include "cifsglob.h"
#include "cifs_debug.h"
#include "cifsproto.h"
+#include "../cifs_common/md4.h"
#ifndef false
#define false 0
@@ -42,29 +43,24 @@ static int
mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
{
int rc;
- struct crypto_shash *md4 = NULL;
- struct sdesc *sdescmd4 = NULL;
+ struct md4_ctx mctx;
- rc = cifs_alloc_hash("md4", &md4, &sdescmd4);
- if (rc)
- goto mdfour_err;
-
- rc = crypto_shash_init(&sdescmd4->shash);
+ rc = cifs_md4_init(&mctx);
if (rc) {
- cifs_dbg(VFS, "%s: Could not init md4 shash\n", __func__);
+ cifs_dbg(VFS, "%s: Could not init MD4\n", __func__);
goto mdfour_err;
}
- rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
+ rc = cifs_md4_update(&mctx, link_str, link_len);
if (rc) {
- cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
+ cifs_dbg(VFS, "%s: Could not update MD4\n", __func__);
goto mdfour_err;
}
- rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
- if (rc)
- cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
+ rc = cifs_md4_final(&mctx, md4_hash);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not finalize MD4\n", __func__);
+ }
mdfour_err:
- cifs_free_hash(&md4, &sdescmd4);
return rc;
}
diff --git a/fs/cifs_common/Makefile b/fs/cifs_common/Makefile
index 2fc9b40345c4..6fedd2f88a25 100644
--- a/fs/cifs_common/Makefile
+++ b/fs/cifs_common/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_CIFS_COMMON) += cifs_arc4.o
+obj-$(CONFIG_CIFS_COMMON) += cifs_md4.o
diff --git a/fs/cifs_common/cifs_md4.c b/fs/cifs_common/cifs_md4.c
new file mode 100644
index 000000000000..b975026759da
--- /dev/null
+++ b/fs/cifs_common/cifs_md4.c
@@ -0,0 +1,201 @@
+/*
+ * Cryptographic API.
+ *
+ * MD4 Message Digest Algorithm (RFC1320).
+ *
+ * Implementation derived from Andrew Tridgell and Steve French's
+ * CIFS MD4 implementation, and the cryptoapi implementation
+ * originally based on the public domain implementation written
+ * by Colin Plumb in 1993.
+ *
+ * Copyright (c) Andrew Tridgell 1997-1998.
+ * Modified by Steve French (sfrench@us.ibm.com) 2002
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include "md4.h"
+
+MODULE_LICENSE("GPL");
+
+static inline u32 lshift(u32 x, unsigned int s)
+{
+ x &= 0xFFFFFFFF;
+ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
+}
+
+static inline u32 F(u32 x, u32 y, u32 z)
+{
+ return (x & y) | ((~x) & z);
+}
+
+static inline u32 G(u32 x, u32 y, u32 z)
+{
+ return (x & y) | (x & z) | (y & z);
+}
+
+static inline u32 H(u32 x, u32 y, u32 z)
+{
+ return x ^ y ^ z;
+}
+
+#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
+#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
+#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
+
+static void md4_transform(u32 *hash, u32 const *in)
+{
+ u32 a, b, c, d;
+
+ a = hash[0];
+ b = hash[1];
+ c = hash[2];
+ d = hash[3];
+
+ ROUND1(a, b, c, d, in[0], 3);
+ ROUND1(d, a, b, c, in[1], 7);
+ ROUND1(c, d, a, b, in[2], 11);
+ ROUND1(b, c, d, a, in[3], 19);
+ ROUND1(a, b, c, d, in[4], 3);
+ ROUND1(d, a, b, c, in[5], 7);
+ ROUND1(c, d, a, b, in[6], 11);
+ ROUND1(b, c, d, a, in[7], 19);
+ ROUND1(a, b, c, d, in[8], 3);
+ ROUND1(d, a, b, c, in[9], 7);
+ ROUND1(c, d, a, b, in[10], 11);
+ ROUND1(b, c, d, a, in[11], 19);
+ ROUND1(a, b, c, d, in[12], 3);
+ ROUND1(d, a, b, c, in[13], 7);
+ ROUND1(c, d, a, b, in[14], 11);
+ ROUND1(b, c, d, a, in[15], 19);
+
+ ROUND2(a, b, c, d,in[ 0], 3);
+ ROUND2(d, a, b, c, in[4], 5);
+ ROUND2(c, d, a, b, in[8], 9);
+ ROUND2(b, c, d, a, in[12], 13);
+ ROUND2(a, b, c, d, in[1], 3);
+ ROUND2(d, a, b, c, in[5], 5);
+ ROUND2(c, d, a, b, in[9], 9);
+ ROUND2(b, c, d, a, in[13], 13);
+ ROUND2(a, b, c, d, in[2], 3);
+ ROUND2(d, a, b, c, in[6], 5);
+ ROUND2(c, d, a, b, in[10], 9);
+ ROUND2(b, c, d, a, in[14], 13);
+ ROUND2(a, b, c, d, in[3], 3);
+ ROUND2(d, a, b, c, in[7], 5);
+ ROUND2(c, d, a, b, in[11], 9);
+ ROUND2(b, c, d, a, in[15], 13);
+
+ ROUND3(a, b, c, d,in[ 0], 3);
+ ROUND3(d, a, b, c, in[8], 9);
+ ROUND3(c, d, a, b, in[4], 11);
+ ROUND3(b, c, d, a, in[12], 15);
+ ROUND3(a, b, c, d, in[2], 3);
+ ROUND3(d, a, b, c, in[10], 9);
+ ROUND3(c, d, a, b, in[6], 11);
+ ROUND3(b, c, d, a, in[14], 15);
+ ROUND3(a, b, c, d, in[1], 3);
+ ROUND3(d, a, b, c, in[9], 9);
+ ROUND3(c, d, a, b, in[5], 11);
+ ROUND3(b, c, d, a, in[13], 15);
+ ROUND3(a, b, c, d, in[3], 3);
+ ROUND3(d, a, b, c, in[11], 9);
+ ROUND3(c, d, a, b, in[7], 11);
+ ROUND3(b, c, d, a, in[15], 15);
+
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+}
+
+static inline void md4_transform_helper(struct md4_ctx *ctx)
+{
+ le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
+ md4_transform(ctx->hash, ctx->block);
+}
+
+int cifs_md4_init(struct md4_ctx *mctx)
+{
+ memset(mctx, 0, sizeof(struct md4_ctx));
+ mctx->hash[0] = 0x67452301;
+ mctx->hash[1] = 0xefcdab89;
+ mctx->hash[2] = 0x98badcfe;
+ mctx->hash[3] = 0x10325476;
+ mctx->byte_count = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_init);
+
+int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
+{
+ const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
+
+ mctx->byte_count += len;
+
+ if (avail > len) {
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, len);
+ return 0;
+ }
+
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, avail);
+
+ md4_transform_helper(mctx);
+ data += avail;
+ len -= avail;
+
+ while (len >= sizeof(mctx->block)) {
+ memcpy(mctx->block, data, sizeof(mctx->block));
+ md4_transform_helper(mctx);
+ data += sizeof(mctx->block);
+ len -= sizeof(mctx->block);
+ }
+
+ memcpy(mctx->block, data, len);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_update);
+
+int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
+{
+ const unsigned int offset = mctx->byte_count & 0x3f;
+ char *p = (char *)mctx->block + offset;
+ int padding = 56 - (offset + 1);
+
+ *p++ = 0x80;
+ if (padding < 0) {
+ memset(p, 0x00, padding + sizeof (u64));
+ md4_transform_helper(mctx);
+ p = (char *)mctx->block;
+ padding = 56;
+ }
+
+ memset(p, 0, padding);
+ mctx->block[14] = mctx->byte_count << 3;
+ mctx->block[15] = mctx->byte_count >> 29;
+ le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
+ sizeof(u64)) / sizeof(u32));
+ md4_transform(mctx->hash, mctx->block);
+ cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
+ memcpy(out, mctx->hash, sizeof(mctx->hash));
+ memset(mctx, 0, sizeof(*mctx));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_final);
diff --git a/fs/cifs_common/md4.h b/fs/cifs_common/md4.h
new file mode 100644
index 000000000000..5337becc699a
--- /dev/null
+++ b/fs/cifs_common/md4.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Common values for ARC4 Cipher Algorithm
+ */
+
+#ifndef _CIFS_MD4_H
+#define _CIFS_MD4_H
+
+#include <linux/types.h>
+
+#define MD4_DIGEST_SIZE 16
+#define MD4_HMAC_BLOCK_SIZE 64
+#define MD4_BLOCK_WORDS 16
+#define MD4_HASH_WORDS 4
+
+struct md4_ctx {
+ u32 hash[MD4_HASH_WORDS];
+ u32 block[MD4_BLOCK_WORDS];
+ u64 byte_count;
+};
+
+
+int cifs_md4_init(struct md4_ctx *mctx);
+int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len);
+int cifs_md4_final(struct md4_ctx *mctx, u8 *out);
+
+#endif /* _CIFS_MD4_H */
--
2.30.2
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] cifs: create a MD4 module and switch cifs.ko to use it
2021-08-19 23:32 [PATCH] cifs: create a MD4 module and switch cifs.ko to use it Ronnie Sahlberg
@ 2021-08-24 16:50 ` Steve French
0 siblings, 0 replies; 2+ messages in thread
From: Steve French @ 2021-08-24 16:50 UTC (permalink / raw)
To: Ronnie Sahlberg; +Cc: linux-cifs
[-- Attachment #1: Type: text/plain, Size: 11062 bytes --]
FIxed various checkpatch errors, and added a commit description
On Thu, Aug 19, 2021 at 6:33 PM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
> fs/cifs/Kconfig | 1 -
> fs/cifs/cifsfs.c | 1 -
> fs/cifs/smbencrypt.c | 24 ++---
> fs/cifs_common/Makefile | 1 +
> fs/cifs_common/cifs_md4.c | 201 ++++++++++++++++++++++++++++++++++++++
> fs/cifs_common/md4.h | 27 +++++
> 6 files changed, 239 insertions(+), 16 deletions(-)
> create mode 100644 fs/cifs_common/cifs_md4.c
> create mode 100644 fs/cifs_common/md4.h
>
> diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
> index aa4457d72392..3b7e3b9e4fd2 100644
> --- a/fs/cifs/Kconfig
> +++ b/fs/cifs/Kconfig
> @@ -4,7 +4,6 @@ config CIFS
> depends on INET
> select NLS
> select CRYPTO
> - select CRYPTO_MD4
> select CRYPTO_MD5
> select CRYPTO_SHA256
> select CRYPTO_SHA512
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index 85c884db909d..c5ba42d75bc2 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -1749,7 +1749,6 @@ MODULE_DESCRIPTION
> MODULE_VERSION(CIFS_VERSION);
> MODULE_SOFTDEP("ecb");
> MODULE_SOFTDEP("hmac");
> -MODULE_SOFTDEP("md4");
> MODULE_SOFTDEP("md5");
> MODULE_SOFTDEP("nls");
> MODULE_SOFTDEP("aes");
> diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
> index 5da7eea3323f..c4b0bf239073 100644
> --- a/fs/cifs/smbencrypt.c
> +++ b/fs/cifs/smbencrypt.c
> @@ -24,6 +24,7 @@
> #include "cifsglob.h"
> #include "cifs_debug.h"
> #include "cifsproto.h"
> +#include "../cifs_common/md4.h"
>
> #ifndef false
> #define false 0
> @@ -42,29 +43,24 @@ static int
> mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
> {
> int rc;
> - struct crypto_shash *md4 = NULL;
> - struct sdesc *sdescmd4 = NULL;
> + struct md4_ctx mctx;
>
> - rc = cifs_alloc_hash("md4", &md4, &sdescmd4);
> - if (rc)
> - goto mdfour_err;
> -
> - rc = crypto_shash_init(&sdescmd4->shash);
> + rc = cifs_md4_init(&mctx);
> if (rc) {
> - cifs_dbg(VFS, "%s: Could not init md4 shash\n", __func__);
> + cifs_dbg(VFS, "%s: Could not init MD4\n", __func__);
> goto mdfour_err;
> }
> - rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
> + rc = cifs_md4_update(&mctx, link_str, link_len);
> if (rc) {
> - cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
> + cifs_dbg(VFS, "%s: Could not update MD4\n", __func__);
> goto mdfour_err;
> }
> - rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
> - if (rc)
> - cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
> + rc = cifs_md4_final(&mctx, md4_hash);
> + if (rc) {
> + cifs_dbg(VFS, "%s: Could not finalize MD4\n", __func__);
> + }
>
> mdfour_err:
> - cifs_free_hash(&md4, &sdescmd4);
> return rc;
> }
>
> diff --git a/fs/cifs_common/Makefile b/fs/cifs_common/Makefile
> index 2fc9b40345c4..6fedd2f88a25 100644
> --- a/fs/cifs_common/Makefile
> +++ b/fs/cifs_common/Makefile
> @@ -4,3 +4,4 @@
> #
>
> obj-$(CONFIG_CIFS_COMMON) += cifs_arc4.o
> +obj-$(CONFIG_CIFS_COMMON) += cifs_md4.o
> diff --git a/fs/cifs_common/cifs_md4.c b/fs/cifs_common/cifs_md4.c
> new file mode 100644
> index 000000000000..b975026759da
> --- /dev/null
> +++ b/fs/cifs_common/cifs_md4.c
> @@ -0,0 +1,201 @@
> +/*
> + * Cryptographic API.
> + *
> + * MD4 Message Digest Algorithm (RFC1320).
> + *
> + * Implementation derived from Andrew Tridgell and Steve French's
> + * CIFS MD4 implementation, and the cryptoapi implementation
> + * originally based on the public domain implementation written
> + * by Colin Plumb in 1993.
> + *
> + * Copyright (c) Andrew Tridgell 1997-1998.
> + * Modified by Steve French (sfrench@us.ibm.com) 2002
> + * Copyright (c) Cryptoapi developers.
> + * Copyright (c) 2002 David S. Miller (davem@redhat.com)
> + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + */
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <asm/byteorder.h>
> +#include "md4.h"
> +
> +MODULE_LICENSE("GPL");
> +
> +static inline u32 lshift(u32 x, unsigned int s)
> +{
> + x &= 0xFFFFFFFF;
> + return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
> +}
> +
> +static inline u32 F(u32 x, u32 y, u32 z)
> +{
> + return (x & y) | ((~x) & z);
> +}
> +
> +static inline u32 G(u32 x, u32 y, u32 z)
> +{
> + return (x & y) | (x & z) | (y & z);
> +}
> +
> +static inline u32 H(u32 x, u32 y, u32 z)
> +{
> + return x ^ y ^ z;
> +}
> +
> +#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
> +#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
> +#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
> +
> +static void md4_transform(u32 *hash, u32 const *in)
> +{
> + u32 a, b, c, d;
> +
> + a = hash[0];
> + b = hash[1];
> + c = hash[2];
> + d = hash[3];
> +
> + ROUND1(a, b, c, d, in[0], 3);
> + ROUND1(d, a, b, c, in[1], 7);
> + ROUND1(c, d, a, b, in[2], 11);
> + ROUND1(b, c, d, a, in[3], 19);
> + ROUND1(a, b, c, d, in[4], 3);
> + ROUND1(d, a, b, c, in[5], 7);
> + ROUND1(c, d, a, b, in[6], 11);
> + ROUND1(b, c, d, a, in[7], 19);
> + ROUND1(a, b, c, d, in[8], 3);
> + ROUND1(d, a, b, c, in[9], 7);
> + ROUND1(c, d, a, b, in[10], 11);
> + ROUND1(b, c, d, a, in[11], 19);
> + ROUND1(a, b, c, d, in[12], 3);
> + ROUND1(d, a, b, c, in[13], 7);
> + ROUND1(c, d, a, b, in[14], 11);
> + ROUND1(b, c, d, a, in[15], 19);
> +
> + ROUND2(a, b, c, d,in[ 0], 3);
> + ROUND2(d, a, b, c, in[4], 5);
> + ROUND2(c, d, a, b, in[8], 9);
> + ROUND2(b, c, d, a, in[12], 13);
> + ROUND2(a, b, c, d, in[1], 3);
> + ROUND2(d, a, b, c, in[5], 5);
> + ROUND2(c, d, a, b, in[9], 9);
> + ROUND2(b, c, d, a, in[13], 13);
> + ROUND2(a, b, c, d, in[2], 3);
> + ROUND2(d, a, b, c, in[6], 5);
> + ROUND2(c, d, a, b, in[10], 9);
> + ROUND2(b, c, d, a, in[14], 13);
> + ROUND2(a, b, c, d, in[3], 3);
> + ROUND2(d, a, b, c, in[7], 5);
> + ROUND2(c, d, a, b, in[11], 9);
> + ROUND2(b, c, d, a, in[15], 13);
> +
> + ROUND3(a, b, c, d,in[ 0], 3);
> + ROUND3(d, a, b, c, in[8], 9);
> + ROUND3(c, d, a, b, in[4], 11);
> + ROUND3(b, c, d, a, in[12], 15);
> + ROUND3(a, b, c, d, in[2], 3);
> + ROUND3(d, a, b, c, in[10], 9);
> + ROUND3(c, d, a, b, in[6], 11);
> + ROUND3(b, c, d, a, in[14], 15);
> + ROUND3(a, b, c, d, in[1], 3);
> + ROUND3(d, a, b, c, in[9], 9);
> + ROUND3(c, d, a, b, in[5], 11);
> + ROUND3(b, c, d, a, in[13], 15);
> + ROUND3(a, b, c, d, in[3], 3);
> + ROUND3(d, a, b, c, in[11], 9);
> + ROUND3(c, d, a, b, in[7], 11);
> + ROUND3(b, c, d, a, in[15], 15);
> +
> + hash[0] += a;
> + hash[1] += b;
> + hash[2] += c;
> + hash[3] += d;
> +}
> +
> +static inline void md4_transform_helper(struct md4_ctx *ctx)
> +{
> + le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
> + md4_transform(ctx->hash, ctx->block);
> +}
> +
> +int cifs_md4_init(struct md4_ctx *mctx)
> +{
> + memset(mctx, 0, sizeof(struct md4_ctx));
> + mctx->hash[0] = 0x67452301;
> + mctx->hash[1] = 0xefcdab89;
> + mctx->hash[2] = 0x98badcfe;
> + mctx->hash[3] = 0x10325476;
> + mctx->byte_count = 0;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(cifs_md4_init);
> +
> +int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
> +{
> + const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
> +
> + mctx->byte_count += len;
> +
> + if (avail > len) {
> + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
> + data, len);
> + return 0;
> + }
> +
> + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
> + data, avail);
> +
> + md4_transform_helper(mctx);
> + data += avail;
> + len -= avail;
> +
> + while (len >= sizeof(mctx->block)) {
> + memcpy(mctx->block, data, sizeof(mctx->block));
> + md4_transform_helper(mctx);
> + data += sizeof(mctx->block);
> + len -= sizeof(mctx->block);
> + }
> +
> + memcpy(mctx->block, data, len);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(cifs_md4_update);
> +
> +int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
> +{
> + const unsigned int offset = mctx->byte_count & 0x3f;
> + char *p = (char *)mctx->block + offset;
> + int padding = 56 - (offset + 1);
> +
> + *p++ = 0x80;
> + if (padding < 0) {
> + memset(p, 0x00, padding + sizeof (u64));
> + md4_transform_helper(mctx);
> + p = (char *)mctx->block;
> + padding = 56;
> + }
> +
> + memset(p, 0, padding);
> + mctx->block[14] = mctx->byte_count << 3;
> + mctx->block[15] = mctx->byte_count >> 29;
> + le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
> + sizeof(u64)) / sizeof(u32));
> + md4_transform(mctx->hash, mctx->block);
> + cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
> + memcpy(out, mctx->hash, sizeof(mctx->hash));
> + memset(mctx, 0, sizeof(*mctx));
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(cifs_md4_final);
> diff --git a/fs/cifs_common/md4.h b/fs/cifs_common/md4.h
> new file mode 100644
> index 000000000000..5337becc699a
> --- /dev/null
> +++ b/fs/cifs_common/md4.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Common values for ARC4 Cipher Algorithm
> + */
> +
> +#ifndef _CIFS_MD4_H
> +#define _CIFS_MD4_H
> +
> +#include <linux/types.h>
> +
> +#define MD4_DIGEST_SIZE 16
> +#define MD4_HMAC_BLOCK_SIZE 64
> +#define MD4_BLOCK_WORDS 16
> +#define MD4_HASH_WORDS 4
> +
> +struct md4_ctx {
> + u32 hash[MD4_HASH_WORDS];
> + u32 block[MD4_BLOCK_WORDS];
> + u64 byte_count;
> +};
> +
> +
> +int cifs_md4_init(struct md4_ctx *mctx);
> +int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len);
> +int cifs_md4_final(struct md4_ctx *mctx, u8 *out);
> +
> +#endif /* _CIFS_MD4_H */
> --
> 2.30.2
>
--
Thanks,
Steve
[-- Attachment #2: 0001-cifs-create-a-MD4-module-and-switch-cifs.ko-to-use-i.patch --]
[-- Type: text/x-patch, Size: 9515 bytes --]
From 32ef55ff407fd8d95d2c7138060bc28713093377 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <lsahlber@redhat.com>
Date: Fri, 20 Aug 2021 09:32:56 +1000
Subject: [PATCH] cifs: create a MD4 module and switch cifs.ko to use it
MD4 support will likely be removed from the crypto directory, but
is needed for compression of NTLMSSP in SMB3 mounts.
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/cifs/Kconfig | 1 -
fs/cifs/cifsfs.c | 1 -
fs/cifs/smbencrypt.c | 22 ++---
fs/cifs_common/Makefile | 1 +
fs/cifs_common/cifs_md4.c | 201 ++++++++++++++++++++++++++++++++++++++
fs/cifs_common/md4.h | 27 +++++
6 files changed, 238 insertions(+), 15 deletions(-)
create mode 100644 fs/cifs_common/cifs_md4.c
create mode 100644 fs/cifs_common/md4.h
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index aa4457d72392..3b7e3b9e4fd2 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -4,7 +4,6 @@ config CIFS
depends on INET
select NLS
select CRYPTO
- select CRYPTO_MD4
select CRYPTO_MD5
select CRYPTO_SHA256
select CRYPTO_SHA512
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index b1b175f229ee..8c20bfa187ac 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -1748,7 +1748,6 @@ MODULE_DESCRIPTION
MODULE_VERSION(CIFS_VERSION);
MODULE_SOFTDEP("ecb");
MODULE_SOFTDEP("hmac");
-MODULE_SOFTDEP("md4");
MODULE_SOFTDEP("md5");
MODULE_SOFTDEP("nls");
MODULE_SOFTDEP("aes");
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 5da7eea3323f..10047cc55286 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -24,6 +24,7 @@
#include "cifsglob.h"
#include "cifs_debug.h"
#include "cifsproto.h"
+#include "../cifs_common/md4.h"
#ifndef false
#define false 0
@@ -42,29 +43,24 @@ static int
mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
{
int rc;
- struct crypto_shash *md4 = NULL;
- struct sdesc *sdescmd4 = NULL;
+ struct md4_ctx mctx;
- rc = cifs_alloc_hash("md4", &md4, &sdescmd4);
- if (rc)
- goto mdfour_err;
-
- rc = crypto_shash_init(&sdescmd4->shash);
+ rc = cifs_md4_init(&mctx);
if (rc) {
- cifs_dbg(VFS, "%s: Could not init md4 shash\n", __func__);
+ cifs_dbg(VFS, "%s: Could not init MD4\n", __func__);
goto mdfour_err;
}
- rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
+ rc = cifs_md4_update(&mctx, link_str, link_len);
if (rc) {
- cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
+ cifs_dbg(VFS, "%s: Could not update MD4\n", __func__);
goto mdfour_err;
}
- rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
+ rc = cifs_md4_final(&mctx, md4_hash);
if (rc)
- cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
+ cifs_dbg(VFS, "%s: Could not finalize MD4\n", __func__);
+
mdfour_err:
- cifs_free_hash(&md4, &sdescmd4);
return rc;
}
diff --git a/fs/cifs_common/Makefile b/fs/cifs_common/Makefile
index 2fc9b40345c4..6fedd2f88a25 100644
--- a/fs/cifs_common/Makefile
+++ b/fs/cifs_common/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_CIFS_COMMON) += cifs_arc4.o
+obj-$(CONFIG_CIFS_COMMON) += cifs_md4.o
diff --git a/fs/cifs_common/cifs_md4.c b/fs/cifs_common/cifs_md4.c
new file mode 100644
index 000000000000..dbf9113b8600
--- /dev/null
+++ b/fs/cifs_common/cifs_md4.c
@@ -0,0 +1,201 @@
+/*
+ * Cryptographic API.
+ *
+ * MD4 Message Digest Algorithm (RFC1320).
+ *
+ * Implementation derived from Andrew Tridgell and Steve French's
+ * CIFS MD4 implementation, and the cryptoapi implementation
+ * originally based on the public domain implementation written
+ * by Colin Plumb in 1993.
+ *
+ * Copyright (c) Andrew Tridgell 1997-1998.
+ * Modified by Steve French (sfrench@us.ibm.com) 2002
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include "md4.h"
+
+MODULE_LICENSE("GPL");
+
+static inline u32 lshift(u32 x, unsigned int s)
+{
+ x &= 0xFFFFFFFF;
+ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
+}
+
+static inline u32 F(u32 x, u32 y, u32 z)
+{
+ return (x & y) | ((~x) & z);
+}
+
+static inline u32 G(u32 x, u32 y, u32 z)
+{
+ return (x & y) | (x & z) | (y & z);
+}
+
+static inline u32 H(u32 x, u32 y, u32 z)
+{
+ return x ^ y ^ z;
+}
+
+#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
+#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
+#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
+
+static void md4_transform(u32 *hash, u32 const *in)
+{
+ u32 a, b, c, d;
+
+ a = hash[0];
+ b = hash[1];
+ c = hash[2];
+ d = hash[3];
+
+ ROUND1(a, b, c, d, in[0], 3);
+ ROUND1(d, a, b, c, in[1], 7);
+ ROUND1(c, d, a, b, in[2], 11);
+ ROUND1(b, c, d, a, in[3], 19);
+ ROUND1(a, b, c, d, in[4], 3);
+ ROUND1(d, a, b, c, in[5], 7);
+ ROUND1(c, d, a, b, in[6], 11);
+ ROUND1(b, c, d, a, in[7], 19);
+ ROUND1(a, b, c, d, in[8], 3);
+ ROUND1(d, a, b, c, in[9], 7);
+ ROUND1(c, d, a, b, in[10], 11);
+ ROUND1(b, c, d, a, in[11], 19);
+ ROUND1(a, b, c, d, in[12], 3);
+ ROUND1(d, a, b, c, in[13], 7);
+ ROUND1(c, d, a, b, in[14], 11);
+ ROUND1(b, c, d, a, in[15], 19);
+
+ ROUND2(a, b, c, d, in[0], 3);
+ ROUND2(d, a, b, c, in[4], 5);
+ ROUND2(c, d, a, b, in[8], 9);
+ ROUND2(b, c, d, a, in[12], 13);
+ ROUND2(a, b, c, d, in[1], 3);
+ ROUND2(d, a, b, c, in[5], 5);
+ ROUND2(c, d, a, b, in[9], 9);
+ ROUND2(b, c, d, a, in[13], 13);
+ ROUND2(a, b, c, d, in[2], 3);
+ ROUND2(d, a, b, c, in[6], 5);
+ ROUND2(c, d, a, b, in[10], 9);
+ ROUND2(b, c, d, a, in[14], 13);
+ ROUND2(a, b, c, d, in[3], 3);
+ ROUND2(d, a, b, c, in[7], 5);
+ ROUND2(c, d, a, b, in[11], 9);
+ ROUND2(b, c, d, a, in[15], 13);
+
+ ROUND3(a, b, c, d, in[0], 3);
+ ROUND3(d, a, b, c, in[8], 9);
+ ROUND3(c, d, a, b, in[4], 11);
+ ROUND3(b, c, d, a, in[12], 15);
+ ROUND3(a, b, c, d, in[2], 3);
+ ROUND3(d, a, b, c, in[10], 9);
+ ROUND3(c, d, a, b, in[6], 11);
+ ROUND3(b, c, d, a, in[14], 15);
+ ROUND3(a, b, c, d, in[1], 3);
+ ROUND3(d, a, b, c, in[9], 9);
+ ROUND3(c, d, a, b, in[5], 11);
+ ROUND3(b, c, d, a, in[13], 15);
+ ROUND3(a, b, c, d, in[3], 3);
+ ROUND3(d, a, b, c, in[11], 9);
+ ROUND3(c, d, a, b, in[7], 11);
+ ROUND3(b, c, d, a, in[15], 15);
+
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+}
+
+static inline void md4_transform_helper(struct md4_ctx *ctx)
+{
+ le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
+ md4_transform(ctx->hash, ctx->block);
+}
+
+int cifs_md4_init(struct md4_ctx *mctx)
+{
+ memset(mctx, 0, sizeof(struct md4_ctx));
+ mctx->hash[0] = 0x67452301;
+ mctx->hash[1] = 0xefcdab89;
+ mctx->hash[2] = 0x98badcfe;
+ mctx->hash[3] = 0x10325476;
+ mctx->byte_count = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_init);
+
+int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
+{
+ const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
+
+ mctx->byte_count += len;
+
+ if (avail > len) {
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, len);
+ return 0;
+ }
+
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, avail);
+
+ md4_transform_helper(mctx);
+ data += avail;
+ len -= avail;
+
+ while (len >= sizeof(mctx->block)) {
+ memcpy(mctx->block, data, sizeof(mctx->block));
+ md4_transform_helper(mctx);
+ data += sizeof(mctx->block);
+ len -= sizeof(mctx->block);
+ }
+
+ memcpy(mctx->block, data, len);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_update);
+
+int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
+{
+ const unsigned int offset = mctx->byte_count & 0x3f;
+ char *p = (char *)mctx->block + offset;
+ int padding = 56 - (offset + 1);
+
+ *p++ = 0x80;
+ if (padding < 0) {
+ memset(p, 0x00, padding + sizeof(u64));
+ md4_transform_helper(mctx);
+ p = (char *)mctx->block;
+ padding = 56;
+ }
+
+ memset(p, 0, padding);
+ mctx->block[14] = mctx->byte_count << 3;
+ mctx->block[15] = mctx->byte_count >> 29;
+ le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
+ sizeof(u64)) / sizeof(u32));
+ md4_transform(mctx->hash, mctx->block);
+ cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
+ memcpy(out, mctx->hash, sizeof(mctx->hash));
+ memset(mctx, 0, sizeof(*mctx));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_final);
diff --git a/fs/cifs_common/md4.h b/fs/cifs_common/md4.h
new file mode 100644
index 000000000000..5337becc699a
--- /dev/null
+++ b/fs/cifs_common/md4.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Common values for ARC4 Cipher Algorithm
+ */
+
+#ifndef _CIFS_MD4_H
+#define _CIFS_MD4_H
+
+#include <linux/types.h>
+
+#define MD4_DIGEST_SIZE 16
+#define MD4_HMAC_BLOCK_SIZE 64
+#define MD4_BLOCK_WORDS 16
+#define MD4_HASH_WORDS 4
+
+struct md4_ctx {
+ u32 hash[MD4_HASH_WORDS];
+ u32 block[MD4_BLOCK_WORDS];
+ u64 byte_count;
+};
+
+
+int cifs_md4_init(struct md4_ctx *mctx);
+int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len);
+int cifs_md4_final(struct md4_ctx *mctx, u8 *out);
+
+#endif /* _CIFS_MD4_H */
--
2.30.2
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-08-24 16:50 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-19 23:32 [PATCH] cifs: create a MD4 module and switch cifs.ko to use it Ronnie Sahlberg
2021-08-24 16:50 ` Steve French
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).