Skip to content

Commit 42c2197

Browse files
Ronnie Sahlbergsmfrench
authored andcommitted
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 <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 71c0286 commit 42c2197

File tree

6 files changed

+238
-15
lines changed

6 files changed

+238
-15
lines changed

fs/cifs/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ config CIFS
44
depends on INET
55
select NLS
66
select CRYPTO
7-
select CRYPTO_MD4
87
select CRYPTO_MD5
98
select CRYPTO_SHA256
109
select CRYPTO_SHA512

fs/cifs/cifsfs.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,6 @@ MODULE_DESCRIPTION
17481748
MODULE_VERSION(CIFS_VERSION);
17491749
MODULE_SOFTDEP("ecb");
17501750
MODULE_SOFTDEP("hmac");
1751-
MODULE_SOFTDEP("md4");
17521751
MODULE_SOFTDEP("md5");
17531752
MODULE_SOFTDEP("nls");
17541753
MODULE_SOFTDEP("aes");

fs/cifs/smbencrypt.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "cifsglob.h"
2525
#include "cifs_debug.h"
2626
#include "cifsproto.h"
27+
#include "../cifs_common/md4.h"
2728

2829
#ifndef false
2930
#define false 0
@@ -42,29 +43,24 @@ static int
4243
mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
4344
{
4445
int rc;
45-
struct crypto_shash *md4 = NULL;
46-
struct sdesc *sdescmd4 = NULL;
46+
struct md4_ctx mctx;
4747

48-
rc = cifs_alloc_hash("md4", &md4, &sdescmd4);
49-
if (rc)
50-
goto mdfour_err;
51-
52-
rc = crypto_shash_init(&sdescmd4->shash);
48+
rc = cifs_md4_init(&mctx);
5349
if (rc) {
54-
cifs_dbg(VFS, "%s: Could not init md4 shash\n", __func__);
50+
cifs_dbg(VFS, "%s: Could not init MD4\n", __func__);
5551
goto mdfour_err;
5652
}
57-
rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
53+
rc = cifs_md4_update(&mctx, link_str, link_len);
5854
if (rc) {
59-
cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
55+
cifs_dbg(VFS, "%s: Could not update MD4\n", __func__);
6056
goto mdfour_err;
6157
}
62-
rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
58+
rc = cifs_md4_final(&mctx, md4_hash);
6359
if (rc)
64-
cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
60+
cifs_dbg(VFS, "%s: Could not finalize MD4\n", __func__);
61+
6562

6663
mdfour_err:
67-
cifs_free_hash(&md4, &sdescmd4);
6864
return rc;
6965
}
7066

fs/cifs_common/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
#
55

66
obj-$(CONFIG_CIFS_COMMON) += cifs_arc4.o
7+
obj-$(CONFIG_CIFS_COMMON) += cifs_md4.o

