smb2transport.c 18.0 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
}

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

393
#ifdef CONFIG_CIFS_SMB311
394 395 396 397 398 399 400 401
int
generate_smb311signingkey(struct cifs_ses *ses)

{
	struct derivation_triplet triplet;
	struct derivation *d;

	d = &triplet.signing;
402 403 404 405
	d->label.iov_base = "SMBSigningKey";
	d->label.iov_len = 14;
	d->context.iov_base = ses->preauth_sha_hash;
	d->context.iov_len = 64;
406 407

	d = &triplet.encryption;
408 409 410 411
	d->label.iov_base = "SMBC2SCipherKey";
	d->label.iov_len = 16;
	d->context.iov_base = ses->preauth_sha_hash;
	d->context.iov_len = 64;
412 413

	d = &triplet.decryption;
414 415 416 417
	d->label.iov_base = "SMBS2CCipherKey";
	d->label.iov_len = 16;
	d->context.iov_base = ses->preauth_sha_hash;
	d->context.iov_len = 64;
418 419 420

	return generate_smb3signingkey(ses, &triplet);
}
421
#endif /* 311 */
422

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

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

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

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

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

450 451 452 453 454
	/*
	 * 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 已提交
455 456 457 458 459
	rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
	if (rc) {
		cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
		return rc;
	}
460 461 462
	
	rc = __cifs_calc_signature(rqst, server, sigptr,
				   &server->secmech.sdesccmacaes->shash);
S
Steve French 已提交
463

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

	return rc;
468 469
}

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

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

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

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

	return rc;
}

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

500 501 502
	if ((shdr->Command == SMB2_NEGOTIATE) ||
	    (shdr->Command == SMB2_SESSION_SETUP) ||
	    (shdr->Command == SMB2_OPLOCK_BREAK) ||
P
Pavel Shilovsky 已提交
503 504 505 506 507 508 509 510 511
	    (!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 " */
512
	if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
513
		cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
514
			 shdr->Command);
P
Pavel Shilovsky 已提交
515 516 517 518 519

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

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

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

	if (rc)
		return rc;

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

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

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

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

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

	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
565 566 567 568 569 570 571 572 573 574 575 576 577
	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;
578 579 580 581 582 583 584

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

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

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

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

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

609
	*mid = smb2_mid_entry_alloc(shdr, ses->server);
610 611 612 613 614 615 616 617 618 619 620 621 622
	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);
623 624 625
	struct kvec iov[2];
	struct smb_rqst rqst = { .rq_iov = iov,
				 .rq_nvec = 2 };
626

627 628 629 630
	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;
631 632 633

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

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

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

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

654
	smb2_seq_num_into_buf(ses->server, shdr);
655

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

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

675
	smb2_seq_num_into_buf(server, shdr);
676

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

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

687
	return mid;
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 717 718

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