smb2transport.c 17.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 *   fs/cifs/smb2transport.c
 *
 *   Copyright (C) International Business Machines  Corp., 2002, 2011
 *                 Etersoft, 2012
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *              Jeremy Allison (jra@samba.org) 2006
 *              Pavel Shilovsky (pshilovsky@samba.org) 2012
 *
 *   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>
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/net.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <asm/processor.h>
#include <linux/mempool.h>
33
#include <linux/highmem.h>
34
#include <crypto/aead.h>
35 36 37 38 39 40
#include "smb2pdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "smb2proto.h"
#include "cifs_debug.h"
#include "smb2status.h"
P
Pavel Shilovsky 已提交
41 42
#include "smb2glob.h"

43 44 45
static int
smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
{
46
	int rc;
47 48 49 50 51 52 53 54
	unsigned int size;

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

	server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
	if (IS_ERR(server->secmech.hmacsha256)) {
		cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
55 56 57
		rc = PTR_ERR(server->secmech.hmacsha256);
		server->secmech.hmacsha256 = NULL;
		return rc;
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 93
	}

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

	return 0;
}

static int
smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
{
	unsigned int size;
	int rc;

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

	rc = smb2_crypto_shash_allocate(server);
	if (rc)
		return rc;

	server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
	if (IS_ERR(server->secmech.cmacaes)) {
		cifs_dbg(VFS, "could not allocate crypto cmac-aes");
		kfree(server->secmech.sdeschmacsha256);
		server->secmech.sdeschmacsha256 = NULL;
		crypto_free_shash(server->secmech.hmacsha256);
		server->secmech.hmacsha256 = NULL;
94 95 96
		rc = PTR_ERR(server->secmech.cmacaes);
		server->secmech.cmacaes = NULL;
		return rc;
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
	}

	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.cmacaes);
	server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
	if (!server->secmech.sdesccmacaes) {
		cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
		kfree(server->secmech.sdeschmacsha256);
		server->secmech.sdeschmacsha256 = NULL;
		crypto_free_shash(server->secmech.hmacsha256);
		crypto_free_shash(server->secmech.cmacaes);
		server->secmech.hmacsha256 = NULL;
		server->secmech.cmacaes = NULL;
		return -ENOMEM;
	}
	server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
	server->secmech.sdesccmacaes->shash.flags = 0x0;

	return 0;
}

S
Sachin Prabhu 已提交
118 119
static struct cifs_ses *
smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
120 121 122 123
{
	struct cifs_ses *ses;

	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
124
		if (ses->Suid != ses_id)
125 126 127
			continue;
		return ses;
	}
S
Sachin Prabhu 已提交
128 129 130 131 132 133 134 135 136 137 138

	return NULL;
}

struct cifs_ses *
smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
{
	struct cifs_ses *ses;

	spin_lock(&cifs_tcp_ses_lock);
	ses = smb2_find_smb_ses_unlocked(server, ses_id);
139 140
	spin_unlock(&cifs_tcp_ses_lock);

S
Sachin Prabhu 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
	return ses;
}

static struct cifs_tcon *
smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
{
	struct cifs_tcon *tcon;

	list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
		if (tcon->tid != tid)
			continue;
		++tcon->tc_count;
		return tcon;
	}

156 157 158
	return NULL;
}

S
Sachin Prabhu 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
/*
 * Obtain tcon corresponding to the tid in the given
 * cifs_ses
 */

struct cifs_tcon *
smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32  tid)
{
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;

	spin_lock(&cifs_tcp_ses_lock);
	ses = smb2_find_smb_ses_unlocked(server, ses_id);
	if (!ses) {
		spin_unlock(&cifs_tcp_ses_lock);
		return NULL;
	}
	tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
	spin_unlock(&cifs_tcp_ses_lock);

	return tcon;
}

