brintos

brintos / linux-shallow public Read only

0
0
Text · 23.2 KiB · b486b14 Raw
950 lines · c
1// SPDX-License-Identifier: LGPL-2.12/*3 *4 *   Copyright (C) International Business Machines  Corp., 2002, 20115 *                 Etersoft, 20126 *   Author(s): Steve French (sfrench@us.ibm.com)7 *              Jeremy Allison (jra@samba.org) 20068 *              Pavel Shilovsky (pshilovsky@samba.org) 20129 *10 */11 12#include <linux/fs.h>13#include <linux/list.h>14#include <linux/wait.h>15#include <linux/net.h>16#include <linux/delay.h>17#include <linux/uaccess.h>18#include <asm/processor.h>19#include <linux/mempool.h>20#include <linux/highmem.h>21#include <crypto/aead.h>22#include "cifsglob.h"23#include "cifsproto.h"24#include "smb2proto.h"25#include "cifs_debug.h"26#include "../common/smb2status.h"27#include "smb2glob.h"28 29static int30smb3_crypto_shash_allocate(struct TCP_Server_Info *server)31{32	struct cifs_secmech *p = &server->secmech;33	int rc;34 35	rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);36	if (rc)37		goto err;38 39	rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);40	if (rc)41		goto err;42 43	return 0;44err:45	cifs_free_hash(&p->hmacsha256);46	return rc;47}48 49int50smb311_crypto_shash_allocate(struct TCP_Server_Info *server)51{52	struct cifs_secmech *p = &server->secmech;53	int rc = 0;54 55	rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);56	if (rc)57		return rc;58 59	rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);60	if (rc)61		goto err;62 63	rc = cifs_alloc_hash("sha512", &p->sha512);64	if (rc)65		goto err;66 67	return 0;68 69err:70	cifs_free_hash(&p->aes_cmac);71	cifs_free_hash(&p->hmacsha256);72	return rc;73}74 75 76static77int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)78{79	struct cifs_chan *chan;80	struct TCP_Server_Info *pserver;81	struct cifs_ses *ses = NULL;82	int i;83	int rc = 0;84	bool is_binding = false;85 86	spin_lock(&cifs_tcp_ses_lock);87 88	/* If server is a channel, select the primary channel */89	pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;90 91	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {92		if (ses->Suid == ses_id)93			goto found;94	}95	trace_smb3_ses_not_found(ses_id);96	cifs_server_dbg(FYI, "%s: Could not find session 0x%llx\n",97			__func__, ses_id);98	rc = -ENOENT;99	goto out;100 101found:102	spin_lock(&ses->ses_lock);103	spin_lock(&ses->chan_lock);104 105	is_binding = (cifs_chan_needs_reconnect(ses, server) &&106		      ses->ses_status == SES_GOOD);107	if (is_binding) {108		/*109		 * If we are in the process of binding a new channel110		 * to an existing session, use the master connection111		 * session key112		 */113		memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);114		spin_unlock(&ses->chan_lock);115		spin_unlock(&ses->ses_lock);116		goto out;117	}118 119	/*120	 * Otherwise, use the channel key.121	 */122 123	for (i = 0; i < ses->chan_count; i++) {124		chan = ses->chans + i;125		if (chan->server == server) {126			memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);127			spin_unlock(&ses->chan_lock);128			spin_unlock(&ses->ses_lock);129			goto out;130		}131	}132	spin_unlock(&ses->chan_lock);133	spin_unlock(&ses->ses_lock);134 135	cifs_dbg(VFS,136		 "%s: Could not find channel signing key for session 0x%llx\n",137		 __func__, ses_id);138	rc = -ENOENT;139 140out:141	spin_unlock(&cifs_tcp_ses_lock);142	return rc;143}144 145static struct cifs_ses *146smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)147{148	struct TCP_Server_Info *pserver;149	struct cifs_ses *ses;150 151	/* If server is a channel, select the primary channel */152	pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;153 154	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {155		if (ses->Suid != ses_id)156			continue;157 158		spin_lock(&ses->ses_lock);159		if (ses->ses_status == SES_EXITING) {160			spin_unlock(&ses->ses_lock);161			continue;162		}163		cifs_smb_ses_inc_refcount(ses);164		spin_unlock(&ses->ses_lock);165		return ses;166	}167 168	return NULL;169}170 171struct cifs_ses *172smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)173{174	struct cifs_ses *ses;175 176	spin_lock(&cifs_tcp_ses_lock);177	ses = smb2_find_smb_ses_unlocked(server, ses_id);178	spin_unlock(&cifs_tcp_ses_lock);179 180	return ses;181}182 183static struct cifs_tcon *184smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)185{186	struct cifs_tcon *tcon;187 188	list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {189		if (tcon->tid != tid)190			continue;191		++tcon->tc_count;192		trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,193				    netfs_trace_tcon_ref_get_find_sess_tcon);194		return tcon;195	}196 197	return NULL;198}199 200/*201 * Obtain tcon corresponding to the tid in the given202 * cifs_ses203 */204 205struct cifs_tcon *206smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32  tid)207{208	struct cifs_ses *ses;209	struct cifs_tcon *tcon;210 211	spin_lock(&cifs_tcp_ses_lock);212	ses = smb2_find_smb_ses_unlocked(server, ses_id);213	if (!ses) {214		spin_unlock(&cifs_tcp_ses_lock);215		return NULL;216	}217	tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);218	if (!tcon) {219		spin_unlock(&cifs_tcp_ses_lock);220		cifs_put_smb_ses(ses);221		return NULL;222	}223	spin_unlock(&cifs_tcp_ses_lock);224	/* tcon already has a ref to ses, so we don't need ses anymore */225	cifs_put_smb_ses(ses);226 227	return tcon;228}229 230int231smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,232			bool allocate_crypto)233{234	int rc;235	unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];236	unsigned char *sigptr = smb2_signature;237	struct kvec *iov = rqst->rq_iov;238	struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;239	struct cifs_ses *ses;240	struct shash_desc *shash = NULL;241	struct smb_rqst drqst;242 243	ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));244	if (unlikely(!ses)) {245		cifs_server_dbg(FYI, "%s: Could not find session\n", __func__);246		return -ENOENT;247	}248 249	memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);250	memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);251 252	if (allocate_crypto) {253		rc = cifs_alloc_hash("hmac(sha256)", &shash);254		if (rc) {255			cifs_server_dbg(VFS,256					"%s: sha256 alloc failed\n", __func__);257			goto out;258		}259	} else {260		shash = server->secmech.hmacsha256;261	}262 263	rc = crypto_shash_setkey(shash->tfm, ses->auth_key.response,264			SMB2_NTLMV2_SESSKEY_SIZE);265	if (rc) {266		cifs_server_dbg(VFS,267				"%s: Could not update with response\n",268				__func__);269		goto out;270	}271 272	rc = crypto_shash_init(shash);273	if (rc) {274		cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);275		goto out;276	}277 278	/*279	 * For SMB2+, __cifs_calc_signature() expects to sign only the actual280	 * data, that is, iov[0] should not contain a rfc1002 length.281	 *282	 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to283	 * __cifs_calc_signature().284	 */285	drqst = *rqst;286	if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {287		rc = crypto_shash_update(shash, iov[0].iov_base,288					 iov[0].iov_len);289		if (rc) {290			cifs_server_dbg(VFS,291					"%s: Could not update with payload\n",292					__func__);293			goto out;294		}295		drqst.rq_iov++;296		drqst.rq_nvec--;297	}298 299	rc = __cifs_calc_signature(&drqst, server, sigptr, shash);300	if (!rc)301		memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);302 303out:304	if (allocate_crypto)305		cifs_free_hash(&shash);306	if (ses)307		cifs_put_smb_ses(ses);308	return rc;309}310 311static int generate_key(struct cifs_ses *ses, struct kvec label,312			struct kvec context, __u8 *key, unsigned int key_size)313{314	unsigned char zero = 0x0;315	__u8 i[4] = {0, 0, 0, 1};316	__u8 L128[4] = {0, 0, 0, 128};317	__u8 L256[4] = {0, 0, 1, 0};318	int rc = 0;319	unsigned char prfhash[SMB2_HMACSHA256_SIZE];320	unsigned char *hashptr = prfhash;321	struct TCP_Server_Info *server = ses->server;322 323	memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);324	memset(key, 0x0, key_size);325 326	rc = smb3_crypto_shash_allocate(server);327	if (rc) {328		cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);329		goto smb3signkey_ret;330	}331 332	rc = crypto_shash_setkey(server->secmech.hmacsha256->tfm,333		ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);334	if (rc) {335		cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);336		goto smb3signkey_ret;337	}338 339	rc = crypto_shash_init(server->secmech.hmacsha256);340	if (rc) {341		cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);342		goto smb3signkey_ret;343	}344 345	rc = crypto_shash_update(server->secmech.hmacsha256, i, 4);346	if (rc) {347		cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);348		goto smb3signkey_ret;349	}350 351	rc = crypto_shash_update(server->secmech.hmacsha256, label.iov_base, label.iov_len);352	if (rc) {353		cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);354		goto smb3signkey_ret;355	}356 357	rc = crypto_shash_update(server->secmech.hmacsha256, &zero, 1);358	if (rc) {359		cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);360		goto smb3signkey_ret;361	}362 363	rc = crypto_shash_update(server->secmech.hmacsha256, context.iov_base, context.iov_len);364	if (rc) {365		cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);366		goto smb3signkey_ret;367	}368 369	if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||370		(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {371		rc = crypto_shash_update(server->secmech.hmacsha256, L256, 4);372	} else {373		rc = crypto_shash_update(server->secmech.hmacsha256, L128, 4);374	}375	if (rc) {376		cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);377		goto smb3signkey_ret;378	}379 380	rc = crypto_shash_final(server->secmech.hmacsha256, hashptr);381	if (rc) {382		cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);383		goto smb3signkey_ret;384	}385 386	memcpy(key, hashptr, key_size);387 388smb3signkey_ret:389	return rc;390}391 392struct derivation {393	struct kvec label;394	struct kvec context;395};396 397struct derivation_triplet {398	struct derivation signing;399	struct derivation encryption;400	struct derivation decryption;401};402 403static int404generate_smb3signingkey(struct cifs_ses *ses,405			struct TCP_Server_Info *server,406			const struct derivation_triplet *ptriplet)407{408	int rc;409	bool is_binding = false;410	int chan_index = 0;411 412	spin_lock(&ses->ses_lock);413	spin_lock(&ses->chan_lock);414	is_binding = (cifs_chan_needs_reconnect(ses, server) &&415		      ses->ses_status == SES_GOOD);416 417	chan_index = cifs_ses_get_chan_index(ses, server);418	if (chan_index == CIFS_INVAL_CHAN_INDEX) {419		spin_unlock(&ses->chan_lock);420		spin_unlock(&ses->ses_lock);421 422		return -EINVAL;423	}424 425	spin_unlock(&ses->chan_lock);426	spin_unlock(&ses->ses_lock);427 428	/*429	 * All channels use the same encryption/decryption keys but430	 * they have their own signing key.431	 *432	 * When we generate the keys, check if it is for a new channel433	 * (binding) in which case we only need to generate a signing434	 * key and store it in the channel as to not overwrite the435	 * master connection signing key stored in the session436	 */437 438	if (is_binding) {439		rc = generate_key(ses, ptriplet->signing.label,440				  ptriplet->signing.context,441				  ses->chans[chan_index].signkey,442				  SMB3_SIGN_KEY_SIZE);443		if (rc)444			return rc;445	} else {446		rc = generate_key(ses, ptriplet->signing.label,447				  ptriplet->signing.context,448				  ses->smb3signingkey,449				  SMB3_SIGN_KEY_SIZE);450		if (rc)451			return rc;452 453		/* safe to access primary channel, since it will never go away */454		spin_lock(&ses->chan_lock);455		memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey,456		       SMB3_SIGN_KEY_SIZE);457		spin_unlock(&ses->chan_lock);458 459		rc = generate_key(ses, ptriplet->encryption.label,460				  ptriplet->encryption.context,461				  ses->smb3encryptionkey,462				  SMB3_ENC_DEC_KEY_SIZE);463		if (rc)464			return rc;465		rc = generate_key(ses, ptriplet->decryption.label,466				  ptriplet->decryption.context,467				  ses->smb3decryptionkey,468				  SMB3_ENC_DEC_KEY_SIZE);469		if (rc)470			return rc;471	}472 473#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS474	cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);475	/*476	 * The session id is opaque in terms of endianness, so we can't477	 * print it as a long long. we dump it as we got it on the wire478	 */479	cifs_dbg(VFS, "Session Id    %*ph\n", (int)sizeof(ses->Suid),480			&ses->Suid);481	cifs_dbg(VFS, "Cipher type   %d\n", server->cipher_type);482	cifs_dbg(VFS, "Session Key   %*ph\n",483		 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);484	cifs_dbg(VFS, "Signing Key   %*ph\n",485		 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);486	if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||487		(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {488		cifs_dbg(VFS, "ServerIn Key  %*ph\n",489				SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);490		cifs_dbg(VFS, "ServerOut Key %*ph\n",491				SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);492	} else {493		cifs_dbg(VFS, "ServerIn Key  %*ph\n",494				SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);495		cifs_dbg(VFS, "ServerOut Key %*ph\n",496				SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);497	}498#endif499	return rc;500}501 502int503generate_smb30signingkey(struct cifs_ses *ses,504			 struct TCP_Server_Info *server)505 506{507	struct derivation_triplet triplet;508	struct derivation *d;509 510	d = &triplet.signing;511	d->label.iov_base = "SMB2AESCMAC";512	d->label.iov_len = 12;513	d->context.iov_base = "SmbSign";514	d->context.iov_len = 8;515 516	d = &triplet.encryption;517	d->label.iov_base = "SMB2AESCCM";518	d->label.iov_len = 11;519	d->context.iov_base = "ServerIn ";520	d->context.iov_len = 10;521 522	d = &triplet.decryption;523	d->label.iov_base = "SMB2AESCCM";524	d->label.iov_len = 11;525	d->context.iov_base = "ServerOut";526	d->context.iov_len = 10;527 528	return generate_smb3signingkey(ses, server, &triplet);529}530 531int532generate_smb311signingkey(struct cifs_ses *ses,533			  struct TCP_Server_Info *server)534 535{536	struct derivation_triplet triplet;537	struct derivation *d;538 539	d = &triplet.signing;540	d->label.iov_base = "SMBSigningKey";541	d->label.iov_len = 14;542	d->context.iov_base = ses->preauth_sha_hash;543	d->context.iov_len = 64;544 545	d = &triplet.encryption;546	d->label.iov_base = "SMBC2SCipherKey";547	d->label.iov_len = 16;548	d->context.iov_base = ses->preauth_sha_hash;549	d->context.iov_len = 64;550 551	d = &triplet.decryption;552	d->label.iov_base = "SMBS2CCipherKey";553	d->label.iov_len = 16;554	d->context.iov_base = ses->preauth_sha_hash;555	d->context.iov_len = 64;556 557	return generate_smb3signingkey(ses, server, &triplet);558}559 560int561smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,562			bool allocate_crypto)563{564	int rc;565	unsigned char smb3_signature[SMB2_CMACAES_SIZE];566	unsigned char *sigptr = smb3_signature;567	struct kvec *iov = rqst->rq_iov;568	struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;569	struct shash_desc *shash = NULL;570	struct smb_rqst drqst;571	u8 key[SMB3_SIGN_KEY_SIZE];572 573	rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);574	if (unlikely(rc)) {575		cifs_server_dbg(FYI, "%s: Could not get signing key\n", __func__);576		return rc;577	}578 579	if (allocate_crypto) {580		rc = cifs_alloc_hash("cmac(aes)", &shash);581		if (rc)582			return rc;583	} else {584		shash = server->secmech.aes_cmac;585	}586 587	memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);588	memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);589 590	rc = crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE);591	if (rc) {592		cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);593		goto out;594	}595 596	/*597	 * we already allocate aes_cmac when we init smb3 signing key,598	 * so unlike smb2 case we do not have to check here if secmech are599	 * initialized600	 */601	rc = crypto_shash_init(shash);602	if (rc) {603		cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);604		goto out;605	}606 607	/*608	 * For SMB2+, __cifs_calc_signature() expects to sign only the actual609	 * data, that is, iov[0] should not contain a rfc1002 length.610	 *611	 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to612	 * __cifs_calc_signature().613	 */614	drqst = *rqst;615	if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {616		rc = crypto_shash_update(shash, iov[0].iov_base,617					 iov[0].iov_len);618		if (rc) {619			cifs_server_dbg(VFS, "%s: Could not update with payload\n",620				 __func__);621			goto out;622		}623		drqst.rq_iov++;624		drqst.rq_nvec--;625	}626 627	rc = __cifs_calc_signature(&drqst, server, sigptr, shash);628	if (!rc)629		memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);630 631out:632	if (allocate_crypto)633		cifs_free_hash(&shash);634	return rc;635}636 637/* must be called with server->srv_mutex held */638static int639smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)640{641	int rc = 0;642	struct smb2_hdr *shdr;643	struct smb2_sess_setup_req *ssr;644	bool is_binding;645	bool is_signed;646 647	shdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;648	ssr = (struct smb2_sess_setup_req *)shdr;649 650	is_binding = shdr->Command == SMB2_SESSION_SETUP &&651		(ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING);652	is_signed = shdr->Flags & SMB2_FLAGS_SIGNED;653 654	if (!is_signed)655		return 0;656	spin_lock(&server->srv_lock);657	if (server->ops->need_neg &&658	    server->ops->need_neg(server)) {659		spin_unlock(&server->srv_lock);660		return 0;661	}662	spin_unlock(&server->srv_lock);663	if (!is_binding && !server->session_estab) {664		strscpy(shdr->Signature, "BSRSPYL");665		return 0;666	}667 668	rc = server->ops->calc_signature(rqst, server, false);669 670	return rc;671}672 673int674smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)675{676	unsigned int rc;677	char server_response_sig[SMB2_SIGNATURE_SIZE];678	struct smb2_hdr *shdr =679			(struct smb2_hdr *)rqst->rq_iov[0].iov_base;680 681	if ((shdr->Command == SMB2_NEGOTIATE) ||682	    (shdr->Command == SMB2_SESSION_SETUP) ||683	    (shdr->Command == SMB2_OPLOCK_BREAK) ||684	    server->ignore_signature ||685	    (!server->session_estab))686		return 0;687 688	/*689	 * BB what if signatures are supposed to be on for session but690	 * server does not send one? BB691	 */692 693	/* Do not need to verify session setups with signature "BSRSPYL " */694	if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)695		cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",696			 shdr->Command);697 698	/*699	 * Save off the original signature so we can modify the smb and check700	 * our calculated signature against what the server sent.701	 */702	memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);703 704	memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);705 706	rc = server->ops->calc_signature(rqst, server, true);707 708	if (rc)709		return rc;710 711	if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) {712		cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n",713			shdr->Command, shdr->MessageId);714		return -EACCES;715	} else716		return 0;717}718 719/*720 * Set message id for the request. Should be called after wait_for_free_request721 * and when srv_mutex is held.722 */723static inline void724smb2_seq_num_into_buf(struct TCP_Server_Info *server,725		      struct smb2_hdr *shdr)726{727	unsigned int i, num = le16_to_cpu(shdr->CreditCharge);728 729	shdr->MessageId = get_next_mid64(server);730	/* skip message numbers according to CreditCharge field */731	for (i = 1; i < num; i++)732		get_next_mid(server);733}734 735static struct mid_q_entry *736smb2_mid_entry_alloc(const struct smb2_hdr *shdr,737		     struct TCP_Server_Info *server)738{739	struct mid_q_entry *temp;740	unsigned int credits = le16_to_cpu(shdr->CreditCharge);741 742	if (server == NULL) {743		cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");744		return NULL;745	}746 747	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);748	memset(temp, 0, sizeof(struct mid_q_entry));749	kref_init(&temp->refcount);750	temp->mid = le64_to_cpu(shdr->MessageId);751	temp->credits = credits > 0 ? credits : 1;752	temp->pid = current->pid;753	temp->command = shdr->Command; /* Always LE */754	temp->when_alloc = jiffies;755	temp->server = server;756 757	/*758	 * The default is for the mid to be synchronous, so the759	 * default callback just wakes up the current task.760	 */761	get_task_struct(current);762	temp->creator = current;763	temp->callback = cifs_wake_up_task;764	temp->callback_data = current;765 766	atomic_inc(&mid_count);767	temp->mid_state = MID_REQUEST_ALLOCATED;768	trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId),769			     le64_to_cpu(shdr->SessionId),770			     le16_to_cpu(shdr->Command), temp->mid);771	return temp;772}773 774static int775smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server,776		   struct smb2_hdr *shdr, struct mid_q_entry **mid)777{778	spin_lock(&server->srv_lock);779	if (server->tcpStatus == CifsExiting) {780		spin_unlock(&server->srv_lock);781		return -ENOENT;782	}783 784	if (server->tcpStatus == CifsNeedReconnect) {785		spin_unlock(&server->srv_lock);786		cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");787		return -EAGAIN;788	}789 790	if (server->tcpStatus == CifsNeedNegotiate &&791	   shdr->Command != SMB2_NEGOTIATE) {792		spin_unlock(&server->srv_lock);793		return -EAGAIN;794	}795	spin_unlock(&server->srv_lock);796 797	spin_lock(&ses->ses_lock);798	if (ses->ses_status == SES_NEW) {799		if ((shdr->Command != SMB2_SESSION_SETUP) &&800		    (shdr->Command != SMB2_NEGOTIATE)) {801			spin_unlock(&ses->ses_lock);802			return -EAGAIN;803		}804		/* else ok - we are setting up session */805	}806 807	if (ses->ses_status == SES_EXITING) {808		if (shdr->Command != SMB2_LOGOFF) {809			spin_unlock(&ses->ses_lock);810			return -EAGAIN;811		}812		/* else ok - we are shutting down the session */813	}814	spin_unlock(&ses->ses_lock);815 816	*mid = smb2_mid_entry_alloc(shdr, server);817	if (*mid == NULL)818		return -ENOMEM;819	spin_lock(&server->mid_lock);820	list_add_tail(&(*mid)->qhead, &server->pending_mid_q);821	spin_unlock(&server->mid_lock);822 823	return 0;824}825 826int827smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,828		   bool log_error)829{830	unsigned int len = mid->resp_buf_size;831	struct kvec iov[1];832	struct smb_rqst rqst = { .rq_iov = iov,833				 .rq_nvec = 1 };834 835	iov[0].iov_base = (char *)mid->resp_buf;836	iov[0].iov_len = len;837 838	dump_smb(mid->resp_buf, min_t(u32, 80, len));839	/* convert the length into a more usable form */840	if (len > 24 && server->sign && !mid->decrypted) {841		int rc;842 843		rc = smb2_verify_signature(&rqst, server);844		if (rc)845			cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",846				 rc);847	}848 849	return map_smb2_to_linux_error(mid->resp_buf, log_error);850}851 852struct mid_q_entry *853smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,854		   struct smb_rqst *rqst)855{856	int rc;857	struct smb2_hdr *shdr =858			(struct smb2_hdr *)rqst->rq_iov[0].iov_base;859	struct mid_q_entry *mid;860 861	smb2_seq_num_into_buf(server, shdr);862 863	rc = smb2_get_mid_entry(ses, server, shdr, &mid);864	if (rc) {865		revert_current_mid_from_hdr(server, shdr);866		return ERR_PTR(rc);867	}868 869	rc = smb2_sign_rqst(rqst, server);870	if (rc) {871		revert_current_mid_from_hdr(server, shdr);872		delete_mid(mid);873		return ERR_PTR(rc);874	}875 876	return mid;877}878 879struct mid_q_entry *880smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)881{882	int rc;883	struct smb2_hdr *shdr =884			(struct smb2_hdr *)rqst->rq_iov[0].iov_base;885	struct mid_q_entry *mid;886 887	spin_lock(&server->srv_lock);888	if (server->tcpStatus == CifsNeedNegotiate &&889	   shdr->Command != SMB2_NEGOTIATE) {890		spin_unlock(&server->srv_lock);891		return ERR_PTR(-EAGAIN);892	}893	spin_unlock(&server->srv_lock);894 895	smb2_seq_num_into_buf(server, shdr);896 897	mid = smb2_mid_entry_alloc(shdr, server);898	if (mid == NULL) {899		revert_current_mid_from_hdr(server, shdr);900		return ERR_PTR(-ENOMEM);901	}902 903	rc = smb2_sign_rqst(rqst, server);904	if (rc) {905		revert_current_mid_from_hdr(server, shdr);906		release_mid(mid);907		return ERR_PTR(rc);908	}909 910	return mid;911}912 913int914smb3_crypto_aead_allocate(struct TCP_Server_Info *server)915{916	struct crypto_aead *tfm;917 918	if (!server->secmech.enc) {919		if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||920		    (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))921			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);922		else923			tfm = crypto_alloc_aead("ccm(aes)", 0, 0);924		if (IS_ERR(tfm)) {925			cifs_server_dbg(VFS, "%s: Failed alloc encrypt aead\n",926				 __func__);927			return PTR_ERR(tfm);928		}929		server->secmech.enc = tfm;930	}931 932	if (!server->secmech.dec) {933		if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||934		    (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))935			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);936		else937			tfm = crypto_alloc_aead("ccm(aes)", 0, 0);938		if (IS_ERR(tfm)) {939			crypto_free_aead(server->secmech.enc);940			server->secmech.enc = NULL;941			cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",942				 __func__);943			return PTR_ERR(tfm);944		}945		server->secmech.dec = tfm;946	}947 948	return 0;949}950