blob: f59b956f9d2502cdaea6bcb9e89319d24c4d4100 [file] [log] [blame]
Steve French929be902021-06-18 00:31:49 -05001// SPDX-License-Identifier: LGPL-2.1
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +04002/*
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +04003 *
4 * Copyright (C) International Business Machines Corp., 2002, 2011
5 * Etersoft, 2012
6 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Jeremy Allison (jra@samba.org) 2006
8 * Pavel Shilovsky (pshilovsky@samba.org) 2012
9 *
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +040010 */
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>
Jeff Laytonfb308a62012-09-18 16:20:35 -070020#include <linux/highmem.h>
Pavel Shilovsky026e93d2016-11-03 16:47:37 -070021#include <crypto/aead.h>
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +040022#include "smb2pdu.h"
23#include "cifsglob.h"
24#include "cifsproto.h"
25#include "smb2proto.h"
26#include "cifs_debug.h"
27#include "smb2status.h"
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -070028#include "smb2glob.h"
29
Steve French95dc8dd2013-07-04 10:35:21 -050030static int
Steve French95dc8dd2013-07-04 10:35:21 -050031smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
32{
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010033 struct cifs_secmech *p = &server->secmech;
Steve French95dc8dd2013-07-04 10:35:21 -050034 int rc;
35
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010036 rc = cifs_alloc_hash("hmac(sha256)",
37 &p->hmacsha256,
38 &p->sdeschmacsha256);
Steve French95dc8dd2013-07-04 10:35:21 -050039 if (rc)
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010040 goto err;
Steve French95dc8dd2013-07-04 10:35:21 -050041
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010042 rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
43 if (rc)
44 goto err;
Steve French95dc8dd2013-07-04 10:35:21 -050045
46 return 0;
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010047err:
48 cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
49 return rc;
Steve French95dc8dd2013-07-04 10:35:21 -050050}
51
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +010052int
53smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
54{
55 struct cifs_secmech *p = &server->secmech;
56 int rc = 0;
57
58 rc = cifs_alloc_hash("hmac(sha256)",
59 &p->hmacsha256,
60 &p->sdeschmacsha256);
61 if (rc)
62 return rc;
63
64 rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
65 if (rc)
66 goto err;
67
68 rc = cifs_alloc_hash("sha512", &p->sha512, &p->sdescsha512);
69 if (rc)
70 goto err;
71
72 return 0;
73
74err:
75 cifs_free_hash(&p->cmacaes, &p->sdesccmacaes);
76 cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
77 return rc;
78}
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +010079
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020080
81static
82int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
83{
84 struct cifs_chan *chan;
85 struct cifs_ses *ses = NULL;
Aurelien Aptelcc95b672020-02-06 13:49:26 +010086 struct TCP_Server_Info *it = NULL;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020087 int i;
88 int rc = 0;
89
90 spin_lock(&cifs_tcp_ses_lock);
91
Aurelien Aptelcc95b672020-02-06 13:49:26 +010092 list_for_each_entry(it, &cifs_tcp_ses_list, tcp_ses_list) {
93 list_for_each_entry(ses, &it->smb_ses_list, smb_ses_list) {
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020094 if (ses->Suid == ses_id)
95 goto found;
96 }
97 }
98 cifs_server_dbg(VFS, "%s: Could not find session 0x%llx\n",
99 __func__, ses_id);
100 rc = -ENOENT;
101 goto out;
102
103found:
104 if (ses->binding) {
105 /*
106 * If we are in the process of binding a new channel
107 * to an existing session, use the master connection
108 * session key
109 */
110 memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
111 goto out;
112 }
113
114 /*
115 * Otherwise, use the channel key.
116 */
117
118 for (i = 0; i < ses->chan_count; i++) {
119 chan = ses->chans + i;
120 if (chan->server == server) {
121 memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
122 goto out;
123 }
124 }
125
126 cifs_dbg(VFS,
127 "%s: Could not find channel signing key for session 0x%llx\n",
128 __func__, ses_id);
129 rc = -ENOENT;
130
131out:
132 spin_unlock(&cifs_tcp_ses_lock);
133 return rc;
134}
135
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800136static struct cifs_ses *
137smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
138{
139 struct cifs_ses *ses;
140
141 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
142 if (ses->Suid != ses_id)
143 continue;
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000144 ++ses->ses_count;
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800145 return ses;
146 }
147
148 return NULL;
149}
150
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700151struct cifs_ses *
152smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500153{
154 struct cifs_ses *ses;
155
156 spin_lock(&cifs_tcp_ses_lock);
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800157 ses = smb2_find_smb_ses_unlocked(server, ses_id);
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500158 spin_unlock(&cifs_tcp_ses_lock);
159
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800160 return ses;
161}
162
163static struct cifs_tcon *
164smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
165{
166 struct cifs_tcon *tcon;
167
168 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
169 if (tcon->tid != tid)
170 continue;
171 ++tcon->tc_count;
172 return tcon;
173 }
174
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500175 return NULL;
176}
177
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800178/*
179 * Obtain tcon corresponding to the tid in the given
180 * cifs_ses
181 */
182
183struct cifs_tcon *
184smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
185{
186 struct cifs_ses *ses;
187 struct cifs_tcon *tcon;
188
189 spin_lock(&cifs_tcp_ses_lock);
190 ses = smb2_find_smb_ses_unlocked(server, ses_id);
191 if (!ses) {
192 spin_unlock(&cifs_tcp_ses_lock);
193 return NULL;
194 }
195 tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000196 if (!tcon) {
197 cifs_put_smb_ses(ses);
198 spin_unlock(&cifs_tcp_ses_lock);
199 return NULL;
200 }
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800201 spin_unlock(&cifs_tcp_ses_lock);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000202 /* tcon already has a ref to ses, so we don't need ses anymore */
203 cifs_put_smb_ses(ses);
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800204
205 return tcon;
206}
207
Steve French38107d42012-12-08 22:08:06 -0600208int
Long Lieda1c542020-03-31 16:21:43 -0700209smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
210 bool allocate_crypto)
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700211{
Al Viro16c568e2015-11-12 22:46:49 -0500212 int rc;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700213 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
214 unsigned char *sigptr = smb2_signature;
Jeff Layton0b688cf2012-09-18 16:20:34 -0700215 struct kvec *iov = rqst->rq_iov;
Ronnie Sahlbergc713c872018-06-12 08:00:58 +1000216 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500217 struct cifs_ses *ses;
Aurelien Aptela5c62f42018-08-02 16:39:52 +0200218 struct shash_desc *shash;
Long Lieda1c542020-03-31 16:21:43 -0700219 struct crypto_shash *hash;
220 struct sdesc *sdesc = NULL;
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300221 struct smb_rqst drqst;
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500222
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700223 ses = smb2_find_smb_ses(server, shdr->SessionId);
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500224 if (!ses) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000225 cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500226 return 0;
227 }
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700228
229 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700230 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700231
Long Lieda1c542020-03-31 16:21:43 -0700232 if (allocate_crypto) {
233 rc = cifs_alloc_hash("hmac(sha256)", &hash, &sdesc);
234 if (rc) {
235 cifs_server_dbg(VFS,
236 "%s: sha256 alloc failed\n", __func__);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000237 goto out;
Long Lieda1c542020-03-31 16:21:43 -0700238 }
239 shash = &sdesc->shash;
240 } else {
241 hash = server->secmech.hmacsha256;
242 shash = &server->secmech.sdeschmacsha256->shash;
Steve French95dc8dd2013-07-04 10:35:21 -0500243 }
244
Long Lieda1c542020-03-31 16:21:43 -0700245 rc = crypto_shash_setkey(hash, ses->auth_key.response,
246 SMB2_NTLMV2_SESSKEY_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700247 if (rc) {
Long Lieda1c542020-03-31 16:21:43 -0700248 cifs_server_dbg(VFS,
249 "%s: Could not update with response\n",
250 __func__);
251 goto out;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700252 }
253
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300254 rc = crypto_shash_init(shash);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700255 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000256 cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
Long Lieda1c542020-03-31 16:21:43 -0700257 goto out;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700258 }
259
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300260 /*
261 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
262 * data, that is, iov[0] should not contain a rfc1002 length.
263 *
264 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
265 * __cifs_calc_signature().
266 */
267 drqst = *rqst;
268 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
269 rc = crypto_shash_update(shash, iov[0].iov_base,
270 iov[0].iov_len);
271 if (rc) {
Long Lieda1c542020-03-31 16:21:43 -0700272 cifs_server_dbg(VFS,
273 "%s: Could not update with payload\n",
274 __func__);
275 goto out;
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300276 }
277 drqst.rq_iov++;
278 drqst.rq_nvec--;
279 }
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700280
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300281 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
Al Viro16c568e2015-11-12 22:46:49 -0500282 if (!rc)
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700283 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700284
Long Lieda1c542020-03-31 16:21:43 -0700285out:
286 if (allocate_crypto)
287 cifs_free_hash(&hash, &sdesc);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000288 if (ses)
289 cifs_put_smb_ses(ses);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700290 return rc;
291}
292
Steve French373512e2015-12-18 13:05:30 -0600293static int generate_key(struct cifs_ses *ses, struct kvec label,
294 struct kvec context, __u8 *key, unsigned int key_size)
Steve French429b46f2013-06-26 23:45:05 -0500295{
296 unsigned char zero = 0x0;
297 __u8 i[4] = {0, 0, 0, 1};
Shyam Prasad N45a45462021-03-25 12:34:54 +0000298 __u8 L128[4] = {0, 0, 0, 128};
299 __u8 L256[4] = {0, 0, 1, 0};
Steve French429b46f2013-06-26 23:45:05 -0500300 int rc = 0;
301 unsigned char prfhash[SMB2_HMACSHA256_SIZE];
302 unsigned char *hashptr = prfhash;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000303 struct TCP_Server_Info *server = ses->server;
Steve French429b46f2013-06-26 23:45:05 -0500304
305 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
Steve French373512e2015-12-18 13:05:30 -0600306 memset(key, 0x0, key_size);
Steve French429b46f2013-06-26 23:45:05 -0500307
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000308 rc = smb3_crypto_shash_allocate(server);
Steve French95dc8dd2013-07-04 10:35:21 -0500309 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000310 cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
Steve French95dc8dd2013-07-04 10:35:21 -0500311 goto smb3signkey_ret;
312 }
313
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000314 rc = crypto_shash_setkey(server->secmech.hmacsha256,
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500315 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500316 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000317 cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500318 goto smb3signkey_ret;
319 }
320
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000321 rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
Steve French429b46f2013-06-26 23:45:05 -0500322 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000323 cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500324 goto smb3signkey_ret;
325 }
326
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000327 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French429b46f2013-06-26 23:45:05 -0500328 i, 4);
329 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000330 cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500331 goto smb3signkey_ret;
332 }
333
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000334 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French373512e2015-12-18 13:05:30 -0600335 label.iov_base, label.iov_len);
Steve French429b46f2013-06-26 23:45:05 -0500336 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000337 cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500338 goto smb3signkey_ret;
339 }
340
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000341 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French429b46f2013-06-26 23:45:05 -0500342 &zero, 1);
343 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000344 cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500345 goto smb3signkey_ret;
346 }
347
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000348 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French373512e2015-12-18 13:05:30 -0600349 context.iov_base, context.iov_len);
Steve French429b46f2013-06-26 23:45:05 -0500350 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000351 cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500352 goto smb3signkey_ret;
353 }
354
Shyam Prasad N45a45462021-03-25 12:34:54 +0000355 if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
356 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
357 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
358 L256, 4);
359 } else {
360 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
361 L128, 4);
362 }
Steve French429b46f2013-06-26 23:45:05 -0500363 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000364 cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500365 goto smb3signkey_ret;
366 }
367
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000368 rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
Steve French429b46f2013-06-26 23:45:05 -0500369 hashptr);
370 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000371 cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500372 goto smb3signkey_ret;
373 }
374
Steve French373512e2015-12-18 13:05:30 -0600375 memcpy(key, hashptr, key_size);
Steve French429b46f2013-06-26 23:45:05 -0500376
377smb3signkey_ret:
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500378 return rc;
Steve French429b46f2013-06-26 23:45:05 -0500379}
380
Steve French373512e2015-12-18 13:05:30 -0600381struct derivation {
382 struct kvec label;
383 struct kvec context;
384};
385
386struct derivation_triplet {
387 struct derivation signing;
388 struct derivation encryption;
389 struct derivation decryption;
390};
391
392static int
393generate_smb3signingkey(struct cifs_ses *ses,
394 const struct derivation_triplet *ptriplet)
395{
396 int rc;
Shyam Prasad N45a45462021-03-25 12:34:54 +0000397#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
398 struct TCP_Server_Info *server = ses->server;
399#endif
Steve French373512e2015-12-18 13:05:30 -0600400
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200401 /*
402 * All channels use the same encryption/decryption keys but
403 * they have their own signing key.
404 *
405 * When we generate the keys, check if it is for a new channel
406 * (binding) in which case we only need to generate a signing
407 * key and store it in the channel as to not overwrite the
408 * master connection signing key stored in the session
409 */
Steve French373512e2015-12-18 13:05:30 -0600410
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200411 if (ses->binding) {
412 rc = generate_key(ses, ptriplet->signing.label,
413 ptriplet->signing.context,
414 cifs_ses_binding_channel(ses)->signkey,
415 SMB3_SIGN_KEY_SIZE);
416 if (rc)
417 return rc;
418 } else {
419 rc = generate_key(ses, ptriplet->signing.label,
420 ptriplet->signing.context,
421 ses->smb3signingkey,
422 SMB3_SIGN_KEY_SIZE);
423 if (rc)
424 return rc;
Paulo Alcantara (SUSE)ff6b6f32019-11-22 12:30:57 -0300425
426 memcpy(ses->chans[0].signkey, ses->smb3signingkey,
427 SMB3_SIGN_KEY_SIZE);
428
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200429 rc = generate_key(ses, ptriplet->encryption.label,
430 ptriplet->encryption.context,
431 ses->smb3encryptionkey,
Shyam Prasad N45a45462021-03-25 12:34:54 +0000432 SMB3_ENC_DEC_KEY_SIZE);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200433 rc = generate_key(ses, ptriplet->decryption.label,
434 ptriplet->decryption.context,
435 ses->smb3decryptionkey,
Shyam Prasad N45a45462021-03-25 12:34:54 +0000436 SMB3_ENC_DEC_KEY_SIZE);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200437 if (rc)
438 return rc;
439 }
Aurélien Apteld38de3c62017-05-24 16:13:25 +0200440
441 if (rc)
442 return rc;
443
444#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
445 cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);
446 /*
447 * The session id is opaque in terms of endianness, so we can't
448 * print it as a long long. we dump it as we got it on the wire
449 */
450 cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
451 &ses->Suid);
Shyam Prasad N45a45462021-03-25 12:34:54 +0000452 cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);
Aurélien Apteld38de3c62017-05-24 16:13:25 +0200453 cifs_dbg(VFS, "Session Key %*ph\n",
454 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
455 cifs_dbg(VFS, "Signing Key %*ph\n",
456 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
Shyam Prasad N45a45462021-03-25 12:34:54 +0000457 if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
458 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
459 cifs_dbg(VFS, "ServerIn Key %*ph\n",
460 SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);
461 cifs_dbg(VFS, "ServerOut Key %*ph\n",
462 SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);
463 } else {
464 cifs_dbg(VFS, "ServerIn Key %*ph\n",
465 SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);
466 cifs_dbg(VFS, "ServerOut Key %*ph\n",
467 SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);
468 }
Aurélien Apteld38de3c62017-05-24 16:13:25 +0200469#endif
470 return rc;
Steve French373512e2015-12-18 13:05:30 -0600471}
472
473int
474generate_smb30signingkey(struct cifs_ses *ses)
475
476{
477 struct derivation_triplet triplet;
478 struct derivation *d;
479
480 d = &triplet.signing;
481 d->label.iov_base = "SMB2AESCMAC";
482 d->label.iov_len = 12;
483 d->context.iov_base = "SmbSign";
484 d->context.iov_len = 8;
485
486 d = &triplet.encryption;
487 d->label.iov_base = "SMB2AESCCM";
488 d->label.iov_len = 11;
489 d->context.iov_base = "ServerIn ";
490 d->context.iov_len = 10;
491
492 d = &triplet.decryption;
493 d->label.iov_base = "SMB2AESCCM";
494 d->label.iov_len = 11;
495 d->context.iov_base = "ServerOut";
496 d->context.iov_len = 10;
497
498 return generate_smb3signingkey(ses, &triplet);
499}
500
501int
502generate_smb311signingkey(struct cifs_ses *ses)
503
504{
505 struct derivation_triplet triplet;
506 struct derivation *d;
507
508 d = &triplet.signing;
Steve French06e22902017-09-25 20:11:58 -0500509 d->label.iov_base = "SMBSigningKey";
510 d->label.iov_len = 14;
511 d->context.iov_base = ses->preauth_sha_hash;
512 d->context.iov_len = 64;
Steve French373512e2015-12-18 13:05:30 -0600513
514 d = &triplet.encryption;
Steve French06e22902017-09-25 20:11:58 -0500515 d->label.iov_base = "SMBC2SCipherKey";
516 d->label.iov_len = 16;
517 d->context.iov_base = ses->preauth_sha_hash;
518 d->context.iov_len = 64;
Steve French373512e2015-12-18 13:05:30 -0600519
520 d = &triplet.decryption;
Steve French06e22902017-09-25 20:11:58 -0500521 d->label.iov_base = "SMBS2CCipherKey";
522 d->label.iov_len = 16;
523 d->context.iov_base = ses->preauth_sha_hash;
524 d->context.iov_len = 64;
Steve French373512e2015-12-18 13:05:30 -0600525
526 return generate_smb3signingkey(ses, &triplet);
527}
528
Steve French429b46f2013-06-26 23:45:05 -0500529int
Long Lieda1c542020-03-31 16:21:43 -0700530smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
531 bool allocate_crypto)
Steve French38107d42012-12-08 22:08:06 -0600532{
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300533 int rc;
Steve French429b46f2013-06-26 23:45:05 -0500534 unsigned char smb3_signature[SMB2_CMACAES_SIZE];
535 unsigned char *sigptr = smb3_signature;
536 struct kvec *iov = rqst->rq_iov;
Ronnie Sahlbergc713c872018-06-12 08:00:58 +1000537 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
Long Lieda1c542020-03-31 16:21:43 -0700538 struct shash_desc *shash;
539 struct crypto_shash *hash;
540 struct sdesc *sdesc = NULL;
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300541 struct smb_rqst drqst;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200542 u8 key[SMB3_SIGN_KEY_SIZE];
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500543
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200544 rc = smb2_get_sign_key(shdr->SessionId, server, key);
545 if (rc)
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500546 return 0;
Steve French429b46f2013-06-26 23:45:05 -0500547
Long Lieda1c542020-03-31 16:21:43 -0700548 if (allocate_crypto) {
549 rc = cifs_alloc_hash("cmac(aes)", &hash, &sdesc);
550 if (rc)
551 return rc;
552
553 shash = &sdesc->shash;
554 } else {
555 hash = server->secmech.cmacaes;
556 shash = &server->secmech.sdesccmacaes->shash;
557 }
558
Steve French429b46f2013-06-26 23:45:05 -0500559 memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700560 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500561
Long Lieda1c542020-03-31 16:21:43 -0700562 rc = crypto_shash_setkey(hash, key, SMB2_CMACAES_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500563 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000564 cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
Long Lieda1c542020-03-31 16:21:43 -0700565 goto out;
Steve French429b46f2013-06-26 23:45:05 -0500566 }
567
Steve French95dc8dd2013-07-04 10:35:21 -0500568 /*
569 * we already allocate sdesccmacaes when we init smb3 signing key,
570 * so unlike smb2 case we do not have to check here if secmech are
571 * initialized
572 */
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300573 rc = crypto_shash_init(shash);
Steve French429b46f2013-06-26 23:45:05 -0500574 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000575 cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
Long Lieda1c542020-03-31 16:21:43 -0700576 goto out;
Steve French429b46f2013-06-26 23:45:05 -0500577 }
Aurelien Aptel82fb82b2018-02-16 19:19:27 +0100578
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300579 /*
580 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
581 * data, that is, iov[0] should not contain a rfc1002 length.
582 *
583 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
584 * __cifs_calc_signature().
585 */
586 drqst = *rqst;
587 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
588 rc = crypto_shash_update(shash, iov[0].iov_base,
589 iov[0].iov_len);
590 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000591 cifs_server_dbg(VFS, "%s: Could not update with payload\n",
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300592 __func__);
Long Lieda1c542020-03-31 16:21:43 -0700593 goto out;
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300594 }
595 drqst.rq_iov++;
596 drqst.rq_nvec--;
597 }
Steve French429b46f2013-06-26 23:45:05 -0500598
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300599 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
Al Viro16c568e2015-11-12 22:46:49 -0500600 if (!rc)
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700601 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500602
Long Lieda1c542020-03-31 16:21:43 -0700603out:
604 if (allocate_crypto)
605 cifs_free_hash(&hash, &sdesc);
Steve French429b46f2013-06-26 23:45:05 -0500606 return rc;
Steve French38107d42012-12-08 22:08:06 -0600607}
608
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700609/* must be called with server->srv_mutex held */
610static int
Jeff Layton0b688cf2012-09-18 16:20:34 -0700611smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700612{
613 int rc = 0;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200614 struct smb2_sync_hdr *shdr;
615 struct smb2_sess_setup_req *ssr;
616 bool is_binding;
617 bool is_signed;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700618
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200619 shdr = (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
620 ssr = (struct smb2_sess_setup_req *)shdr;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700621
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200622 is_binding = shdr->Command == SMB2_SESSION_SETUP &&
623 (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING);
624 is_signed = shdr->Flags & SMB2_FLAGS_SIGNED;
625
626 if (!is_signed)
627 return 0;
628 if (server->tcpStatus == CifsNeedNegotiate)
629 return 0;
630 if (!is_binding && !server->session_estab) {
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700631 strncpy(shdr->Signature, "BSRSPYL", 8);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200632 return 0;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700633 }
634
Long Lieda1c542020-03-31 16:21:43 -0700635 rc = server->ops->calc_signature(rqst, server, false);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700636
637 return rc;
638}
639
640int
Jeff Layton0b688cf2012-09-18 16:20:34 -0700641smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700642{
643 unsigned int rc;
Steve Frenchedad7342020-03-27 12:47:41 -0500644 char server_response_sig[SMB2_SIGNATURE_SIZE];
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800645 struct smb2_sync_hdr *shdr =
Ronnie Sahlberg977b6172018-06-01 10:53:02 +1000646 (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700647
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700648 if ((shdr->Command == SMB2_NEGOTIATE) ||
649 (shdr->Command == SMB2_SESSION_SETUP) ||
650 (shdr->Command == SMB2_OPLOCK_BREAK) ||
Steve French4f5c10f2019-09-03 21:18:49 -0500651 server->ignore_signature ||
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700652 (!server->session_estab))
653 return 0;
654
655 /*
656 * BB what if signatures are supposed to be on for session but
657 * server does not send one? BB
658 */
659
660 /* Do not need to verify session setups with signature "BSRSPYL " */
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700661 if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
Joe Perchesf96637b2013-05-04 22:12:25 -0500662 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700663 shdr->Command);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700664
665 /*
666 * Save off the origiginal signature so we can modify the smb and check
667 * our calculated signature against what the server sent.
668 */
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700669 memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700670
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700671 memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700672
Long Lieda1c542020-03-31 16:21:43 -0700673 rc = server->ops->calc_signature(rqst, server, true);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700674
675 if (rc)
676 return rc;
677
Steve Frenchf460c502020-03-29 16:44:43 -0500678 if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) {
Steve French9692ea92020-04-15 01:12:34 -0500679 cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n",
680 shdr->Command, shdr->MessageId);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700681 return -EACCES;
Steve Frenchf460c502020-03-29 16:44:43 -0500682 } else
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700683 return 0;
684}
685
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400686/*
687 * Set message id for the request. Should be called after wait_for_free_request
688 * and when srv_mutex is held.
689 */
690static inline void
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700691smb2_seq_num_into_buf(struct TCP_Server_Info *server,
692 struct smb2_sync_hdr *shdr)
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400693{
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700694 unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +0400695
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700696 shdr->MessageId = get_next_mid64(server);
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +0400697 /* skip message numbers according to CreditCharge field */
698 for (i = 1; i < num; i++)
699 get_next_mid(server);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400700}
701
702static struct mid_q_entry *
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700703smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400704 struct TCP_Server_Info *server)
705{
706 struct mid_q_entry *temp;
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800707 unsigned int credits = le16_to_cpu(shdr->CreditCharge);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400708
709 if (server == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500710 cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400711 return NULL;
712 }
713
714 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
NeilBrowna6f74e82017-04-10 12:08:53 +1000715 memset(temp, 0, sizeof(struct mid_q_entry));
Lars Persson696e4202018-06-25 14:05:25 +0200716 kref_init(&temp->refcount);
NeilBrowna6f74e82017-04-10 12:08:53 +1000717 temp->mid = le64_to_cpu(shdr->MessageId);
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800718 temp->credits = credits > 0 ? credits : 1;
NeilBrowna6f74e82017-04-10 12:08:53 +1000719 temp->pid = current->pid;
720 temp->command = shdr->Command; /* Always LE */
721 temp->when_alloc = jiffies;
722 temp->server = server;
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400723
NeilBrowna6f74e82017-04-10 12:08:53 +1000724 /*
725 * The default is for the mid to be synchronous, so the
726 * default callback just wakes up the current task.
727 */
Vincent Whitchurchf1f27ad2020-01-23 17:09:06 +0100728 get_task_struct(current);
729 temp->creator = current;
NeilBrowna6f74e82017-04-10 12:08:53 +1000730 temp->callback = cifs_wake_up_task;
731 temp->callback_data = current;
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400732
733 atomic_inc(&midCount);
734 temp->mid_state = MID_REQUEST_ALLOCATED;
Steve French53a3e0d2019-02-26 21:26:20 -0600735 trace_smb3_cmd_enter(shdr->TreeId, shdr->SessionId,
736 le16_to_cpu(shdr->Command), temp->mid);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400737 return temp;
738}
739
740static int
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200741smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server,
742 struct smb2_sync_hdr *shdr, struct mid_q_entry **mid)
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400743{
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200744 if (server->tcpStatus == CifsExiting)
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400745 return -ENOENT;
746
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200747 if (server->tcpStatus == CifsNeedReconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500748 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400749 return -EAGAIN;
750 }
751
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200752 if (server->tcpStatus == CifsNeedNegotiate &&
Pavel Shilovsky2084ed52019-03-05 15:51:55 -0800753 shdr->Command != SMB2_NEGOTIATE)
754 return -EAGAIN;
755
Shirish Pargaonkar7f485582013-10-12 10:06:03 -0500756 if (ses->status == CifsNew) {
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700757 if ((shdr->Command != SMB2_SESSION_SETUP) &&
758 (shdr->Command != SMB2_NEGOTIATE))
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400759 return -EAGAIN;
760 /* else ok - we are setting up session */
761 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -0500762
763 if (ses->status == CifsExiting) {
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700764 if (shdr->Command != SMB2_LOGOFF)
Shirish Pargaonkar7f485582013-10-12 10:06:03 -0500765 return -EAGAIN;
766 /* else ok - we are shutting down the session */
767 }
768
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200769 *mid = smb2_mid_entry_alloc(shdr, server);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400770 if (*mid == NULL)
771 return -ENOMEM;
772 spin_lock(&GlobalMid_Lock);
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200773 list_add_tail(&(*mid)->qhead, &server->pending_mid_q);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400774 spin_unlock(&GlobalMid_Lock);
Steve French53a3e0d2019-02-26 21:26:20 -0600775
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400776 return 0;
777}
778
779int
780smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
781 bool log_error)
782{
Ronnie Sahlberge19b2bc2018-04-09 18:06:28 +1000783 unsigned int len = mid->resp_buf_size;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +1000784 struct kvec iov[1];
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800785 struct smb_rqst rqst = { .rq_iov = iov,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +1000786 .rq_nvec = 1 };
Jeff Layton0b688cf2012-09-18 16:20:34 -0700787
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800788 iov[0].iov_base = (char *)mid->resp_buf;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +1000789 iov[0].iov_len = len;
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400790
791 dump_smb(mid->resp_buf, min_t(u32, 80, len));
792 /* convert the length into a more usable form */
Pavel Shilovsky4326ed22016-11-17 15:24:46 -0800793 if (len > 24 && server->sign && !mid->decrypted) {
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700794 int rc;
795
Jeff Layton0b688cf2012-09-18 16:20:34 -0700796 rc = smb2_verify_signature(&rqst, server);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700797 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000798 cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -0500799 rc);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700800 }
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400801
802 return map_smb2_to_linux_error(mid->resp_buf, log_error);
803}
804
Jeff Laytonfec344e2012-09-18 16:20:35 -0700805struct mid_q_entry *
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200806smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,
807 struct smb_rqst *rqst)
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400808{
809 int rc;
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800810 struct smb2_sync_hdr *shdr =
Ronnie Sahlbergc713c872018-06-12 08:00:58 +1000811 (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400812 struct mid_q_entry *mid;
813
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200814 smb2_seq_num_into_buf(server, shdr);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400815
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200816 rc = smb2_get_mid_entry(ses, server, shdr, &mid);
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800817 if (rc) {
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200818 revert_current_mid_from_hdr(server, shdr);
Jeff Laytonfec344e2012-09-18 16:20:35 -0700819 return ERR_PTR(rc);
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800820 }
821
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200822 rc = smb2_sign_rqst(rqst, server);
Jeff Laytonfec344e2012-09-18 16:20:35 -0700823 if (rc) {
Aurelien Aptelf780bd32019-09-20 06:08:34 +0200824 revert_current_mid_from_hdr(server, shdr);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700825 cifs_delete_mid(mid);
Jeff Laytonfec344e2012-09-18 16:20:35 -0700826 return ERR_PTR(rc);
827 }
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800828
Jeff Laytonfec344e2012-09-18 16:20:35 -0700829 return mid;
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400830}
831
Jeff Laytonfec344e2012-09-18 16:20:35 -0700832struct mid_q_entry *
833smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +0400834{
Jeff Laytonfec344e2012-09-18 16:20:35 -0700835 int rc;
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800836 struct smb2_sync_hdr *shdr =
Ronnie Sahlbergc713c872018-06-12 08:00:58 +1000837 (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +0400838 struct mid_q_entry *mid;
839
Pavel Shilovsky2084ed52019-03-05 15:51:55 -0800840 if (server->tcpStatus == CifsNeedNegotiate &&
841 shdr->Command != SMB2_NEGOTIATE)
842 return ERR_PTR(-EAGAIN);
843
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700844 smb2_seq_num_into_buf(server, shdr);
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +0400845
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700846 mid = smb2_mid_entry_alloc(shdr, server);
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800847 if (mid == NULL) {
848 revert_current_mid_from_hdr(server, shdr);
Jeff Laytonfec344e2012-09-18 16:20:35 -0700849 return ERR_PTR(-ENOMEM);
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800850 }
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +0400851
Jeff Laytonfec344e2012-09-18 16:20:35 -0700852 rc = smb2_sign_rqst(rqst, server);
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +0400853 if (rc) {
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800854 revert_current_mid_from_hdr(server, shdr);
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +0400855 DeleteMidQEntry(mid);
Jeff Laytonfec344e2012-09-18 16:20:35 -0700856 return ERR_PTR(rc);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700857 }
858
Jeff Laytonfec344e2012-09-18 16:20:35 -0700859 return mid;
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +0400860}
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700861
862int
863smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
864{
865 struct crypto_aead *tfm;
866
867 if (!server->secmech.ccmaesencrypt) {
Steve French63ca5652020-10-15 23:41:40 -0500868 if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
869 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
Steve French2b2f7542019-06-07 15:16:10 -0500870 tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
871 else
872 tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700873 if (IS_ERR(tfm)) {
Steve French63ca5652020-10-15 23:41:40 -0500874 cifs_server_dbg(VFS, "%s: Failed alloc encrypt aead\n",
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700875 __func__);
876 return PTR_ERR(tfm);
877 }
878 server->secmech.ccmaesencrypt = tfm;
879 }
880
881 if (!server->secmech.ccmaesdecrypt) {
Steve French63ca5652020-10-15 23:41:40 -0500882 if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
883 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
Steve French2b2f7542019-06-07 15:16:10 -0500884 tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
885 else
886 tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700887 if (IS_ERR(tfm)) {
888 crypto_free_aead(server->secmech.ccmaesencrypt);
889 server->secmech.ccmaesencrypt = NULL;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000890 cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700891 __func__);
892 return PTR_ERR(tfm);
893 }
894 server->secmech.ccmaesdecrypt = tfm;
895 }
896
897 return 0;
898}