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