182
int
183
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
P
Pavel Shilovsky 已提交
184
{
185
	int rc;
P
Pavel Shilovsky 已提交
186 187
	unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
	unsigned char *sigptr = smb2_signature;
188
	struct kvec *iov = rqst->rq_iov;
189
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
190 191
	struct cifs_ses *ses;

192
	ses = smb2_find_smb_ses(server, shdr->SessionId);
193 194 195 196
	if (!ses) {
		cifs_dbg(VFS, "%s: Could not find session\n", __func__);
		return 0;
	}
P
Pavel Shilovsky 已提交
197 198

	memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
199
	memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
200

201 202 203 204 205 206
	rc = smb2_crypto_shash_allocate(server);
	if (rc) {
		cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__);
		return rc;
	}

P
Pavel Shilovsky 已提交
207
	rc = crypto_shash_setkey(server->secmech.hmacsha256,
208
		ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
P
Pavel Shilovsky 已提交
209
	if (rc) {
210
		cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
P
Pavel Shilovsky 已提交
211 212 213 214 215
		return rc;
	}

	rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
	if (rc) {
216
		cifs_dbg(VFS, "%s: Could not init sha256", __func__);
P
Pavel Shilovsky 已提交
217 218 219
		return rc;
	}

220 221
	rc = __cifs_calc_signature(rqst, server, sigptr,
		&server->secmech.sdeschmacsha256->shash);
P
Pavel Shilovsky 已提交
222

223
	if (!rc)
224
		memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
225 226 227 228

	return rc;
}

229 230
static int generate_key(struct cifs_ses *ses, struct kvec label,
			struct kvec context, __u8 *key, unsigned int key_size)
S
Steve French 已提交
231 232 233 234 235 236 237 238 239
{
	unsigned char zero = 0x0;
	__u8 i[4] = {0, 0, 0, 1};
	__u8 L[4] = {0, 0, 0, 128};
	int rc = 0;
	unsigned char prfhash[SMB2_HMACSHA256_SIZE];
	unsigned char *hashptr = prfhash;

	memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
240
	memset(key, 0x0, key_size);
S
Steve French 已提交
241

242
	rc = smb3_crypto_shash_allocate(ses->server);
243 244 245 246 247
	if (rc) {
		cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
		goto smb3signkey_ret;
	}

248 249
	rc = crypto_shash_setkey(ses->server->secmech.hmacsha256,
		ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
S
Steve French 已提交
250 251 252 253 254
	if (rc) {
		cifs_dbg(VFS, "%s: Could not set with session key\n", __func__);
		goto smb3signkey_ret;
	}

255
	rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash);
S
Steve French 已提交
256 257 258 259 260
	if (rc) {
		cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
		goto smb3signkey_ret;
	}

261
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
262 263 264 265 266 267
				i, 4);
	if (rc) {
		cifs_dbg(VFS, "%s: Could not update with n\n", __func__);
		goto smb3signkey_ret;
	}

268
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
269
				label.iov_base, label.iov_len);
S
Steve French 已提交
270 271 272 273 274
	if (rc) {
		cifs_dbg(VFS, "%s: Could not update with label\n", __func__);
		goto smb3signkey_ret;
	}

275
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
276 277 278 279 280 281
				&zero, 1);
	if (rc) {
		cifs_dbg(VFS, "%s: Could not update with zero\n", __func__);
		goto smb3signkey_ret;
	}

282
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
283
				context.iov_base, context.iov_len);
S
Steve French 已提交
284 285 286 287 288
	if (rc) {
		cifs_dbg(VFS, "%s: Could not update with context\n", __func__);
		goto smb3signkey_ret;
	}

289
	rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
290 291 292 293 294 295
				L, 4);
	if (rc) {
		cifs_dbg(VFS, "%s: Could not update with L\n", __func__);
		goto smb3signkey_ret;
	}

296
	rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash,
S
Steve French 已提交
297 298 299 300 301 302
				hashptr);
	if (rc) {
		cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
		goto smb3signkey_ret;
	}

303
	memcpy(key, hashptr, key_size);
S
Steve French 已提交
304 305

smb3signkey_ret:
306
	return rc;
S
Steve French 已提交
307 308
}

309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
struct derivation {
	struct kvec label;
	struct kvec context;
};

struct derivation_triplet {
	struct derivation signing;
	struct derivation encryption;
	struct derivation decryption;
};

static int
generate_smb3signingkey(struct cifs_ses *ses,
			const struct derivation_triplet *ptriplet)
{
	int rc;

	rc = generate_key(ses, ptriplet->signing.label,
			  ptriplet->signing.context, ses->smb3signingkey,
			  SMB3_SIGN_KEY_SIZE);
	if (rc)
		return rc;

	rc = generate_key(ses, ptriplet->encryption.label,
			  ptriplet->encryption.context, ses->smb3encryptionkey,
			  SMB3_SIGN_KEY_SIZE);
	if (rc)
		return rc;

338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
	rc = generate_key(ses, ptriplet->decryption.label,
			  ptriplet->decryption.context,
			  ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);

	if (rc)
		return rc;

#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
	cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);
	/*
	 * The session id is opaque in terms of endianness, so we can't
	 * print it as a long long. we dump it as we got it on the wire
	 */
	cifs_dbg(VFS, "Session Id    %*ph\n", (int)sizeof(ses->Suid),
			&ses->Suid);
	cifs_dbg(VFS, "Session Key   %*ph\n",
		 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
	cifs_dbg(VFS, "Signing Key   %*ph\n",
		 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
	cifs_dbg(VFS, "ServerIn Key  %*ph\n",
		 SMB3_SIGN_KEY_SIZE, ses->smb3encryptionkey);
	cifs_dbg(VFS, "ServerOut Key %*ph\n",
		 SMB3_SIGN_KEY_SIZE, ses->smb3decryptionkey);
#endif
	return rc;
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
}

int
generate_smb30signingkey(struct cifs_ses *ses)

{
	struct derivation_triplet triplet;
	struct derivation *d;

	d = &triplet.signing;
	d->label.iov_base = "SMB2AESCMAC";
	d->label.iov_len = 12;
	d->context.iov_base = "SmbSign";
	d->context.iov_len = 8;

	d = &triplet.encryption;
	d->label.iov_base = "SMB2AESCCM";
	d->label.iov_len = 11;
	d->context.iov_base = "ServerIn ";
	d->context.iov_len = 10;

	d = &triplet.decryption;
	d->label.iov_base = "SMB2AESCCM";
	d->label.iov_len = 11;
	d->context.iov_base = "ServerOut";
	d->context.iov_len = 10;

	return generate_smb3signingkey(ses, &triplet);
}

int
generate_smb311signingkey(struct cifs_ses *ses)

{
	struct derivation_triplet triplet;
	struct derivation *d;

	d = &triplet.signing;
	d->label.iov_base = "SMB2AESCMAC";
	d->label.iov_len = 12;
	d->context.iov_base = "SmbSign";
	d->context.iov_len = 8;

	d = &triplet.encryption;
	d->label.iov_base = "SMB2AESCCM";
	d->label.iov_len = 11;
	d->context.iov_base = "ServerIn ";
	d->context.iov_len = 10;

	d = &triplet.decryption;
	d->label.iov_base = "SMB2AESCCM";
	d->label.iov_len = 11;
	d->context.iov_base = "ServerOut";
	d->context.iov_len = 10;

	return generate_smb3signingkey(ses, &triplet);
}

421 422 423
int
smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
{
424
	int rc = 0;
S
Steve French 已提交
425 426 427
	unsigned char smb3_signature[SMB2_CMACAES_SIZE];
	unsigned char *sigptr = smb3_signature;
	struct kvec *iov = rqst->rq_iov;
428
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
429 430
	struct cifs_ses *ses;

431
	ses = smb2_find_smb_ses(server, shdr->SessionId);
432 433 434 435
	if (!ses) {
		cifs_dbg(VFS, "%s: Could not find session\n", __func__);
		return 0;
	}
S
Steve French 已提交
436 437

	memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
438
	memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
S
Steve French 已提交
439 440

	rc = crypto_shash_setkey(server->secmech.cmacaes,
441 442
		ses->smb3signingkey, SMB2_CMACAES_SIZE);

S
Steve French 已提交
443 444 445 446 447
	if (rc) {
		cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
		return rc;
	}

448 449 450 451 452
	/*
	 * we already allocate sdesccmacaes when we init smb3 signing key,
	 * so unlike smb2 case we do not have to check here if secmech are
	 * initialized
	 */
S
Steve French 已提交
453 454 455 456 457
	rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
	if (rc) {
		cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
		return rc;
	}
458 459 460
	
	rc = __cifs_calc_signature(rqst, server, sigptr,
				   &server->secmech.sdesccmacaes->shash);
S
Steve French 已提交
461

462
	if (!rc)
463
		memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
S
Steve French 已提交
464 465

	return rc;
466 467
}

P
Pavel Shilovsky 已提交
468 469
/* must be called with server->srv_mutex held */
static int
470
smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
P
Pavel Shilovsky 已提交
471 472
{
	int rc = 0;
473 474
	struct smb2_sync_hdr *shdr =
			(struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
P
Pavel Shilovsky 已提交
475

476
	if (!(shdr->Flags & SMB2_FLAGS_SIGNED) ||
P
Pavel Shilovsky 已提交
477 478 479 480
	    server->tcpStatus == CifsNeedNegotiate)
		return rc;

	if (!server->session_estab) {
481
		strncpy(shdr->Signature, "BSRSPYL", 8);
P
Pavel Shilovsky 已提交
482 483 484
		return rc;
	}

485
	rc = server->ops->calc_signature(rqst, server);
P
Pavel Shilovsky 已提交
486 487 488 489 490

	return rc;
}

int
491
smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
P
Pavel Shilovsky 已提交
492 493 494
{
	unsigned int rc;
	char server_response_sig[16];
495 496
	struct smb2_sync_hdr *shdr =
			(struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
P
Pavel Shilovsky 已提交
497

498 499 500
	if ((shdr->Command == SMB2_NEGOTIATE) ||
	    (shdr->Command == SMB2_SESSION_SETUP) ||
	    (shdr->Command == SMB2_OPLOCK_BREAK) ||
P
Pavel Shilovsky 已提交
501 502 503 504 505 506 507 508 509
	    (!server->session_estab))
		return 0;

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

	/* Do not need to verify session setups with signature "BSRSPYL " */
510
	if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
511
		cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
512
			 shdr->Command);
P
Pavel Shilovsky 已提交
513 514 515 516 517

	/*
	 * Save off the origiginal signature so we can modify the smb and check
	 * our calculated signature against what the server sent.
	 */
518
	memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
519

520
	memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
P
Pavel Shilovsky 已提交
521 522

	mutex_lock(&server->srv_mutex);
523
	rc = server->ops->calc_signature(rqst, server);
P
Pavel Shilovsky 已提交
524 525 526 527 528
	mutex_unlock(&server->srv_mutex);

	if (rc)
		return rc;

529
	if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE))
P
Pavel Shilovsky 已提交
530 531 532 533 534
		return -EACCES;
	else
		return 0;
}

