| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | // SPDX-License-Identifier: GPL-2.0-or-later
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org> | 
					
						
							|  |  |  |  *   Copyright (C) 2018 Samsung Electronics Co., Ltd. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/fs.h>
 | 
					
						
							|  |  |  | #include <linux/uaccess.h>
 | 
					
						
							|  |  |  | #include <linux/backing-dev.h>
 | 
					
						
							|  |  |  | #include <linux/writeback.h>
 | 
					
						
							|  |  |  | #include <linux/uio.h>
 | 
					
						
							|  |  |  | #include <linux/xattr.h>
 | 
					
						
							|  |  |  | #include <crypto/hash.h>
 | 
					
						
							|  |  |  | #include <crypto/aead.h>
 | 
					
						
							|  |  |  | #include <linux/random.h>
 | 
					
						
							|  |  |  | #include <linux/scatterlist.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "auth.h"
 | 
					
						
							|  |  |  | #include "glob.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/fips.h>
 | 
					
						
							|  |  |  | #include <crypto/des.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "server.h"
 | 
					
						
							|  |  |  | #include "smb_common.h"
 | 
					
						
							|  |  |  | #include "connection.h"
 | 
					
						
							|  |  |  | #include "mgmt/user_session.h"
 | 
					
						
							|  |  |  | #include "mgmt/user_config.h"
 | 
					
						
							|  |  |  | #include "crypto_ctx.h"
 | 
					
						
							|  |  |  | #include "transport_ipc.h"
 | 
					
						
							| 
									
										
										
										
											2023-05-21 20:46:30 -05:00
										 |  |  | #include "../common/arc4.h"
 | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Fixed format data defining GSS header and fixed string | 
					
						
							|  |  |  |  * "not_defined_in_RFC4178@please_ignore". | 
					
						
							|  |  |  |  * So sec blob data in neg phase could be generated statically. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static char NEGOTIATE_GSS_HEADER[AUTH_GSS_LENGTH] = { | 
					
						
							|  |  |  | #ifdef CONFIG_SMB_SERVER_KERBEROS5
 | 
					
						
							|  |  |  | 	0x60, 0x5e, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, | 
					
						
							|  |  |  | 	0x05, 0x02, 0xa0, 0x54, 0x30, 0x52, 0xa0, 0x24, | 
					
						
							|  |  |  | 	0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, | 
					
						
							|  |  |  | 	0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a, | 
					
						
							|  |  |  | 	0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02, | 
					
						
							|  |  |  | 	0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, | 
					
						
							|  |  |  | 	0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a, 0x30, 0x28, | 
					
						
							|  |  |  | 	0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f, 0x74, 0x5f, | 
					
						
							|  |  |  | 	0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, | 
					
						
							|  |  |  | 	0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43, 0x34, 0x31, | 
					
						
							|  |  |  | 	0x37, 0x38, 0x40, 0x70, 0x6c, 0x65, 0x61, 0x73, | 
					
						
							|  |  |  | 	0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	0x60, 0x48, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, | 
					
						
							|  |  |  | 	0x05, 0x02, 0xa0, 0x3e, 0x30, 0x3c, 0xa0, 0x0e, | 
					
						
							|  |  |  | 	0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, | 
					
						
							|  |  |  | 	0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a, | 
					
						
							|  |  |  | 	0x30, 0x28, 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f, | 
					
						
							|  |  |  | 	0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, | 
					
						
							|  |  |  | 	0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43, | 
					
						
							|  |  |  | 	0x34, 0x31, 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65, | 
					
						
							|  |  |  | 	0x61, 0x73, 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f, | 
					
						
							|  |  |  | 	0x72, 0x65 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ksmbd_copy_gss_neg_header(void *buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ksmbd_gen_sess_key() - function to generate session key | 
					
						
							|  |  |  |  * @sess:	session of connection | 
					
						
							|  |  |  |  * @hash:	source hash value to be used for find session key | 
					
						
							|  |  |  |  * @hmac:	source hmac value to be used for finding session key | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			      char *hmac) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ksmbd_crypto_ctx *ctx; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	int rc; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ctx = ksmbd_crypto_ctx_find_hmacmd5(); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	if (!ctx) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx), | 
					
						
							|  |  |  | 				 hash, | 
					
						
							|  |  |  | 				 CIFS_HMAC_MD5_HASH_SIZE); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "hmacmd5 set key fail error %d\n", rc); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_init(CRYPTO_HMACMD5(ctx)); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not init hmacmd5 error %d\n", rc); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), | 
					
						
							|  |  |  | 				 hmac, | 
					
						
							|  |  |  | 				 SMB2_NTLMV2_SESSKEY_SIZE); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "Could not update with response error %d\n", rc); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", rc); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess, | 
					
						
							|  |  |  | 			    char *ntlmv2_hash, char *dname) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	int ret, len, conv_len; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	wchar_t *domain = NULL; | 
					
						
							|  |  |  | 	__le16 *uniname = NULL; | 
					
						
							|  |  |  | 	struct ksmbd_crypto_ctx *ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx = ksmbd_crypto_ctx_find_hmacmd5(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "can't generate ntlmv2 hash\n"); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx), | 
					
						
							|  |  |  | 				  user_passkey(sess->user), | 
					
						
							|  |  |  | 				  CIFS_ENCPWD_SIZE); | 
					
						
							|  |  |  | 	if (ret) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not set NT Hash as a key\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = crypto_shash_init(CRYPTO_HMACMD5(ctx)); | 
					
						
							|  |  |  | 	if (ret) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not init hmacmd5\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* convert user_name to unicode */ | 
					
						
							|  |  |  | 	len = strlen(user_name(sess->user)); | 
					
						
							|  |  |  | 	uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!uniname) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len, | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 				  conn->local_nls); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	if (conv_len < 0 || conv_len > len) { | 
					
						
							|  |  |  | 		ret = -EINVAL; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	UniStrupr(uniname); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ret = crypto_shash_update(CRYPTO_HMACMD5(ctx), | 
					
						
							|  |  |  | 				  (char *)uniname, | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 				  UNICODE_LEN(conv_len)); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (ret) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not update with user\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Convert domain name or conn name to unicode and uppercase */ | 
					
						
							|  |  |  | 	len = strlen(dname); | 
					
						
							|  |  |  | 	domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!domain) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	conv_len = smb_strtoUTF16((__le16 *)domain, dname, len, | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 				  conn->local_nls); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	if (conv_len < 0 || conv_len > len) { | 
					
						
							|  |  |  | 		ret = -EINVAL; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ret = crypto_shash_update(CRYPTO_HMACMD5(ctx), | 
					
						
							|  |  |  | 				  (char *)domain, | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 				  UNICODE_LEN(conv_len)); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (ret) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not update with domain\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_hash); | 
					
						
							|  |  |  | 	if (ret) | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not generate md5 hash\n"); | 
					
						
							| 
									
										
										
										
											2021-05-26 15:27:11 +09:00
										 |  |  | out: | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	kfree(uniname); | 
					
						
							|  |  |  | 	kfree(domain); | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler | 
					
						
							| 
									
										
										
										
											2023-12-15 19:03:57 -08:00
										 |  |  |  * @conn:		connection | 
					
						
							|  |  |  |  * @sess:		session of connection | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  |  * @ntlmv2:		NTLMv2 challenge response | 
					
						
							|  |  |  |  * @blen:		NTLMv2 blob length | 
					
						
							|  |  |  |  * @domain_name:	domain name | 
					
						
							| 
									
										
										
										
											2023-12-15 19:03:57 -08:00
										 |  |  |  * @cryptkey:		session crypto key | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Return:	0 on success, error number on error | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, | 
					
						
							|  |  |  | 		      struct ntlmv2_resp *ntlmv2, int blen, char *domain_name, | 
					
						
							|  |  |  | 		      char *cryptkey) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	char ntlmv2_hash[CIFS_ENCPWD_SIZE]; | 
					
						
							|  |  |  | 	char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE]; | 
					
						
							| 
									
										
										
										
											2023-05-03 08:44:14 +09:00
										 |  |  | 	struct ksmbd_crypto_ctx *ctx = NULL; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	char *construct = NULL; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	int rc, len; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-03 08:44:14 +09:00
										 |  |  | 	ctx = ksmbd_crypto_ctx_find_hmacmd5(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx), | 
					
						
							|  |  |  | 				 ntlmv2_hash, | 
					
						
							|  |  |  | 				 CIFS_HMAC_MD5_HASH_SIZE); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not set NTLMV2 Hash as a key\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_init(CRYPTO_HMACMD5(ctx)); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not init hmacmd5\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	len = CIFS_CRYPTO_KEY_SIZE + blen; | 
					
						
							|  |  |  | 	construct = kzalloc(len, GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!construct) { | 
					
						
							|  |  |  | 		rc = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 	memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE); | 
					
						
							| 
									
										
										
										
											2021-05-26 15:28:48 +09:00
										 |  |  | 	memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not update with response\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_rsp); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not generate md5 hash\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-05-03 08:44:14 +09:00
										 |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	ctx = NULL; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not generate sess key\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 15:29:24 +09:00
										 |  |  | 	if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0) | 
					
						
							|  |  |  | 		rc = -EINVAL; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | out: | 
					
						
							| 
									
										
										
										
											2023-05-03 08:44:14 +09:00
										 |  |  | 	if (ctx) | 
					
						
							|  |  |  | 		ksmbd_release_crypto_ctx(ctx); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	kfree(construct); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct | 
					
						
							|  |  |  |  * authenticate blob | 
					
						
							|  |  |  |  * @authblob:	authenticate blob source pointer | 
					
						
							| 
									
										
										
										
											2023-12-15 19:03:57 -08:00
										 |  |  |  * @blob_len:	length of the @authblob message | 
					
						
							|  |  |  |  * @conn:	connection | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  |  * @sess:	session of connection | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Return:	0 on success, error number on error | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 				   int blob_len, struct ksmbd_conn *conn, | 
					
						
							|  |  |  | 				   struct ksmbd_session *sess) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *domain_name; | 
					
						
							| 
									
										
										
										
											2021-10-19 17:39:38 +02:00
										 |  |  | 	unsigned int nt_off, dn_off; | 
					
						
							|  |  |  | 	unsigned short nt_len, dn_len; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (blob_len < sizeof(struct authenticate_message)) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "negotiate blob len %d too small\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    blob_len); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (memcmp(authblob->Signature, "NTLMSSP", 8)) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "blob signature incorrect %s\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    authblob->Signature); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset); | 
					
						
							|  |  |  | 	nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length); | 
					
						
							| 
									
										
										
										
											2021-10-19 17:39:38 +02:00
										 |  |  | 	dn_off = le32_to_cpu(authblob->DomainName.BufferOffset); | 
					
						
							|  |  |  | 	dn_len = le16_to_cpu(authblob->DomainName.Length); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-30 13:03:15 +09:00
										 |  |  | 	if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len || | 
					
						
							|  |  |  | 	    nt_len < CIFS_ENCPWD_SIZE) | 
					
						
							| 
									
										
										
										
											2021-10-19 17:39:38 +02:00
										 |  |  | 		return -EINVAL; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO : use domain name that imported from configuration file */ | 
					
						
							| 
									
										
										
										
											2021-10-19 17:39:38 +02:00
										 |  |  | 	domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off, | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 					     dn_len, true, conn->local_nls); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (IS_ERR(domain_name)) | 
					
						
							|  |  |  | 		return PTR_ERR(domain_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* process NTLMv2 authentication */ | 
					
						
							|  |  |  | 	ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 		    domain_name); | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	ret = ksmbd_auth_ntlmv2(conn, sess, | 
					
						
							|  |  |  | 				(struct ntlmv2_resp *)((char *)authblob + nt_off), | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 				nt_len - CIFS_ENCPWD_SIZE, | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 				domain_name, conn->ntlmssp.cryptkey); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	kfree(domain_name); | 
					
						
							| 
									
										
										
										
											2022-02-01 18:20:34 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* The recovered secondary session key */ | 
					
						
							|  |  |  | 	if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) { | 
					
						
							|  |  |  | 		struct arc4_ctx *ctx_arc4; | 
					
						
							|  |  |  | 		unsigned int sess_key_off, sess_key_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset); | 
					
						
							|  |  |  | 		sess_key_len = le16_to_cpu(authblob->SessionKey.Length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (blob_len < (u64)sess_key_off + sess_key_len) | 
					
						
							|  |  |  | 			return -EINVAL; | 
					
						
							| 
									
										
										
										
											2023-08-25 23:40:31 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (sess_key_len > CIFS_KEY_SIZE) | 
					
						
							|  |  |  | 			return -EINVAL; | 
					
						
							| 
									
										
										
										
											2022-02-01 18:20:34 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL); | 
					
						
							|  |  |  | 		if (!ctx_arc4) | 
					
						
							|  |  |  | 			return -ENOMEM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cifs_arc4_setkey(ctx_arc4, sess->sess_key, | 
					
						
							|  |  |  | 				 SMB2_NTLMV2_SESSKEY_SIZE); | 
					
						
							|  |  |  | 		cifs_arc4_crypt(ctx_arc4, sess->sess_key, | 
					
						
							|  |  |  | 				(char *)authblob + sess_key_off, sess_key_len); | 
					
						
							|  |  |  | 		kfree_sensitive(ctx_arc4); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct | 
					
						
							|  |  |  |  * negotiate blob | 
					
						
							|  |  |  |  * @negblob: negotiate blob source pointer | 
					
						
							| 
									
										
										
										
											2023-12-15 19:03:57 -08:00
										 |  |  |  * @blob_len:	length of the @authblob message | 
					
						
							|  |  |  |  * @conn:	connection | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob, | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 				  int blob_len, struct ksmbd_conn *conn) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (blob_len < sizeof(struct negotiate_message)) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "negotiate blob len %d too small\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    blob_len); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (memcmp(negblob->Signature, "NTLMSSP", 8)) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "blob signature incorrect %s\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    negblob->Signature); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 	conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct | 
					
						
							|  |  |  |  * challenge blob | 
					
						
							|  |  |  |  * @chgblob: challenge blob source pointer to initialize | 
					
						
							| 
									
										
										
										
											2023-12-15 19:03:57 -08:00
										 |  |  |  * @conn:	connection | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | unsigned int | 
					
						
							|  |  |  | ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 				   struct ksmbd_conn *conn) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct target_info *tinfo; | 
					
						
							|  |  |  | 	wchar_t *name; | 
					
						
							|  |  |  | 	__u8 *target_name; | 
					
						
							| 
									
										
										
										
											2021-05-29 07:59:40 +09:00
										 |  |  | 	unsigned int flags, blob_off, blob_len, type, target_info_len = 0; | 
					
						
							|  |  |  | 	int len, uni_len, conv_len; | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 	int cflags = conn->ntlmssp.client_flags; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8); | 
					
						
							|  |  |  | 	chgblob->MessageType = NtLmChallenge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	flags = NTLMSSP_NEGOTIATE_UNICODE | | 
					
						
							|  |  |  | 		NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_TARGET_TYPE_SERVER | | 
					
						
							|  |  |  | 		NTLMSSP_NEGOTIATE_TARGET_INFO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cflags & NTLMSSP_NEGOTIATE_SIGN) { | 
					
						
							|  |  |  | 		flags |= NTLMSSP_NEGOTIATE_SIGN; | 
					
						
							|  |  |  | 		flags |= cflags & (NTLMSSP_NEGOTIATE_128 | | 
					
						
							| 
									
										
										
										
											2021-05-26 16:36:15 +09:00
										 |  |  | 				   NTLMSSP_NEGOTIATE_56); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 23:37:41 +09:00
										 |  |  | 	if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn)) | 
					
						
							|  |  |  | 		flags |= NTLMSSP_NEGOTIATE_SEAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) | 
					
						
							|  |  |  | 		flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cflags & NTLMSSP_REQUEST_TARGET) | 
					
						
							|  |  |  | 		flags |= NTLMSSP_REQUEST_TARGET; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 	if (conn->use_spnego && | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | 	    (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-01 18:20:34 +09:00
										 |  |  | 	if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH) | 
					
						
							|  |  |  | 		flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	chgblob->NegotiateFlags = cpu_to_le32(flags); | 
					
						
							|  |  |  | 	len = strlen(ksmbd_netbios_name()); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (!name) | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len, | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 				  conn->local_nls); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	if (conv_len < 0 || conv_len > len) { | 
					
						
							|  |  |  | 		kfree(name); | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uni_len = UNICODE_LEN(conv_len); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	blob_off = sizeof(struct challenge_message); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	blob_len = blob_off + uni_len; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	chgblob->TargetName.Length = cpu_to_le16(uni_len); | 
					
						
							|  |  |  | 	chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize random conn challenge */ | 
					
						
							| 
									
										
										
										
											2021-12-15 14:57:27 +09:00
										 |  |  | 	get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64)); | 
					
						
							|  |  |  | 	memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 	       CIFS_CRYPTO_KEY_SIZE); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Add Target Information to security buffer */ | 
					
						
							|  |  |  | 	chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	target_name = (__u8 *)chgblob + blob_off; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 	memcpy(target_name, name, uni_len); | 
					
						
							|  |  |  | 	tinfo = (struct target_info *)(target_name + uni_len); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	chgblob->TargetInfoArray.Length = 0; | 
					
						
							|  |  |  | 	/* Add target info list for NetBIOS/DNS settings */ | 
					
						
							|  |  |  | 	for (type = NTLMSSP_AV_NB_COMPUTER_NAME; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:36:15 +09:00
										 |  |  | 	     type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) { | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		tinfo->Type = cpu_to_le16(type); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:37:05 +09:00
										 |  |  | 		tinfo->Length = cpu_to_le16(uni_len); | 
					
						
							|  |  |  | 		memcpy(tinfo->Content, name, uni_len); | 
					
						
							|  |  |  | 		tinfo = (struct target_info *)((char *)tinfo + 4 + uni_len); | 
					
						
							|  |  |  | 		target_info_len += 4 + uni_len; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Add terminator subblock */ | 
					
						
							|  |  |  | 	tinfo->Type = 0; | 
					
						
							|  |  |  | 	tinfo->Length = 0; | 
					
						
							|  |  |  | 	target_info_len += 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	chgblob->TargetInfoArray.Length = cpu_to_le16(target_info_len); | 
					
						
							|  |  |  | 	chgblob->TargetInfoArray.MaximumLength = cpu_to_le16(target_info_len); | 
					
						
							|  |  |  | 	blob_len += target_info_len; | 
					
						
							|  |  |  | 	kfree(name); | 
					
						
							|  |  |  | 	ksmbd_debug(AUTH, "NTLMSSP SecurityBufferLength %d\n", blob_len); | 
					
						
							|  |  |  | 	return blob_len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_SMB_SERVER_KERBEROS5
 | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    int in_len, char *out_blob, int *out_len) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ksmbd_spnego_authen_response *resp; | 
					
						
							| 
									
										
										
										
											2024-10-09 10:39:16 +09:00
										 |  |  | 	struct ksmbd_login_response_ext *resp_ext = NULL; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	struct ksmbd_user *user = NULL; | 
					
						
							|  |  |  | 	int retval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp = ksmbd_ipc_spnego_authen_request(in_blob, in_len); | 
					
						
							|  |  |  | 	if (!resp) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "SPNEGO_AUTHEN_REQUEST failure\n"); | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(resp->login_response.status & KSMBD_USER_FLAG_OK)) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "krb5 authentication failure\n"); | 
					
						
							|  |  |  | 		retval = -EPERM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (*out_len <= resp->spnego_blob_len) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "buf len %d, but blob len %d\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    *out_len, resp->spnego_blob_len); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		retval = -EINVAL; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (resp->session_key_len > sizeof(sess->sess_key)) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "session key is too long\n"); | 
					
						
							|  |  |  | 		retval = -EINVAL; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-09 10:39:16 +09:00
										 |  |  | 	if (resp->login_response.status & KSMBD_USER_FLAG_EXTENSION) | 
					
						
							|  |  |  | 		resp_ext = ksmbd_ipc_login_request_ext(resp->login_response.account); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	user = ksmbd_alloc_user(&resp->login_response, resp_ext); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (!user) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "login failure\n"); | 
					
						
							|  |  |  | 		retval = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sess->user = user; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(sess->sess_key, resp->payload, resp->session_key_len); | 
					
						
							|  |  |  | 	memcpy(out_blob, resp->payload + resp->session_key_len, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 	       resp->spnego_blob_len); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	*out_len = resp->spnego_blob_len; | 
					
						
							|  |  |  | 	retval = 0; | 
					
						
							|  |  |  | out: | 
					
						
							| 
									
										
										
										
											2021-04-02 12:47:14 +09:00
										 |  |  | 	kvfree(resp); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    int in_len, char *out_blob, int *out_len) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	return -EOPNOTSUPP; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ksmbd_sign_smb2_pdu() - function to generate packet signing | 
					
						
							|  |  |  |  * @conn:	connection | 
					
						
							|  |  |  |  * @key:	signing key | 
					
						
							|  |  |  |  * @iov:        buffer iov array | 
					
						
							|  |  |  |  * @n_vec:	number of iovecs | 
					
						
							|  |  |  |  * @sig:	signature value generated for client request packet | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			int n_vec, char *sig) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ksmbd_crypto_ctx *ctx; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	int rc, i; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ctx = ksmbd_crypto_ctx_find_hmacsha256(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx), | 
					
						
							|  |  |  | 				 key, | 
					
						
							|  |  |  | 				 SMB2_NTLMV2_SESSKEY_SIZE); | 
					
						
							|  |  |  | 	if (rc) | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx)); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < n_vec; i++) { | 
					
						
							|  |  |  | 		rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), | 
					
						
							|  |  |  | 					 iov[i].iov_base, | 
					
						
							|  |  |  | 					 iov[i].iov_len); | 
					
						
							|  |  |  | 		if (rc) { | 
					
						
							|  |  |  | 			ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc); | 
					
						
							|  |  |  | 			goto out; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig); | 
					
						
							|  |  |  | 	if (rc) | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc); | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ksmbd_sign_smb3_pdu() - function to generate packet signing | 
					
						
							|  |  |  |  * @conn:	connection | 
					
						
							|  |  |  |  * @key:	signing key | 
					
						
							|  |  |  |  * @iov:        buffer iov array | 
					
						
							|  |  |  |  * @n_vec:	number of iovecs | 
					
						
							|  |  |  |  * @sig:	signature value generated for client request packet | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			int n_vec, char *sig) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ksmbd_crypto_ctx *ctx; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	int rc, i; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ctx = ksmbd_crypto_ctx_find_cmacaes(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "could not crypto alloc cmac\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx), | 
					
						
							|  |  |  | 				 key, | 
					
						
							|  |  |  | 				 SMB2_CMACAES_SIZE); | 
					
						
							|  |  |  | 	if (rc) | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_init(CRYPTO_CMACAES(ctx)); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "cmaces init error %d\n", rc); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < n_vec; i++) { | 
					
						
							|  |  |  | 		rc = crypto_shash_update(CRYPTO_CMACAES(ctx), | 
					
						
							|  |  |  | 					 iov[i].iov_base, | 
					
						
							|  |  |  | 					 iov[i].iov_len); | 
					
						
							|  |  |  | 		if (rc) { | 
					
						
							|  |  |  | 			ksmbd_debug(AUTH, "cmaces update error %d\n", rc); | 
					
						
							|  |  |  | 			goto out; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig); | 
					
						
							|  |  |  | 	if (rc) | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "cmaces generation error %d\n", rc); | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct derivation { | 
					
						
							|  |  |  | 	struct kvec label; | 
					
						
							|  |  |  | 	struct kvec context; | 
					
						
							|  |  |  | 	bool binding; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess, | 
					
						
							|  |  |  | 			struct kvec label, struct kvec context, __u8 *key, | 
					
						
							|  |  |  | 			unsigned int key_size) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned char zero = 0x0; | 
					
						
							|  |  |  | 	__u8 i[4] = {0, 0, 0, 1}; | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	__u8 L128[4] = {0, 0, 0, 128}; | 
					
						
							|  |  |  | 	__u8 L256[4] = {0, 0, 1, 0}; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	int rc; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	unsigned char prfhash[SMB2_HMACSHA256_SIZE]; | 
					
						
							|  |  |  | 	unsigned char *hashptr = prfhash; | 
					
						
							|  |  |  | 	struct ksmbd_crypto_ctx *ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); | 
					
						
							|  |  |  | 	memset(key, 0x0, key_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx = ksmbd_crypto_ctx_find_hmacsha256(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx), | 
					
						
							|  |  |  | 				 sess->sess_key, | 
					
						
							|  |  |  | 				 SMB2_NTLMV2_SESSKEY_SIZE); | 
					
						
							|  |  |  | 	if (rc) | 
					
						
							|  |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx)); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc); | 
					
						
							|  |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with n\n"); | 
					
						
							|  |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), | 
					
						
							|  |  |  | 				 label.iov_base, | 
					
						
							|  |  |  | 				 label.iov_len); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with label\n"); | 
					
						
							|  |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with zero\n"); | 
					
						
							|  |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), | 
					
						
							|  |  |  | 				 context.iov_base, | 
					
						
							|  |  |  | 				 context.iov_len); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with context\n"); | 
					
						
							|  |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-01 00:01:21 +09:00
										 |  |  | 	if (key_size == SMB3_ENC_DEC_KEY_SIZE && | 
					
						
							|  |  |  | 	    (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || | 
					
						
							|  |  |  | 	     conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 		rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with L\n"); | 
					
						
							|  |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    rc); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		goto smb3signkey_ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(key, hashptr, key_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | smb3signkey_ret: | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int generate_smb3signingkey(struct ksmbd_session *sess, | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | 				   struct ksmbd_conn *conn, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 				   const struct derivation *signing) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	int rc; | 
					
						
							|  |  |  | 	struct channel *chann; | 
					
						
							|  |  |  | 	char *key; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | 	chann = lookup_chann_list(sess, conn); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (!chann) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	if (conn->dialect >= SMB30_PROT_ID && signing->binding) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		key = chann->smb3signingkey; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		key = sess->smb3signingkey; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	rc = generate_key(conn, sess, signing->label, signing->context, key, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			  SMB3_SIGN_KEY_SIZE); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (rc) | 
					
						
							|  |  |  | 		return rc; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	if (!(conn->dialect >= SMB30_PROT_ID && signing->binding)) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ksmbd_debug(AUTH, "dumping generated AES signing keys\n"); | 
					
						
							|  |  |  | 	ksmbd_debug(AUTH, "Session Id    %llu\n", sess->id); | 
					
						
							|  |  |  | 	ksmbd_debug(AUTH, "Session Key   %*ph\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 		    SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	ksmbd_debug(AUTH, "Signing Key   %*ph\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 		    SMB3_SIGN_KEY_SIZE, key); | 
					
						
							| 
									
										
										
										
											2021-05-26 15:30:04 +09:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess, | 
					
						
							|  |  |  | 			       struct ksmbd_conn *conn) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct derivation d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d.label.iov_base = "SMB2AESCMAC"; | 
					
						
							|  |  |  | 	d.label.iov_len = 12; | 
					
						
							|  |  |  | 	d.context.iov_base = "SmbSign"; | 
					
						
							|  |  |  | 	d.context.iov_len = 8; | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | 	d.binding = conn->binding; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | 	return generate_smb3signingkey(sess, conn, &d); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess, | 
					
						
							|  |  |  | 				struct ksmbd_conn *conn) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct derivation d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d.label.iov_base = "SMBSigningKey"; | 
					
						
							|  |  |  | 	d.label.iov_len = 14; | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | 	if (conn->binding) { | 
					
						
							|  |  |  | 		struct preauth_session *preauth_sess; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id); | 
					
						
							|  |  |  | 		if (!preauth_sess) | 
					
						
							|  |  |  | 			return -ENOENT; | 
					
						
							|  |  |  | 		d.context.iov_base = preauth_sess->Preauth_HashValue; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		d.context.iov_base = sess->Preauth_HashValue; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	d.context.iov_len = 64; | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | 	d.binding = conn->binding; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-18 10:04:19 +09:00
										 |  |  | 	return generate_smb3signingkey(sess, conn, &d); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct derivation_twin { | 
					
						
							|  |  |  | 	struct derivation encryption; | 
					
						
							|  |  |  | 	struct derivation decryption; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | static int generate_smb3encryptionkey(struct ksmbd_conn *conn, | 
					
						
							|  |  |  | 				      struct ksmbd_session *sess, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 				      const struct derivation_twin *ptwin) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	rc = generate_key(conn, sess, ptwin->encryption.label, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			  ptwin->encryption.context, sess->smb3encryptionkey, | 
					
						
							|  |  |  | 			  SMB3_ENC_DEC_KEY_SIZE); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (rc) | 
					
						
							|  |  |  | 		return rc; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	rc = generate_key(conn, sess, ptwin->decryption.label, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			  ptwin->decryption.context, | 
					
						
							|  |  |  | 			  sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (rc) | 
					
						
							|  |  |  | 		return rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ksmbd_debug(AUTH, "dumping generated AES encryption keys\n"); | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	ksmbd_debug(AUTH, "Cipher type   %d\n", conn->cipher_type); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	ksmbd_debug(AUTH, "Session Id    %llu\n", sess->id); | 
					
						
							|  |  |  | 	ksmbd_debug(AUTH, "Session Key   %*ph\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 		    SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key); | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || | 
					
						
							|  |  |  | 	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) { | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "ServerIn Key  %*ph\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey); | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "ServerOut Key %*ph\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey); | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "ServerIn Key  %*ph\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey); | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "ServerOut Key %*ph\n", | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			    SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey); | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-26 15:30:04 +09:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn, | 
					
						
							|  |  |  | 				  struct ksmbd_session *sess) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct derivation_twin twin; | 
					
						
							|  |  |  | 	struct derivation *d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d = &twin.encryption; | 
					
						
							|  |  |  | 	d->label.iov_base = "SMB2AESCCM"; | 
					
						
							|  |  |  | 	d->label.iov_len = 11; | 
					
						
							|  |  |  | 	d->context.iov_base = "ServerOut"; | 
					
						
							|  |  |  | 	d->context.iov_len = 10; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d = &twin.decryption; | 
					
						
							|  |  |  | 	d->label.iov_base = "SMB2AESCCM"; | 
					
						
							|  |  |  | 	d->label.iov_len = 11; | 
					
						
							|  |  |  | 	d->context.iov_base = "ServerIn "; | 
					
						
							|  |  |  | 	d->context.iov_len = 10; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	return generate_smb3encryptionkey(conn, sess, &twin); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn, | 
					
						
							|  |  |  | 				   struct ksmbd_session *sess) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct derivation_twin twin; | 
					
						
							|  |  |  | 	struct derivation *d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d = &twin.encryption; | 
					
						
							|  |  |  | 	d->label.iov_base = "SMBS2CCipherKey"; | 
					
						
							|  |  |  | 	d->label.iov_len = 16; | 
					
						
							|  |  |  | 	d->context.iov_base = sess->Preauth_HashValue; | 
					
						
							|  |  |  | 	d->context.iov_len = 64; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	d = &twin.decryption; | 
					
						
							|  |  |  | 	d->label.iov_base = "SMBC2SCipherKey"; | 
					
						
							|  |  |  | 	d->label.iov_len = 16; | 
					
						
							|  |  |  | 	d->context.iov_base = sess->Preauth_HashValue; | 
					
						
							|  |  |  | 	d->context.iov_len = 64; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 13:36:52 +09:00
										 |  |  | 	return generate_smb3encryptionkey(conn, sess, &twin); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 				     __u8 *pi_hash) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	int rc; | 
					
						
							| 
									
										
										
										
											2021-11-03 08:08:44 +09:00
										 |  |  | 	struct smb2_hdr *rcv_hdr = smb2_get_msg(buf); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId; | 
					
						
							| 
									
										
										
										
											2021-11-03 08:08:44 +09:00
										 |  |  | 	int msg_size = get_rfc1002_len(buf); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	struct ksmbd_crypto_ctx *ctx = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 15:56:18 +09:00
										 |  |  | 	if (conn->preauth_info->Preauth_HashId != | 
					
						
							|  |  |  | 	    SMB2_PREAUTH_INTEGRITY_SHA512) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx = ksmbd_crypto_ctx_find_sha512(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "could not alloc sha512\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_init(CRYPTO_SHA512(ctx)); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not init shashn"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_SHA512(ctx), pi_hash, 64); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with n\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_SHA512(ctx), all_bytes_msg, msg_size); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with n\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_final(CRYPTO_SHA512(ctx), pi_hash); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 		      __u8 *pi_hash) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 	int rc; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	struct ksmbd_crypto_ctx *ctx = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx = ksmbd_crypto_ctx_find_sha256(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 		ksmbd_debug(AUTH, "could not alloc sha256\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_init(CRYPTO_SHA256(ctx)); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not init shashn"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_update(CRYPTO_SHA256(ctx), sd_buf, len); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "could not update with n\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_shash_final(CRYPTO_SHA256(ctx), pi_hash); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							|  |  |  | 		ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 23:36:34 +09:00
										 |  |  | static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 				    int enc, u8 *key) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ksmbd_session *sess; | 
					
						
							|  |  |  | 	u8 *ses_enc_key; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 23:36:34 +09:00
										 |  |  | 	if (enc) | 
					
						
							|  |  |  | 		sess = work->sess; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		sess = ksmbd_session_lookup_all(work->conn, ses_id); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (!sess) | 
					
						
							| 
									
										
										
										
											2021-05-26 15:30:50 +09:00
										 |  |  | 		return -EINVAL; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ses_enc_key = enc ? sess->smb3encryptionkey : | 
					
						
							|  |  |  | 		sess->smb3decryptionkey; | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 				   unsigned int buflen) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	void *addr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (is_vmalloc_addr(buf)) | 
					
						
							|  |  |  | 		addr = vmalloc_to_page(buf); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		addr = virt_to_page(buf); | 
					
						
							|  |  |  | 	sg_set_page(sg, addr, buflen, offset_in_page(buf)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 					 u8 *sign) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct scatterlist *sg; | 
					
						
							| 
									
										
										
										
											2021-11-03 08:25:54 +09:00
										 |  |  | 	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; | 
					
						
							| 
									
										
										
										
											2023-08-29 23:39:31 +09:00
										 |  |  | 	int i, *nr_entries, total_entries = 0, sg_idx = 0; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 15:31:37 +09:00
										 |  |  | 	if (!nvec) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-29 23:39:31 +09:00
										 |  |  | 	nr_entries = kcalloc(nvec, sizeof(int), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!nr_entries) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	for (i = 0; i < nvec - 1; i++) { | 
					
						
							|  |  |  | 		unsigned long kaddr = (unsigned long)iov[i + 1].iov_base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (is_vmalloc_addr(iov[i + 1].iov_base)) { | 
					
						
							|  |  |  | 			nr_entries[i] = ((kaddr + iov[i + 1].iov_len + | 
					
						
							|  |  |  | 					PAGE_SIZE - 1) >> PAGE_SHIFT) - | 
					
						
							|  |  |  | 				(kaddr >> PAGE_SHIFT); | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 			nr_entries[i]++; | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		total_entries += nr_entries[i]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Add two entries for transform header and signature */ | 
					
						
							|  |  |  | 	total_entries += 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL); | 
					
						
							| 
									
										
										
										
											2023-08-29 23:39:31 +09:00
										 |  |  | 	if (!sg) { | 
					
						
							|  |  |  | 		kfree(nr_entries); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2023-08-29 23:39:31 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sg_init_table(sg, total_entries); | 
					
						
							|  |  |  | 	smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len); | 
					
						
							|  |  |  | 	for (i = 0; i < nvec - 1; i++) { | 
					
						
							|  |  |  | 		void *data = iov[i + 1].iov_base; | 
					
						
							|  |  |  | 		int len = iov[i + 1].iov_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (is_vmalloc_addr(data)) { | 
					
						
							|  |  |  | 			int j, offset = offset_in_page(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (j = 0; j < nr_entries[i]; j++) { | 
					
						
							|  |  |  | 				unsigned int bytes = PAGE_SIZE - offset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 15:32:26 +09:00
										 |  |  | 				if (!len) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (bytes > len) | 
					
						
							|  |  |  | 					bytes = len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				sg_set_page(&sg[sg_idx++], | 
					
						
							|  |  |  | 					    vmalloc_to_page(data), bytes, | 
					
						
							|  |  |  | 					    offset_in_page(data)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				data += bytes; | 
					
						
							|  |  |  | 				len -= bytes; | 
					
						
							|  |  |  | 				offset = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			sg_set_page(&sg[sg_idx++], virt_to_page(data), len, | 
					
						
							|  |  |  | 				    offset_in_page(data)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE); | 
					
						
							| 
									
										
										
										
											2023-08-29 23:39:31 +09:00
										 |  |  | 	kfree(nr_entries); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	return sg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 23:36:34 +09:00
										 |  |  | int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov, | 
					
						
							| 
									
										
										
										
											2021-05-26 17:57:12 +09:00
										 |  |  | 			unsigned int nvec, int enc) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-22 23:36:34 +09:00
										 |  |  | 	struct ksmbd_conn *conn = work->conn; | 
					
						
							| 
									
										
										
										
											2021-11-03 08:25:54 +09:00
										 |  |  | 	struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base); | 
					
						
							|  |  |  | 	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; | 
					
						
							| 
									
										
										
										
											2021-05-26 15:34:37 +09:00
										 |  |  | 	int rc; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	struct scatterlist *sg; | 
					
						
							|  |  |  | 	u8 sign[SMB2_SIGNATURE_SIZE] = {}; | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	u8 key[SMB3_ENC_DEC_KEY_SIZE]; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	struct aead_request *req; | 
					
						
							|  |  |  | 	char *iv; | 
					
						
							|  |  |  | 	unsigned int iv_len; | 
					
						
							|  |  |  | 	struct crypto_aead *tfm; | 
					
						
							|  |  |  | 	unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); | 
					
						
							|  |  |  | 	struct ksmbd_crypto_ctx *ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 23:36:34 +09:00
										 |  |  | 	rc = ksmbd_get_encryption_key(work, | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 				      le64_to_cpu(tr_hdr->SessionId), | 
					
						
							|  |  |  | 				      enc, | 
					
						
							|  |  |  | 				      key); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							| 
									
										
										
										
											2021-06-28 15:23:19 +09:00
										 |  |  | 		pr_err("Could not get %scryption key\n", enc ? "en" : "de"); | 
					
						
							| 
									
										
										
										
											2021-05-26 15:35:26 +09:00
										 |  |  | 		return rc; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM || | 
					
						
							|  |  |  | 	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		ctx = ksmbd_crypto_ctx_find_gcm(); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		ctx = ksmbd_crypto_ctx_find_ccm(); | 
					
						
							|  |  |  | 	if (!ctx) { | 
					
						
							| 
									
										
										
										
											2021-06-28 15:23:19 +09:00
										 |  |  | 		pr_err("crypto alloc failed\n"); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:34:56 +09:00
										 |  |  | 		return -ENOMEM; | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM || | 
					
						
							|  |  |  | 	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		tfm = CRYPTO_GCM(ctx); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		tfm = CRYPTO_CCM(ctx); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || | 
					
						
							|  |  |  | 	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) | 
					
						
							|  |  |  | 		rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	if (rc) { | 
					
						
							| 
									
										
										
										
											2021-06-28 15:23:19 +09:00
										 |  |  | 		pr_err("Failed to set aead key %d\n", rc); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		goto free_ctx; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE); | 
					
						
							|  |  |  | 	if (rc) { | 
					
						
							| 
									
										
										
										
											2021-06-28 15:23:19 +09:00
										 |  |  | 		pr_err("Failed to set authsize %d\n", rc); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		goto free_ctx; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req = aead_request_alloc(tfm, GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!req) { | 
					
						
							|  |  |  | 		rc = -ENOMEM; | 
					
						
							|  |  |  | 		goto free_ctx; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!enc) { | 
					
						
							|  |  |  | 		memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE); | 
					
						
							|  |  |  | 		crypt_len += SMB2_SIGNATURE_SIZE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sg = ksmbd_init_sg(iov, nvec, sign); | 
					
						
							|  |  |  | 	if (!sg) { | 
					
						
							| 
									
										
										
										
											2021-06-28 15:23:19 +09:00
										 |  |  | 		pr_err("Failed to init sg\n"); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		rc = -ENOMEM; | 
					
						
							|  |  |  | 		goto free_req; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iv_len = crypto_aead_ivsize(tfm); | 
					
						
							|  |  |  | 	iv = kzalloc(iv_len, GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!iv) { | 
					
						
							|  |  |  | 		rc = -ENOMEM; | 
					
						
							|  |  |  | 		goto free_sg; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 	if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM || | 
					
						
							|  |  |  | 	    conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) { | 
					
						
							|  |  |  | 		memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE); | 
					
						
							| 
									
										
										
										
											2021-03-30 14:25:35 +09:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		iv[0] = 3; | 
					
						
							| 
									
										
										
										
											2021-05-06 11:43:37 +09:00
										 |  |  | 		memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE); | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	aead_request_set_crypt(req, sg, sg, crypt_len, iv); | 
					
						
							|  |  |  | 	aead_request_set_ad(req, assoc_data_len); | 
					
						
							|  |  |  | 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (enc) | 
					
						
							|  |  |  | 		rc = crypto_aead_encrypt(req); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		rc = crypto_aead_decrypt(req); | 
					
						
							| 
									
										
										
										
											2021-05-26 15:53:26 +09:00
										 |  |  | 	if (rc) | 
					
						
							|  |  |  | 		goto free_iv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (enc) | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 		memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 15:53:26 +09:00
										 |  |  | free_iv: | 
					
						
							| 
									
										
										
										
											2021-03-16 10:49:09 +09:00
										 |  |  | 	kfree(iv); | 
					
						
							|  |  |  | free_sg: | 
					
						
							|  |  |  | 	kfree(sg); | 
					
						
							|  |  |  | free_req: | 
					
						
							|  |  |  | 	kfree(req); | 
					
						
							|  |  |  | free_ctx: | 
					
						
							|  |  |  | 	ksmbd_release_crypto_ctx(ctx); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } |