ksmbd: fix racy issue while destroying session on multichannel
[linux-block.git] / fs / ksmbd / auth.c
CommitLineData
e2f34481
NJ
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
4 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
5 */
6
7#include <linux/kernel.h>
8#include <linux/fs.h>
9#include <linux/uaccess.h>
10#include <linux/backing-dev.h>
11#include <linux/writeback.h>
12#include <linux/uio.h>
13#include <linux/xattr.h>
14#include <crypto/hash.h>
15#include <crypto/aead.h>
16#include <linux/random.h>
17#include <linux/scatterlist.h>
18
19#include "auth.h"
20#include "glob.h"
21
22#include <linux/fips.h>
23#include <crypto/des.h>
24
25#include "server.h"
26#include "smb_common.h"
27#include "connection.h"
28#include "mgmt/user_session.h"
29#include "mgmt/user_config.h"
30#include "crypto_ctx.h"
31#include "transport_ipc.h"
f9929ef6 32#include "../smbfs_common/arc4.h"
e2f34481
NJ
33
34/*
35 * Fixed format data defining GSS header and fixed string
36 * "not_defined_in_RFC4178@please_ignore".
37 * So sec blob data in neg phase could be generated statically.
38 */
39static char NEGOTIATE_GSS_HEADER[AUTH_GSS_LENGTH] = {
40#ifdef CONFIG_SMB_SERVER_KERBEROS5
41 0x60, 0x5e, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
42 0x05, 0x02, 0xa0, 0x54, 0x30, 0x52, 0xa0, 0x24,
43 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
44 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a,
45 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02,
46 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
47 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a, 0x30, 0x28,
48 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f, 0x74, 0x5f,
49 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f,
50 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43, 0x34, 0x31,
51 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65, 0x61, 0x73,
52 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65
53#else
54 0x60, 0x48, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
55 0x05, 0x02, 0xa0, 0x3e, 0x30, 0x3c, 0xa0, 0x0e,
56 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
57 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a,
58 0x30, 0x28, 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f,
59 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
60 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43,
61 0x34, 0x31, 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65,
62 0x61, 0x73, 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f,
63 0x72, 0x65
64#endif
65};
66
e2f34481
NJ
67void ksmbd_copy_gss_neg_header(void *buf)
68{
69 memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
70}
71
e2f34481
NJ
72/**
73 * ksmbd_gen_sess_key() - function to generate session key
74 * @sess: session of connection
75 * @hash: source hash value to be used for find session key
76 * @hmac: source hmac value to be used for finding session key
77 *
78 */
64b39f4a 79static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
070fb21e 80 char *hmac)
e2f34481
NJ
81{
82 struct ksmbd_crypto_ctx *ctx;
0e579cd1 83 int rc;
e2f34481
NJ
84
85 ctx = ksmbd_crypto_ctx_find_hmacmd5();
0e579cd1
NJ
86 if (!ctx) {
87 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
88 return -ENOMEM;
89 }
e2f34481
NJ
90
91 rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
92 hash,
93 CIFS_HMAC_MD5_HASH_SIZE);
94 if (rc) {
95 ksmbd_debug(AUTH, "hmacmd5 set key fail error %d\n", rc);
96 goto out;
97 }
98
99 rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
100 if (rc) {
101 ksmbd_debug(AUTH, "could not init hmacmd5 error %d\n", rc);
102 goto out;
103 }
104
105 rc = crypto_shash_update(CRYPTO_HMACMD5(ctx),
106 hmac,
107 SMB2_NTLMV2_SESSKEY_SIZE);
108 if (rc) {
070fb21e 109 ksmbd_debug(AUTH, "Could not update with response error %d\n", rc);
e2f34481
NJ
110 goto out;
111 }
112
113 rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key);
114 if (rc) {
070fb21e 115 ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", rc);
e2f34481
NJ
116 goto out;
117 }
118
119out:
120 ksmbd_release_crypto_ctx(ctx);
121 return rc;
122}
123
af7c39d9
NJ
124static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
125 char *ntlmv2_hash, char *dname)
e2f34481 126{
a2d0b503 127 int ret, len, conv_len;
e2f34481
NJ
128 wchar_t *domain = NULL;
129 __le16 *uniname = NULL;
130 struct ksmbd_crypto_ctx *ctx;
131
132 ctx = ksmbd_crypto_ctx_find_hmacmd5();
133 if (!ctx) {
134 ksmbd_debug(AUTH, "can't generate ntlmv2 hash\n");
0e579cd1 135 return -ENOMEM;
e2f34481
NJ
136 }
137
138 ret = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
139 user_passkey(sess->user),
140 CIFS_ENCPWD_SIZE);
141 if (ret) {
142 ksmbd_debug(AUTH, "Could not set NT Hash as a key\n");
143 goto out;
144 }
145
146 ret = crypto_shash_init(CRYPTO_HMACMD5(ctx));
147 if (ret) {
148 ksmbd_debug(AUTH, "could not init hmacmd5\n");
149 goto out;
150 }
151
152 /* convert user_name to unicode */
153 len = strlen(user_name(sess->user));
154 uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
155 if (!uniname) {
156 ret = -ENOMEM;
157 goto out;
158 }
159
a2d0b503 160 conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
af7c39d9 161 conn->local_nls);
a2d0b503
NJ
162 if (conv_len < 0 || conv_len > len) {
163 ret = -EINVAL;
164 goto out;
e2f34481 165 }
a2d0b503 166 UniStrupr(uniname);
e2f34481
NJ
167
168 ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
169 (char *)uniname,
a2d0b503 170 UNICODE_LEN(conv_len));
e2f34481
NJ
171 if (ret) {
172 ksmbd_debug(AUTH, "Could not update with user\n");
173 goto out;
174 }
175
176 /* Convert domain name or conn name to unicode and uppercase */
177 len = strlen(dname);
178 domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
179 if (!domain) {
180 ret = -ENOMEM;
181 goto out;
182 }
183
a2d0b503 184 conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
af7c39d9 185 conn->local_nls);
a2d0b503
NJ
186 if (conv_len < 0 || conv_len > len) {
187 ret = -EINVAL;
188 goto out;
189 }
e2f34481
NJ
190
191 ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
192 (char *)domain,
a2d0b503 193 UNICODE_LEN(conv_len));
e2f34481
NJ
194 if (ret) {
195 ksmbd_debug(AUTH, "Could not update with domain\n");
196 goto out;
197 }
198
199 ret = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_hash);
e2f34481
NJ
200 if (ret)
201 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
7e38ea25 202out:
e2f34481
NJ
203 kfree(uniname);
204 kfree(domain);
205 ksmbd_release_crypto_ctx(ctx);
206 return ret;
207}
208
e2f34481
NJ
209/**
210 * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
211 * @sess: session of connection
212 * @ntlmv2: NTLMv2 challenge response
213 * @blen: NTLMv2 blob length
214 * @domain_name: domain name
215 *
216 * Return: 0 on success, error number on error
217 */
af7c39d9
NJ
218int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
219 struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
220 char *cryptkey)
e2f34481
NJ
221{
222 char ntlmv2_hash[CIFS_ENCPWD_SIZE];
223 char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
224 struct ksmbd_crypto_ctx *ctx;
225 char *construct = NULL;
0e579cd1 226 int rc, len;
e2f34481
NJ
227
228 ctx = ksmbd_crypto_ctx_find_hmacmd5();
229 if (!ctx) {
0e579cd1
NJ
230 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
231 return -ENOMEM;
e2f34481
NJ
232 }
233
af7c39d9 234 rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name);
e2f34481
NJ
235 if (rc) {
236 ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
237 goto out;
238 }
239
240 rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
241 ntlmv2_hash,
242 CIFS_HMAC_MD5_HASH_SIZE);
243 if (rc) {
244 ksmbd_debug(AUTH, "Could not set NTLMV2 Hash as a key\n");
245 goto out;
246 }
247
248 rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
249 if (rc) {
250 ksmbd_debug(AUTH, "Could not init hmacmd5\n");
251 goto out;
252 }
253
254 len = CIFS_CRYPTO_KEY_SIZE + blen;
255 construct = kzalloc(len, GFP_KERNEL);
256 if (!construct) {
257 rc = -ENOMEM;
258 goto out;
259 }
260
ce53d365 261 memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE);
192cc732 262 memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen);
e2f34481
NJ
263
264 rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len);
265 if (rc) {
266 ksmbd_debug(AUTH, "Could not update with response\n");
267 goto out;
268 }
269
270 rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_rsp);
271 if (rc) {
272 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
273 goto out;
274 }
275
276 rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp);
277 if (rc) {
278 ksmbd_debug(AUTH, "Could not generate sess key\n");
279 goto out;
280 }
281
b72802aa
NJ
282 if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
283 rc = -EINVAL;
e2f34481
NJ
284out:
285 ksmbd_release_crypto_ctx(ctx);
286 kfree(construct);
287 return rc;
288}
289
e2f34481
NJ
290/**
291 * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
292 * authenticate blob
293 * @authblob: authenticate blob source pointer
294 * @usr: user details
295 * @sess: session of connection
296 *
297 * Return: 0 on success, error number on error
298 */
299int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
ce53d365
NJ
300 int blob_len, struct ksmbd_conn *conn,
301 struct ksmbd_session *sess)
e2f34481
NJ
302{
303 char *domain_name;
0d994cd4
MM
304 unsigned int nt_off, dn_off;
305 unsigned short nt_len, dn_len;
e2f34481
NJ
306 int ret;
307
308 if (blob_len < sizeof(struct authenticate_message)) {
309 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
070fb21e 310 blob_len);
e2f34481
NJ
311 return -EINVAL;
312 }
313
314 if (memcmp(authblob->Signature, "NTLMSSP", 8)) {
315 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
070fb21e 316 authblob->Signature);
e2f34481
NJ
317 return -EINVAL;
318 }
319
e2f34481
NJ
320 nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
321 nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
0d994cd4
MM
322 dn_off = le32_to_cpu(authblob->DomainName.BufferOffset);
323 dn_len = le16_to_cpu(authblob->DomainName.Length);
324
325 if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len)
326 return -EINVAL;
e2f34481 327
e2f34481 328 /* TODO : use domain name that imported from configuration file */
0d994cd4 329 domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off,
ce53d365 330 dn_len, true, conn->local_nls);
e2f34481
NJ
331 if (IS_ERR(domain_name))
332 return PTR_ERR(domain_name);
333
334 /* process NTLMv2 authentication */
335 ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n",
070fb21e 336 domain_name);
af7c39d9
NJ
337 ret = ksmbd_auth_ntlmv2(conn, sess,
338 (struct ntlmv2_resp *)((char *)authblob + nt_off),
070fb21e 339 nt_len - CIFS_ENCPWD_SIZE,
ce53d365 340 domain_name, conn->ntlmssp.cryptkey);
e2f34481 341 kfree(domain_name);
f9929ef6
NJ
342
343 /* The recovered secondary session key */
344 if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) {
345 struct arc4_ctx *ctx_arc4;
346 unsigned int sess_key_off, sess_key_len;
347
348 sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset);
349 sess_key_len = le16_to_cpu(authblob->SessionKey.Length);
350
351 if (blob_len < (u64)sess_key_off + sess_key_len)
352 return -EINVAL;
353
354 ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
355 if (!ctx_arc4)
356 return -ENOMEM;
357
358 cifs_arc4_setkey(ctx_arc4, sess->sess_key,
359 SMB2_NTLMV2_SESSKEY_SIZE);
360 cifs_arc4_crypt(ctx_arc4, sess->sess_key,
361 (char *)authblob + sess_key_off, sess_key_len);
362 kfree_sensitive(ctx_arc4);
363 }
364
e2f34481
NJ
365 return ret;
366}
367
368/**
369 * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
370 * negotiate blob
371 * @negblob: negotiate blob source pointer
372 * @rsp: response header pointer to be updated
373 * @sess: session of connection
374 *
375 */
376int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
ce53d365 377 int blob_len, struct ksmbd_conn *conn)
e2f34481
NJ
378{
379 if (blob_len < sizeof(struct negotiate_message)) {
380 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
070fb21e 381 blob_len);
e2f34481
NJ
382 return -EINVAL;
383 }
384
385 if (memcmp(negblob->Signature, "NTLMSSP", 8)) {
386 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
070fb21e 387 negblob->Signature);
e2f34481
NJ
388 return -EINVAL;
389 }
390
ce53d365 391 conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags);
e2f34481
NJ
392 return 0;
393}
394
395/**
396 * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
397 * challenge blob
398 * @chgblob: challenge blob source pointer to initialize
399 * @rsp: response header pointer to be updated
400 * @sess: session of connection
401 *
402 */
403unsigned int
404ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
ce53d365 405 struct ksmbd_conn *conn)
e2f34481
NJ
406{
407 struct target_info *tinfo;
408 wchar_t *name;
409 __u8 *target_name;
152de8c6
NJ
410 unsigned int flags, blob_off, blob_len, type, target_info_len = 0;
411 int len, uni_len, conv_len;
ce53d365 412 int cflags = conn->ntlmssp.client_flags;
e2f34481
NJ
413
414 memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
415 chgblob->MessageType = NtLmChallenge;
416
417 flags = NTLMSSP_NEGOTIATE_UNICODE |
418 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_TARGET_TYPE_SERVER |
419 NTLMSSP_NEGOTIATE_TARGET_INFO;
420
421 if (cflags & NTLMSSP_NEGOTIATE_SIGN) {
422 flags |= NTLMSSP_NEGOTIATE_SIGN;
423 flags |= cflags & (NTLMSSP_NEGOTIATE_128 |
70478059 424 NTLMSSP_NEGOTIATE_56);
e2f34481
NJ
425 }
426
427 if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
428 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
429
430 if (cflags & NTLMSSP_REQUEST_TARGET)
431 flags |= NTLMSSP_REQUEST_TARGET;
432
ce53d365 433 if (conn->use_spnego &&
64b39f4a 434 (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
e2f34481
NJ
435 flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
436
f9929ef6
NJ
437 if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
438 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
439
e2f34481
NJ
440 chgblob->NegotiateFlags = cpu_to_le32(flags);
441 len = strlen(ksmbd_netbios_name());
a2d0b503 442 name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
e2f34481
NJ
443 if (!name)
444 return -ENOMEM;
445
a2d0b503 446 conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
ce53d365 447 conn->local_nls);
a2d0b503
NJ
448 if (conv_len < 0 || conv_len > len) {
449 kfree(name);
450 return -EINVAL;
451 }
452
453 uni_len = UNICODE_LEN(conv_len);
e2f34481
NJ
454
455 blob_off = sizeof(struct challenge_message);
a2d0b503 456 blob_len = blob_off + uni_len;
e2f34481 457
a2d0b503
NJ
458 chgblob->TargetName.Length = cpu_to_le16(uni_len);
459 chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len);
e2f34481
NJ
460 chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
461
462 /* Initialize random conn challenge */
ce53d365
NJ
463 get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64));
464 memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey,
070fb21e 465 CIFS_CRYPTO_KEY_SIZE);
e2f34481
NJ
466
467 /* Add Target Information to security buffer */
468 chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
469
470 target_name = (__u8 *)chgblob + blob_off;
a2d0b503
NJ
471 memcpy(target_name, name, uni_len);
472 tinfo = (struct target_info *)(target_name + uni_len);
e2f34481
NJ
473
474 chgblob->TargetInfoArray.Length = 0;
475 /* Add target info list for NetBIOS/DNS settings */
476 for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
70478059 477 type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
e2f34481 478 tinfo->Type = cpu_to_le16(type);
a2d0b503
NJ
479 tinfo->Length = cpu_to_le16(uni_len);
480 memcpy(tinfo->Content, name, uni_len);
481 tinfo = (struct target_info *)((char *)tinfo + 4 + uni_len);
482 target_info_len += 4 + uni_len;
e2f34481
NJ
483 }
484
485 /* Add terminator subblock */
486 tinfo->Type = 0;
487 tinfo->Length = 0;
488 target_info_len += 4;
489
490 chgblob->TargetInfoArray.Length = cpu_to_le16(target_info_len);
491 chgblob->TargetInfoArray.MaximumLength = cpu_to_le16(target_info_len);
492 blob_len += target_info_len;
493 kfree(name);
494 ksmbd_debug(AUTH, "NTLMSSP SecurityBufferLength %d\n", blob_len);
495 return blob_len;
496}
497
498#ifdef CONFIG_SMB_SERVER_KERBEROS5
64b39f4a 499int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
070fb21e 500 int in_len, char *out_blob, int *out_len)
e2f34481
NJ
501{
502 struct ksmbd_spnego_authen_response *resp;
503 struct ksmbd_user *user = NULL;
504 int retval;
505
506 resp = ksmbd_ipc_spnego_authen_request(in_blob, in_len);
507 if (!resp) {
508 ksmbd_debug(AUTH, "SPNEGO_AUTHEN_REQUEST failure\n");
509 return -EINVAL;
510 }
511
512 if (!(resp->login_response.status & KSMBD_USER_FLAG_OK)) {
513 ksmbd_debug(AUTH, "krb5 authentication failure\n");
514 retval = -EPERM;
515 goto out;
516 }
517
518 if (*out_len <= resp->spnego_blob_len) {
519 ksmbd_debug(AUTH, "buf len %d, but blob len %d\n",
070fb21e 520 *out_len, resp->spnego_blob_len);
e2f34481
NJ
521 retval = -EINVAL;
522 goto out;
523 }
524
525 if (resp->session_key_len > sizeof(sess->sess_key)) {
526 ksmbd_debug(AUTH, "session key is too long\n");
527 retval = -EINVAL;
528 goto out;
529 }
530
531 user = ksmbd_alloc_user(&resp->login_response);
532 if (!user) {
533 ksmbd_debug(AUTH, "login failure\n");
534 retval = -ENOMEM;
535 goto out;
536 }
537 sess->user = user;
538
539 memcpy(sess->sess_key, resp->payload, resp->session_key_len);
540 memcpy(out_blob, resp->payload + resp->session_key_len,
070fb21e 541 resp->spnego_blob_len);
e2f34481
NJ
542 *out_len = resp->spnego_blob_len;
543 retval = 0;
544out:
79f6b11a 545 kvfree(resp);
e2f34481
NJ
546 return retval;
547}
548#else
64b39f4a 549int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
070fb21e 550 int in_len, char *out_blob, int *out_len)
e2f34481
NJ
551{
552 return -EOPNOTSUPP;
553}
554#endif
555
556/**
557 * ksmbd_sign_smb2_pdu() - function to generate packet signing
558 * @conn: connection
559 * @key: signing key
560 * @iov: buffer iov array
561 * @n_vec: number of iovecs
562 * @sig: signature value generated for client request packet
563 *
564 */
64b39f4a 565int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
070fb21e 566 int n_vec, char *sig)
e2f34481
NJ
567{
568 struct ksmbd_crypto_ctx *ctx;
0e579cd1 569 int rc, i;
e2f34481
NJ
570
571 ctx = ksmbd_crypto_ctx_find_hmacsha256();
572 if (!ctx) {
0e579cd1
NJ
573 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
574 return -ENOMEM;
e2f34481
NJ
575 }
576
577 rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
578 key,
579 SMB2_NTLMV2_SESSKEY_SIZE);
580 if (rc)
581 goto out;
582
583 rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
584 if (rc) {
585 ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
586 goto out;
587 }
588
589 for (i = 0; i < n_vec; i++) {
590 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
591 iov[i].iov_base,
592 iov[i].iov_len);
593 if (rc) {
594 ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc);
595 goto out;
596 }
597 }
598
599 rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig);
600 if (rc)
601 ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc);
602out:
603 ksmbd_release_crypto_ctx(ctx);
604 return rc;
605}
606
607/**
608 * ksmbd_sign_smb3_pdu() - function to generate packet signing
609 * @conn: connection
610 * @key: signing key
611 * @iov: buffer iov array
612 * @n_vec: number of iovecs
613 * @sig: signature value generated for client request packet
614 *
615 */
64b39f4a 616int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
070fb21e 617 int n_vec, char *sig)
e2f34481
NJ
618{
619 struct ksmbd_crypto_ctx *ctx;
0e579cd1 620 int rc, i;
e2f34481
NJ
621
622 ctx = ksmbd_crypto_ctx_find_cmacaes();
623 if (!ctx) {
0e579cd1
NJ
624 ksmbd_debug(AUTH, "could not crypto alloc cmac\n");
625 return -ENOMEM;
e2f34481
NJ
626 }
627
628 rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx),
629 key,
630 SMB2_CMACAES_SIZE);
631 if (rc)
632 goto out;
633
634 rc = crypto_shash_init(CRYPTO_CMACAES(ctx));
635 if (rc) {
636 ksmbd_debug(AUTH, "cmaces init error %d\n", rc);
637 goto out;
638 }
639
640 for (i = 0; i < n_vec; i++) {
641 rc = crypto_shash_update(CRYPTO_CMACAES(ctx),
642 iov[i].iov_base,
643 iov[i].iov_len);
644 if (rc) {
645 ksmbd_debug(AUTH, "cmaces update error %d\n", rc);
646 goto out;
647 }
648 }
649
650 rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig);
651 if (rc)
652 ksmbd_debug(AUTH, "cmaces generation error %d\n", rc);
653out:
654 ksmbd_release_crypto_ctx(ctx);
655 return rc;
656}
657
658struct derivation {
659 struct kvec label;
660 struct kvec context;
661 bool binding;
662};
663
af7c39d9
NJ
664static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
665 struct kvec label, struct kvec context, __u8 *key,
666 unsigned int key_size)
e2f34481
NJ
667{
668 unsigned char zero = 0x0;
669 __u8 i[4] = {0, 0, 0, 1};
5a0ca770
NJ
670 __u8 L128[4] = {0, 0, 0, 128};
671 __u8 L256[4] = {0, 0, 1, 0};
0e579cd1 672 int rc;
e2f34481
NJ
673 unsigned char prfhash[SMB2_HMACSHA256_SIZE];
674 unsigned char *hashptr = prfhash;
675 struct ksmbd_crypto_ctx *ctx;
676
677 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
678 memset(key, 0x0, key_size);
679
680 ctx = ksmbd_crypto_ctx_find_hmacsha256();
681 if (!ctx) {
0e579cd1
NJ
682 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
683 return -ENOMEM;
e2f34481
NJ
684 }
685
686 rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
687 sess->sess_key,
688 SMB2_NTLMV2_SESSKEY_SIZE);
689 if (rc)
690 goto smb3signkey_ret;
691
692 rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
693 if (rc) {
694 ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
695 goto smb3signkey_ret;
696 }
697
698 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4);
699 if (rc) {
700 ksmbd_debug(AUTH, "could not update with n\n");
701 goto smb3signkey_ret;
702 }
703
704 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
705 label.iov_base,
706 label.iov_len);
707 if (rc) {
708 ksmbd_debug(AUTH, "could not update with label\n");
709 goto smb3signkey_ret;
710 }
711
712 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1);
713 if (rc) {
714 ksmbd_debug(AUTH, "could not update with zero\n");
715 goto smb3signkey_ret;
716 }
717
718 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
719 context.iov_base,
720 context.iov_len);
721 if (rc) {
722 ksmbd_debug(AUTH, "could not update with context\n");
723 goto smb3signkey_ret;
724 }
725
af7c39d9
NJ
726 if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
727 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
5a0ca770
NJ
728 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
729 else
730 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
e2f34481
NJ
731 if (rc) {
732 ksmbd_debug(AUTH, "could not update with L\n");
733 goto smb3signkey_ret;
734 }
735
736 rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr);
737 if (rc) {
738 ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
070fb21e 739 rc);
e2f34481
NJ
740 goto smb3signkey_ret;
741 }
742
743 memcpy(key, hashptr, key_size);
744
745smb3signkey_ret:
746 ksmbd_release_crypto_ctx(ctx);
747 return rc;
748}
749
750static int generate_smb3signingkey(struct ksmbd_session *sess,
f5a544e3 751 struct ksmbd_conn *conn,
070fb21e 752 const struct derivation *signing)
e2f34481
NJ
753{
754 int rc;
755 struct channel *chann;
756 char *key;
757
f5a544e3 758 chann = lookup_chann_list(sess, conn);
e2f34481
NJ
759 if (!chann)
760 return 0;
761
af7c39d9 762 if (conn->dialect >= SMB30_PROT_ID && signing->binding)
e2f34481
NJ
763 key = chann->smb3signingkey;
764 else
765 key = sess->smb3signingkey;
766
af7c39d9 767 rc = generate_key(conn, sess, signing->label, signing->context, key,
070fb21e 768 SMB3_SIGN_KEY_SIZE);
e2f34481
NJ
769 if (rc)
770 return rc;
771
af7c39d9 772 if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
e2f34481
NJ
773 memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
774
775 ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
776 ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
777 ksmbd_debug(AUTH, "Session Key %*ph\n",
070fb21e 778 SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
e2f34481 779 ksmbd_debug(AUTH, "Signing Key %*ph\n",
070fb21e 780 SMB3_SIGN_KEY_SIZE, key);
876edcc4 781 return 0;
e2f34481
NJ
782}
783
f5a544e3
NJ
784int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
785 struct ksmbd_conn *conn)
e2f34481
NJ
786{
787 struct derivation d;
788
789 d.label.iov_base = "SMB2AESCMAC";
790 d.label.iov_len = 12;
791 d.context.iov_base = "SmbSign";
792 d.context.iov_len = 8;
f5a544e3 793 d.binding = conn->binding;
e2f34481 794
f5a544e3 795 return generate_smb3signingkey(sess, conn, &d);
e2f34481
NJ
796}
797
f5a544e3
NJ
798int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
799 struct ksmbd_conn *conn)
e2f34481
NJ
800{
801 struct derivation d;
802
803 d.label.iov_base = "SMBSigningKey";
804 d.label.iov_len = 14;
f5a544e3
NJ
805 if (conn->binding) {
806 struct preauth_session *preauth_sess;
807
808 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
809 if (!preauth_sess)
810 return -ENOENT;
811 d.context.iov_base = preauth_sess->Preauth_HashValue;
812 } else {
813 d.context.iov_base = sess->Preauth_HashValue;
814 }
e2f34481 815 d.context.iov_len = 64;
f5a544e3 816 d.binding = conn->binding;
e2f34481 817
f5a544e3 818 return generate_smb3signingkey(sess, conn, &d);
e2f34481
NJ
819}
820
821struct derivation_twin {
822 struct derivation encryption;
823 struct derivation decryption;
824};
825
af7c39d9
NJ
826static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
827 struct ksmbd_session *sess,
070fb21e 828 const struct derivation_twin *ptwin)
e2f34481
NJ
829{
830 int rc;
831
af7c39d9 832 rc = generate_key(conn, sess, ptwin->encryption.label,
070fb21e
NJ
833 ptwin->encryption.context, sess->smb3encryptionkey,
834 SMB3_ENC_DEC_KEY_SIZE);
e2f34481
NJ
835 if (rc)
836 return rc;
837
af7c39d9 838 rc = generate_key(conn, sess, ptwin->decryption.label,
070fb21e
NJ
839 ptwin->decryption.context,
840 sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
e2f34481
NJ
841 if (rc)
842 return rc;
843
844 ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
af7c39d9 845 ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type);
e2f34481
NJ
846 ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
847 ksmbd_debug(AUTH, "Session Key %*ph\n",
070fb21e 848 SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
af7c39d9
NJ
849 if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
850 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
5a0ca770 851 ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
070fb21e 852 SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
5a0ca770 853 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
070fb21e 854 SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
5a0ca770
NJ
855 } else {
856 ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
070fb21e 857 SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
5a0ca770 858 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
070fb21e 859 SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
5a0ca770 860 }
876edcc4 861 return 0;
e2f34481
NJ
862}
863
af7c39d9
NJ
864int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
865 struct ksmbd_session *sess)
e2f34481
NJ
866{
867 struct derivation_twin twin;
868 struct derivation *d;
869
870 d = &twin.encryption;
871 d->label.iov_base = "SMB2AESCCM";
872 d->label.iov_len = 11;
873 d->context.iov_base = "ServerOut";
874 d->context.iov_len = 10;
875
876 d = &twin.decryption;
877 d->label.iov_base = "SMB2AESCCM";
878 d->label.iov_len = 11;
879 d->context.iov_base = "ServerIn ";
880 d->context.iov_len = 10;
881
af7c39d9 882 return generate_smb3encryptionkey(conn, sess, &twin);
e2f34481
NJ
883}
884
af7c39d9
NJ
885int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
886 struct ksmbd_session *sess)
e2f34481
NJ
887{
888 struct derivation_twin twin;
889 struct derivation *d;
890
891 d = &twin.encryption;
892 d->label.iov_base = "SMBS2CCipherKey";
893 d->label.iov_len = 16;
894 d->context.iov_base = sess->Preauth_HashValue;
895 d->context.iov_len = 64;
896
897 d = &twin.decryption;
898 d->label.iov_base = "SMBC2SCipherKey";
899 d->label.iov_len = 16;
900 d->context.iov_base = sess->Preauth_HashValue;
901 d->context.iov_len = 64;
902
af7c39d9 903 return generate_smb3encryptionkey(conn, sess, &twin);
e2f34481
NJ
904}
905
64b39f4a 906int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
070fb21e 907 __u8 *pi_hash)
e2f34481 908{
0e579cd1 909 int rc;
cb451720 910 struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
e2f34481 911 char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
cb451720 912 int msg_size = get_rfc1002_len(buf);
e2f34481
NJ
913 struct ksmbd_crypto_ctx *ctx = NULL;
914
d3cd8c49
NJ
915 if (conn->preauth_info->Preauth_HashId !=
916 SMB2_PREAUTH_INTEGRITY_SHA512)
917 return -EINVAL;
918
919 ctx = ksmbd_crypto_ctx_find_sha512();
920 if (!ctx) {
0e579cd1
NJ
921 ksmbd_debug(AUTH, "could not alloc sha512\n");
922 return -ENOMEM;
64b39f4a 923 }
e2f34481
NJ
924
925 rc = crypto_shash_init(CRYPTO_SHA512(ctx));
926 if (rc) {
927 ksmbd_debug(AUTH, "could not init shashn");
928 goto out;
929 }
930
931 rc = crypto_shash_update(CRYPTO_SHA512(ctx), pi_hash, 64);
932 if (rc) {
933 ksmbd_debug(AUTH, "could not update with n\n");
934 goto out;
935 }
936
937 rc = crypto_shash_update(CRYPTO_SHA512(ctx), all_bytes_msg, msg_size);
938 if (rc) {
939 ksmbd_debug(AUTH, "could not update with n\n");
940 goto out;
941 }
942
943 rc = crypto_shash_final(CRYPTO_SHA512(ctx), pi_hash);
944 if (rc) {
945 ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
946 goto out;
947 }
948out:
949 ksmbd_release_crypto_ctx(ctx);
950 return rc;
951}
952
953int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
070fb21e 954 __u8 *pi_hash)
e2f34481 955{
0e579cd1 956 int rc;
e2f34481
NJ
957 struct ksmbd_crypto_ctx *ctx = NULL;
958
959 ctx = ksmbd_crypto_ctx_find_sha256();
960 if (!ctx) {
0e579cd1
NJ
961 ksmbd_debug(AUTH, "could not alloc sha256\n");
962 return -ENOMEM;
e2f34481
NJ
963 }
964
965 rc = crypto_shash_init(CRYPTO_SHA256(ctx));
966 if (rc) {
967 ksmbd_debug(AUTH, "could not init shashn");
968 goto out;
969 }
970
971 rc = crypto_shash_update(CRYPTO_SHA256(ctx), sd_buf, len);
972 if (rc) {
973 ksmbd_debug(AUTH, "could not update with n\n");
974 goto out;
975 }
976
977 rc = crypto_shash_final(CRYPTO_SHA256(ctx), pi_hash);
978 if (rc) {
979 ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
980 goto out;
981 }
982out:
983 ksmbd_release_crypto_ctx(ctx);
984 return rc;
985}
986
64b39f4a 987static int ksmbd_get_encryption_key(struct ksmbd_conn *conn, __u64 ses_id,
070fb21e 988 int enc, u8 *key)
e2f34481
NJ
989{
990 struct ksmbd_session *sess;
991 u8 *ses_enc_key;
992
f5a544e3 993 sess = ksmbd_session_lookup_all(conn, ses_id);
e2f34481 994 if (!sess)
522dcc76 995 return -EINVAL;
e2f34481
NJ
996
997 ses_enc_key = enc ? sess->smb3encryptionkey :
998 sess->smb3decryptionkey;
5a0ca770 999 memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
e2f34481
NJ
1000
1001 return 0;
1002}
1003
1004static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
070fb21e 1005 unsigned int buflen)
e2f34481
NJ
1006{
1007 void *addr;
1008
1009 if (is_vmalloc_addr(buf))
1010 addr = vmalloc_to_page(buf);
1011 else
1012 addr = virt_to_page(buf);
1013 sg_set_page(sg, addr, buflen, offset_in_page(buf));
1014}
1015
64b39f4a 1016static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
070fb21e 1017 u8 *sign)
e2f34481
NJ
1018{
1019 struct scatterlist *sg;
2dd9129f 1020 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
e2f34481
NJ
1021 int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
1022
41a7848a
NJ
1023 if (!nvec)
1024 return NULL;
1025
e2f34481
NJ
1026 for (i = 0; i < nvec - 1; i++) {
1027 unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
1028
1029 if (is_vmalloc_addr(iov[i + 1].iov_base)) {
1030 nr_entries[i] = ((kaddr + iov[i + 1].iov_len +
1031 PAGE_SIZE - 1) >> PAGE_SHIFT) -
1032 (kaddr >> PAGE_SHIFT);
64b39f4a 1033 } else {
e2f34481 1034 nr_entries[i]++;
64b39f4a 1035 }
e2f34481
NJ
1036 total_entries += nr_entries[i];
1037 }
1038
1039 /* Add two entries for transform header and signature */
1040 total_entries += 2;
1041
1042 sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
1043 if (!sg)
1044 return NULL;
1045
1046 sg_init_table(sg, total_entries);
1047 smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
1048 for (i = 0; i < nvec - 1; i++) {
1049 void *data = iov[i + 1].iov_base;
1050 int len = iov[i + 1].iov_len;
1051
1052 if (is_vmalloc_addr(data)) {
1053 int j, offset = offset_in_page(data);
1054
1055 for (j = 0; j < nr_entries[i]; j++) {
1056 unsigned int bytes = PAGE_SIZE - offset;
1057
08591ccf 1058 if (!len)
e2f34481
NJ
1059 break;
1060
1061 if (bytes > len)
1062 bytes = len;
1063
1064 sg_set_page(&sg[sg_idx++],
1065 vmalloc_to_page(data), bytes,
1066 offset_in_page(data));
1067
1068 data += bytes;
1069 len -= bytes;
1070 offset = 0;
1071 }
1072 } else {
1073 sg_set_page(&sg[sg_idx++], virt_to_page(data), len,
1074 offset_in_page(data));
1075 }
e2f34481
NJ
1076 }
1077 smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
1078 return sg;
1079}
1080
64b39f4a 1081int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
070fb21e 1082 unsigned int nvec, int enc)
e2f34481 1083{
2dd9129f
NJ
1084 struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
1085 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
03f1c3d3 1086 int rc;
e2f34481
NJ
1087 struct scatterlist *sg;
1088 u8 sign[SMB2_SIGNATURE_SIZE] = {};
5a0ca770 1089 u8 key[SMB3_ENC_DEC_KEY_SIZE];
e2f34481
NJ
1090 struct aead_request *req;
1091 char *iv;
1092 unsigned int iv_len;
1093 struct crypto_aead *tfm;
1094 unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
1095 struct ksmbd_crypto_ctx *ctx;
1096
1097 rc = ksmbd_get_encryption_key(conn,
1098 le64_to_cpu(tr_hdr->SessionId),
1099 enc,
1100 key);
1101 if (rc) {
bde1694a 1102 pr_err("Could not get %scryption key\n", enc ? "en" : "de");
27aa646d 1103 return rc;
e2f34481
NJ
1104 }
1105
5a0ca770
NJ
1106 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1107 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
e2f34481
NJ
1108 ctx = ksmbd_crypto_ctx_find_gcm();
1109 else
1110 ctx = ksmbd_crypto_ctx_find_ccm();
1111 if (!ctx) {
bde1694a 1112 pr_err("crypto alloc failed\n");
0e579cd1 1113 return -ENOMEM;
e2f34481
NJ
1114 }
1115
5a0ca770
NJ
1116 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1117 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
e2f34481
NJ
1118 tfm = CRYPTO_GCM(ctx);
1119 else
1120 tfm = CRYPTO_CCM(ctx);
1121
5a0ca770
NJ
1122 if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
1123 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
1124 rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
1125 else
1126 rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
e2f34481 1127 if (rc) {
bde1694a 1128 pr_err("Failed to set aead key %d\n", rc);
e2f34481
NJ
1129 goto free_ctx;
1130 }
1131
1132 rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
1133 if (rc) {
bde1694a 1134 pr_err("Failed to set authsize %d\n", rc);
e2f34481
NJ
1135 goto free_ctx;
1136 }
1137
1138 req = aead_request_alloc(tfm, GFP_KERNEL);
1139 if (!req) {
e2f34481
NJ
1140 rc = -ENOMEM;
1141 goto free_ctx;
1142 }
1143
1144 if (!enc) {
1145 memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
1146 crypt_len += SMB2_SIGNATURE_SIZE;
1147 }
1148
1149 sg = ksmbd_init_sg(iov, nvec, sign);
1150 if (!sg) {
bde1694a 1151 pr_err("Failed to init sg\n");
e2f34481
NJ
1152 rc = -ENOMEM;
1153 goto free_req;
1154 }
1155
1156 iv_len = crypto_aead_ivsize(tfm);
1157 iv = kzalloc(iv_len, GFP_KERNEL);
1158 if (!iv) {
e2f34481
NJ
1159 rc = -ENOMEM;
1160 goto free_sg;
1161 }
1162
5a0ca770
NJ
1163 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1164 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
1165 memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
64b39f4a 1166 } else {
e2f34481 1167 iv[0] = 3;
5a0ca770 1168 memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
e2f34481
NJ
1169 }
1170
1171 aead_request_set_crypt(req, sg, sg, crypt_len, iv);
1172 aead_request_set_ad(req, assoc_data_len);
1173 aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
1174
1175 if (enc)
1176 rc = crypto_aead_encrypt(req);
1177 else
1178 rc = crypto_aead_decrypt(req);
73b8b085
NJ
1179 if (rc)
1180 goto free_iv;
1181
1182 if (enc)
e2f34481
NJ
1183 memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
1184
73b8b085 1185free_iv:
e2f34481
NJ
1186 kfree(iv);
1187free_sg:
1188 kfree(sg);
1189free_req:
1190 kfree(req);
1191free_ctx:
1192 ksmbd_release_crypto_ctx(ctx);
1193 return rc;
1194}