535 536 537 538 539
/*
 * Set message id for the request. Should be called after wait_for_free_request
 * and when srv_mutex is held.
 */
static inline void
540 541
smb2_seq_num_into_buf(struct TCP_Server_Info *server,
		      struct smb2_sync_hdr *shdr)
542
{
543
	unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
544

545
	shdr->MessageId = get_next_mid64(server);
546 547 548
	/* skip message numbers according to CreditCharge field */
	for (i = 1; i < num; i++)
		get_next_mid(server);
549 550 551
}

static struct mid_q_entry *
552
smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
553 554 555 556 557
		     struct TCP_Server_Info *server)
{
	struct mid_q_entry *temp;

	if (server == NULL) {
558
		cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
559 560 561 562
		return NULL;
	}

	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
563 564 565 566 567 568 569 570 571 572 573 574 575
	memset(temp, 0, sizeof(struct mid_q_entry));
	temp->mid = le64_to_cpu(shdr->MessageId);
	temp->pid = current->pid;
	temp->command = shdr->Command; /* Always LE */
	temp->when_alloc = jiffies;
	temp->server = server;

	/*
	 * The default is for the mid to be synchronous, so the
	 * default callback just wakes up the current task.
	 */
	temp->callback = cifs_wake_up_task;
	temp->callback_data = current;
576 577 578 579 580 581 582

	atomic_inc(&midCount);
	temp->mid_state = MID_REQUEST_ALLOCATED;
	return temp;
}

static int
583
smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_sync_hdr *shdr,
584 585 586 587 588 589
		   struct mid_q_entry **mid)
{
	if (ses->server->tcpStatus == CifsExiting)
		return -ENOENT;

