File Index
Files and directories
Sign in
FILE

auth.c

File preview with syntax highlighting.

linux-6.19.14/fs/smb/server/auth.c C
  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 <crypto/md5.h>
 17#include <crypto/sha2.h>
 18#include <crypto/utils.h>
 19#include <linux/random.h>
 20#include <linux/scatterlist.h>
 21
 22#include "auth.h"
 23#include "glob.h"
 24
 25#include <linux/fips.h>
 26#include <crypto/arc4.h>
 27#include <crypto/des.h>
 28
 29#include "server.h"
 30#include "smb_common.h"
 31#include "connection.h"
 32#include "mgmt/user_session.h"
 33#include "mgmt/user_config.h"
 34#include "crypto_ctx.h"
 35#include "transport_ipc.h"
 36
 37/*
 38 * Fixed format data defining GSS header and fixed string
 39 * "not_defined_in_RFC4178@please_ignore".
 40 * So sec blob data in neg phase could be generated statically.
 41 */
 42static char NEGOTIATE_GSS_HEADER[AUTH_GSS_LENGTH] = {
 43#ifdef CONFIG_SMB_SERVER_KERBEROS5
 44	0x60, 0x5e, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
 45	0x05, 0x02, 0xa0, 0x54, 0x30, 0x52, 0xa0, 0x24,
 46	0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
 47	0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a,
 48	0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02,
 49	0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
 50	0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a, 0x30, 0x28,
 51	0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f, 0x74, 0x5f,
 52	0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f,
 53	0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43, 0x34, 0x31,
 54	0x37, 0x38, 0x40, 0x70, 0x6c, 0x65, 0x61, 0x73,
 55	0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65
 56#else
 57	0x60, 0x48, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
 58	0x05, 0x02, 0xa0, 0x3e, 0x30, 0x3c, 0xa0, 0x0e,
 59	0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
 60	0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a,
 61	0x30, 0x28, 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f,
 62	0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
 63	0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43,
 64	0x34, 0x31, 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65,
 65	0x61, 0x73, 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f,
 66	0x72, 0x65
 67#endif
 68};
 69
 70void ksmbd_copy_gss_neg_header(void *buf)
 71{
 72	memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
 73}
 74
 75static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
 76			    char *ntlmv2_hash, char *dname)
 77{
 78	int ret, len, conv_len;
 79	wchar_t *domain = NULL;
 80	__le16 *uniname = NULL;
 81	struct hmac_md5_ctx ctx;
 82
 83	hmac_md5_init_usingrawkey(&ctx, user_passkey(sess->user),
 84				  CIFS_ENCPWD_SIZE);
 85
 86	/* convert user_name to unicode */
 87	len = strlen(user_name(sess->user));
 88	uniname = kzalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
 89	if (!uniname) {
 90		ret = -ENOMEM;
 91		goto out;
 92	}
 93
 94	conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
 95				  conn->local_nls);
 96	if (conv_len < 0 || conv_len > len) {
 97		ret = -EINVAL;
 98		goto out;
 99	}
