cifsencrypt.c 21.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/cifsencrypt.c
 *
4
 *   Copyright (C) International Business Machines  Corp., 2005,2013
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *   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>
23
#include <linux/slab.h>
L
Linus Torvalds 已提交
24
#include "cifspdu.h"
S
Steve French 已提交
25
#include "cifsglob.h"
L
Linus Torvalds 已提交
26 27 28
#include "cifs_debug.h"
#include "cifs_unicode.h"
#include "cifsproto.h"
29
#include "ntlmssp.h"
30
#include <linux/ctype.h>
S
Steve French 已提交
31
#include <linux/random.h>
32
#include <linux/highmem.h>
L
Linus Torvalds 已提交
33

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
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");
		return PTR_ERR(server->secmech.md5);
	}

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

	return 0;
}

64 65 66 67 68 69 70
/*
 * 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.
 */
71
static int cifs_calc_signature(struct smb_rqst *rqst,
72
			struct TCP_Server_Info *server, char *signature)
73
{
74
	int i;
75
	int rc;
76 77
	struct kvec *iov = rqst->rq_iov;
	int n_vec = rqst->rq_nvec;
78

79
	if (iov == NULL || signature == NULL || server == NULL)
80
		return -EINVAL;
81

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

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

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

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

130 131 132 133 134 135 136 137 138 139
	/* 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]);
	}

140
	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
141
	if (rc)
142
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
143

144
	return rc;
145 146
}

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

S
Steve French 已提交
155
	if ((cifs_pdu == NULL) || (server == NULL))
156 157
		return -EINVAL;

158 159
	if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
	    server->tcpStatus == CifsNeedNegotiate)
160 161
		return rc;

162
	if (!server->session_estab) {
163
		memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
164 165 166
		return rc;
	}

S
Steve French 已提交
167
	cifs_pdu->Signature.Sequence.SequenceNumber =
168
				cpu_to_le32(server->sequence_number);
S
Steve French 已提交
169
	cifs_pdu->Signature.Sequence.Reserved = 0;
170

171 172
	*pexpected_response_sequence_number = ++server->sequence_number;
	++server->sequence_number;
173

174
	rc = cifs_calc_signature(rqst, server, smb_signature);
S
Steve French 已提交
175 176 177 178
	if (rc)
		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
	else
		memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
179

S
Steve French 已提交
180
	return rc;
181 182
}

183 184 185 186 187 188 189 190 191
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);
}

192 193 194 195 196 197 198 199 200
/* 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;

201
	return cifs_sign_smbv(&iov, 1, server,
202 203 204
			      pexpected_response_sequence_number);
}

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

214
	if (cifs_pdu == NULL || server == NULL)
L
Linus Torvalds 已提交
215 216
		return -EINVAL;

217
	if (!server->session_estab)
L
Linus Torvalds 已提交
218 219 220
		return 0;

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

227 228 229
	/* BB what if signatures are supposed to be on for session but
	   server does not send one? BB */

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

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

239 240
	cifs_pdu->Signature.Sequence.SequenceNumber =
					cpu_to_le32(expected_sequence_number);
L
Linus Torvalds 已提交
241 242
	cifs_pdu->Signature.Sequence.Reserved = 0;

243
	mutex_lock(&server->srv_mutex);
244
	rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
245
	mutex_unlock(&server->srv_mutex);
L
Linus Torvalds 已提交
246

247
	if (rc)
L
Linus Torvalds 已提交
248 249
		return rc;

250 251
/*	cifs_dump_mem("what we think it should be: ",
		      what_we_think_sig_should_be, 16); */
L
Linus Torvalds 已提交
252

253
	if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
L
Linus Torvalds 已提交
254 255 256 257 258 259
		return -EACCES;
	else
		return 0;

}

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

	if (!ses)
L
Linus Torvalds 已提交
268 269
		return -EINVAL;

270
	ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
271
	if (!ses->auth_key.response)
272
		return -ENOMEM;
273

274 275
	ses->auth_key.len = temp_len;

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

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

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

296
	return rc;
L
Linus Torvalds 已提交
297 298
}

299
#ifdef CONFIG_CIFS_WEAK_PW_HASH
300
int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
301
			char *lnm_session_key)
302 303
{
	int i;
304
	int rc;
305 306 307
	char password_with_pad[CIFS_ENCPWD_SIZE];

	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
308 309 310
	if (password)
		strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);

311
	if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) {
312 313
		memcpy(lnm_session_key, password_with_pad,
			CIFS_ENCPWD_SIZE);
314
		return 0;
315
	}
316

317 318 319 320 321 322 323 324 325 326 327
	/* 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. */

328
	for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
329 330
		password_with_pad[i] = toupper(password_with_pad[i]);

331
	rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key);
332

333
	return rc;
334 335 336
}
#endif /* CIFS_WEAK_PW_HASH */

337 338 339 340
/* 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.
341 342
 */
static int
343
build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
344
{
345
	unsigned int dlen;
346
	unsigned int size = 2 * sizeof(struct ntlmssp2_name);
347 348
	char *defdmname = "WORKGROUP";
	unsigned char *blobptr;
349 350
	struct ntlmssp2_name *attrptr;

351 352 353 354 355 356 357 358
	if (!ses->domainName) {
		ses->domainName = kstrdup(defdmname, GFP_KERNEL);
		if (!ses->domainName)
			return -ENOMEM;
	}

	dlen = strlen(ses->domainName);

359 360 361 362 363
	/*
	 * 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
364
	 */
365
	ses->auth_key.len = size + 2 * dlen;
366 367 368
	ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
	if (!ses->auth_key.response) {
		ses->auth_key.len = 0;
369 370
		return -ENOMEM;
	}
371

372
	blobptr = ses->auth_key.response;
373 374
	attrptr = (struct ntlmssp2_name *) blobptr;

375 376 377 378
	/*
	 * As defined in MS-NTLM 3.3.2, just this av pair field
	 * is sufficient as part of the temp
	 */
379 380 381
	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);
382
	cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
383

384 385 386 387 388 389 390 391 392 393 394 395 396 397
	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
398
find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
399 400 401 402 403 404 405 406
{
	unsigned int attrsize;
	unsigned int type;
	unsigned int onesize = sizeof(struct ntlmssp2_name);
	unsigned char *blobptr;
	unsigned char *blobend;
	struct ntlmssp2_name *attrptr;

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

410 411
	blobptr = ses->auth_key.response;
	blobend = blobptr + ses->auth_key.len;
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430

	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) {
			if (!attrsize)
				break;
			if (!ses->domainName) {
				ses->domainName =
					kmalloc(attrsize + 1, GFP_KERNEL);
				if (!ses->domainName)
						return -ENOMEM;
431
				cifs_from_utf16(ses->domainName,
432
					(__le16 *)blobptr, attrsize, attrsize,
433
					nls_cp, false);
434 435 436 437 438 439 440 441 442
				break;
			}
		}
		blobptr += attrsize; /* advance attr  value */
	}

	return 0;
}

443
static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
444
			    const struct nls_table *nls_cp)
S
Steve French 已提交
445 446 447
{
	int rc = 0;
	int len;
448
	char nt_hash[CIFS_NTHASH_SIZE];
449
	__le16 *user;
450
	wchar_t *domain;
451
	wchar_t *server;
S
Steve French 已提交
452

453
	if (!ses->server->secmech.sdeschmacmd5) {
454
		cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
455 456
		return -1;
	}
457

458
	/* calculate md4 hash of password */
459
	E_md4hash(ses->password, nt_hash, nls_cp);
460

461
	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
462
				CIFS_NTHASH_SIZE);
463
	if (rc) {
464
		cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
465 466
		return rc;
	}
467 468 469

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

474
	/* convert ses->user_name to unicode */
J
Jeff Layton 已提交
475
	len = ses->user_name ? strlen(ses->user_name) : 0;
S
Steve French 已提交
476
	user = kmalloc(2 + (len * 2), GFP_KERNEL);
477 478
	if (user == NULL) {
		rc = -ENOMEM;
479
		return rc;
480
	}
J
Jeff Layton 已提交
481 482

	if (len) {
483
		len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
J
Jeff Layton 已提交
484 485 486 487
		UniStrupr(user);
	} else {
		memset(user, '\0', 2);
	}
488

489
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
490
				(char *)user, 2 * len);
491 492
	kfree(user);
	if (rc) {
493
		cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
494 495
		return rc;
	}
S
Steve French 已提交
496 497

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

501
		domain = kmalloc(2 + (len * 2), GFP_KERNEL);
502 503
		if (domain == NULL) {
			rc = -ENOMEM;
504
			return rc;
505
		}
506 507
		len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
				      nls_cp);
508
		rc =
509 510
		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
					(char *)domain, 2 * len);
S
Steve French 已提交
511
		kfree(domain);
512
		if (rc) {
513 514
			cifs_dbg(VFS, "%s: Could not update with domain\n",
				 __func__);
515 516
			return rc;
		}
517 518 519 520 521 522
	} else if (ses->serverName) {
		len = strlen(ses->serverName);

		server = kmalloc(2 + (len * 2), GFP_KERNEL);
		if (server == NULL) {
			rc = -ENOMEM;
523
			return rc;
524
		}
525
		len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
526
					nls_cp);
527
		rc =
528 529 530
		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
					(char *)server, 2 * len);
		kfree(server);
531
		if (rc) {
532 533
			cifs_dbg(VFS, "%s: Could not update with server\n",
				 __func__);
534 535
			return rc;
		}
S
Steve French 已提交
536
	}
537 538

	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
539
					ntlmv2_hash);
540
	if (rc)
541
		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
542 543 544 545 546

	return rc;
}

static int
547
CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
548 549 550 551 552
{
	int rc;
	unsigned int offset = CIFS_SESS_KEY_SIZE + 8;

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

557
	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
558
				ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
559
	if (rc) {
560 561
		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
			 __func__);
562 563
		return rc;
	}
564 565 566

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

571
	if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
572
		memcpy(ses->auth_key.response + offset,
573
			ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
574 575 576
	else
		memcpy(ses->auth_key.response + offset,
			ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
577
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
578
		ses->auth_key.response + offset, ses->auth_key.len - offset);
579
	if (rc) {
580
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
581 582
		return rc;
	}
583 584 585

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

	return rc;
}

592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
{
	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");
		return PTR_ERR(server->secmech.hmacmd5);
	}

	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;
}
619

620
int
621
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
622
{
623
	int rc;
624
	int baselen;
625
	unsigned int tilen;
626
	struct ntlmv2_resp *buf;
627 628
	char ntlmv2_hash[16];
	unsigned char *tiblob = NULL; /* target info blob */
S
Steve French 已提交
629

630
	if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
631
		if (!ses->domainName) {
632
			rc = find_domain_name(ses, nls_cp);
633
			if (rc) {
634 635
				cifs_dbg(VFS, "error %d finding domain name\n",
					 rc);
636 637 638 639
				goto setup_ntlmv2_rsp_ret;
			}
		}
	} else {
640
		rc = build_avpair_blob(ses, nls_cp);
641
		if (rc) {
642
			cifs_dbg(VFS, "error %d building av pair blob\n", rc);
643
			goto setup_ntlmv2_rsp_ret;
644 645
		}
	}
S
Steve French 已提交
646

647
	baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
648 649 650 651
	tilen = ses->auth_key.len;
	tiblob = ses->auth_key.response;

	ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
652 653
	if (!ses->auth_key.response) {
		rc = ENOMEM;
654
		ses->auth_key.len = 0;
655 656
		goto setup_ntlmv2_rsp_ret;
	}
