cifsencrypt.c 23.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/cifsencrypt.c
 *
4 5 6
 *   Encryption and hashing operations relating to NTLM, NTLMv2.  See MS-NLMP
 *   for more detailed information
 *
7
 *   Copyright (C) International Business Machines  Corp., 2005,2013
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library 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 Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <linux/fs.h>
26
#include <linux/slab.h>
L
Linus Torvalds 已提交
27
#include "cifspdu.h"
S
Steve French 已提交
28
#include "cifsglob.h"
L
Linus Torvalds 已提交
29 30 31
#include "cifs_debug.h"
#include "cifs_unicode.h"
#include "cifsproto.h"
32
#include "ntlmssp.h"
33
#include <linux/ctype.h>
S
Steve French 已提交
34
#include <linux/random.h>
35
#include <linux/highmem.h>
L
Linus Torvalds 已提交
36

37 38 39 40 41 42 43 44 45 46 47 48
static int
cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
{
	int rc;
	unsigned int size;

	if (server->secmech.sdescmd5 != NULL)
		return 0; /* already allocated */

	server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
	if (IS_ERR(server->secmech.md5)) {
		cifs_dbg(VFS, "could not allocate crypto md5\n");
49 50 51
		rc = PTR_ERR(server->secmech.md5);
		server->secmech.md5 = NULL;
		return rc;
52 53 54 55 56 57 58 59
	}

	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.md5);
	server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
	if (!server->secmech.sdescmd5) {
		crypto_free_shash(server->secmech.md5);
		server->secmech.md5 = NULL;
60
		return -ENOMEM;
61 62 63 64 65 66 67
	}
	server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
	server->secmech.sdescmd5->shash.flags = 0x0;

	return 0;
}

68 69 70 71 72 73 74
/*
 * Calculate and return the CIFS signature based on the mac key and SMB PDU.
 * The 16 byte signature must be allocated by the caller. Note we only use the
 * 1st eight bytes and that the smb header signature field on input contains
 * the sequence number before this function is called. Also, this function
 * should be called with the server->srv_mutex held.
 */
75
static int cifs_calc_signature(struct smb_rqst *rqst,
76
			struct TCP_Server_Info *server, char *signature)
77
{
78
	int i;
79
	int rc;
80 81
	struct kvec *iov = rqst->rq_iov;
	int n_vec = rqst->rq_nvec;
82

83
	if (iov == NULL || signature == NULL || server == NULL)
84
		return -EINVAL;
85

86
	if (!server->secmech.sdescmd5) {
87 88 89 90 91
		rc = cifs_crypto_shash_md5_allocate(server);
		if (rc) {
			cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
			return -1;
		}
92 93 94 95
	}

	rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
	if (rc) {
96
		cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
97 98 99
		return rc;
	}

100
	rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
101
		server->session_key.response, server->session_key.len);
102
	if (rc) {
103
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
104 105
		return rc;
	}
106

107
	for (i = 0; i < n_vec; i++) {
108 109
		if (iov[i].iov_len == 0)
			continue;
S
Steve French 已提交
110
		if (iov[i].iov_base == NULL) {
111
			cifs_dbg(VFS, "null iovec entry\n");
112
			return -EIO;
113
		}
S
Steve French 已提交
114
		/* The first entry includes a length field (which does not get
115
		   signed that occupies the first 4 bytes before the header */
S
Steve French 已提交
116
		if (i == 0) {
117
			if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
118
				break; /* nothing to sign or corrupt header */
119
			rc =
120 121
			crypto_shash_update(&server->secmech.sdescmd5->shash,
				iov[i].iov_base + 4, iov[i].iov_len - 4);
122 123
		} else {
			rc =
124 125
			crypto_shash_update(&server->secmech.sdescmd5->shash,
				iov[i].iov_base, iov[i].iov_len);
126 127
		}
		if (rc) {
128 129
			cifs_dbg(VFS, "%s: Could not update with payload\n",
				 __func__);
130 131
			return rc;
		}
132
	}
