Blame view

fs/cifs/smbencrypt.c 6.3 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
     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.
  */
9651ddbac   Herbert Xu   cifs: Use skcipher
25
  #include <crypto/skcipher.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #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
  #include <linux/fs.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
  #include <linux/random.h>
2baa26825   Steve French   Remap reserved po...
32
  #include "cifs_fs_sb.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
  #include "cifs_unicode.h"
  #include "cifspdu.h"
3979877e5   Steve French   [CIFS] Support fo...
35
  #include "cifsglob.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  #include "cifs_debug.h"
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
37
  #include "cifsproto.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

4b18f2a9c   Steve French   [CIFS] convert us...
39
40
  #ifndef false
  #define false 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  #endif
4b18f2a9c   Steve French   [CIFS] convert us...
42
43
  #ifndef true
  #define true 1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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)))
43988d768   Steve French   [CIFS] Use ecb de...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  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];
9651ddbac   Herbert Xu   cifs: Use skcipher
72
  	struct crypto_skcipher *tfm_des;
43988d768   Steve French   [CIFS] Use ecb de...
73
  	struct scatterlist sgin, sgout;
9651ddbac   Herbert Xu   cifs: Use skcipher
74
  	struct skcipher_request *req;
43988d768   Steve French   [CIFS] Use ecb de...
75
76
  
  	str_to_key(key, key2);
9651ddbac   Herbert Xu   cifs: Use skcipher
77
  	tfm_des = crypto_alloc_skcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC);
43988d768   Steve French   [CIFS] Use ecb de...
78
79
  	if (IS_ERR(tfm_des)) {
  		rc = PTR_ERR(tfm_des);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
80
81
  		cifs_dbg(VFS, "could not allocate des crypto API
  ");
43988d768   Steve French   [CIFS] Use ecb de...
82
83
  		goto smbhash_err;
  	}
9651ddbac   Herbert Xu   cifs: Use skcipher
84
85
86
87
88
89
90
  	req = skcipher_request_alloc(tfm_des, GFP_KERNEL);
  	if (!req) {
  		rc = -ENOMEM;
  		cifs_dbg(VFS, "could not allocate des crypto API
  ");
  		goto smbhash_free_skcipher;
  	}
43988d768   Steve French   [CIFS] Use ecb de...
91

9651ddbac   Herbert Xu   cifs: Use skcipher
92
  	crypto_skcipher_setkey(tfm_des, key2, 8);
43988d768   Steve French   [CIFS] Use ecb de...
93
94
95
  
  	sg_init_one(&sgin, in, 8);
  	sg_init_one(&sgout, out, 8);
9651ddbac   Herbert Xu   cifs: Use skcipher
96
97
98
99
  	skcipher_request_set_callback(req, 0, NULL, NULL);
  	skcipher_request_set_crypt(req, &sgin, &sgout, 8, NULL);
  
  	rc = crypto_skcipher_encrypt(req);
e4fb0edb7   Jeff Layton   cifs: free blkcip...
100
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
101
102
  		cifs_dbg(VFS, "could not encrypt crypt key rc: %d
  ", rc);
43988d768   Steve French   [CIFS] Use ecb de...
103

9651ddbac   Herbert Xu   cifs: Use skcipher
104
105
106
107
  	skcipher_request_free(req);
  
  smbhash_free_skcipher:
  	crypto_free_skcipher(tfm_des);
43988d768   Steve French   [CIFS] Use ecb de...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  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...
140
141
142
143
144
145
146
147
148
149
150
  /* 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...
151
  		rc = PTR_ERR(md4);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
152
153
154
  		cifs_dbg(VFS, "%s: Crypto md4 allocation error %d
  ",
  			 __func__, rc);
ffeb414a5   Jeff Layton   cifs: fix two com...
155
  		return rc;
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
156
157
158
159
160
  	}
  	size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
  	sdescmd4 = kmalloc(size, GFP_KERNEL);
  	if (!sdescmd4) {
  		rc = -ENOMEM;
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
161
162
163
164
165
166
167
  		goto mdfour_err;
  	}
  	sdescmd4->shash.tfm = md4;
  	sdescmd4->shash.flags = 0x0;
  
  	rc = crypto_shash_init(&sdescmd4->shash);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
168
169
  		cifs_dbg(VFS, "%s: Could not init md4 shash
  ", __func__);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
170
171
  		goto mdfour_err;
  	}
14cae3243   Shirish Pargaonkar   cifs: Cleanup: ch...
172
173
  	rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
174
175
  		cifs_dbg(VFS, "%s: Could not update with link_str
  ", __func__);
14cae3243   Shirish Pargaonkar   cifs: Cleanup: ch...
176
177
  		goto mdfour_err;
  	}
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
178
  	rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
14cae3243   Shirish Pargaonkar   cifs: Cleanup: ch...
179
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
180
181
  		cifs_dbg(VFS, "%s: Could not generate md4 hash
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182

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

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

43988d768   Steve French   [CIFS] Use ecb de...
204
205
206
207
  	memcpy(p14, passwd, 14);
  	rc = E_P16(p14, p16);
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208

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

43988d768   Steve French   [CIFS] Use ecb de...
212
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  }
790fe579f   Steve French   [CIFS] more white...
214
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
   * Creates the MD4 Hash of the users password in NT UNICODE.
   */
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
217
  int
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
218
219
  E_md4hash(const unsigned char *passwd, unsigned char *p16,
  	const struct nls_table *codepage)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  {
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
221
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	int len;
9c32c63bb   Steve French   cifs: Fix sparse ...
223
  	__le16 wpwd[129];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
  
  	/* Password cannot be longer than 128 characters */
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
226
  	if (passwd) /* Password must be converted to NT unicode */
acbbb76a2   Steve French   CIFS: Rename *UCS...
227
  		len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
228
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  		len = 0;
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
230
231
  		*wpwd = 0; /* Ensure string is null terminated */
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

9c32c63bb   Steve French   cifs: Fix sparse ...
233
  	rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__le16));
f99dbfa4b   Giel van Schijndel   cifs: use memzero...
234
  	memzero_explicit(wpwd, sizeof(wpwd));
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
235
236
  
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  /* Does the NT MD4 hash then des encryption. */
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
239
  int
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
240
241
  SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
  		const struct nls_table *codepage)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  {
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
243
  	int rc;
43988d768   Steve French   [CIFS] Use ecb de...
244
  	unsigned char p16[16], p21[21];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245

43988d768   Steve French   [CIFS] Use ecb de...
246
  	memset(p16, '\0', 16);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	memset(p21, '\0', 21);
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
248
  	rc = E_md4hash(passwd, p16, codepage);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
249
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
250
251
252
  		cifs_dbg(FYI, "%s Can't generate NT hash, error: %d
  ",
  			 __func__, rc);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
253
254
  		return rc;
  	}
43988d768   Steve French   [CIFS] Use ecb de...
255
256
  	memcpy(p21, p16, 16);
  	rc = E_P24(p21, c8, p24);
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
257
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  }