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