657
	ses->auth_key.len += baselen;
658 659 660 661 662 663 664 665 666

	buf = (struct ntlmv2_resp *)
			(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
	buf->blob_signature = cpu_to_le32(0x00000101);
	buf->reserved = 0;
	buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
	get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
	buf->reserved2 = 0;

667
	memcpy(ses->auth_key.response + baselen, tiblob, tilen);
668

669 670 671 672 673 674
	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;
	}

675
	/* calculate ntlmv2_hash */
676
	rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
677
	if (rc) {
678
		cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
679 680
		goto setup_ntlmv2_rsp_ret;
	}
681 682

	/* calculate first part of the client response (CR1) */
683
	rc = CalcNTLMv2_response(ses, ntlmv2_hash);
684
	if (rc) {
685
		cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
686 687
		goto setup_ntlmv2_rsp_ret;
	}
688

689
	/* now calculate the session key for NTLMv2 */
690
	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
691
		ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
692
	if (rc) {
693 694
		cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
			 __func__);
695 696
		goto setup_ntlmv2_rsp_ret;
	}
697 698 699

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

704
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
705 706
		ses->auth_key.response + CIFS_SESS_KEY_SIZE,
		CIFS_HMAC_MD5_HASH_SIZE);
707
	if (rc) {
708
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
709 710
		goto setup_ntlmv2_rsp_ret;
	}
711 712 713

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

setup_ntlmv2_rsp_ret:
718
	kfree(tiblob);
719 720

	return rc;
S
Steve French 已提交
721 722
}

723
int
724
calc_seckey(struct cifs_ses *ses)
725 726 727 728 729 730 731 732 733 734
{
	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);
735 736
	if (IS_ERR(tfm_arc4)) {
		rc = PTR_ERR(tfm_arc4);
737
		cifs_dbg(VFS, "could not allocate crypto API arc4\n");
738
		return rc;
739 740 741 742
	}

	desc.tfm = tfm_arc4;

743
	rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
744
					CIFS_SESS_KEY_SIZE);
745
	if (rc) {
746 747
		cifs_dbg(VFS, "%s: Could not set response as a key\n",
			 __func__);
748 749
		return rc;
	}
750 751

	sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
752
	sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
753 754 755

	rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
	if (rc) {
756
		cifs_dbg(VFS, "could not encrypt session key rc: %d\n", rc);
757 758 759 760 761 762 763 764 765 766 767
		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);

768
	return rc;
769 770 771 772 773
}

void
cifs_crypto_shash_release(struct TCP_Server_Info *server)
{
774
	if (server->secmech.cmacaes) {
S
Steve French 已提交
775
		crypto_free_shash(server->secmech.cmacaes);
776 777
		server->secmech.cmacaes = NULL;
	}
S
Steve French 已提交
778

779
	if (server->secmech.hmacsha256) {
P
Pavel Shilovsky 已提交
780
		crypto_free_shash(server->secmech.hmacsha256);
781 782
		server->secmech.hmacsha256 = NULL;
	}
P
Pavel Shilovsky 已提交
783

784
	if (server->secmech.md5) {
785
		crypto_free_shash(server->secmech.md5);
786 787
		server->secmech.md5 = NULL;
	}
788

789
	if (server->secmech.hmacmd5) {
790
		crypto_free_shash(server->secmech.hmacmd5);
791 792
		server->secmech.hmacmd5 = NULL;
	}
793

S
Steve French 已提交
794
	kfree(server->secmech.sdesccmacaes);
795
	server->secmech.sdesccmacaes = NULL;
P
Pavel Shilovsky 已提交
796
	kfree(server->secmech.sdeschmacsha256);
797
	server->secmech.sdeschmacsha256 = NULL;
798
	kfree(server->secmech.sdeschmacmd5);
799
	server->secmech.sdeschmacmd5 = NULL;
800
	kfree(server->secmech.sdescmd5);
801
	server->secmech.sdescmd5 = NULL;
802
}