Blame view

fs/cifs/smbencrypt.c 9.79 KB
790fe579f   Steve French   [CIFS] more white...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
50c2f7538   Steve French   [CIFS] whitespace...
10

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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.
50c2f7538   Steve French   [CIFS] whitespace...
15

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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.
50c2f7538   Steve French   [CIFS] whitespace...
20

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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>
5a0e3ad6a   Tejun Heo   include cleanup: ...
27
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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"
3979877e5   Steve French   [CIFS] Support fo...
34
  #include "cifsglob.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include "cifs_debug.h"
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
36
  #include "cifsproto.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

4b18f2a9c   Steve French   [CIFS] convert us...
38
39
  #ifndef false
  #define false 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #endif
4b18f2a9c   Steve French   [CIFS] convert us...
41
42
  #ifndef true
  #define true 1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
47
48
  #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)))
43988d768   Steve French   [CIFS] Use ecb de...
49
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
81
82
83
84
85
86
87
88
89
90
91
92
  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);
  		cERROR(1, "could not allocate des crypto API
  ");
  		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);
e4fb0edb7   Jeff Layton   cifs: free blkcip...
93
  	if (rc)
43988d768   Steve French   [CIFS] Use ecb de...
94
95
  		cERROR(1, "could not encrypt crypt key rc: %d
  ", rc);
43988d768   Steve French   [CIFS] Use ecb de...
96

e4fb0edb7   Jeff Layton   cifs: free blkcip...
97
  	crypto_free_blkcipher(tfm_des);
43988d768   Steve French   [CIFS] Use ecb de...
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;
  }
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
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)) {
ffeb414a5   Jeff Layton   cifs: fix two com...
141
  		rc = PTR_ERR(md4);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
142
143
  		cERROR(1, "%s: Crypto md4 allocation error %d
  ", __func__, rc);
ffeb414a5   Jeff Layton   cifs: fix two com...
144
  		return rc;
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  	}
  	size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
  	sdescmd4 = kmalloc(size, GFP_KERNEL);
  	if (!sdescmd4) {
  		rc = -ENOMEM;
  		cERROR(1, "%s: Memory allocation failure
  ", __func__);
  		goto mdfour_err;
  	}
  	sdescmd4->shash.tfm = md4;
  	sdescmd4->shash.flags = 0x0;
  
  	rc = crypto_shash_init(&sdescmd4->shash);
  	if (rc) {
  		cERROR(1, "%s: Could not init md4 shash
  ", __func__);
  		goto mdfour_err;
  	}
14cae3243   Shirish Pargaonkar   cifs: Cleanup: ch...
163
164
165
166
167
168
  	rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
  	if (rc) {
  		cERROR(1, "%s: Could not update with link_str
  ", __func__);
  		goto mdfour_err;
  	}
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
169
  	rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
14cae3243   Shirish Pargaonkar   cifs: Cleanup: ch...
170
171
172
  	if (rc)
  		cERROR(1, "%s: Could not genereate md4 hash
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173

ee2c92585   Shirish Pargaonkar   cifs: More crypto...
174
175
176
177
178
179
  mdfour_err:
  	crypto_free_shash(md4);
  	kfree(sdescmd4);
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
  /*
     This implements the X/Open SMB password encryption
790fe579f   Steve French   [CIFS] more white...
182
     It takes a password, a 8 byte "crypt key" and puts 24 bytes of
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
     encrypted password into p24 */
  /* Note that password must be uppercased and null terminated */
43988d768   Steve French   [CIFS] Use ecb de...
185
  int
4e53a3fb9   Jeff Layton   cifs: have calc_l...
186
  SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  {
43988d768   Steve French   [CIFS] Use ecb de...
188
189
  	int rc;
  	unsigned char p14[14], p16[16], p21[21];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  	memset(p14, '\0', 14);
43988d768   Steve French   [CIFS] Use ecb de...
192
193
  	memset(p16, '\0', 16);
  	memset(p21, '\0', 21);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194

43988d768   Steve French   [CIFS] Use ecb de...
195
196
197
198
  	memcpy(p14, passwd, 14);
  	rc = E_P16(p14, p16);
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199

43988d768   Steve French   [CIFS] Use ecb de...
200
201
  	memcpy(p21, p16, 16);
  	rc = E_P24(p21, c8, p24);
50c2f7538   Steve French   [CIFS] whitespace...
202

43988d768   Steve French   [CIFS] Use ecb de...
203
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
207
  }
  
  /* Routines for Windows NT MD4 Hash functions. */
  static int
63d2583f5   Steve French   [CIFS] Fix walkin...
208
  _my_wcslen(__u16 *str)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
214
215
216
217
  {
  	int len = 0;
  	while (*str++ != 0)
  		len++;
  	return len;
  }
  
  /*
   * Convert a string into an NT UNICODE string.
790fe579f   Steve French   [CIFS] more white...
218
   * Note that regardless of processor type
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
   * this must be in intel (little-endian)
   * format.
   */
  
  static int
63d2583f5   Steve French   [CIFS] Fix walkin...
224
  _my_mbstowcs(__u16 *dst, const unsigned char *src, int len)
790fe579f   Steve French   [CIFS] more white...
225
  {	/* BB not a very good conversion routine - change/fix */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
229
230
231
232
233
234
235
236
237
238
  	int i;
  	__u16 val;
  
  	for (i = 0; i < len; i++) {
  		val = *src;
  		SSVAL(dst, 0, val);
  		dst++;
  		src++;
  		if (val == 0)
  			break;
  	}
  	return i;
  }
790fe579f   Steve French   [CIFS] more white...
239
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
   * Creates the MD4 Hash of the users password in NT UNICODE.
   */
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
242
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
  E_md4hash(const unsigned char *passwd, unsigned char *p16)
  {
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
245
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
248
249
  	int len;
  	__u16 wpwd[129];
  
  	/* Password cannot be longer than 128 characters */
790fe579f   Steve French   [CIFS] more white...
250
  	if (passwd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  		len = strlen((char *) passwd);
63d2583f5   Steve French   [CIFS] Fix walkin...
252
  		if (len > 128)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  			len = 128;
63d2583f5   Steve French   [CIFS] Fix walkin...
254

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
259
260
261
  		/* Password must be converted to NT unicode */
  		_my_mbstowcs(wpwd, passwd, len);
  	} else
  		len = 0;
  
  	wpwd[len] = 0;	/* Ensure string is null terminated */
  	/* Calculate length in bytes */
630f3f0c4   Steve French   [CIFS] acl suppor...
262
  	len = _my_wcslen(wpwd) * sizeof(__u16);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263

ee2c92585   Shirish Pargaonkar   cifs: More crypto...
264
  	rc = mdfour(p16, (unsigned char *) wpwd, len);
790fe579f   Steve French   [CIFS] more white...
265
  	memset(wpwd, 0, 129 * 2);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
266
267
  
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  }
e10847ed4   Steve French   [CIFS] More remov...
269
  #if 0 /* currently unused */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  /* Does both the NT and LM owfs of a user's password */
2cd646a2d   Steve French   [CIFS] Remove sta...
271
  static void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
  {
  	char passwd[514];
  
  	memset(passwd, '\0', 514);
  	if (strlen(pwd) < 513)
  		strcpy(passwd, pwd);
  	else
  		memcpy(passwd, pwd, 512);
  	/* Calculate the MD4 hash (NT compatible) of the password */
  	memset(nt_p16, '\0', 16);
  	E_md4hash(passwd, nt_p16);
  
  	/* Mangle the passwords into Lanman format */
  	passwd[14] = '\0';
  /*	strupper(passwd); */
  
  	/* Calculate the SMB (lanman) hash functions of the password */
  
  	memset(p16, '\0', 16);
  	E_P16((unsigned char *) passwd, (unsigned char *) p16);
  
  	/* clear out local copy of user's password (just being paranoid). */
630f3f0c4   Steve French   [CIFS] acl suppor...
295
  	memset(passwd, '\0', sizeof(passwd));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  }
e10847ed4   Steve French   [CIFS] More remov...
297
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
299
300
301
302
303
304
305
  
  /* Does the NTLMv2 owfs of a user's password */
  #if 0  /* function not needed yet - but will be soon */
  static void
  ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
  		const char *domain_n, unsigned char kr_buf[16],
  		const struct nls_table *nls_codepage)
  {
50c2f7538   Steve French   [CIFS] whitespace...
306
307
  	wchar_t *user_u;
  	wchar_t *dom_u;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
311
  	int user_l, domain_l;
  	struct HMACMD5Context ctx;
  
  	/* might as well do one alloc to hold both (user_u and dom_u) */
790fe579f   Steve French   [CIFS] more white...
312
313
  	user_u = kmalloc(2048 * sizeof(wchar_t), GFP_KERNEL);
  	if (user_u == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
  		return;
  	dom_u = user_u + 1024;
50c2f7538   Steve French   [CIFS] whitespace...
316

63d2583f5   Steve French   [CIFS] Fix walkin...
317
318
319
320
  	/* push_ucs2(NULL, user_u, user_n, (user_l+1)*2,
  			STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
  	   push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2,
  			STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  
  	/* BB user and domain may need to be uppercased */
  	user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
  	domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
  
  	user_l++;		/* trailing null */
  	domain_l++;
  
  	hmac_md5_init_limK_to_64(owf, 16, &ctx);
  	hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
  	hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
  	hmac_md5_final(kr_buf, &ctx);
  
  	kfree(user_u);
  }
790fe579f   Steve French   [CIFS] more white...
336
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
  /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
e10847ed4   Steve French   [CIFS] More remov...
339
  #if 0 /* currently unused */
2cd646a2d   Steve French   [CIFS] Remove sta...
340
  static void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
345
346
347
348
349
350
351
  NTLMSSPOWFencrypt(unsigned char passwd[8],
  		  unsigned char *ntlmchalresp, unsigned char p24[24])
  {
  	unsigned char p21[21];
  
  	memset(p21, '\0', 21);
  	memcpy(p21, passwd, 8);
  	memset(p21 + 8, 0xbd, 8);
  
  	E_P24(p21, ntlmchalresp, p24);
  }
e10847ed4   Steve French   [CIFS] More remov...
352
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
  
  /* Does the NT MD4 hash then des encryption. */
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
355
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
  SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
  {
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
358
  	int rc;
43988d768   Steve French   [CIFS] Use ecb de...
359
  	unsigned char p16[16], p21[21];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360

43988d768   Steve French   [CIFS] Use ecb de...
361
  	memset(p16, '\0', 16);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  	memset(p21, '\0', 21);
43988d768   Steve French   [CIFS] Use ecb de...
363
  	rc = E_md4hash(passwd, p16);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
364
365
366
367
  	if (rc) {
  		cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
  		return rc;
  	}
43988d768   Steve French   [CIFS] Use ecb de...
368
369
  	memcpy(p21, p16, 16);
  	rc = E_P24(p21, c8, p24);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
370
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
376
377
378
  }
  
  
  /* Does the md5 encryption from the NT hash for NTLMv2. */
  /* These routines will be needed later */
  #if 0
  static void
  SMBOWFencrypt_ntv2(const unsigned char kr[16],
790fe579f   Steve French   [CIFS] more white...
379
380
  		   const struct data_blob *srv_chal,
  		   const struct data_blob *cli_chal, unsigned char resp_buf[16])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  {
790fe579f   Steve French   [CIFS] more white...
382
  	struct HMACMD5Context ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383

790fe579f   Steve French   [CIFS] more white...
384
385
386
387
  	hmac_md5_init_limK_to_64(kr, 16, &ctx);
  	hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
  	hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
  	hmac_md5_final(resp_buf, &ctx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  }
  
  static void
  SMBsesskeygen_ntv2(const unsigned char kr[16],
  		   const unsigned char *nt_resp, __u8 sess_key[16])
  {
  	struct HMACMD5Context ctx;
  
  	hmac_md5_init_limK_to_64(kr, 16, &ctx);
  	hmac_md5_update(nt_resp, 16, &ctx);
  	hmac_md5_final((unsigned char *) sess_key, &ctx);
  }
  
  static void
  SMBsesskeygen_ntv1(const unsigned char kr[16],
  		   const unsigned char *nt_resp, __u8 sess_key[16])
  {
  	mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
  }
  #endif