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