	if (ses->server->tcpStatus == CifsNeedReconnect) {
590
		cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
591 592 593
		return -EAGAIN;
	}

594
	if (ses->status == CifsNew) {
595 596
		if ((shdr->Command != SMB2_SESSION_SETUP) &&
		    (shdr->Command != SMB2_NEGOTIATE))
597 598 599
			return -EAGAIN;
		/* else ok - we are setting up session */
	}
600 601

	if (ses->status == CifsExiting) {
602
		if (shdr->Command != SMB2_LOGOFF)
603 604 605 606
			return -EAGAIN;
		/* else ok - we are shutting down the session */
	}

607
	*mid = smb2_mid_entry_alloc(shdr, ses->server);
608 609 610 611 612 613 614 615 616 617 618 619 620
	if (*mid == NULL)
		return -ENOMEM;
	spin_lock(&GlobalMid_Lock);
	list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
	spin_unlock(&GlobalMid_Lock);
	return 0;
}

int
smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
		   bool log_error)
{
	unsigned int len = get_rfc1002_length(mid->resp_buf);
621 622 623
	struct kvec iov[2];
	struct smb_rqst rqst = { .rq_iov = iov,
				 .rq_nvec = 2 };
624

625 626 627 628
	iov[0].iov_base = (char *)mid->resp_buf;
	iov[0].iov_len = 4;
	iov[1].iov_base = (char *)mid->resp_buf + 4;
	iov[1].iov_len = len;
629 630 631

	dump_smb(mid->resp_buf, min_t(u32, 80, len));
	/* convert the length into a more usable form */
632
	if (len > 24 && server->sign && !mid->decrypted) {
P
Pavel Shilovsky 已提交
633 634
		int rc;

635
		rc = smb2_verify_signature(&rqst, server);
P
Pavel Shilovsky 已提交
636
		if (rc)
637 638
			cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
				 rc);
P
Pavel Shilovsky 已提交
639
	}
640 641 642 643

	return map_smb2_to_linux_error(mid->resp_buf, log_error);
}

644 645
struct mid_q_entry *
smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
646 647
{
	int rc;
648 649
	struct smb2_sync_hdr *shdr =
			(struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
650 651
	struct mid_q_entry *mid;

652
	smb2_seq_num_into_buf(ses->server, shdr);
653

654
	rc = smb2_get_mid_entry(ses, shdr, &mid);
655
	if (rc)
656 657 658
		return ERR_PTR(rc);
	rc = smb2_sign_rqst(rqst, ses->server);
	if (rc) {
P
Pavel Shilovsky 已提交
659
		cifs_delete_mid(mid);
660 661 662
		return ERR_PTR(rc);
	}
	return mid;
663 664
}

665 666
struct mid_q_entry *
smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
667
{
668
	int rc;
669 670
	struct smb2_sync_hdr *shdr =
			(struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
671 672
	struct mid_q_entry *mid;

673
	smb2_seq_num_into_buf(server, shdr);
674

675
	mid = smb2_mid_entry_alloc(shdr, server);
676
	if (mid == NULL)
677
		return ERR_PTR(-ENOMEM);
678

679
	rc = smb2_sign_rqst(rqst, server);
680 681
	if (rc) {
		DeleteMidQEntry(mid);
682
		return ERR_PTR(rc);
P
Pavel Shilovsky 已提交
683 684
	}

685
	return mid;
686
}
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716

int
smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
{
	struct crypto_aead *tfm;

	if (!server->secmech.ccmaesencrypt) {
		tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
		if (IS_ERR(tfm)) {
			cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
				 __func__);
			return PTR_ERR(tfm);
		}
		server->secmech.ccmaesencrypt = tfm;
	}

	if (!server->secmech.ccmaesdecrypt) {
		tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
		if (IS_ERR(tfm)) {
			crypto_free_aead(server->secmech.ccmaesencrypt);
			server->secmech.ccmaesencrypt = NULL;
			cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
				 __func__);
			return PTR_ERR(tfm);
		}
		server->secmech.ccmaesdecrypt = tfm;
	}

	return 0;
}