133

134 135 136 137 138 139 140 141 142 143
	/* now hash over the rq_pages array */
	for (i = 0; i < rqst->rq_npages; i++) {
		struct kvec p_iov;

		cifs_rqst_page_to_kvec(rqst, i, &p_iov);
		crypto_shash_update(&server->secmech.sdescmd5->shash,
					p_iov.iov_base, p_iov.iov_len);
		kunmap(rqst->rq_pages[i]);
	}

144
	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
145
	if (rc)
146
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
147

148
	return rc;
149 150
}

151
/* must be called with server->srv_mutex held */
152
int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
153
		   __u32 *pexpected_response_sequence_number)
154 155 156
{
	int rc = 0;
	char smb_signature[20];
157
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
158

S
Steve French 已提交
159
	if ((cifs_pdu == NULL) || (server == NULL))
160 161
		return -EINVAL;

162 163
	if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
	    server->tcpStatus == CifsNeedNegotiate)
164 165
		return rc;

166
	if (!server->session_estab) {
167
		memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
168 169 170
		return rc;
	}

S
Steve French 已提交
171
	cifs_pdu->Signature.Sequence.SequenceNumber =
172
				cpu_to_le32(server->sequence_number);
S
Steve French 已提交
173
	cifs_pdu->Signature.Sequence.Reserved = 0;
174

175 176
	*pexpected_response_sequence_number = ++server->sequence_number;
	++server->sequence_number;
177

178
	rc = cifs_calc_signature(rqst, server, smb_signature);
S
Steve French 已提交
179 180 181 182
	if (rc)
		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
	else
		memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
183

S
Steve French 已提交
184
	return rc;
185 186
}

187 188 189 190 191 192 193 194 195
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
		   __u32 *pexpected_response_sequence)
{
	struct smb_rqst rqst = { .rq_iov = iov,
				 .rq_nvec = n_vec };

	return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
}

196 197 198 199 200 201 202 203 204
/* must be called with server->srv_mutex held */
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
		  __u32 *pexpected_response_sequence_number)
{
	struct kvec iov;

	iov.iov_base = cifs_pdu;
	iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;

205
	return cifs_sign_smbv(&iov, 1, server,
206 207 208
			      pexpected_response_sequence_number);
}

209
int cifs_verify_signature(struct smb_rqst *rqst,
210
			  struct TCP_Server_Info *server,
S
Steve French 已提交
211
			  __u32 expected_sequence_number)
L
Linus Torvalds 已提交
212
{
213
	unsigned int rc;
L
Linus Torvalds 已提交
214 215
	char server_response_sig[8];
	char what_we_think_sig_should_be[20];
216
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
L
Linus Torvalds 已提交
217

218
	if (cifs_pdu == NULL || server == NULL)
L
Linus Torvalds 已提交
219 220
		return -EINVAL;

221
	if (!server->session_estab)
L
Linus Torvalds 已提交
222 223 224
		return 0;

	if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
225
		struct smb_com_lock_req *pSMB =
S
Steve French 已提交
226 227
			(struct smb_com_lock_req *)cifs_pdu;
	    if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
L
Linus Torvalds 已提交
228 229 230
			return 0;
	}

231 232 233
	/* BB what if signatures are supposed to be on for session but
	   server does not send one? BB */

L
Linus Torvalds 已提交
234
	/* Do not need to verify session setups with signature "BSRSPYL "  */
235
	if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
236 237
		cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
			 cifs_pdu->Command);
L
Linus Torvalds 已提交
238 239 240

	/* save off the origiginal signature so we can modify the smb and check
		its signature against what the server sent */
241
	memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
L
Linus Torvalds 已提交
242

243 244
	cifs_pdu->Signature.Sequence.SequenceNumber =
					cpu_to_le32(expected_sequence_number);
L
Linus Torvalds 已提交
245 246
	cifs_pdu->Signature.Sequence.Reserved = 0;

247
	mutex_lock(&server->srv_mutex);
248
	rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
249
	mutex_unlock(&server->srv_mutex);
L
Linus Torvalds 已提交
250

251
	if (rc)
L
Linus Torvalds 已提交
252 253
		return rc;

254 255
/*	cifs_dump_mem("what we think it should be: ",
		      what_we_think_sig_should_be, 16); */
L
Linus Torvalds 已提交
256

257
	if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
L
Linus Torvalds 已提交
258 259 260 261 262 263
		return -EACCES;
	else
		return 0;

}

264
/* first calculate 24 bytes ntlm response and then 16 byte session key */
265
int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
L
Linus Torvalds 已提交
266
{
267
	int rc = 0;
268 269 270 271
	unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
	char temp_key[CIFS_SESS_KEY_SIZE];

	if (!ses)
L
Linus Torvalds 已提交
272 273
		return -EINVAL;

274
	ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
275
	if (!ses->auth_key.response)
276
		return -ENOMEM;
277

278 279
	ses->auth_key.len = temp_len;

280
	rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
281
			ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
282
	if (rc) {
283 284
		cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n",
			 __func__, rc);
285 286 287
		return rc;
	}

288
	rc = E_md4hash(ses->password, temp_key, nls_cp);
289
	if (rc) {
290 291
		cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
			 __func__, rc);
292 293
		return rc;
	}
294

295 296
	rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
	if (rc)
297 298
		cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n",
			 __func__, rc);
299

300
	return rc;
L
Linus Torvalds 已提交
301 302
}

303
#ifdef CONFIG_CIFS_WEAK_PW_HASH
304
int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
305
			char *lnm_session_key)
306 307
{
	int i;
308
	int rc;
309 310 311
	char password_with_pad[CIFS_ENCPWD_SIZE];

	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
312 313 314
	if (password)
		strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);

315
	if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) {
316 317
		memcpy(lnm_session_key, password_with_pad,
			CIFS_ENCPWD_SIZE);
318
		return 0;
319
	}
320

321 322 323 324 325 326 327 328 329 330 331
	/* calculate old style session key */
	/* calling toupper is less broken than repeatedly
	calling nls_toupper would be since that will never
	work for UTF8, but neither handles multibyte code pages
	but the only alternative would be converting to UCS-16 (Unicode)
	(using a routine something like UniStrupr) then
	uppercasing and then converting back from Unicode - which
	would only worth doing it if we knew it were utf8. Basically
	utf8 and other multibyte codepages each need their own strupper
	function since a byte at a time will ont work. */

332
	for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
333 334
		password_with_pad[i] = toupper(password_with_pad[i]);

335
	rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key);
336

337
	return rc;
338 339 340
}
#endif /* CIFS_WEAK_PW_HASH */

341 342 343 344
/* Build a proper attribute value/target info pairs blob.
 * Fill in netbios and dns domain name and workstation name
 * and client time (total five av pairs and + one end of fields indicator.
 * Allocate domain name which gets freed when session struct is deallocated.
345 346
 */
