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