100	UniStrupr(uniname);
101
102	hmac_md5_update(&ctx, (const u8 *)uniname, UNICODE_LEN(conv_len));
103
104	/* Convert domain name or conn name to unicode and uppercase */
105	len = strlen(dname);
106	domain = kzalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
107	if (!domain) {
108		ret = -ENOMEM;
109		goto out;
110	}
111
112	conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
113				  conn->local_nls);
114	if (conv_len < 0 || conv_len > len) {
115		ret = -EINVAL;
116		goto out;
117	}
118
119	hmac_md5_update(&ctx, (const u8 *)domain, UNICODE_LEN(conv_len));
120	hmac_md5_final(&ctx, ntlmv2_hash);
121	ret = 0;
122out:
123	kfree(uniname);
124	kfree(domain);
125	return ret;
126}
127
128/**
129 * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
130 * @conn:		connection
131 * @sess:		session of connection
132 * @ntlmv2:		NTLMv2 challenge response
133 * @blen:		NTLMv2 blob length
134 * @domain_name:	domain name
135 * @cryptkey:		session crypto key
136 *
137 * Return:	0 on success, error number on error
138 */
139int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
140		      struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
141		      char *cryptkey)
142{
143	char ntlmv2_hash[CIFS_ENCPWD_SIZE];
144	char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
145	struct hmac_md5_ctx ctx;
146	int rc;
147
148	if (fips_enabled) {
149		ksmbd_debug(AUTH, "NTLMv2 support is disabled due to FIPS\n");
150		return -EOPNOTSUPP;
151	}
152
153	rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name);
154	if (rc) {
155		ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
156		return rc;
157	}
158
159	hmac_md5_init_usingrawkey(&ctx, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
160	hmac_md5_update(&ctx, cryptkey, CIFS_CRYPTO_KEY_SIZE);
161	hmac_md5_update(&ctx, (const u8 *)&ntlmv2->blob_signature, blen);
162	hmac_md5_final(&ctx, ntlmv2_rsp);
163
164	/* Generate the session key */
165	hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
166			     ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE,
167			     sess->sess_key);
168
169	if (crypto_memneq(ntlmv2->ntlmv2_hash, ntlmv2_rsp,
170			  CIFS_HMAC_MD5_HASH_SIZE))
171		return -EINVAL;
172	return 0;
173}
174
175/**
176 * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
177 * authenticate blob
178 * @authblob:	authenticate blob source pointer
179 * @blob_len:	length of the @authblob message
180 * @conn:	connection
181 * @sess:	session of connection
182 *
183 * Return:	0 on success, error number on error
184 */
185int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
186				   int blob_len, struct ksmbd_conn *conn,
187				   struct ksmbd_session *sess)
188{
189	char *domain_name;
190	unsigned int nt_off, dn_off;
191	unsigned short nt_len, dn_len;
192	int ret;
193
194	if (blob_len < sizeof(struct authenticate_message)) {
195		ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
196			    blob_len);
197		return -EINVAL;
198	}
199
200	if (memcmp(authblob->Signature, "NTLMSSP", 8)) {
201		ksmbd_debug(AUTH, "blob signature incorrect %s\n",
202			    authblob->Signature);
203		return -EINVAL;
204	}
205
206	nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
207	nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
208	dn_off = le32_to_cpu(authblob->DomainName.BufferOffset);
209	dn_len = le16_to_cpu(authblob->DomainName.Length);
210
211	if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len ||
212	    nt_len < CIFS_ENCPWD_SIZE)
213		return -EINVAL;
214
215	/* TODO : use domain name that imported from configuration file */
216	domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off,
217					     dn_len, true, conn->local_nls);
218	if (IS_ERR(domain_name))
219		return PTR_ERR(domain_name);
220
221	/* process NTLMv2 authentication */
222	ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n",
223		    domain_name);
224	ret = ksmbd_auth_ntlmv2(conn, sess,
225				(struct ntlmv2_resp *)((char *)authblob + nt_off),
226				nt_len - CIFS_ENCPWD_SIZE,
227				domain_name, conn->ntlmssp.cryptkey);
228	kfree(domain_name);
229
230	/* The recovered secondary session key */
231	if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) {
232		struct arc4_ctx *ctx_arc4;
233		unsigned int sess_key_off, sess_key_len;
234
235		sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset);
236		sess_key_len = le16_to_cpu(authblob->SessionKey.Length);
237
238		if (blob_len < (u64)sess_key_off + sess_key_len)
239			return -EINVAL;
240
241		if (sess_key_len > CIFS_KEY_SIZE)
242			return -EINVAL;
243
244		ctx_arc4 = kmalloc(sizeof(*ctx_arc4), KSMBD_DEFAULT_GFP);
245		if (!ctx_arc4)
246			return -ENOMEM;
247
248		arc4_setkey(ctx_arc4, sess->sess_key, SMB2_NTLMV2_SESSKEY_SIZE);
249		arc4_crypt(ctx_arc4, sess->sess_key,
250			   (char *)authblob + sess_key_off, sess_key_len);
251		kfree_sensitive(ctx_arc4);
252	}
253
254	return ret;
255}
256
257/**
258 * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
259 * negotiate blob
260 * @negblob: negotiate blob source pointer
261 * @blob_len:	length of the @authblob message
262 * @conn:	connection
263 *
264 */
265int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
266				  int blob_len, struct ksmbd_conn *conn)
267{
268	if (blob_len < sizeof(struct negotiate_message)) {
269		ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
270			    blob_len);
271		return -EINVAL;
272	}
273
274	if (memcmp(negblob->Signature, "NTLMSSP", 8)) {
275		ksmbd_debug(AUTH, "blob signature incorrect %s\n",
276			    negblob->Signature);
277		return -EINVAL;
278	}
279
280	conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags);
281	return 0;
282}
283
284/**
285 * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
286 * challenge blob
287 * @chgblob: challenge blob source pointer to initialize
288 * @conn:	connection
289 *
290 */
291unsigned int
292ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
293				   struct ksmbd_conn *conn)
294{
295	struct target_info *tinfo;
296	wchar_t *name;
297	__u8 *target_name;
298	unsigned int flags, blob_off, blob_len, type, target_info_len = 0;
299	int len, uni_len, conv_len;
300	int cflags = conn->ntlmssp.client_flags;
301
302	memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
303	chgblob->MessageType = NtLmChallenge;
304
305	flags = NTLMSSP_NEGOTIATE_UNICODE |
306		NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_TARGET_TYPE_SERVER |
307		NTLMSSP_NEGOTIATE_TARGET_INFO;
308
309	if (cflags & NTLMSSP_NEGOTIATE_SIGN) {
310		flags |= NTLMSSP_NEGOTIATE_SIGN;
311		flags |= cflags & (NTLMSSP_NEGOTIATE_128 |
312				   NTLMSSP_NEGOTIATE_56);
313	}
314
315	if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn))
316		flags |= NTLMSSP_NEGOTIATE_SEAL;
317
318	if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
319		flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
320
321	if (cflags & NTLMSSP_REQUEST_TARGET)
322		flags |= NTLMSSP_REQUEST_TARGET;
323
324	if (conn->use_spnego &&
325	    (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
326		flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
327
328	if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
329		flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
330
331	chgblob->NegotiateFlags = cpu_to_le32(flags);
332	len = strlen(ksmbd_netbios_name());
333	name = kmalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
334	if (!name)
335		return -ENOMEM;
336
337	conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
338				  conn->local_nls);
339	if (conv_len < 0 || conv_len > len) {
340		kfree(name);
341		return -EINVAL;
342	}
343
344	uni_len = UNICODE_LEN(conv_len);
345
346	blob_off = sizeof(struct challenge_message);
347	blob_len = blob_off + uni_len;
348
349	chgblob->TargetName.Length = cpu_to_le16(uni_len);
350	chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len);
351	chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
352
353	/* Initialize random conn challenge */
354	get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64));
355	memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey,
356	       CIFS_CRYPTO_KEY_SIZE);
357
358	/* Add Target Information to security buffer */
359	chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
360
361	target_name = (__u8 *)chgblob + blob_off;
362	memcpy(target_name, name, uni_len);
363	tinfo = (struct target_info *)(target_name + uni_len);
364
365	chgblob->TargetInfoArray.Length = 0;
366	/* Add target info list for NetBIOS/DNS settings */
367	for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
368	     type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
369		tinfo->Type = cpu_to_le16(type);
370		tinfo->Length = cpu_to_le16(uni_len);
371		memcpy(tinfo->Content, name, uni_len);
372		tinfo = (struct target_info *)((char *)tinfo + 4 + uni_len);
373		target_info_len += 4 + uni_len;
374	}
375
376	/* Add terminator subblock */
377	tinfo->Type = 0;
378	tinfo->Length = 0;
379	target_info_len += 4;
380
381	chgblob->TargetInfoArray.Length = cpu_to_le16(target_info_len);
382	chgblob->TargetInfoArray.MaximumLength = cpu_to_le16(target_info_len);
383	blob_len += target_info_len;
384	kfree(name);
385	ksmbd_debug(AUTH, "NTLMSSP SecurityBufferLength %d\n", blob_len);
386	return blob_len;
387}
388
389#ifdef CONFIG_SMB_SERVER_KERBEROS5
390int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
391			    int in_len, char *out_blob, int *out_len)
392{
393	struct ksmbd_spnego_authen_response *resp;
394	struct ksmbd_login_response_ext *resp_ext = NULL;
395	struct ksmbd_user *user = NULL;
396	int retval;
397
398	resp = ksmbd_ipc_spnego_authen_request(in_blob, in_len);
399	if (!resp) {
400		ksmbd_debug(AUTH, "SPNEGO_AUTHEN_REQUEST failure\n");
401		return -EINVAL;
402	}
403
404	if (!(resp->login_response.status & KSMBD_USER_FLAG_OK)) {
405		ksmbd_debug(AUTH, "krb5 authentication failure\n");
406		retval = -EPERM;
407		goto out;
408	}
409
410	if (*out_len <= resp->spnego_blob_len) {
411		ksmbd_debug(AUTH, "buf len %d, but blob len %d\n",
412			    *out_len, resp->spnego_blob_len);
413		retval = -EINVAL;
414		goto out;
415	}
416
417	if (resp->session_key_len > sizeof(sess->sess_key)) {
418		ksmbd_debug(AUTH, "session key is too long\n");
419		retval = -EINVAL;
420		goto out;
421	}
422
423	if (resp->login_response.status & KSMBD_USER_FLAG_EXTENSION)
424		resp_ext = ksmbd_ipc_login_request_ext(resp->login_response.account);
425
426	user = ksmbd_alloc_user(&resp->login_response, resp_ext);
427	if (!user) {
428		ksmbd_debug(AUTH, "login failure\n");
429		retval = -ENOMEM;
430		goto out;
431	}
432
433	if (!sess->user) {
434		/* First successful authentication */
435		sess->user = user;
436	} else {
437		if (!ksmbd_compare_user(sess->user, user)) {
438			ksmbd_debug(AUTH, "different user tried to reuse session\n");
439			retval = -EPERM;
440			ksmbd_free_user(user);
441			goto out;
442		}
443		ksmbd_free_user(user);
444	}
445
446	memcpy(sess->sess_key, resp->payload, resp->session_key_len);
447	memcpy(out_blob, resp->payload + resp->session_key_len,
448	       resp->spnego_blob_len);
449	*out_len = resp->spnego_blob_len;
450	retval = 0;
451out:
452	kvfree(resp);
453	return retval;
454}
455#else
456int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
457			    int in_len, char *out_blob, int *out_len)
458{
459	return -EOPNOTSUPP;
460}
461#endif
462
463/**
464 * ksmbd_sign_smb2_pdu() - function to generate packet signing
465 * @conn:	connection
466 * @key:	signing key
467 * @iov:        buffer iov array
468 * @n_vec:	number of iovecs
469 * @sig:	signature value generated for client request packet
470 *
471 */
472void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
473			 int n_vec, char *sig)
474{
475	struct hmac_sha256_ctx ctx;
476	int i;
477
478	hmac_sha256_init_usingrawkey(&ctx, key, SMB2_NTLMV2_SESSKEY_SIZE);
479	for (i = 0; i < n_vec; i++)
480		hmac_sha256_update(&ctx, iov[i].iov_base, iov[i].iov_len);
481	hmac_sha256_final(&ctx, sig);
482}
483
484/**
485 * ksmbd_sign_smb3_pdu() - function to generate packet signing
486 * @conn:	connection
487 * @key:	signing key
488 * @iov:        buffer iov array
489 * @n_vec:	number of iovecs
490 * @sig:	signature value generated for client request packet
491 *
492 */
493int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
494			int n_vec, char *sig)
495{
496	struct ksmbd_crypto_ctx *ctx;
497	int rc, i;
498
499	ctx = ksmbd_crypto_ctx_find_cmacaes();
500	if (!ctx) {
501		ksmbd_debug(AUTH, "could not crypto alloc cmac\n");
502		return -ENOMEM;
503	}
504
505	rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx),
506				 key,
507				 SMB2_CMACAES_SIZE);
508	if (rc)
509		goto out;
510
511	rc = crypto_shash_init(CRYPTO_CMACAES(ctx));
512	if (rc) {
513		ksmbd_debug(AUTH, "cmaces init error %d\n", rc);
514		goto out;
515	}
516
517	for (i = 0; i < n_vec; i++) {
518		rc = crypto_shash_update(CRYPTO_CMACAES(ctx),
519					 iov[i].iov_base,
520					 iov[i].iov_len);
521		if (rc) {
522			ksmbd_debug(AUTH, "cmaces update error %d\n", rc);
523			goto out;
524		}
525	}
526
527	rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig);
528	if (rc)
529		ksmbd_debug(AUTH, "cmaces generation error %d\n", rc);
530out:
531	ksmbd_release_crypto_ctx(ctx);
532	return rc;
533}
534
535struct derivation {
536	struct kvec label;
537	struct kvec context;
538	bool binding;
539};
540
541static void generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
542			 struct kvec label, struct kvec context, __u8 *key,
543			 unsigned int key_size)
544{
545	unsigned char zero = 0x0;
546	__u8 i[4] = {0, 0, 0, 1};
547	__u8 L128[4] = {0, 0, 0, 128};
548	__u8 L256[4] = {0, 0, 1, 0};
549	unsigned char prfhash[SMB2_HMACSHA256_SIZE];
550	struct hmac_sha256_ctx ctx;
551
552	hmac_sha256_init_usingrawkey(&ctx, sess->sess_key,
553				     SMB2_NTLMV2_SESSKEY_SIZE);
554	hmac_sha256_update(&ctx, i, 4);
555	hmac_sha256_update(&ctx, label.iov_base, label.iov_len);
556	hmac_sha256_update(&ctx, &zero, 1);
557	hmac_sha256_update(&ctx, context.iov_base, context.iov_len);
558
559	if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
560	    (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
561	     conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
562		hmac_sha256_update(&ctx, L256, 4);
563	else
564		hmac_sha256_update(&ctx, L128, 4);
565
566	hmac_sha256_final(&ctx, prfhash);
567	memcpy(key, prfhash, key_size);
568}
569
570static int generate_smb3signingkey(struct ksmbd_session *sess,
571				   struct ksmbd_conn *conn,
572				   const struct derivation *signing)
573{
574	struct channel *chann;
575	char *key;
576
577	chann = lookup_chann_list(sess, conn);
578	if (!chann)
579		return 0;
580
581	if (conn->dialect >= SMB30_PROT_ID && signing->binding)
582		key = chann->smb3signingkey;
583	else
584		key = sess->smb3signingkey;
585
586	generate_key(conn, sess, signing->label, signing->context, key,
587		     SMB3_SIGN_KEY_SIZE);
588
589	if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
590		memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
591
592	ksmbd_debug(AUTH, "generated SMB3 signing key\n");
593	ksmbd_debug(AUTH, "Session Id    %llu\n", sess->id);
594	return 0;
595}
596
597int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
598			       struct ksmbd_conn *conn)
599{
600	struct derivation d;
601
602	d.label.iov_base = "SMB2AESCMAC";
603	d.label.iov_len = 12;
604	d.context.iov_base = "SmbSign";
605	d.context.iov_len = 8;
606	d.binding = conn->binding;
607
608	return generate_smb3signingkey(sess, conn, &d);
609}
610
611int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
612				struct ksmbd_conn *conn)
613{
614	struct derivation d;
615
616	d.label.iov_base = "SMBSigningKey";
617	d.label.iov_len = 14;
618	if (conn->binding) {
619		struct preauth_session *preauth_sess;
620
621		preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
622		if (!preauth_sess)
623			return -ENOENT;
624		d.context.iov_base = preauth_sess->Preauth_HashValue;
625	} else {
626		d.context.iov_base = sess->Preauth_HashValue;
627	}
628	d.context.iov_len = 64;
629	d.binding = conn->binding;
630
631	return generate_smb3signingkey(sess, conn, &d);
632}
633
634struct derivation_twin {
635	struct derivation encryption;
636	struct derivation decryption;
637};
638
639static void generate_smb3encryptionkey(struct ksmbd_conn *conn,
640				       struct ksmbd_session *sess,
641				       const struct derivation_twin *ptwin)
642{
643	generate_key(conn, sess, ptwin->encryption.label,
644		     ptwin->encryption.context, sess->smb3encryptionkey,
645		     SMB3_ENC_DEC_KEY_SIZE);
646
647	generate_key(conn, sess, ptwin->decryption.label,
648		     ptwin->decryption.context,
649		     sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
650
651	ksmbd_debug(AUTH, "generated SMB3 encryption/decryption keys\n");
652	ksmbd_debug(AUTH, "Cipher type   %d\n", conn->cipher_type);
653	ksmbd_debug(AUTH, "Session Id    %llu\n", sess->id);
654}
655
656void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
657				   struct ksmbd_session *sess)
658{
659	struct derivation_twin twin;
660	struct derivation *d;
661
662	d = &twin.encryption;
663	d->label.iov_base = "SMB2AESCCM";
664	d->label.iov_len = 11;
665	d->context.iov_base = "ServerOut";
666	d->context.iov_len = 10;
667
668	d = &twin.decryption;
669	d->label.iov_base = "SMB2AESCCM";
670	d->label.iov_len = 11;
671	d->context.iov_base = "ServerIn ";
672	d->context.iov_len = 10;
673
674	generate_smb3encryptionkey(conn, sess, &twin);
675}
676
677void ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
678				    struct ksmbd_session *sess)
679{
680	struct derivation_twin twin;
681	struct derivation *d;
682
683	d = &twin.encryption;
684	d->label.iov_base = "SMBS2CCipherKey";
685	d->label.iov_len = 16;
686	d->context.iov_base = sess->Preauth_HashValue;
687	d->context.iov_len = 64;
688
689	d = &twin.decryption;
690	d->label.iov_base = "SMBC2SCipherKey";
691	d->label.iov_len = 16;
692	d->context.iov_base = sess->Preauth_HashValue;
693	d->context.iov_len = 64;
694
695	generate_smb3encryptionkey(conn, sess, &twin);
696}
697
698int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
699				     __u8 *pi_hash)
700{
701	struct smb2_hdr *rcv_hdr = smb_get_msg(buf);
702	char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
703	int msg_size = get_rfc1002_len(buf);
704	struct sha512_ctx sha_ctx;
705
706	if (conn->preauth_info->Preauth_HashId !=
707	    SMB2_PREAUTH_INTEGRITY_SHA512)
708		return -EINVAL;
709
710	sha512_init(&sha_ctx);
711	sha512_update(&sha_ctx, pi_hash, 64);
712	sha512_update(&sha_ctx, all_bytes_msg, msg_size);
713	sha512_final(&sha_ctx, pi_hash);
714	return 0;
715}
716
717static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
718				    int enc, u8 *key)
719{
720	struct ksmbd_session *sess;
721	u8 *ses_enc_key;
722
723	if (enc)
724		sess = work->sess;
725	else
726		sess = ksmbd_session_lookup_all(work->conn, ses_id);
727	if (!sess)
728		return -EINVAL;
729
730	ses_enc_key = enc ? sess->smb3encryptionkey :
731		sess->smb3decryptionkey;
732	memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
733	if (!enc)
734		ksmbd_user_session_put(sess);
735
736	return 0;
737}
738
739static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
740				   unsigned int buflen)
741{
742	void *addr;
743
744	if (is_vmalloc_addr(buf))
745		addr = vmalloc_to_page(buf);
746	else
747		addr = virt_to_page(buf);
748	sg_set_page(sg, addr, buflen, offset_in_page(buf));
749}
750
751static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
752					 u8 *sign)
753{
754	struct scatterlist *sg;
755	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
756	int i, *nr_entries, total_entries = 0, sg_idx = 0;
757
758	if (!nvec)
759		return NULL;
760
761	nr_entries = kcalloc(nvec, sizeof(int), KSMBD_DEFAULT_GFP);
762	if (!nr_entries)
763		return NULL;
764
765	for (i = 0; i < nvec - 1; i++) {
766		unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
767
768		if (is_vmalloc_addr(iov[i + 1].iov_base)) {
769			nr_entries[i] = ((kaddr + iov[i + 1].iov_len +
770					PAGE_SIZE - 1) >> PAGE_SHIFT) -
771				(kaddr >> PAGE_SHIFT);
772		} else {
773			nr_entries[i]++;
774		}
775		total_entries += nr_entries[i];
776	}
777
778	/* Add two entries for transform header and signature */
779	total_entries += 2;
780
781	sg = kmalloc_array(total_entries, sizeof(struct scatterlist),
782			   KSMBD_DEFAULT_GFP);
783	if (!sg) {
784		kfree(nr_entries);
785		return NULL;
786	}
787
788	sg_init_table(sg, total_entries);
789	smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
790	for (i = 0; i < nvec - 1; i++) {
791		void *data = iov[i + 1].iov_base;
792		int len = iov[i + 1].iov_len;
793
794		if (is_vmalloc_addr(data)) {
795			int j, offset = offset_in_page(data);
796
797			for (j = 0; j < nr_entries[i]; j++) {
798				unsigned int bytes = PAGE_SIZE - offset;
799
800				if (!len)
801					break;
802
803				if (bytes > len)
804					bytes = len;
805
806				sg_set_page(&sg[sg_idx++],
807					    vmalloc_to_page(data), bytes,
808					    offset_in_page(data));
809
810				data += bytes;
811				len -= bytes;
812				offset = 0;
813			}
814		} else {
815			sg_set_page(&sg[sg_idx++], virt_to_page(data), len,
816				    offset_in_page(data));
817		}
818	}
819	smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
820	kfree(nr_entries);
821	return sg;
822}
823
824int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
825			unsigned int nvec, int enc)
826{
827	struct ksmbd_conn *conn = work->conn;
828	struct smb2_transform_hdr *tr_hdr = smb_get_msg(iov[0].iov_base);
829	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
830	int rc;
831	struct scatterlist *sg;
832	u8 sign[SMB2_SIGNATURE_SIZE] = {};
833	u8 key[SMB3_ENC_DEC_KEY_SIZE];
834	struct aead_request *req;
835	char *iv;
836	unsigned int iv_len;
837	struct crypto_aead *tfm;
838	unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
839	struct ksmbd_crypto_ctx *ctx;
840
841	rc = ksmbd_get_encryption_key(work,
842				      le64_to_cpu(tr_hdr->SessionId),
843				      enc,
844				      key);
845	if (rc) {
846		pr_err("Could not get %scryption key\n", enc ? "en" : "de");
847		return rc;
848	}
849
850	if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
851	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
852		ctx = ksmbd_crypto_ctx_find_gcm();
853	else
854		ctx = ksmbd_crypto_ctx_find_ccm();
855	if (!ctx) {
856		pr_err("crypto alloc failed\n");
857		return -ENOMEM;
858	}
859
860	if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
861	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
862		tfm = CRYPTO_GCM(ctx);
863	else
864		tfm = CRYPTO_CCM(ctx);
865
866	if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
867	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
868		rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
869	else
870		rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
871	if (rc) {
872		pr_err("Failed to set aead key %d\n", rc);
873		goto free_ctx;
874	}
875
876	rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
877	if (rc) {
878		pr_err("Failed to set authsize %d\n", rc);
879		goto free_ctx;
880	}
881
882	req = aead_request_alloc(tfm, KSMBD_DEFAULT_GFP);
883	if (!req) {
884		rc = -ENOMEM;
885		goto free_ctx;
886	}
887
888	if (!enc) {
889		memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
890		crypt_len += SMB2_SIGNATURE_SIZE;
891	}
892
893	sg = ksmbd_init_sg(iov, nvec, sign);
894	if (!sg) {
895		pr_err("Failed to init sg\n");
896		rc = -ENOMEM;
897		goto free_req;
898	}
899
900	iv_len = crypto_aead_ivsize(tfm);
901	iv = kzalloc(iv_len, KSMBD_DEFAULT_GFP);
902	if (!iv) {
903		rc = -ENOMEM;
904		goto free_sg;
905	}
906
907	if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
908	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
909		memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
910	} else {
911		iv[0] = 3;
912		memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
913	}
914
915	aead_request_set_crypt(req, sg, sg, crypt_len, iv);
916	aead_request_set_ad(req, assoc_data_len);
917	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
918
919	if (enc)
920		rc = crypto_aead_encrypt(req);
921	else
922		rc = crypto_aead_decrypt(req);
923	if (rc)
924		goto free_iv;
925
926	if (enc)
927		memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
928
929free_iv:
930	kfree(iv);
931free_sg:
932	kfree(sg);
933free_req:
934	aead_request_free(req);
935free_ctx:
936	ksmbd_release_crypto_ctx(ctx);
937	return rc;
938}
~/ Read-only file preview.