static int
347
build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
348
{
349
	unsigned int dlen;
350
	unsigned int size = 2 * sizeof(struct ntlmssp2_name);
351 352
	char *defdmname = "WORKGROUP";
	unsigned char *blobptr;
353 354
	struct ntlmssp2_name *attrptr;

355 356 357 358 359 360 361 362
	if (!ses->domainName) {
		ses->domainName = kstrdup(defdmname, GFP_KERNEL);
		if (!ses->domainName)
			return -ENOMEM;
	}

	dlen = strlen(ses->domainName);

363 364 365 366 367
	/*
	 * The length of this blob is two times the size of a
	 * structure (av pair) which holds name/size
	 * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
	 * unicode length of a netbios domain name
368
	 */
369
	ses->auth_key.len = size + 2 * dlen;
370 371 372
	ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
	if (!ses->auth_key.response) {
		ses->auth_key.len = 0;
373 374
		return -ENOMEM;
	}
375

376
	blobptr = ses->auth_key.response;
377 378
	attrptr = (struct ntlmssp2_name *) blobptr;

379 380 381 382
	/*
	 * As defined in MS-NTLM 3.3.2, just this av pair field
	 * is sufficient as part of the temp
	 */
383 384 385
	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
	attrptr->length = cpu_to_le16(2 * dlen);
	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
386
	cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
387

388 389 390 391 392 393 394 395 396 397 398 399 400 401
	return 0;
}

/* Server has provided av pairs/target info in the type 2 challenge
 * packet and we have plucked it and stored within smb session.
 * We parse that blob here to find netbios domain name to be used
 * as part of ntlmv2 authentication (in Target String), if not already
 * specified on the command line.
 * If this function returns without any error but without fetching
 * domain name, authentication may fail against some server but
 * may not fail against other (those who are not very particular
 * about target string i.e. for some, just user name might suffice.
 */
static int
402
find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
403 404 405 406 407 408 409 410
{
	unsigned int attrsize;
	unsigned int type;
	unsigned int onesize = sizeof(struct ntlmssp2_name);
	unsigned char *blobptr;
	unsigned char *blobend;
	struct ntlmssp2_name *attrptr;

411
	if (!ses->auth_key.len || !ses->auth_key.response)
412 413
		return 0;

414 415
	blobptr = ses->auth_key.response;
	blobend = blobptr + ses->auth_key.len;
416 417 418 419 420 421 422 423 424 425 426 427

	while (blobptr + onesize < blobend) {
		attrptr = (struct ntlmssp2_name *) blobptr;
		type = le16_to_cpu(attrptr->type);
		if (type == NTLMSSP_AV_EOL)
			break;
		blobptr += 2; /* advance attr type */
		attrsize = le16_to_cpu(attrptr->length);
		blobptr += 2; /* advance attr size */
		if (blobptr + attrsize > blobend)
			break;
		if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
428
			if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
429 430 431 432 433 434
				break;
			if (!ses->domainName) {
				ses->domainName =
					kmalloc(attrsize + 1, GFP_KERNEL);
				if (!ses->domainName)
						return -ENOMEM;
435
				cifs_from_utf16(ses->domainName,
436
					(__le16 *)blobptr, attrsize, attrsize,
437
					nls_cp, NO_MAP_UNI_RSVD);
438 439 440 441 442 443 444 445 446
				break;
			}
		}
		blobptr += attrsize; /* advance attr  value */
	}

	return 0;
}

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
/* Server has provided av pairs/target info in the type 2 challenge
 * packet and we have plucked it and stored within smb session.
 * We parse that blob here to find the server given timestamp
 * as part of ntlmv2 authentication (or local current time as
 * default in case of failure)
 */
static __le64
find_timestamp(struct cifs_ses *ses)
{
	unsigned int attrsize;
	unsigned int type;
	unsigned int onesize = sizeof(struct ntlmssp2_name);
	unsigned char *blobptr;
	unsigned char *blobend;
	struct ntlmssp2_name *attrptr;

	if (!ses->auth_key.len || !ses->auth_key.response)
		return 0;

	blobptr = ses->auth_key.response;
	blobend = blobptr + ses->auth_key.len;

	while (blobptr + onesize < blobend) {
		attrptr = (struct ntlmssp2_name *) blobptr;
		type = le16_to_cpu(attrptr->type);
		if (type == NTLMSSP_AV_EOL)
			break;
		blobptr += 2; /* advance attr type */
		attrsize = le16_to_cpu(attrptr->length);
		blobptr += 2; /* advance attr size */
		if (blobptr + attrsize > blobend)
			break;
		if (type == NTLMSSP_AV_TIMESTAMP) {
			if (attrsize == sizeof(u64))
				return *((__le64 *)blobptr);
		}
		blobptr += attrsize; /* advance attr value */
	}

	return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
}

