smbencrypt.c 6.0 KB
Newer Older
S
Steve French 已提交
1
/*
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9
   Unix SMB/Netbios implementation.
   Version 1.9.
   SMB parameters and setup
   Copyright (C) Andrew Tridgell 1992-2000
   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
   Modified by Jeremy Allison 1995.
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
   Modified by Steve French (sfrench@us.ibm.com) 2002-2003
10

L
Linus Torvalds 已提交
11 12 13 14
   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.
15

L
Linus Torvalds 已提交
16 17 18 19
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
20

L
Linus Torvalds 已提交
21 22 23 24 25 26
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <linux/module.h>
27
#include <linux/slab.h>
L
Linus Torvalds 已提交
28 29 30 31 32 33
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/random.h>
#include "cifs_unicode.h"
#include "cifspdu.h"
34
#include "cifsglob.h"
L
Linus Torvalds 已提交
35
#include "cifs_debug.h"
36
#include "cifsproto.h"
L
Linus Torvalds 已提交
37

38 39
#ifndef false
#define false 0
L
Linus Torvalds 已提交
40
#endif
41 42
#ifndef true
#define true 1
L
Linus Torvalds 已提交
43 44 45 46 47 48 49
#endif

/* following came from the other byteorder.h to avoid include conflicts */
#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
static void
str_to_key(unsigned char *str, unsigned char *key)
{
	int i;

	key[0] = str[0] >> 1;
	key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
	key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
	key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
	key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
	key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
	key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
	key[7] = str[6] & 0x7F;
	for (i = 0; i < 8; i++)
		key[i] = (key[i] << 1);
}

static int
smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
{
	int rc;
	unsigned char key2[8];
	struct crypto_blkcipher *tfm_des;
	struct scatterlist sgin, sgout;
	struct blkcipher_desc desc;

	str_to_key(key, key2);

	tfm_des = crypto_alloc_blkcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC);
	if (IS_ERR(tfm_des)) {
		rc = PTR_ERR(tfm_des);
81
		cERROR(1, "could not allocate des crypto API");
82 83 84 85 86 87 88 89 90 91 92
		goto smbhash_err;
	}

	desc.tfm = tfm_des;

	crypto_blkcipher_setkey(tfm_des, key2, 8);

	sg_init_one(&sgin, in, 8);
	sg_init_one(&sgout, out, 8);

	rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8);
J
Jeff Layton 已提交
93
	if (rc)
94
		cERROR(1, "could not encrypt crypt key rc: %d", rc);
95

J
Jeff Layton 已提交
96
	crypto_free_blkcipher(tfm_des);
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
smbhash_err:
	return rc;
}

static int
E_P16(unsigned char *p14, unsigned char *p16)
{
	int rc;
	unsigned char sp8[8] =
	    { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };

	rc = smbhash(p16, sp8, p14);
	if (rc)
		return rc;
	rc = smbhash(p16 + 8, sp8, p14 + 7);
	return rc;
}

static int
E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
{
	int rc;

	rc = smbhash(p24, c8, p21);
	if (rc)
		return rc;
	rc = smbhash(p24 + 8, c8, p21 + 7);
	if (rc)
		return rc;
	rc = smbhash(p24 + 16, c8, p21 + 14);
	return rc;
}

130 131 132 133 134 135 136 137 138 139 140
/* produce a md4 message digest from data of length n bytes */
int
mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
{
	int rc;
	unsigned int size;
	struct crypto_shash *md4;
	struct sdesc *sdescmd4;

	md4 = crypto_alloc_shash("md4", 0, 0);
	if (IS_ERR(md4)) {
141
		rc = PTR_ERR(md4);
142
		cERROR(1, "%s: Crypto md4 allocation error %d", __func__, rc);
143
		return rc;
144 145 146 147 148
	}
	size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
	sdescmd4 = kmalloc(size, GFP_KERNEL);
	if (!sdescmd4) {
		rc = -ENOMEM;
149
		cERROR(1, "%s: Memory allocation failure", __func__);
150 151 152 153 154 155 156
		goto mdfour_err;
	}
	sdescmd4->shash.tfm = md4;
	sdescmd4->shash.flags = 0x0;

	rc = crypto_shash_init(&sdescmd4->shash);
	if (rc) {
157
		cERROR(1, "%s: Could not init md4 shash", __func__);
158 159
		goto mdfour_err;
	}
160 161
	rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
	if (rc) {
162
		cERROR(1, "%s: Could not update with link_str", __func__);
163 164
		goto mdfour_err;
	}
165
	rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
166
	if (rc)
167
		cERROR(1, "%s: Could not genereate md4 hash", __func__);
L
Linus Torvalds 已提交
168

169 170 171 172 173 174 175
mdfour_err:
	crypto_free_shash(md4);
	kfree(sdescmd4);

	return rc;
}

L
Linus Torvalds 已提交
176 177
/*
   This implements the X/Open SMB password encryption
S
Steve French 已提交
178
   It takes a password, a 8 byte "crypt key" and puts 24 bytes of
L
Linus Torvalds 已提交
179 180
   encrypted password into p24 */
/* Note that password must be uppercased and null terminated */
181
int
182
SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
L
Linus Torvalds 已提交
183
{
184 185
	int rc;
	unsigned char p14[14], p16[16], p21[21];
L
Linus Torvalds 已提交
186 187

	memset(p14, '\0', 14);
188 189
	memset(p16, '\0', 16);
	memset(p21, '\0', 21);
L
Linus Torvalds 已提交
190

191 192 193 194
	memcpy(p14, passwd, 14);
	rc = E_P16(p14, p16);
	if (rc)
		return rc;
L
Linus Torvalds 已提交
195

196 197
	memcpy(p21, p16, 16);
	rc = E_P24(p21, c8, p24);
198

199
	return rc;
L
Linus Torvalds 已提交
200 201
}

S
Steve French 已提交
202
/*
L
Linus Torvalds 已提交
203 204 205
 * Creates the MD4 Hash of the users password in NT UNICODE.
 */

206
int
207 208
E_md4hash(const unsigned char *passwd, unsigned char *p16,
	const struct nls_table *codepage)
L
Linus Torvalds 已提交
209
{
210
	int rc;
L
Linus Torvalds 已提交
211
	int len;
212
	__le16 wpwd[129];
L
Linus Torvalds 已提交
213 214

	/* Password cannot be longer than 128 characters */
215
	if (passwd) /* Password must be converted to NT unicode */
216
		len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
217
	else {
L
Linus Torvalds 已提交
218
		len = 0;
219 220
		*wpwd = 0; /* Ensure string is null terminated */
	}
L
Linus Torvalds 已提交
221

222 223
	rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__le16));
	memset(wpwd, 0, 129 * sizeof(__le16));
224 225

	return rc;
L
Linus Torvalds 已提交
226 227 228
}

/* Does the NT MD4 hash then des encryption. */
229
int
230 231
SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
		const struct nls_table *codepage)
L
Linus Torvalds 已提交
232
{
233
	int rc;
234
	unsigned char p16[16], p21[21];
L
Linus Torvalds 已提交
235

236
	memset(p16, '\0', 16);
L
Linus Torvalds 已提交
237 238
	memset(p21, '\0', 21);

239
	rc = E_md4hash(passwd, p16, codepage);
240 241 242 243
	if (rc) {
		cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
		return rc;
	}
244 245
	memcpy(p21, p16, 16);
	rc = E_P24(p21, c8, p24);
246
	return rc;
L
Linus Torvalds 已提交
247
}