blob: 2bf047b390a98bcc702ac6a6f1c26948b9499caa [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 "cifsglob.h"
23#include "cifsproto.h"
24#include "smb2proto.h"
25#include "cifs_debug.h"
26#include "smb2status.h"
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -070027#include "smb2glob.h"
28
Steve French95dc8dd2013-07-04 10:35:21 -050029static int
Steve French95dc8dd2013-07-04 10:35:21 -050030smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
31{
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010032 struct cifs_secmech *p = &server->secmech;
Steve French95dc8dd2013-07-04 10:35:21 -050033 int rc;
34
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010035 rc = cifs_alloc_hash("hmac(sha256)",
36 &p->hmacsha256,
37 &p->sdeschmacsha256);
Steve French95dc8dd2013-07-04 10:35:21 -050038 if (rc)
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010039 goto err;
Steve French95dc8dd2013-07-04 10:35:21 -050040
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010041 rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
42 if (rc)
43 goto err;
Steve French95dc8dd2013-07-04 10:35:21 -050044
45 return 0;
Aurelien Aptel82fb82b2018-02-16 19:19:27 +010046err:
47 cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
48 return rc;
Steve French95dc8dd2013-07-04 10:35:21 -050049}
50
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +010051int
52smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
53{
54 struct cifs_secmech *p = &server->secmech;
55 int rc = 0;
56
57 rc = cifs_alloc_hash("hmac(sha256)",
58 &p->hmacsha256,
59 &p->sdeschmacsha256);
60 if (rc)
61 return rc;
62
63 rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
64 if (rc)
65 goto err;
66
67 rc = cifs_alloc_hash("sha512", &p->sha512, &p->sdescsha512);
68 if (rc)
69 goto err;
70
71 return 0;
72
73err:
74 cifs_free_hash(&p->cmacaes, &p->sdesccmacaes);
75 cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
76 return rc;
77}
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +010078
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020079
80static
81int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
82{
83 struct cifs_chan *chan;
84 struct cifs_ses *ses = NULL;
Aurelien Aptelcc95b672020-02-06 13:49:26 +010085 struct TCP_Server_Info *it = NULL;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020086 int i;
87 int rc = 0;
88
89 spin_lock(&cifs_tcp_ses_lock);
90
Aurelien Aptelcc95b672020-02-06 13:49:26 +010091 list_for_each_entry(it, &cifs_tcp_ses_list, tcp_ses_list) {
92 list_for_each_entry(ses, &it->smb_ses_list, smb_ses_list) {
Aurelien Apteld70e9fa2019-09-20 06:31:10 +020093 if (ses->Suid == ses_id)
94 goto found;
95 }
96 }
97 cifs_server_dbg(VFS, "%s: Could not find session 0x%llx\n",
98 __func__, ses_id);
99 rc = -ENOENT;
100 goto out;
101
102found:
103 if (ses->binding) {
104 /*
105 * If we are in the process of binding a new channel
106 * to an existing session, use the master connection
107 * session key
108 */
109 memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
110 goto out;
111 }
112
113 /*
114 * Otherwise, use the channel key.
115 */
116
117 for (i = 0; i < ses->chan_count; i++) {
118 chan = ses->chans + i;
119 if (chan->server == server) {
120 memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
121 goto out;
122 }
123 }
124
125 cifs_dbg(VFS,
126 "%s: Could not find channel signing key for session 0x%llx\n",
127 __func__, ses_id);
128 rc = -ENOENT;
129
130out:
131 spin_unlock(&cifs_tcp_ses_lock);
132 return rc;
133}
134
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800135static struct cifs_ses *
136smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
137{
138 struct cifs_ses *ses;
139
140 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
141 if (ses->Suid != ses_id)
142 continue;
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000143 ++ses->ses_count;
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800144 return ses;
145 }
146
147 return NULL;
148}
149
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700150struct cifs_ses *
151smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500152{
153 struct cifs_ses *ses;
154
155 spin_lock(&cifs_tcp_ses_lock);
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800156 ses = smb2_find_smb_ses_unlocked(server, ses_id);
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500157 spin_unlock(&cifs_tcp_ses_lock);
158
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800159 return ses;
160}
161
162static struct cifs_tcon *
163smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
164{
165 struct cifs_tcon *tcon;
166
167 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
168 if (tcon->tid != tid)
169 continue;
170 ++tcon->tc_count;
171 return tcon;
172 }
173
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500174 return NULL;
175}
176
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800177/*
178 * Obtain tcon corresponding to the tid in the given
179 * cifs_ses
180 */
181
182struct cifs_tcon *
183smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
184{
185 struct cifs_ses *ses;
186 struct cifs_tcon *tcon;
187
188 spin_lock(&cifs_tcp_ses_lock);
189 ses = smb2_find_smb_ses_unlocked(server, ses_id);
190 if (!ses) {
191 spin_unlock(&cifs_tcp_ses_lock);
192 return NULL;
193 }
194 tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000195 if (!tcon) {
196 cifs_put_smb_ses(ses);
197 spin_unlock(&cifs_tcp_ses_lock);
198 return NULL;
199 }
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800200 spin_unlock(&cifs_tcp_ses_lock);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000201 /* tcon already has a ref to ses, so we don't need ses anymore */
202 cifs_put_smb_ses(ses);
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800203
204 return tcon;
205}
206
Steve French38107d42012-12-08 22:08:06 -0600207int
Long Lieda1c542020-03-31 16:21:43 -0700208smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
209 bool allocate_crypto)
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700210{
Al Viro16c568e2015-11-12 22:46:49 -0500211 int rc;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700212 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
213 unsigned char *sigptr = smb2_signature;
Jeff Layton0b688cf2012-09-18 16:20:34 -0700214 struct kvec *iov = rqst->rq_iov;
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900215 struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500216 struct cifs_ses *ses;
Aurelien Aptela5c62f42018-08-02 16:39:52 +0200217 struct shash_desc *shash;
Long Lieda1c542020-03-31 16:21:43 -0700218 struct crypto_shash *hash;
219 struct sdesc *sdesc = NULL;
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300220 struct smb_rqst drqst;
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500221
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900222 ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500223 if (!ses) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000224 cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500225 return 0;
226 }
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700227
228 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700229 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700230
Long Lieda1c542020-03-31 16:21:43 -0700231 if (allocate_crypto) {
232 rc = cifs_alloc_hash("hmac(sha256)", &hash, &sdesc);
233 if (rc) {
234 cifs_server_dbg(VFS,
235 "%s: sha256 alloc failed\n", __func__);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000236 goto out;
Long Lieda1c542020-03-31 16:21:43 -0700237 }
238 shash = &sdesc->shash;
239 } else {
240 hash = server->secmech.hmacsha256;
241 shash = &server->secmech.sdeschmacsha256->shash;
Steve French95dc8dd2013-07-04 10:35:21 -0500242 }
243
Long Lieda1c542020-03-31 16:21:43 -0700244 rc = crypto_shash_setkey(hash, ses->auth_key.response,
245 SMB2_NTLMV2_SESSKEY_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700246 if (rc) {
Long Lieda1c542020-03-31 16:21:43 -0700247 cifs_server_dbg(VFS,
248 "%s: Could not update with response\n",
249 __func__);
250 goto out;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700251 }
252
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300253 rc = crypto_shash_init(shash);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700254 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000255 cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
Long Lieda1c542020-03-31 16:21:43 -0700256 goto out;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700257 }
258
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300259 /*
260 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
261 * data, that is, iov[0] should not contain a rfc1002 length.
262 *
263 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
264 * __cifs_calc_signature().
265 */
266 drqst = *rqst;
267 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
268 rc = crypto_shash_update(shash, iov[0].iov_base,
269 iov[0].iov_len);
270 if (rc) {
Long Lieda1c542020-03-31 16:21:43 -0700271 cifs_server_dbg(VFS,
272 "%s: Could not update with payload\n",
273 __func__);
274 goto out;
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300275 }
276 drqst.rq_iov++;
277 drqst.rq_nvec--;
278 }
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700279
Paulo Alcantara8de8c462018-06-23 14:52:24 -0300280 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
Al Viro16c568e2015-11-12 22:46:49 -0500281 if (!rc)
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700282 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700283
Long Lieda1c542020-03-31 16:21:43 -0700284out:
285 if (allocate_crypto)
286 cifs_free_hash(&hash, &sdesc);
Shyam Prasad Ne695a9a2021-05-23 16:54:42 +0000287 if (ses)
288 cifs_put_smb_ses(ses);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700289 return rc;
290}
291
Steve French373512e2015-12-18 13:05:30 -0600292static int generate_key(struct cifs_ses *ses, struct kvec label,
293 struct kvec context, __u8 *key, unsigned int key_size)
Steve French429b46f2013-06-26 23:45:05 -0500294{
295 unsigned char zero = 0x0;
296 __u8 i[4] = {0, 0, 0, 1};
Shyam Prasad N45a45462021-03-25 12:34:54 +0000297 __u8 L128[4] = {0, 0, 0, 128};
298 __u8 L256[4] = {0, 0, 1, 0};
Steve French429b46f2013-06-26 23:45:05 -0500299 int rc = 0;
300 unsigned char prfhash[SMB2_HMACSHA256_SIZE];
301 unsigned char *hashptr = prfhash;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000302 struct TCP_Server_Info *server = ses->server;
Steve French429b46f2013-06-26 23:45:05 -0500303
304 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
Steve French373512e2015-12-18 13:05:30 -0600305 memset(key, 0x0, key_size);
Steve French429b46f2013-06-26 23:45:05 -0500306
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000307 rc = smb3_crypto_shash_allocate(server);
Steve French95dc8dd2013-07-04 10:35:21 -0500308 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000309 cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
Steve French95dc8dd2013-07-04 10:35:21 -0500310 goto smb3signkey_ret;
311 }
312
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000313 rc = crypto_shash_setkey(server->secmech.hmacsha256,
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500314 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500315 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000316 cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500317 goto smb3signkey_ret;
318 }
319
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000320 rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
Steve French429b46f2013-06-26 23:45:05 -0500321 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000322 cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500323 goto smb3signkey_ret;
324 }
325
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000326 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French429b46f2013-06-26 23:45:05 -0500327 i, 4);
328 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000329 cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500330 goto smb3signkey_ret;
331 }
332
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000333 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French373512e2015-12-18 13:05:30 -0600334 label.iov_base, label.iov_len);
Steve French429b46f2013-06-26 23:45:05 -0500335 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000336 cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500337 goto smb3signkey_ret;
338 }
339
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000340 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French429b46f2013-06-26 23:45:05 -0500341 &zero, 1);
342 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000343 cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500344 goto smb3signkey_ret;
345 }
346
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000347 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
Steve French373512e2015-12-18 13:05:30 -0600348 context.iov_base, context.iov_len);
Steve French429b46f2013-06-26 23:45:05 -0500349 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000350 cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500351 goto smb3signkey_ret;
352 }
353
Shyam Prasad N45a45462021-03-25 12:34:54 +0000354 if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
355 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
356 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
357 L256, 4);
358 } else {
359 rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
360 L128, 4);
361 }
Steve French429b46f2013-06-26 23:45:05 -0500362 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000363 cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500364 goto smb3signkey_ret;
365 }
366
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000367 rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
Steve French429b46f2013-06-26 23:45:05 -0500368 hashptr);
369 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000370 cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
Steve French429b46f2013-06-26 23:45:05 -0500371 goto smb3signkey_ret;
372 }
373
Steve French373512e2015-12-18 13:05:30 -0600374 memcpy(key, hashptr, key_size);
Steve French429b46f2013-06-26 23:45:05 -0500375
376smb3signkey_ret:
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500377 return rc;
Steve French429b46f2013-06-26 23:45:05 -0500378}
379
Steve French373512e2015-12-18 13:05:30 -0600380struct derivation {
381 struct kvec label;
382 struct kvec context;
383};
384
385struct derivation_triplet {
386 struct derivation signing;
387 struct derivation encryption;
388 struct derivation decryption;
389};
390
391static int
392generate_smb3signingkey(struct cifs_ses *ses,
393 const struct derivation_triplet *ptriplet)
394{
395 int rc;
Shyam Prasad N45a45462021-03-25 12:34:54 +0000396#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
397 struct TCP_Server_Info *server = ses->server;
398#endif
Steve French373512e2015-12-18 13:05:30 -0600399
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200400 /*
401 * All channels use the same encryption/decryption keys but
402 * they have their own signing key.
403 *
404 * When we generate the keys, check if it is for a new channel
405 * (binding) in which case we only need to generate a signing
406 * key and store it in the channel as to not overwrite the
407 * master connection signing key stored in the session
408 */
Steve French373512e2015-12-18 13:05:30 -0600409
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200410 if (ses->binding) {
411 rc = generate_key(ses, ptriplet->signing.label,
412 ptriplet->signing.context,
413 cifs_ses_binding_channel(ses)->signkey,
414 SMB3_SIGN_KEY_SIZE);
415 if (rc)
416 return rc;
417 } else {
418 rc = generate_key(ses, ptriplet->signing.label,
419 ptriplet->signing.context,
420 ses->smb3signingkey,
421 SMB3_SIGN_KEY_SIZE);
422 if (rc)
423 return rc;
Paulo Alcantara (SUSE)ff6b6f32019-11-22 12:30:57 -0300424
425 memcpy(ses->chans[0].signkey, ses->smb3signingkey,
426 SMB3_SIGN_KEY_SIZE);
427
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200428 rc = generate_key(ses, ptriplet->encryption.label,
429 ptriplet->encryption.context,
430 ses->smb3encryptionkey,
Shyam Prasad N45a45462021-03-25 12:34:54 +0000431 SMB3_ENC_DEC_KEY_SIZE);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200432 rc = generate_key(ses, ptriplet->decryption.label,
433 ptriplet->decryption.context,
434 ses->smb3decryptionkey,
Shyam Prasad N45a45462021-03-25 12:34:54 +0000435 SMB3_ENC_DEC_KEY_SIZE);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200436 if (rc)
437 return rc;
438 }
Aurélien Apteld38de3c62017-05-24 16:13:25 +0200439
440 if (rc)
441 return rc;
442
443#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
444 cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);
445 /*
446 * The session id is opaque in terms of endianness, so we can't
447 * print it as a long long. we dump it as we got it on the wire
448 */
449 cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
450 &ses->Suid);
Shyam Prasad N45a45462021-03-25 12:34:54 +0000451 cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);
Aurélien Apteld38de3c62017-05-24 16:13:25 +0200452 cifs_dbg(VFS, "Session Key %*ph\n",
453 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
454 cifs_dbg(VFS, "Signing Key %*ph\n",
455 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
Shyam Prasad N45a45462021-03-25 12:34:54 +0000456 if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
457 (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
458 cifs_dbg(VFS, "ServerIn Key %*ph\n",
459 SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);
460 cifs_dbg(VFS, "ServerOut Key %*ph\n",
461 SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);
462 } else {
463 cifs_dbg(VFS, "ServerIn Key %*ph\n",
464 SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);
465 cifs_dbg(VFS, "ServerOut Key %*ph\n",
466 SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);
467 }
Aurélien Apteld38de3c62017-05-24 16:13:25 +0200468#endif
469 return rc;
Steve French373512e2015-12-18 13:05:30 -0600470}
471
472int
473generate_smb30signingkey(struct cifs_ses *ses)
474
475{
476 struct derivation_triplet triplet;
477 struct derivation *d;
478
479 d = &triplet.signing;
480 d->label.iov_base = "SMB2AESCMAC";
481 d->label.iov_len = 12;
482 d->context.iov_base = "SmbSign";
483 d->context.iov_len = 8;
484
485 d = &triplet.encryption;
486 d->label.iov_base = "SMB2AESCCM";
487 d->label.iov_len = 11;
488 d->context.iov_base = "ServerIn ";
489 d->context.iov_len = 10;
490
491 d = &triplet.decryption;
492 d->label.iov_base = "SMB2AESCCM";
493 d->label.iov_len = 11;
494 d->context.iov_base = "ServerOut";
495 d->context.iov_len = 10;
496
497 return generate_smb3signingkey(ses, &triplet);
498}
499
500int
501generate_smb311signingkey(struct cifs_ses *ses)
502
503{
504 struct derivation_triplet triplet;
505 struct derivation *d;
506
507 d = &triplet.signing;
Steve French06e22902017-09-25 20:11:58 -0500508 d->label.iov_base = "SMBSigningKey";
509 d->label.iov_len = 14;
510 d->context.iov_base = ses->preauth_sha_hash;
511 d->context.iov_len = 64;
Steve French373512e2015-12-18 13:05:30 -0600512
513 d = &triplet.encryption;
Steve French06e22902017-09-25 20:11:58 -0500514 d->label.iov_base = "SMBC2SCipherKey";
515 d->label.iov_len = 16;
516 d->context.iov_base = ses->preauth_sha_hash;
517 d->context.iov_len = 64;
Steve French373512e2015-12-18 13:05:30 -0600518
519 d = &triplet.decryption;
Steve French06e22902017-09-25 20:11:58 -0500520 d->label.iov_base = "SMBS2CCipherKey";
521 d->label.iov_len = 16;
522 d->context.iov_base = ses->preauth_sha_hash;
523 d->context.iov_len = 64;
Steve French373512e2015-12-18 13:05:30 -0600524
525 return generate_smb3signingkey(ses, &triplet);
526}
527
Steve French429b46f2013-06-26 23:45:05 -0500528int
Long Lieda1c542020-03-31 16:21:43 -0700529smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
530 bool allocate_crypto)
Steve French38107d42012-12-08 22:08:06 -0600531{
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300532 int rc;
Steve French429b46f2013-06-26 23:45:05 -0500533 unsigned char smb3_signature[SMB2_CMACAES_SIZE];
534 unsigned char *sigptr = smb3_signature;
535 struct kvec *iov = rqst->rq_iov;
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900536 struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
Long Lieda1c542020-03-31 16:21:43 -0700537 struct shash_desc *shash;
538 struct crypto_shash *hash;
539 struct sdesc *sdesc = NULL;
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300540 struct smb_rqst drqst;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200541 u8 key[SMB3_SIGN_KEY_SIZE];
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500542
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900543 rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200544 if (rc)
Shirish Pargaonkar32811d22013-08-29 08:35:11 -0500545 return 0;
Steve French429b46f2013-06-26 23:45:05 -0500546
Long Lieda1c542020-03-31 16:21:43 -0700547 if (allocate_crypto) {
548 rc = cifs_alloc_hash("cmac(aes)", &hash, &sdesc);
549 if (rc)
550 return rc;
551
552 shash = &sdesc->shash;
553 } else {
554 hash = server->secmech.cmacaes;
555 shash = &server->secmech.sdesccmacaes->shash;
556 }
557
Steve French429b46f2013-06-26 23:45:05 -0500558 memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700559 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500560
Long Lieda1c542020-03-31 16:21:43 -0700561 rc = crypto_shash_setkey(hash, key, SMB2_CMACAES_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500562 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000563 cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
Long Lieda1c542020-03-31 16:21:43 -0700564 goto out;
Steve French429b46f2013-06-26 23:45:05 -0500565 }
566
Steve French95dc8dd2013-07-04 10:35:21 -0500567 /*
568 * we already allocate sdesccmacaes when we init smb3 signing key,
569 * so unlike smb2 case we do not have to check here if secmech are
570 * initialized
571 */
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300572 rc = crypto_shash_init(shash);
Steve French429b46f2013-06-26 23:45:05 -0500573 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000574 cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
Long Lieda1c542020-03-31 16:21:43 -0700575 goto out;
Steve French429b46f2013-06-26 23:45:05 -0500576 }
Aurelien Aptel82fb82b2018-02-16 19:19:27 +0100577
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300578 /*
579 * For SMB2+, __cifs_calc_signature() expects to sign only the actual
580 * data, that is, iov[0] should not contain a rfc1002 length.
581 *
582 * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
583 * __cifs_calc_signature().
584 */
585 drqst = *rqst;
586 if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
587 rc = crypto_shash_update(shash, iov[0].iov_base,
588 iov[0].iov_len);
589 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000590 cifs_server_dbg(VFS, "%s: Could not update with payload\n",
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300591 __func__);
Long Lieda1c542020-03-31 16:21:43 -0700592 goto out;
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300593 }
594 drqst.rq_iov++;
595 drqst.rq_nvec--;
596 }
Steve French429b46f2013-06-26 23:45:05 -0500597
Paulo Alcantara27c32b42018-06-23 14:52:23 -0300598 rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
Al Viro16c568e2015-11-12 22:46:49 -0500599 if (!rc)
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700600 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
Steve French429b46f2013-06-26 23:45:05 -0500601
Long Lieda1c542020-03-31 16:21:43 -0700602out:
603 if (allocate_crypto)
604 cifs_free_hash(&hash, &sdesc);
Steve French429b46f2013-06-26 23:45:05 -0500605 return rc;
Steve French38107d42012-12-08 22:08:06 -0600606}
607
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700608/* must be called with server->srv_mutex held */
609static int
Jeff Layton0b688cf2012-09-18 16:20:34 -0700610smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700611{
612 int rc = 0;
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900613 struct smb2_hdr *shdr;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200614 struct smb2_sess_setup_req *ssr;
615 bool is_binding;
616 bool is_signed;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700617
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900618 shdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200619 ssr = (struct smb2_sess_setup_req *)shdr;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700620
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200621 is_binding = shdr->Command == SMB2_SESSION_SETUP &&
622 (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING);
623 is_signed = shdr->Flags & SMB2_FLAGS_SIGNED;
624
625 if (!is_signed)
626 return 0;
627 if (server->tcpStatus == CifsNeedNegotiate)
628 return 0;
629 if (!is_binding && !server->session_estab) {
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700630 strncpy(shdr->Signature, "BSRSPYL", 8);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +0200631 return 0;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700632 }
633
Long Lieda1c542020-03-31 16:21:43 -0700634 rc = server->ops->calc_signature(rqst, server, false);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700635
636 return rc;
637}
638
639int
Jeff Layton0b688cf2012-09-18 16:20:34 -0700640smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700641{
642 unsigned int rc;
Steve Frenchedad7342020-03-27 12:47:41 -0500643 char server_response_sig[SMB2_SIGNATURE_SIZE];
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900644 struct smb2_hdr *shdr =
645 (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700646
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700647 if ((shdr->Command == SMB2_NEGOTIATE) ||
648 (shdr->Command == SMB2_SESSION_SETUP) ||
649 (shdr->Command == SMB2_OPLOCK_BREAK) ||
Steve French4f5c10f2019-09-03 21:18:49 -0500650 server->ignore_signature ||
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700651 (!server->session_estab))
652 return 0;
653
654 /*
655 * BB what if signatures are supposed to be on for session but
656 * server does not send one? BB
657 */
658
659 /* Do not need to verify session setups with signature "BSRSPYL " */
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700660 if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
Joe Perchesf96637b2013-05-04 22:12:25 -0500661 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700662 shdr->Command);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700663
664 /*
665 * Save off the origiginal signature so we can modify the smb and check
666 * our calculated signature against what the server sent.
667 */
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700668 memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700669
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700670 memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700671
Long Lieda1c542020-03-31 16:21:43 -0700672 rc = server->ops->calc_signature(rqst, server, true);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700673
674 if (rc)
675 return rc;
676
Steve Frenchf460c502020-03-29 16:44:43 -0500677 if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) {
Steve French9692ea92020-04-15 01:12:34 -0500678 cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n",
679 shdr->Command, shdr->MessageId);
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700680 return -EACCES;
Steve Frenchf460c502020-03-29 16:44:43 -0500681 } else
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700682 return 0;
683}
684
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400685/*
686 * Set message id for the request. Should be called after wait_for_free_request
687 * and when srv_mutex is held.
688 */
689static inline void
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700690smb2_seq_num_into_buf(struct TCP_Server_Info *server,
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900691 struct smb2_hdr *shdr)
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400692{
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700693 unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +0400694
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700695 shdr->MessageId = get_next_mid64(server);
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +0400696 /* skip message numbers according to CreditCharge field */
697 for (i = 1; i < num; i++)
698 get_next_mid(server);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400699}
700
701static struct mid_q_entry *
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900702smb2_mid_entry_alloc(const struct smb2_hdr *shdr,
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400703 struct TCP_Server_Info *server)
704{
705 struct mid_q_entry *temp;
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800706 unsigned int credits = le16_to_cpu(shdr->CreditCharge);
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400707
708 if (server == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500709 cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400710 return NULL;
711 }
712
713 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
NeilBrowna6f74e82017-04-10 12:08:53 +1000714 memset(temp, 0, sizeof(struct mid_q_entry));
Lars Persson696e4202018-06-25 14:05:25 +0200715 kref_init(&temp->refcount);
NeilBrowna6f74e82017-04-10 12:08:53 +1000716 temp->mid = le64_to_cpu(shdr->MessageId);
Pavel Shilovskyc781af72019-03-04 14:02:50 -0800717 temp->credits = credits > 0 ? credits : 1;
NeilBrowna6f74e82017-04-10 12:08:53 +1000718 temp->pid = current->pid;
719 temp->command = shdr->Command; /* Always LE */
720 temp->when_alloc = jiffies;
721 temp->server = server;
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400722
NeilBrowna6f74e82017-04-10 12:08:53 +1000723 /*
724 * The default is for the mid to be synchronous, so the
725 * default callback just wakes up the current task.
726 */
Vincent Whitchurchf1f27ad2020-01-23 17:09:06 +0100727 get_task_struct(current);
728 temp->creator = current;
NeilBrowna6f74e82017-04-10 12:08:53 +1000729 temp->callback = cifs_wake_up_task;
730 temp->callback_data = current;
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400731
732 atomic_inc(&midCount);
733 temp->mid_state = MID_REQUEST_ALLOCATED;
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900734 trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId),
735 le64_to_cpu(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,
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900742 struct smb2_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;
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900810 struct smb2_hdr *shdr =
811 (struct smb2_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;
Ronnie Sahlberg0d35e382021-11-05 08:39:01 +0900836 struct smb2_hdr *shdr =
837 (struct smb2_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}