489
static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
490
			    const struct nls_table *nls_cp)
S
Steve French 已提交
491 492 493
{
	int rc = 0;
	int len;
494
	char nt_hash[CIFS_NTHASH_SIZE];
495
	__le16 *user;
496
	wchar_t *domain;
497
	wchar_t *server;
S
Steve French 已提交
498

499
	if (!ses->server->secmech.sdeschmacmd5) {
500
		cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
501 502
		return -1;
	}
503

504
	/* calculate md4 hash of password */
505
	E_md4hash(ses->password, nt_hash, nls_cp);
506

507
	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
508
				CIFS_NTHASH_SIZE);
509
	if (rc) {
510
		cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
511 512
		return rc;
	}
513 514 515

	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
	if (rc) {
516
		cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
517 518
		return rc;
	}
S
Steve French 已提交
519

520
	/* convert ses->user_name to unicode */
J
Jeff Layton 已提交
521
	len = ses->user_name ? strlen(ses->user_name) : 0;
S
Steve French 已提交
522
	user = kmalloc(2 + (len * 2), GFP_KERNEL);
523 524
	if (user == NULL) {
		rc = -ENOMEM;
525
		return rc;
526
	}
J
Jeff Layton 已提交
527 528

	if (len) {
529
		len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
J
Jeff Layton 已提交
530 531 532 533
		UniStrupr(user);
	} else {
		memset(user, '\0', 2);
	}
534

535
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
536
				(char *)user, 2 * len);
537 538
	kfree(user);
	if (rc) {
539
		cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
540 541
		return rc;
	}
S
Steve French 已提交
542 543

	/* convert ses->domainName to unicode and uppercase */
544
	if (ses->domainName) {
S
Steve French 已提交
545
		len = strlen(ses->domainName);
S
Steve French 已提交
546

547
		domain = kmalloc(2 + (len * 2), GFP_KERNEL);
548 549
		if (domain == NULL) {
			rc = -ENOMEM;
550
			return rc;
551
		}
552 553
		len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
				      nls_cp);
554
		rc =
555 556
		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
					(char *)domain, 2 * len);
S
Steve French 已提交
557
		kfree(domain);
558
		if (rc) {
559 560
			cifs_dbg(VFS, "%s: Could not update with domain\n",
				 __func__);
561 562
			return rc;
		}
563 564
	} else {
		/* We use ses->serverName if no domain name available */
565 566 567 568 569
		len = strlen(ses->serverName);

		server = kmalloc(2 + (len * 2), GFP_KERNEL);
		if (server == NULL) {
			rc = -ENOMEM;
570
			return rc;
571
		}
572
		len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
573
					nls_cp);
574
		rc =
575 576 577
		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
					(char *)server, 2 * len);
		kfree(server);
578
		if (rc) {
579 580
			cifs_dbg(VFS, "%s: Could not update with server\n",
				 __func__);
581 582
			return rc;
		}
S
Steve French 已提交
583
	}
584 585

	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
586
					ntlmv2_hash);
587
	if (rc)
588
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
589 590 591 592 593

	return rc;
}

static int
594
CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
595 596
{
	int rc;
597 598 599 600 601 602 603
	struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
	    (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
	unsigned int hash_len;

	/* The MD5 hash starts at challenge_key.key */
	hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
		offsetof(struct ntlmv2_resp, challenge.key[0]));
604 605

	if (!ses->server->secmech.sdeschmacmd5) {
606
		cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
607 608 609
		return -1;
	}

610
	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
611
				 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
612
	if (rc) {
613 614
		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
			 __func__);
615 616
		return rc;
	}