fs/cifs_common/cifs_md4.c

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Cryptographic API.
3+
*
4+
* MD4 Message Digest Algorithm (RFC1320).
5+
*
6+
* Implementation derived from Andrew Tridgell and Steve French's
7+
* CIFS MD4 implementation, and the cryptoapi implementation
8+
* originally based on the public domain implementation written
9+
* by Colin Plumb in 1993.
10+
*
11+
* Copyright (c) Andrew Tridgell 1997-1998.
12+
* Modified by Steve French ([email protected]) 2002
13+
* Copyright (c) Cryptoapi developers.
14+
* Copyright (c) 2002 David S. Miller ([email protected])
15+
* Copyright (c) 2002 James Morris <[email protected]>
16+
*
17+
* This program is free software; you can redistribute it and/or modify
18+
* it under the terms of the GNU General Public License as published by
19+
* the Free Software Foundation; either version 2 of the License, or
20+
* (at your option) any later version.
21+
*
22+
*/
23+
#include <linux/init.h>
24+
#include <linux/kernel.h>
25+
#include <linux/module.h>
26+
#include <linux/string.h>
27+
#include <linux/types.h>
28+
#include <asm/byteorder.h>
29+
#include "md4.h"
30+
31+
MODULE_LICENSE("GPL");
32+
33+
static inline u32 lshift(u32 x, unsigned int s)
34+
{
35+
x &= 0xFFFFFFFF;
36+
return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
37+
}
38+
39+
static inline u32 F(u32 x, u32 y, u32 z)
40+
{
41+
return (x & y) | ((~x) & z);
42+
}
43+
44+
static inline u32 G(u32 x, u32 y, u32 z)
45+
{
46+
return (x & y) | (x & z) | (y & z);
47+
}
48+
49+
static inline u32 H(u32 x, u32 y, u32 z)
50+
{
51+
return x ^ y ^ z;
52+
}
53+
54+
#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
55+
#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
56+
#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
57+
58+
static void md4_transform(u32 *hash, u32 const *in)
59+
{
60+
u32 a, b, c, d;
61+
62+
a = hash[0];
63+
b = hash[1];
64+
c = hash[2];
65+
d = hash[3];
66+
67+
ROUND1(a, b, c, d, in[0], 3);
68+
ROUND1(d, a, b, c, in[1], 7);
69+
ROUND1(c, d, a, b, in[2], 11);
70+
ROUND1(b, c, d, a, in[3], 19);
71+
ROUND1(a, b, c, d, in[4], 3);
72+
ROUND1(d, a, b, c, in[5], 7);
73+
ROUND1(c, d, a, b, in[6], 11);
74+
ROUND1(b, c, d, a, in[7], 19);
75+
ROUND1(a, b, c, d, in[8], 3);
76+
ROUND1(d, a, b, c, in[9], 7);
77+
ROUND1(c, d, a, b, in[10], 11);
78+
ROUND1(b, c, d, a, in[11], 19);
79+
ROUND1(a, b, c, d, in[12], 3);
80+
ROUND1(d, a, b, c, in[13], 7);
81+
ROUND1(c, d, a, b, in[14], 11);
82+
ROUND1(b, c, d, a, in[15], 19);
83+
84+
ROUND2(a, b, c, d, in[0], 3);
85+
ROUND2(d, a, b, c, in[4], 5);
86+
ROUND2(c, d, a, b, in[8], 9);
87+
ROUND2(b, c, d, a, in[12], 13);
88+
ROUND2(a, b, c, d, in[1], 3);
89+
ROUND2(d, a, b, c, in[5], 5);
90+
ROUND2(c, d, a, b, in[9], 9);
91+
ROUND2(b, c, d, a, in[13], 13);
92+
ROUND2(a, b, c, d, in[2], 3);
93+
ROUND2(d, a, b, c, in[6], 5);
94+
ROUND2(c, d, a, b, in[10], 9);
95+
ROUND2(b, c, d, a, in[14], 13);
96+
ROUND2(a, b, c, d, in[3], 3);
97+
ROUND2(d, a, b, c, in[7], 5);
98+
ROUND2(c, d, a, b, in[11], 9);
99+
ROUND2(b, c, d, a, in[15], 13);
100+
101+
ROUND3(a, b, c, d, in[0], 3);
102+
ROUND3(d, a, b, c, in[8], 9);
103+
ROUND3(c, d, a, b, in[4], 11);
104+
ROUND3(b, c, d, a, in[12], 15);
105+
ROUND3(a, b, c, d, in[2], 3);
106+
ROUND3(d, a, b, c, in[10], 9);
107+
ROUND3(c, d, a, b, in[6], 11);
108+
ROUND3(b, c, d, a, in[14], 15);
109+
ROUND3(a, b, c, d, in[1], 3);
110+
ROUND3(d, a, b, c, in[9], 9);
111+
ROUND3(c, d, a, b, in[5], 11);
112+
ROUND3(b, c, d, a, in[13], 15);
113+
ROUND3(a, b, c, d, in[3], 3);
114+
ROUND3(d, a, b, c, in[11], 9);
115+
ROUND3(c, d, a, b, in[7], 11);
116+
ROUND3(b, c, d, a, in[15], 15);
117+
118+
hash[0] += a;
119+
hash[1] += b;
120+
hash[2] += c;
121+
hash[3] += d;
122+
}
123+
124+
static inline void md4_transform_helper(struct md4_ctx *ctx)
125+
{
126+
le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
127+
md4_transform(ctx->hash, ctx->block);
128+
}
129+
130+
int cifs_md4_init(struct md4_ctx *mctx)
131+
{
132+
memset(mctx, 0, sizeof(struct md4_ctx));
133+
mctx->hash[0] = 0x67452301;
134+
mctx->hash[1] = 0xefcdab89;
135+
mctx->hash[2] = 0x98badcfe;
136+
mctx->hash[3] = 0x10325476;
137+
mctx->byte_count = 0;
138+
139+
return 0;
140+
}
141+
EXPORT_SYMBOL_GPL(cifs_md4_init);
142+
143+
int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
144+
{
145+
const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
146+
147+
mctx->byte_count += len;
148+
149+
if (avail > len) {
150+
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
151+
data, len);
152+
return 0;
153+
}
154+
155+
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
156+
data, avail);
157+
158+
md4_transform_helper(mctx);
159+
data += avail;
160+
len -= avail;
161+
162+
while (len >= sizeof(mctx->block)) {
163+
memcpy(mctx->block, data, sizeof(mctx->block));
164+
md4_transform_helper(mctx);
165+
data += sizeof(mctx->block);
166+
len -= sizeof(mctx->block);
167+
}
168+
169+
memcpy(mctx->block, data, len);
170+
171+
return 0;
172+
}
173+
EXPORT_SYMBOL_GPL(cifs_md4_update);
174+
175+
int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
176+
{
177+
const unsigned int offset = mctx->byte_count & 0x3f;
178+
char *p = (char *)mctx->block + offset;
179+
int padding = 56 - (offset + 1);
180+
181+
*p++ = 0x80;
182+
if (padding < 0) {
183+
memset(p, 0x00, padding + sizeof(u64));
184+
md4_transform_helper(mctx);
185+
p = (char *)mctx->block;
186+
padding = 56;
187+
}
188+
189+
memset(p, 0, padding);
190+
mctx->block[14] = mctx->byte_count << 3;
191+
mctx->block[15] = mctx->byte_count >> 29;
192+
le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
193+
sizeof(u64)) / sizeof(u32));
194+
md4_transform(mctx->hash, mctx->block);
195+
cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
196+
memcpy(out, mctx->hash, sizeof(mctx->hash));
197+
memset(mctx, 0, sizeof(*mctx));
198+
199+
return 0;
200+
}
201+
EXPORT_SYMBOL_GPL(cifs_md4_final);

fs/cifs_common/md4.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/*
3+
* Common values for ARC4 Cipher Algorithm
4+
*/
5+
6+
#ifndef _CIFS_MD4_H
7+
#define _CIFS_MD4_H
8+
9+
#include <linux/types.h>
10+
11+
#define MD4_DIGEST_SIZE 16
12+
#define MD4_HMAC_BLOCK_SIZE 64
13+
#define MD4_BLOCK_WORDS 16
14+
#define MD4_HASH_WORDS 4
15+
16+
struct md4_ctx {
17+
u32 hash[MD4_HASH_WORDS];
18+
u32 block[MD4_BLOCK_WORDS];
19+
u64 byte_count;
20+
};
21+
22+
23+
int cifs_md4_init(struct md4_ctx *mctx);
24+
int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len);
25+
int cifs_md4_final(struct md4_ctx *mctx, u8 *out);
26+
27+
#endif /* _CIFS_MD4_H */

0 commit comments

Comments
 (0)