blob: dc3d061edda9285e16cc963557f811e975343887 [file] [log] [blame]
Namjae Jeone2f34482021-03-16 10:49:09 +09001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
4 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
5 */
6
7#include <linux/kernel.h>
8#include <linux/fs.h>
9#include <linux/uaccess.h>
10#include <linux/backing-dev.h>
11#include <linux/writeback.h>
12#include <linux/uio.h>
13#include <linux/xattr.h>
14#include <crypto/hash.h>
15#include <crypto/aead.h>
16#include <linux/random.h>
17#include <linux/scatterlist.h>
18
19#include "auth.h"
20#include "glob.h"
21
22#include <linux/fips.h>
23#include <crypto/des.h>
24
25#include "server.h"
26#include "smb_common.h"
27#include "connection.h"
28#include "mgmt/user_session.h"
29#include "mgmt/user_config.h"
30#include "crypto_ctx.h"
31#include "transport_ipc.h"
Namjae Jeone2f34482021-03-16 10:49:09 +090032
33/*
34 * Fixed format data defining GSS header and fixed string
35 * "not_defined_in_RFC4178@please_ignore".
36 * So sec blob data in neg phase could be generated statically.
37 */
38static char NEGOTIATE_GSS_HEADER[AUTH_GSS_LENGTH] = {
39#ifdef CONFIG_SMB_SERVER_KERBEROS5
40 0x60, 0x5e, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
41 0x05, 0x02, 0xa0, 0x54, 0x30, 0x52, 0xa0, 0x24,
42 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
43 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a,
44 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02,
45 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
46 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a, 0x30, 0x28,
47 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f, 0x74, 0x5f,
48 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f,
49 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43, 0x34, 0x31,
50 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65, 0x61, 0x73,
51 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65
52#else
53 0x60, 0x48, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
54 0x05, 0x02, 0xa0, 0x3e, 0x30, 0x3c, 0xa0, 0x0e,
55 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
56 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a,
57 0x30, 0x28, 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f,
58 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
59 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43,
60 0x34, 0x31, 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65,
61 0x61, 0x73, 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f,
62 0x72, 0x65
63#endif
64};
65
Namjae Jeone2f34482021-03-16 10:49:09 +090066void ksmbd_copy_gss_neg_header(void *buf)
67{
68 memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
69}
70
Namjae Jeone2f34482021-03-16 10:49:09 +090071/**
72 * ksmbd_gen_sess_key() - function to generate session key
73 * @sess: session of connection
74 * @hash: source hash value to be used for find session key
75 * @hmac: source hmac value to be used for finding session key
76 *
77 */
Namjae Jeon64b39f42021-03-30 14:25:35 +090078static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
Namjae Jeon070fb212021-05-26 17:57:12 +090079 char *hmac)
Namjae Jeone2f34482021-03-16 10:49:09 +090080{
81 struct ksmbd_crypto_ctx *ctx;
Namjae Jeon0e579cd2021-05-26 16:34:56 +090082 int rc;
Namjae Jeone2f34482021-03-16 10:49:09 +090083
84 ctx = ksmbd_crypto_ctx_find_hmacmd5();
Namjae Jeon0e579cd2021-05-26 16:34:56 +090085 if (!ctx) {
86 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
87 return -ENOMEM;
88 }
Namjae Jeone2f34482021-03-16 10:49:09 +090089
90 rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
91 hash,
92 CIFS_HMAC_MD5_HASH_SIZE);
93 if (rc) {
94 ksmbd_debug(AUTH, "hmacmd5 set key fail error %d\n", rc);
95 goto out;
96 }
97
98 rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
99 if (rc) {
100 ksmbd_debug(AUTH, "could not init hmacmd5 error %d\n", rc);
101 goto out;
102 }
103
104 rc = crypto_shash_update(CRYPTO_HMACMD5(ctx),
105 hmac,
106 SMB2_NTLMV2_SESSKEY_SIZE);
107 if (rc) {
Namjae Jeon070fb212021-05-26 17:57:12 +0900108 ksmbd_debug(AUTH, "Could not update with response error %d\n", rc);
Namjae Jeone2f34482021-03-16 10:49:09 +0900109 goto out;
110 }
111
112 rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key);
113 if (rc) {
Namjae Jeon070fb212021-05-26 17:57:12 +0900114 ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", rc);
Namjae Jeone2f34482021-03-16 10:49:09 +0900115 goto out;
116 }
117
118out:
119 ksmbd_release_crypto_ctx(ctx);
120 return rc;
121}
122
123static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
Namjae Jeon070fb212021-05-26 17:57:12 +0900124 char *dname)
Namjae Jeone2f34482021-03-16 10:49:09 +0900125{
Namjae Jeona2d0b502021-05-26 16:37:05 +0900126 int ret, len, conv_len;
Namjae Jeone2f34482021-03-16 10:49:09 +0900127 wchar_t *domain = NULL;
128 __le16 *uniname = NULL;
129 struct ksmbd_crypto_ctx *ctx;
130
131 ctx = ksmbd_crypto_ctx_find_hmacmd5();
132 if (!ctx) {
133 ksmbd_debug(AUTH, "can't generate ntlmv2 hash\n");
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900134 return -ENOMEM;
Namjae Jeone2f34482021-03-16 10:49:09 +0900135 }
136
137 ret = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
138 user_passkey(sess->user),
139 CIFS_ENCPWD_SIZE);
140 if (ret) {
141 ksmbd_debug(AUTH, "Could not set NT Hash as a key\n");
142 goto out;
143 }
144
145 ret = crypto_shash_init(CRYPTO_HMACMD5(ctx));
146 if (ret) {
147 ksmbd_debug(AUTH, "could not init hmacmd5\n");
148 goto out;
149 }
150
151 /* convert user_name to unicode */
152 len = strlen(user_name(sess->user));
153 uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
154 if (!uniname) {
155 ret = -ENOMEM;
156 goto out;
157 }
158
Namjae Jeona2d0b502021-05-26 16:37:05 +0900159 conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
Namjae Jeon070fb212021-05-26 17:57:12 +0900160 sess->conn->local_nls);
Namjae Jeona2d0b502021-05-26 16:37:05 +0900161 if (conv_len < 0 || conv_len > len) {
162 ret = -EINVAL;
163 goto out;
Namjae Jeone2f34482021-03-16 10:49:09 +0900164 }
Namjae Jeona2d0b502021-05-26 16:37:05 +0900165 UniStrupr(uniname);
Namjae Jeone2f34482021-03-16 10:49:09 +0900166
167 ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
168 (char *)uniname,
Namjae Jeona2d0b502021-05-26 16:37:05 +0900169 UNICODE_LEN(conv_len));
Namjae Jeone2f34482021-03-16 10:49:09 +0900170 if (ret) {
171 ksmbd_debug(AUTH, "Could not update with user\n");
172 goto out;
173 }
174
175 /* Convert domain name or conn name to unicode and uppercase */
176 len = strlen(dname);
177 domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
178 if (!domain) {
179 ret = -ENOMEM;
180 goto out;
181 }
182
Namjae Jeona2d0b502021-05-26 16:37:05 +0900183 conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
Namjae Jeon070fb212021-05-26 17:57:12 +0900184 sess->conn->local_nls);
Namjae Jeona2d0b502021-05-26 16:37:05 +0900185 if (conv_len < 0 || conv_len > len) {
186 ret = -EINVAL;
187 goto out;
188 }
Namjae Jeone2f34482021-03-16 10:49:09 +0900189
190 ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
191 (char *)domain,
Namjae Jeona2d0b502021-05-26 16:37:05 +0900192 UNICODE_LEN(conv_len));
Namjae Jeone2f34482021-03-16 10:49:09 +0900193 if (ret) {
194 ksmbd_debug(AUTH, "Could not update with domain\n");
195 goto out;
196 }
197
198 ret = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_hash);
Namjae Jeone2f34482021-03-16 10:49:09 +0900199 if (ret)
200 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
Namjae Jeon7e38ea22021-05-26 15:27:11 +0900201out:
Namjae Jeone2f34482021-03-16 10:49:09 +0900202 kfree(uniname);
203 kfree(domain);
204 ksmbd_release_crypto_ctx(ctx);
205 return ret;
206}
207
208/**
Namjae Jeone2f34482021-03-16 10:49:09 +0900209 * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
210 * @sess: session of connection
211 * @ntlmv2: NTLMv2 challenge response
212 * @blen: NTLMv2 blob length
213 * @domain_name: domain name
214 *
215 * Return: 0 on success, error number on error
216 */
Namjae Jeon64b39f42021-03-30 14:25:35 +0900217int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2,
Namjae Jeonce53d362021-12-15 14:57:27 +0900218 int blen, char *domain_name, char *cryptkey)
Namjae Jeone2f34482021-03-16 10:49:09 +0900219{
220 char ntlmv2_hash[CIFS_ENCPWD_SIZE];
221 char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
222 struct ksmbd_crypto_ctx *ctx;
223 char *construct = NULL;
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900224 int rc, len;
Namjae Jeone2f34482021-03-16 10:49:09 +0900225
226 ctx = ksmbd_crypto_ctx_find_hmacmd5();
227 if (!ctx) {
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900228 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
229 return -ENOMEM;
Namjae Jeone2f34482021-03-16 10:49:09 +0900230 }
231
232 rc = calc_ntlmv2_hash(sess, ntlmv2_hash, domain_name);
233 if (rc) {
234 ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
235 goto out;
236 }
237
238 rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
239 ntlmv2_hash,
240 CIFS_HMAC_MD5_HASH_SIZE);
241 if (rc) {
242 ksmbd_debug(AUTH, "Could not set NTLMV2 Hash as a key\n");
243 goto out;
244 }
245
246 rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
247 if (rc) {
248 ksmbd_debug(AUTH, "Could not init hmacmd5\n");
249 goto out;
250 }
251
252 len = CIFS_CRYPTO_KEY_SIZE + blen;
253 construct = kzalloc(len, GFP_KERNEL);
254 if (!construct) {
255 rc = -ENOMEM;
256 goto out;
257 }
258
Namjae Jeonce53d362021-12-15 14:57:27 +0900259 memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE);
Namjae Jeon192cc732021-05-26 15:28:48 +0900260 memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen);
Namjae Jeone2f34482021-03-16 10:49:09 +0900261
262 rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len);
263 if (rc) {
264 ksmbd_debug(AUTH, "Could not update with response\n");
265 goto out;
266 }
267
268 rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_rsp);
269 if (rc) {
270 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
271 goto out;
272 }
273
274 rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp);
275 if (rc) {
276 ksmbd_debug(AUTH, "Could not generate sess key\n");
277 goto out;
278 }
279
Namjae Jeonb72802a2021-05-26 15:29:24 +0900280 if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
281 rc = -EINVAL;
Namjae Jeone2f34482021-03-16 10:49:09 +0900282out:
283 ksmbd_release_crypto_ctx(ctx);
284 kfree(construct);
285 return rc;
286}
287
288/**
Namjae Jeone2f34482021-03-16 10:49:09 +0900289 * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
290 * authenticate blob
291 * @authblob: authenticate blob source pointer
292 * @usr: user details
293 * @sess: session of connection
294 *
295 * Return: 0 on success, error number on error
296 */
297int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
Namjae Jeonce53d362021-12-15 14:57:27 +0900298 int blob_len, struct ksmbd_conn *conn,
299 struct ksmbd_session *sess)
Namjae Jeone2f34482021-03-16 10:49:09 +0900300{
301 char *domain_name;
Marios Makassikis0d994cd2021-10-19 17:39:38 +0200302 unsigned int nt_off, dn_off;
303 unsigned short nt_len, dn_len;
Namjae Jeone2f34482021-03-16 10:49:09 +0900304 int ret;
305
306 if (blob_len < sizeof(struct authenticate_message)) {
307 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900308 blob_len);
Namjae Jeone2f34482021-03-16 10:49:09 +0900309 return -EINVAL;
310 }
311
312 if (memcmp(authblob->Signature, "NTLMSSP", 8)) {
313 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900314 authblob->Signature);
Namjae Jeone2f34482021-03-16 10:49:09 +0900315 return -EINVAL;
316 }
317
Namjae Jeone2f34482021-03-16 10:49:09 +0900318 nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
319 nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
Marios Makassikis0d994cd2021-10-19 17:39:38 +0200320 dn_off = le32_to_cpu(authblob->DomainName.BufferOffset);
321 dn_len = le16_to_cpu(authblob->DomainName.Length);
322
323 if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len)
324 return -EINVAL;
Namjae Jeone2f34482021-03-16 10:49:09 +0900325
Namjae Jeone2f34482021-03-16 10:49:09 +0900326 /* TODO : use domain name that imported from configuration file */
Marios Makassikis0d994cd2021-10-19 17:39:38 +0200327 domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off,
Namjae Jeonce53d362021-12-15 14:57:27 +0900328 dn_len, true, conn->local_nls);
Namjae Jeone2f34482021-03-16 10:49:09 +0900329 if (IS_ERR(domain_name))
330 return PTR_ERR(domain_name);
331
332 /* process NTLMv2 authentication */
333 ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900334 domain_name);
335 ret = ksmbd_auth_ntlmv2(sess, (struct ntlmv2_resp *)((char *)authblob + nt_off),
336 nt_len - CIFS_ENCPWD_SIZE,
Namjae Jeonce53d362021-12-15 14:57:27 +0900337 domain_name, conn->ntlmssp.cryptkey);
Namjae Jeone2f34482021-03-16 10:49:09 +0900338 kfree(domain_name);
339 return ret;
340}
341
342/**
343 * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
344 * negotiate blob
345 * @negblob: negotiate blob source pointer
346 * @rsp: response header pointer to be updated
347 * @sess: session of connection
348 *
349 */
350int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
Namjae Jeonce53d362021-12-15 14:57:27 +0900351 int blob_len, struct ksmbd_conn *conn)
Namjae Jeone2f34482021-03-16 10:49:09 +0900352{
353 if (blob_len < sizeof(struct negotiate_message)) {
354 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900355 blob_len);
Namjae Jeone2f34482021-03-16 10:49:09 +0900356 return -EINVAL;
357 }
358
359 if (memcmp(negblob->Signature, "NTLMSSP", 8)) {
360 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900361 negblob->Signature);
Namjae Jeone2f34482021-03-16 10:49:09 +0900362 return -EINVAL;
363 }
364
Namjae Jeonce53d362021-12-15 14:57:27 +0900365 conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags);
Namjae Jeone2f34482021-03-16 10:49:09 +0900366 return 0;
367}
368
369/**
370 * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
371 * challenge blob
372 * @chgblob: challenge blob source pointer to initialize
373 * @rsp: response header pointer to be updated
374 * @sess: session of connection
375 *
376 */
377unsigned int
378ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
Namjae Jeonce53d362021-12-15 14:57:27 +0900379 struct ksmbd_conn *conn)
Namjae Jeone2f34482021-03-16 10:49:09 +0900380{
381 struct target_info *tinfo;
382 wchar_t *name;
383 __u8 *target_name;
Namjae Jeon152de8c2021-05-29 07:59:40 +0900384 unsigned int flags, blob_off, blob_len, type, target_info_len = 0;
385 int len, uni_len, conv_len;
Namjae Jeonce53d362021-12-15 14:57:27 +0900386 int cflags = conn->ntlmssp.client_flags;
Namjae Jeone2f34482021-03-16 10:49:09 +0900387
388 memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
389 chgblob->MessageType = NtLmChallenge;
390
391 flags = NTLMSSP_NEGOTIATE_UNICODE |
392 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_TARGET_TYPE_SERVER |
393 NTLMSSP_NEGOTIATE_TARGET_INFO;
394
395 if (cflags & NTLMSSP_NEGOTIATE_SIGN) {
396 flags |= NTLMSSP_NEGOTIATE_SIGN;
397 flags |= cflags & (NTLMSSP_NEGOTIATE_128 |
Namjae Jeon70478052021-05-26 16:36:15 +0900398 NTLMSSP_NEGOTIATE_56);
Namjae Jeone2f34482021-03-16 10:49:09 +0900399 }
400
401 if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
402 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
403
404 if (cflags & NTLMSSP_REQUEST_TARGET)
405 flags |= NTLMSSP_REQUEST_TARGET;
406
Namjae Jeonce53d362021-12-15 14:57:27 +0900407 if (conn->use_spnego &&
Namjae Jeon64b39f42021-03-30 14:25:35 +0900408 (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
Namjae Jeone2f34482021-03-16 10:49:09 +0900409 flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
410
411 chgblob->NegotiateFlags = cpu_to_le32(flags);
412 len = strlen(ksmbd_netbios_name());
Namjae Jeona2d0b502021-05-26 16:37:05 +0900413 name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
Namjae Jeone2f34482021-03-16 10:49:09 +0900414 if (!name)
415 return -ENOMEM;
416
Namjae Jeona2d0b502021-05-26 16:37:05 +0900417 conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
Namjae Jeonce53d362021-12-15 14:57:27 +0900418 conn->local_nls);
Namjae Jeona2d0b502021-05-26 16:37:05 +0900419 if (conv_len < 0 || conv_len > len) {
420 kfree(name);
421 return -EINVAL;
422 }
423
424 uni_len = UNICODE_LEN(conv_len);
Namjae Jeone2f34482021-03-16 10:49:09 +0900425
426 blob_off = sizeof(struct challenge_message);
Namjae Jeona2d0b502021-05-26 16:37:05 +0900427 blob_len = blob_off + uni_len;
Namjae Jeone2f34482021-03-16 10:49:09 +0900428
Namjae Jeona2d0b502021-05-26 16:37:05 +0900429 chgblob->TargetName.Length = cpu_to_le16(uni_len);
430 chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len);
Namjae Jeone2f34482021-03-16 10:49:09 +0900431 chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
432
433 /* Initialize random conn challenge */
Namjae Jeonce53d362021-12-15 14:57:27 +0900434 get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64));
435 memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey,
Namjae Jeon070fb212021-05-26 17:57:12 +0900436 CIFS_CRYPTO_KEY_SIZE);
Namjae Jeone2f34482021-03-16 10:49:09 +0900437
438 /* Add Target Information to security buffer */
439 chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
440
441 target_name = (__u8 *)chgblob + blob_off;
Namjae Jeona2d0b502021-05-26 16:37:05 +0900442 memcpy(target_name, name, uni_len);
443 tinfo = (struct target_info *)(target_name + uni_len);
Namjae Jeone2f34482021-03-16 10:49:09 +0900444
445 chgblob->TargetInfoArray.Length = 0;
446 /* Add target info list for NetBIOS/DNS settings */
447 for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
Namjae Jeon70478052021-05-26 16:36:15 +0900448 type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
Namjae Jeone2f34482021-03-16 10:49:09 +0900449 tinfo->Type = cpu_to_le16(type);
Namjae Jeona2d0b502021-05-26 16:37:05 +0900450 tinfo->Length = cpu_to_le16(uni_len);
451 memcpy(tinfo->Content, name, uni_len);
452 tinfo = (struct target_info *)((char *)tinfo + 4 + uni_len);
453 target_info_len += 4 + uni_len;
Namjae Jeone2f34482021-03-16 10:49:09 +0900454 }
455
456 /* Add terminator subblock */
457 tinfo->Type = 0;
458 tinfo->Length = 0;
459 target_info_len += 4;
460
461 chgblob->TargetInfoArray.Length = cpu_to_le16(target_info_len);
462 chgblob->TargetInfoArray.MaximumLength = cpu_to_le16(target_info_len);
463 blob_len += target_info_len;
464 kfree(name);
465 ksmbd_debug(AUTH, "NTLMSSP SecurityBufferLength %d\n", blob_len);
466 return blob_len;
467}
468
469#ifdef CONFIG_SMB_SERVER_KERBEROS5
Namjae Jeon64b39f42021-03-30 14:25:35 +0900470int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
Namjae Jeon070fb212021-05-26 17:57:12 +0900471 int in_len, char *out_blob, int *out_len)
Namjae Jeone2f34482021-03-16 10:49:09 +0900472{
473 struct ksmbd_spnego_authen_response *resp;
474 struct ksmbd_user *user = NULL;
475 int retval;
476
477 resp = ksmbd_ipc_spnego_authen_request(in_blob, in_len);
478 if (!resp) {
479 ksmbd_debug(AUTH, "SPNEGO_AUTHEN_REQUEST failure\n");
480 return -EINVAL;
481 }
482
483 if (!(resp->login_response.status & KSMBD_USER_FLAG_OK)) {
484 ksmbd_debug(AUTH, "krb5 authentication failure\n");
485 retval = -EPERM;
486 goto out;
487 }
488
489 if (*out_len <= resp->spnego_blob_len) {
490 ksmbd_debug(AUTH, "buf len %d, but blob len %d\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900491 *out_len, resp->spnego_blob_len);
Namjae Jeone2f34482021-03-16 10:49:09 +0900492 retval = -EINVAL;
493 goto out;
494 }
495
496 if (resp->session_key_len > sizeof(sess->sess_key)) {
497 ksmbd_debug(AUTH, "session key is too long\n");
498 retval = -EINVAL;
499 goto out;
500 }
501
502 user = ksmbd_alloc_user(&resp->login_response);
503 if (!user) {
504 ksmbd_debug(AUTH, "login failure\n");
505 retval = -ENOMEM;
506 goto out;
507 }
508 sess->user = user;
509
510 memcpy(sess->sess_key, resp->payload, resp->session_key_len);
511 memcpy(out_blob, resp->payload + resp->session_key_len,
Namjae Jeon070fb212021-05-26 17:57:12 +0900512 resp->spnego_blob_len);
Namjae Jeone2f34482021-03-16 10:49:09 +0900513 *out_len = resp->spnego_blob_len;
514 retval = 0;
515out:
Namjae Jeon79f6b112021-04-02 12:47:14 +0900516 kvfree(resp);
Namjae Jeone2f34482021-03-16 10:49:09 +0900517 return retval;
518}
519#else
Namjae Jeon64b39f42021-03-30 14:25:35 +0900520int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
Namjae Jeon070fb212021-05-26 17:57:12 +0900521 int in_len, char *out_blob, int *out_len)
Namjae Jeone2f34482021-03-16 10:49:09 +0900522{
523 return -EOPNOTSUPP;
524}
525#endif
526
527/**
528 * ksmbd_sign_smb2_pdu() - function to generate packet signing
529 * @conn: connection
530 * @key: signing key
531 * @iov: buffer iov array
532 * @n_vec: number of iovecs
533 * @sig: signature value generated for client request packet
534 *
535 */
Namjae Jeon64b39f42021-03-30 14:25:35 +0900536int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
Namjae Jeon070fb212021-05-26 17:57:12 +0900537 int n_vec, char *sig)
Namjae Jeone2f34482021-03-16 10:49:09 +0900538{
539 struct ksmbd_crypto_ctx *ctx;
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900540 int rc, i;
Namjae Jeone2f34482021-03-16 10:49:09 +0900541
542 ctx = ksmbd_crypto_ctx_find_hmacsha256();
543 if (!ctx) {
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900544 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
545 return -ENOMEM;
Namjae Jeone2f34482021-03-16 10:49:09 +0900546 }
547
548 rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
549 key,
550 SMB2_NTLMV2_SESSKEY_SIZE);
551 if (rc)
552 goto out;
553
554 rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
555 if (rc) {
556 ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
557 goto out;
558 }
559
560 for (i = 0; i < n_vec; i++) {
561 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
562 iov[i].iov_base,
563 iov[i].iov_len);
564 if (rc) {
565 ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc);
566 goto out;
567 }
568 }
569
570 rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig);
571 if (rc)
572 ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc);
573out:
574 ksmbd_release_crypto_ctx(ctx);
575 return rc;
576}
577
578/**
579 * ksmbd_sign_smb3_pdu() - function to generate packet signing
580 * @conn: connection
581 * @key: signing key
582 * @iov: buffer iov array
583 * @n_vec: number of iovecs
584 * @sig: signature value generated for client request packet
585 *
586 */
Namjae Jeon64b39f42021-03-30 14:25:35 +0900587int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
Namjae Jeon070fb212021-05-26 17:57:12 +0900588 int n_vec, char *sig)
Namjae Jeone2f34482021-03-16 10:49:09 +0900589{
590 struct ksmbd_crypto_ctx *ctx;
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900591 int rc, i;
Namjae Jeone2f34482021-03-16 10:49:09 +0900592
593 ctx = ksmbd_crypto_ctx_find_cmacaes();
594 if (!ctx) {
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900595 ksmbd_debug(AUTH, "could not crypto alloc cmac\n");
596 return -ENOMEM;
Namjae Jeone2f34482021-03-16 10:49:09 +0900597 }
598
599 rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx),
600 key,
601 SMB2_CMACAES_SIZE);
602 if (rc)
603 goto out;
604
605 rc = crypto_shash_init(CRYPTO_CMACAES(ctx));
606 if (rc) {
607 ksmbd_debug(AUTH, "cmaces init error %d\n", rc);
608 goto out;
609 }
610
611 for (i = 0; i < n_vec; i++) {
612 rc = crypto_shash_update(CRYPTO_CMACAES(ctx),
613 iov[i].iov_base,
614 iov[i].iov_len);
615 if (rc) {
616 ksmbd_debug(AUTH, "cmaces update error %d\n", rc);
617 goto out;
618 }
619 }
620
621 rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig);
622 if (rc)
623 ksmbd_debug(AUTH, "cmaces generation error %d\n", rc);
624out:
625 ksmbd_release_crypto_ctx(ctx);
626 return rc;
627}
628
629struct derivation {
630 struct kvec label;
631 struct kvec context;
632 bool binding;
633};
634
635static int generate_key(struct ksmbd_session *sess, struct kvec label,
Namjae Jeon070fb212021-05-26 17:57:12 +0900636 struct kvec context, __u8 *key, unsigned int key_size)
Namjae Jeone2f34482021-03-16 10:49:09 +0900637{
638 unsigned char zero = 0x0;
639 __u8 i[4] = {0, 0, 0, 1};
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900640 __u8 L128[4] = {0, 0, 0, 128};
641 __u8 L256[4] = {0, 0, 1, 0};
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900642 int rc;
Namjae Jeone2f34482021-03-16 10:49:09 +0900643 unsigned char prfhash[SMB2_HMACSHA256_SIZE];
644 unsigned char *hashptr = prfhash;
645 struct ksmbd_crypto_ctx *ctx;
646
647 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
648 memset(key, 0x0, key_size);
649
650 ctx = ksmbd_crypto_ctx_find_hmacsha256();
651 if (!ctx) {
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900652 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
653 return -ENOMEM;
Namjae Jeone2f34482021-03-16 10:49:09 +0900654 }
655
656 rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
657 sess->sess_key,
658 SMB2_NTLMV2_SESSKEY_SIZE);
659 if (rc)
660 goto smb3signkey_ret;
661
662 rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
663 if (rc) {
664 ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
665 goto smb3signkey_ret;
666 }
667
668 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4);
669 if (rc) {
670 ksmbd_debug(AUTH, "could not update with n\n");
671 goto smb3signkey_ret;
672 }
673
674 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
675 label.iov_base,
676 label.iov_len);
677 if (rc) {
678 ksmbd_debug(AUTH, "could not update with label\n");
679 goto smb3signkey_ret;
680 }
681
682 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1);
683 if (rc) {
684 ksmbd_debug(AUTH, "could not update with zero\n");
685 goto smb3signkey_ret;
686 }
687
688 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
689 context.iov_base,
690 context.iov_len);
691 if (rc) {
692 ksmbd_debug(AUTH, "could not update with context\n");
693 goto smb3signkey_ret;
694 }
695
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900696 if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
697 sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
698 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
699 else
700 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
Namjae Jeone2f34482021-03-16 10:49:09 +0900701 if (rc) {
702 ksmbd_debug(AUTH, "could not update with L\n");
703 goto smb3signkey_ret;
704 }
705
706 rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr);
707 if (rc) {
708 ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900709 rc);
Namjae Jeone2f34482021-03-16 10:49:09 +0900710 goto smb3signkey_ret;
711 }
712
713 memcpy(key, hashptr, key_size);
714
715smb3signkey_ret:
716 ksmbd_release_crypto_ctx(ctx);
717 return rc;
718}
719
720static int generate_smb3signingkey(struct ksmbd_session *sess,
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900721 struct ksmbd_conn *conn,
Namjae Jeon070fb212021-05-26 17:57:12 +0900722 const struct derivation *signing)
Namjae Jeone2f34482021-03-16 10:49:09 +0900723{
724 int rc;
725 struct channel *chann;
726 char *key;
727
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900728 chann = lookup_chann_list(sess, conn);
Namjae Jeone2f34482021-03-16 10:49:09 +0900729 if (!chann)
730 return 0;
731
732 if (sess->conn->dialect >= SMB30_PROT_ID && signing->binding)
733 key = chann->smb3signingkey;
734 else
735 key = sess->smb3signingkey;
736
737 rc = generate_key(sess, signing->label, signing->context, key,
Namjae Jeon070fb212021-05-26 17:57:12 +0900738 SMB3_SIGN_KEY_SIZE);
Namjae Jeone2f34482021-03-16 10:49:09 +0900739 if (rc)
740 return rc;
741
742 if (!(sess->conn->dialect >= SMB30_PROT_ID && signing->binding))
743 memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
744
745 ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
746 ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
747 ksmbd_debug(AUTH, "Session Key %*ph\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900748 SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
Namjae Jeone2f34482021-03-16 10:49:09 +0900749 ksmbd_debug(AUTH, "Signing Key %*ph\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900750 SMB3_SIGN_KEY_SIZE, key);
Namjae Jeon876edcc2021-05-26 15:30:04 +0900751 return 0;
Namjae Jeone2f34482021-03-16 10:49:09 +0900752}
753
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900754int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
755 struct ksmbd_conn *conn)
Namjae Jeone2f34482021-03-16 10:49:09 +0900756{
757 struct derivation d;
758
759 d.label.iov_base = "SMB2AESCMAC";
760 d.label.iov_len = 12;
761 d.context.iov_base = "SmbSign";
762 d.context.iov_len = 8;
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900763 d.binding = conn->binding;
Namjae Jeone2f34482021-03-16 10:49:09 +0900764
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900765 return generate_smb3signingkey(sess, conn, &d);
Namjae Jeone2f34482021-03-16 10:49:09 +0900766}
767
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900768int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
769 struct ksmbd_conn *conn)
Namjae Jeone2f34482021-03-16 10:49:09 +0900770{
771 struct derivation d;
772
773 d.label.iov_base = "SMBSigningKey";
774 d.label.iov_len = 14;
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900775 if (conn->binding) {
776 struct preauth_session *preauth_sess;
Namjae Jeone2f34482021-03-16 10:49:09 +0900777
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900778 preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
779 if (!preauth_sess)
780 return -ENOENT;
781 d.context.iov_base = preauth_sess->Preauth_HashValue;
782 } else {
783 d.context.iov_base = sess->Preauth_HashValue;
784 }
785 d.context.iov_len = 64;
786 d.binding = conn->binding;
787
788 return generate_smb3signingkey(sess, conn, &d);
Namjae Jeone2f34482021-03-16 10:49:09 +0900789}
790
791struct derivation_twin {
792 struct derivation encryption;
793 struct derivation decryption;
794};
795
796static int generate_smb3encryptionkey(struct ksmbd_session *sess,
Namjae Jeon070fb212021-05-26 17:57:12 +0900797 const struct derivation_twin *ptwin)
Namjae Jeone2f34482021-03-16 10:49:09 +0900798{
799 int rc;
800
801 rc = generate_key(sess, ptwin->encryption.label,
Namjae Jeon070fb212021-05-26 17:57:12 +0900802 ptwin->encryption.context, sess->smb3encryptionkey,
803 SMB3_ENC_DEC_KEY_SIZE);
Namjae Jeone2f34482021-03-16 10:49:09 +0900804 if (rc)
805 return rc;
806
807 rc = generate_key(sess, ptwin->decryption.label,
Namjae Jeon070fb212021-05-26 17:57:12 +0900808 ptwin->decryption.context,
809 sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
Namjae Jeone2f34482021-03-16 10:49:09 +0900810 if (rc)
811 return rc;
812
813 ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900814 ksmbd_debug(AUTH, "Cipher type %d\n", sess->conn->cipher_type);
Namjae Jeone2f34482021-03-16 10:49:09 +0900815 ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
816 ksmbd_debug(AUTH, "Session Key %*ph\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900817 SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900818 if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
819 sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
820 ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900821 SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900822 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900823 SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900824 } else {
825 ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900826 SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900827 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
Namjae Jeon070fb212021-05-26 17:57:12 +0900828 SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900829 }
Namjae Jeon876edcc2021-05-26 15:30:04 +0900830 return 0;
Namjae Jeone2f34482021-03-16 10:49:09 +0900831}
832
833int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess)
834{
835 struct derivation_twin twin;
836 struct derivation *d;
837
838 d = &twin.encryption;
839 d->label.iov_base = "SMB2AESCCM";
840 d->label.iov_len = 11;
841 d->context.iov_base = "ServerOut";
842 d->context.iov_len = 10;
843
844 d = &twin.decryption;
845 d->label.iov_base = "SMB2AESCCM";
846 d->label.iov_len = 11;
847 d->context.iov_base = "ServerIn ";
848 d->context.iov_len = 10;
849
850 return generate_smb3encryptionkey(sess, &twin);
851}
852
853int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess)
854{
855 struct derivation_twin twin;
856 struct derivation *d;
857
858 d = &twin.encryption;
859 d->label.iov_base = "SMBS2CCipherKey";
860 d->label.iov_len = 16;
861 d->context.iov_base = sess->Preauth_HashValue;
862 d->context.iov_len = 64;
863
864 d = &twin.decryption;
865 d->label.iov_base = "SMBC2SCipherKey";
866 d->label.iov_len = 16;
867 d->context.iov_base = sess->Preauth_HashValue;
868 d->context.iov_len = 64;
869
870 return generate_smb3encryptionkey(sess, &twin);
871}
872
Namjae Jeon64b39f42021-03-30 14:25:35 +0900873int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
Namjae Jeon070fb212021-05-26 17:57:12 +0900874 __u8 *pi_hash)
Namjae Jeone2f34482021-03-16 10:49:09 +0900875{
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900876 int rc;
Namjae Jeoncb451722021-11-03 08:08:44 +0900877 struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
Namjae Jeone2f34482021-03-16 10:49:09 +0900878 char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
Namjae Jeoncb451722021-11-03 08:08:44 +0900879 int msg_size = get_rfc1002_len(buf);
Namjae Jeone2f34482021-03-16 10:49:09 +0900880 struct ksmbd_crypto_ctx *ctx = NULL;
881
Namjae Jeond3cd8c42021-05-26 15:56:18 +0900882 if (conn->preauth_info->Preauth_HashId !=
883 SMB2_PREAUTH_INTEGRITY_SHA512)
884 return -EINVAL;
885
886 ctx = ksmbd_crypto_ctx_find_sha512();
887 if (!ctx) {
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900888 ksmbd_debug(AUTH, "could not alloc sha512\n");
889 return -ENOMEM;
Namjae Jeon64b39f42021-03-30 14:25:35 +0900890 }
Namjae Jeone2f34482021-03-16 10:49:09 +0900891
892 rc = crypto_shash_init(CRYPTO_SHA512(ctx));
893 if (rc) {
894 ksmbd_debug(AUTH, "could not init shashn");
895 goto out;
896 }
897
898 rc = crypto_shash_update(CRYPTO_SHA512(ctx), pi_hash, 64);
899 if (rc) {
900 ksmbd_debug(AUTH, "could not update with n\n");
901 goto out;
902 }
903
904 rc = crypto_shash_update(CRYPTO_SHA512(ctx), all_bytes_msg, msg_size);
905 if (rc) {
906 ksmbd_debug(AUTH, "could not update with n\n");
907 goto out;
908 }
909
910 rc = crypto_shash_final(CRYPTO_SHA512(ctx), pi_hash);
911 if (rc) {
912 ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
913 goto out;
914 }
915out:
916 ksmbd_release_crypto_ctx(ctx);
917 return rc;
918}
919
920int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
Namjae Jeon070fb212021-05-26 17:57:12 +0900921 __u8 *pi_hash)
Namjae Jeone2f34482021-03-16 10:49:09 +0900922{
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900923 int rc;
Namjae Jeone2f34482021-03-16 10:49:09 +0900924 struct ksmbd_crypto_ctx *ctx = NULL;
925
926 ctx = ksmbd_crypto_ctx_find_sha256();
927 if (!ctx) {
Namjae Jeon0e579cd2021-05-26 16:34:56 +0900928 ksmbd_debug(AUTH, "could not alloc sha256\n");
929 return -ENOMEM;
Namjae Jeone2f34482021-03-16 10:49:09 +0900930 }
931
932 rc = crypto_shash_init(CRYPTO_SHA256(ctx));
933 if (rc) {
934 ksmbd_debug(AUTH, "could not init shashn");
935 goto out;
936 }
937
938 rc = crypto_shash_update(CRYPTO_SHA256(ctx), sd_buf, len);
939 if (rc) {
940 ksmbd_debug(AUTH, "could not update with n\n");
941 goto out;
942 }
943
944 rc = crypto_shash_final(CRYPTO_SHA256(ctx), pi_hash);
945 if (rc) {
946 ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
947 goto out;
948 }
949out:
950 ksmbd_release_crypto_ctx(ctx);
951 return rc;
952}
953
Namjae Jeon64b39f42021-03-30 14:25:35 +0900954static int ksmbd_get_encryption_key(struct ksmbd_conn *conn, __u64 ses_id,
Namjae Jeon070fb212021-05-26 17:57:12 +0900955 int enc, u8 *key)
Namjae Jeone2f34482021-03-16 10:49:09 +0900956{
957 struct ksmbd_session *sess;
958 u8 *ses_enc_key;
959
Namjae Jeonf5a544e2021-06-18 10:04:19 +0900960 sess = ksmbd_session_lookup_all(conn, ses_id);
Namjae Jeone2f34482021-03-16 10:49:09 +0900961 if (!sess)
Namjae Jeon522dcc72021-05-26 15:30:50 +0900962 return -EINVAL;
Namjae Jeone2f34482021-03-16 10:49:09 +0900963
964 ses_enc_key = enc ? sess->smb3encryptionkey :
965 sess->smb3decryptionkey;
Namjae Jeon5a0ca772021-05-06 11:43:37 +0900966 memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
Namjae Jeone2f34482021-03-16 10:49:09 +0900967
968 return 0;
969}
970
971static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
Namjae Jeon070fb212021-05-26 17:57:12 +0900972 unsigned int buflen)
Namjae Jeone2f34482021-03-16 10:49:09 +0900973{
974 void *addr;
975
976 if (is_vmalloc_addr(buf))
977 addr = vmalloc_to_page(buf);
978 else
979 addr = virt_to_page(buf);
980 sg_set_page(sg, addr, buflen, offset_in_page(buf));
981}
982
Namjae Jeon64b39f42021-03-30 14:25:35 +0900983static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
Namjae Jeon070fb212021-05-26 17:57:12 +0900984 u8 *sign)
Namjae Jeone2f34482021-03-16 10:49:09 +0900985{
986 struct scatterlist *sg;
Namjae Jeon2dd91292021-11-03 08:25:54 +0900987 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
Namjae Jeone2f34482021-03-16 10:49:09 +0900988 int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
989
Namjae Jeon41a78482021-05-26 15:31:37 +0900990 if (!nvec)
991 return NULL;
992
Namjae Jeone2f34482021-03-16 10:49:09 +0900993 for (i = 0; i < nvec - 1; i++) {
994 unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
995
996 if (is_vmalloc_addr(iov[i + 1].iov_base)) {
997 nr_entries[i] = ((kaddr + iov[i + 1].iov_len +
998 PAGE_SIZE - 1) >> PAGE_SHIFT) -
999 (kaddr >> PAGE_SHIFT);
Namjae Jeon64b39f42021-03-30 14:25:35 +09001000 } else {
Namjae Jeone2f34482021-03-16 10:49:09 +09001001 nr_entries[i]++;
Namjae Jeon64b39f42021-03-30 14:25:35 +09001002 }
Namjae Jeone2f34482021-03-16 10:49:09 +09001003 total_entries += nr_entries[i];
1004 }
1005
1006 /* Add two entries for transform header and signature */
1007 total_entries += 2;
1008
1009 sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
1010 if (!sg)
1011 return NULL;
1012
1013 sg_init_table(sg, total_entries);
1014 smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
1015 for (i = 0; i < nvec - 1; i++) {
1016 void *data = iov[i + 1].iov_base;
1017 int len = iov[i + 1].iov_len;
1018
1019 if (is_vmalloc_addr(data)) {
1020 int j, offset = offset_in_page(data);
1021
1022 for (j = 0; j < nr_entries[i]; j++) {
1023 unsigned int bytes = PAGE_SIZE - offset;
1024
Namjae Jeon08591cc2021-05-26 15:32:26 +09001025 if (!len)
Namjae Jeone2f34482021-03-16 10:49:09 +09001026 break;
1027
1028 if (bytes > len)
1029 bytes = len;
1030
1031 sg_set_page(&sg[sg_idx++],
1032 vmalloc_to_page(data), bytes,
1033 offset_in_page(data));
1034
1035 data += bytes;
1036 len -= bytes;
1037 offset = 0;
1038 }
1039 } else {
1040 sg_set_page(&sg[sg_idx++], virt_to_page(data), len,
1041 offset_in_page(data));
1042 }
Namjae Jeone2f34482021-03-16 10:49:09 +09001043 }
1044 smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
1045 return sg;
1046}
1047
Namjae Jeon64b39f42021-03-30 14:25:35 +09001048int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
Namjae Jeon070fb212021-05-26 17:57:12 +09001049 unsigned int nvec, int enc)
Namjae Jeone2f34482021-03-16 10:49:09 +09001050{
Namjae Jeon2dd91292021-11-03 08:25:54 +09001051 struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
1052 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
Namjae Jeon03f1c3d2021-05-26 15:34:37 +09001053 int rc;
Namjae Jeone2f34482021-03-16 10:49:09 +09001054 struct scatterlist *sg;
1055 u8 sign[SMB2_SIGNATURE_SIZE] = {};
Namjae Jeon5a0ca772021-05-06 11:43:37 +09001056 u8 key[SMB3_ENC_DEC_KEY_SIZE];
Namjae Jeone2f34482021-03-16 10:49:09 +09001057 struct aead_request *req;
1058 char *iv;
1059 unsigned int iv_len;
1060 struct crypto_aead *tfm;
1061 unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
1062 struct ksmbd_crypto_ctx *ctx;
1063
1064 rc = ksmbd_get_encryption_key(conn,
1065 le64_to_cpu(tr_hdr->SessionId),
1066 enc,
1067 key);
1068 if (rc) {
Namjae Jeonbde16942021-06-28 15:23:19 +09001069 pr_err("Could not get %scryption key\n", enc ? "en" : "de");
Namjae Jeon27aa6462021-05-26 15:35:26 +09001070 return rc;
Namjae Jeone2f34482021-03-16 10:49:09 +09001071 }
1072
Namjae Jeon5a0ca772021-05-06 11:43:37 +09001073 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1074 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
Namjae Jeone2f34482021-03-16 10:49:09 +09001075 ctx = ksmbd_crypto_ctx_find_gcm();
1076 else
1077 ctx = ksmbd_crypto_ctx_find_ccm();
1078 if (!ctx) {
Namjae Jeonbde16942021-06-28 15:23:19 +09001079 pr_err("crypto alloc failed\n");
Namjae Jeon0e579cd2021-05-26 16:34:56 +09001080 return -ENOMEM;
Namjae Jeone2f34482021-03-16 10:49:09 +09001081 }
1082
Namjae Jeon5a0ca772021-05-06 11:43:37 +09001083 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1084 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
Namjae Jeone2f34482021-03-16 10:49:09 +09001085 tfm = CRYPTO_GCM(ctx);
1086 else
1087 tfm = CRYPTO_CCM(ctx);
1088
Namjae Jeon5a0ca772021-05-06 11:43:37 +09001089 if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
1090 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
1091 rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
1092 else
1093 rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
Namjae Jeone2f34482021-03-16 10:49:09 +09001094 if (rc) {
Namjae Jeonbde16942021-06-28 15:23:19 +09001095 pr_err("Failed to set aead key %d\n", rc);
Namjae Jeone2f34482021-03-16 10:49:09 +09001096 goto free_ctx;
1097 }
1098
1099 rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
1100 if (rc) {
Namjae Jeonbde16942021-06-28 15:23:19 +09001101 pr_err("Failed to set authsize %d\n", rc);
Namjae Jeone2f34482021-03-16 10:49:09 +09001102 goto free_ctx;
1103 }
1104
1105 req = aead_request_alloc(tfm, GFP_KERNEL);
1106 if (!req) {
Namjae Jeone2f34482021-03-16 10:49:09 +09001107 rc = -ENOMEM;
1108 goto free_ctx;
1109 }
1110
1111 if (!enc) {
1112 memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
1113 crypt_len += SMB2_SIGNATURE_SIZE;
1114 }
1115
1116 sg = ksmbd_init_sg(iov, nvec, sign);
1117 if (!sg) {
Namjae Jeonbde16942021-06-28 15:23:19 +09001118 pr_err("Failed to init sg\n");
Namjae Jeone2f34482021-03-16 10:49:09 +09001119 rc = -ENOMEM;
1120 goto free_req;
1121 }
1122
1123 iv_len = crypto_aead_ivsize(tfm);
1124 iv = kzalloc(iv_len, GFP_KERNEL);
1125 if (!iv) {
Namjae Jeone2f34482021-03-16 10:49:09 +09001126 rc = -ENOMEM;
1127 goto free_sg;
1128 }
1129
Namjae Jeon5a0ca772021-05-06 11:43:37 +09001130 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1131 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
1132 memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
Namjae Jeon64b39f42021-03-30 14:25:35 +09001133 } else {
Namjae Jeone2f34482021-03-16 10:49:09 +09001134 iv[0] = 3;
Namjae Jeon5a0ca772021-05-06 11:43:37 +09001135 memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
Namjae Jeone2f34482021-03-16 10:49:09 +09001136 }
1137
1138 aead_request_set_crypt(req, sg, sg, crypt_len, iv);
1139 aead_request_set_ad(req, assoc_data_len);
1140 aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
1141
1142 if (enc)
1143 rc = crypto_aead_encrypt(req);
1144 else
1145 rc = crypto_aead_decrypt(req);
Namjae Jeon73b8b082021-05-26 15:53:26 +09001146 if (rc)
1147 goto free_iv;
1148
1149 if (enc)
Namjae Jeone2f34482021-03-16 10:49:09 +09001150 memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
1151
Namjae Jeon73b8b082021-05-26 15:53:26 +09001152free_iv:
Namjae Jeone2f34482021-03-16 10:49:09 +09001153 kfree(iv);
1154free_sg:
1155 kfree(sg);
1156free_req:
1157 kfree(req);
1158free_ctx:
1159 ksmbd_release_crypto_ctx(ctx);
1160 return rc;
1161}