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