617 618 619

	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
	if (rc) {
620
		cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
621 622 623
		return rc;
	}

624
	if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
625 626
		memcpy(ntlmv2->challenge.key,
		       ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
627
	else
628 629
		memcpy(ntlmv2->challenge.key,
		       ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
630
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
631
				 ntlmv2->challenge.key, hash_len);
632
	if (rc) {
633
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
634 635
		return rc;
	}
636

637
	/* Note that the MD5 digest over writes anon.challenge_key.key */
638
	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
639
				ntlmv2->ntlmv2_hash);
640
	if (rc)
641
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
642 643 644 645

	return rc;
}

646 647
static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
{
648
	int rc;
649 650 651 652 653 654 655 656 657
	unsigned int size;

	/* check if already allocated */
	if (server->secmech.sdeschmacmd5)
		return 0;

	server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
	if (IS_ERR(server->secmech.hmacmd5)) {
		cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
658 659 660
		rc = PTR_ERR(server->secmech.hmacmd5);
		server->secmech.hmacmd5 = NULL;
		return rc;
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
	}

	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.hmacmd5);
	server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
	if (!server->secmech.sdeschmacmd5) {
		crypto_free_shash(server->secmech.hmacmd5);
		server->secmech.hmacmd5 = NULL;
		return -ENOMEM;
	}
	server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
	server->secmech.sdeschmacmd5->shash.flags = 0x0;

	return 0;
}
676

677
int
678
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
679
{
680
	int rc;
681
	int baselen;
682
	unsigned int tilen;
683
	struct ntlmv2_resp *ntlmv2;
684 685
	char ntlmv2_hash[16];
	unsigned char *tiblob = NULL; /* target info blob */
686
	__le64 rsp_timestamp;
S
Steve French 已提交
687

688
	if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
689
		if (!ses->domainName) {
690
			rc = find_domain_name(ses, nls_cp);
691
			if (rc) {
692 693
				cifs_dbg(VFS, "error %d finding domain name\n",
					 rc);
694 695 696 697
				goto setup_ntlmv2_rsp_ret;
			}
		}
	} else {
698
		rc = build_avpair_blob(ses, nls_cp);
699
		if (rc) {
700
			cifs_dbg(VFS, "error %d building av pair blob\n", rc);
701
			goto setup_ntlmv2_rsp_ret;
702 703
		}
	}
S
Steve French 已提交
704

705 706 707 708 709 710
	/* Must be within 5 minutes of the server (or in range +/-2h
	 * in case of Mac OS X), so simply carry over server timestamp
	 * (as Windows 7 does)
	 */
	rsp_timestamp = find_timestamp(ses);

711
	baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
712 713 714 715
	tilen = ses->auth_key.len;
	tiblob = ses->auth_key.response;

	ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
716 717
	if (!ses->auth_key.response) {
		rc = ENOMEM;
718
		ses->auth_key.len = 0;
719 720
		goto setup_ntlmv2_rsp_ret;
	}
721
	ses->auth_key.len += baselen;
722

723
	ntlmv2 = (struct ntlmv2_resp *)
724
			(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
725 726
	ntlmv2->blob_signature = cpu_to_le32(0x00000101);
	ntlmv2->reserved = 0;
727 728
	ntlmv2->time = rsp_timestamp;

729 730
	get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
	ntlmv2->reserved2 = 0;
731

732
	memcpy(ses->auth_key.response + baselen, tiblob, tilen);
733

734 735 736 737 738 739
	rc = crypto_hmacmd5_alloc(ses->server);
	if (rc) {
		cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
		goto setup_ntlmv2_rsp_ret;
	}

740
	/* calculate ntlmv2_hash */
741
	rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
742
	if (rc) {
743
		cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
744 745
		goto setup_ntlmv2_rsp_ret;
	}
746 747

	/* calculate first part of the client response (CR1) */
748
	rc = CalcNTLMv2_response(ses, ntlmv2_hash);
749
	if (rc) {
750
		cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
751 752
		goto setup_ntlmv2_rsp_ret;
	}
753

754
	/* now calculate the session key for NTLMv2 */
755
	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
756
		ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
757
	if (rc) {
758 759
		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
			 __func__);
760 761
		goto setup_ntlmv2_rsp_ret;
	}
762 763 764

	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
	if (rc) {
765
		cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
766 767 768
		goto setup_ntlmv2_rsp_ret;
	}

769
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
770
		ntlmv2->ntlmv2_hash,
771
		CIFS_HMAC_MD5_HASH_SIZE);
772
	if (rc) {
773
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
774 775
		goto setup_ntlmv2_rsp_ret;
	}
776 777 778

	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
		ses->auth_key.response);
779
	if (rc)
780
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
781 782

setup_ntlmv2_rsp_ret:
783
	kfree(tiblob);
784 785

	return rc;
S
Steve French 已提交
786 787
}

788
int
789
calc_seckey(struct cifs_ses *ses)
790 791 792 793 794 795 796 797 798 799
{
	int rc;
	struct crypto_blkcipher *tfm_arc4;
	struct scatterlist sgin, sgout;
	struct blkcipher_desc desc;
	unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */

	get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);

	tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
800 801
	if (IS_ERR(tfm_arc4)) {
		rc = PTR_ERR(tfm_arc4);
802
		cifs_dbg(VFS, "could not allocate crypto API arc4\n");
803
		return rc;
804 805 806 807
	}

	desc.tfm = tfm_arc4;

808
	rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
809
					CIFS_SESS_KEY_SIZE);
810
	if (rc) {
811 812
		cifs_dbg(VFS, "%s: Could not set response as a key\n",
			 __func__);
813 814
		return rc;
	}
815 816

	sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
817
	sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
818 819 820

	rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
	if (rc) {
821
		cifs_dbg(VFS, "could not encrypt session key rc: %d\n", rc);
822 823 824 825 826 827 828 829 830 831 832
		crypto_free_blkcipher(tfm_arc4);
		return rc;
	}

	/* make secondary_key/nonce as session key */
	memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
	/* and make len as that of session key only */
	ses->auth_key.len = CIFS_SESS_KEY_SIZE;

	crypto_free_blkcipher(tfm_arc4);

833
	return rc;
834 835 836 837 838
}

void
cifs_crypto_shash_release(struct TCP_Server_Info *server)
{
839
	if (server->secmech.cmacaes) {
S
Steve French 已提交
840
		crypto_free_shash(server->secmech.cmacaes);
841 842
		server->secmech.cmacaes = NULL;
	}
S
Steve French 已提交
843

844
	if (server->secmech.hmacsha256) {
P
Pavel Shilovsky 已提交
845
		crypto_free_shash(server->secmech.hmacsha256);
846 847
		server->secmech.hmacsha256 = NULL;
	}
P
Pavel Shilovsky 已提交
848

849
	if (server->secmech.md5) {
850
		crypto_free_shash(server->secmech.md5);
851 852
		server->secmech.md5 = NULL;
	}
853

854
	if (server->secmech.hmacmd5) {
855
		crypto_free_shash(server->secmech.hmacmd5);
856 857
		server->secmech.hmacmd5 = NULL;
	}
858

S
Steve French 已提交
859
	kfree(server->secmech.sdesccmacaes);
860
	server->secmech.sdesccmacaes = NULL;
P
Pavel Shilovsky 已提交
861
	kfree(server->secmech.sdeschmacsha256);
862
	server->secmech.sdeschmacsha256 = NULL;
863
	kfree(server->secmech.sdeschmacmd5);
864
	server->secmech.sdeschmacmd5 = NULL;
865
	kfree(server->secmech.sdescmd5);
866
	server->secmech.sdescmd5 = NULL;
867
}