]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - fs/cifsd/auth.c
cifsd: simplify error handling in ksmbd_gen_preauth_integrity_hash()
[mirror_ubuntu-jammy-kernel.git] / fs / cifsd / 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"
32#include "buffer_pool.h"
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
72static void
73str_to_key(unsigned char *str, unsigned char *key)
74{
75 int i;
76
77 key[0] = str[0] >> 1;
78 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
79 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
80 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
81 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
82 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
83 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
84 key[7] = str[6] & 0x7F;
85 for (i = 0; i < 8; i++)
86 key[i] = (key[i] << 1);
87}
88
89static int
90smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
91{
92 unsigned char key2[8];
93 struct des_ctx ctx;
94
e2f34481
NJ
95 if (fips_enabled) {
96 ksmbd_debug(AUTH,
97 "FIPS compliance enabled: DES not permitted\n");
98 return -ENOENT;
99 }
100
94096702 101 str_to_key(key, key2);
e2f34481
NJ
102 des_expand_key(&ctx, key2, DES_KEY_SIZE);
103 des_encrypt(&ctx, out, in);
104 memzero_explicit(&ctx, sizeof(ctx));
105 return 0;
106}
107
64b39f4a 108static int ksmbd_enc_p24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
e2f34481
NJ
109{
110 int rc;
111
112 rc = smbhash(p24, c8, p21);
113 if (rc)
114 return rc;
115 rc = smbhash(p24 + 8, c8, p21 + 7);
116 if (rc)
117 return rc;
fd43cbbe 118 return smbhash(p24 + 16, c8, p21 + 14);
e2f34481
NJ
119}
120
121/* produce a md4 message digest from data of length n bytes */
64b39f4a
NJ
122static int ksmbd_enc_md4(unsigned char *md4_hash, unsigned char *link_str,
123 int link_len)
e2f34481
NJ
124{
125 int rc;
126 struct ksmbd_crypto_ctx *ctx;
127
128 ctx = ksmbd_crypto_ctx_find_md4();
129 if (!ctx) {
130 ksmbd_debug(AUTH, "Crypto md4 allocation error\n");
131 return -EINVAL;
132 }
133
134 rc = crypto_shash_init(CRYPTO_MD4(ctx));
135 if (rc) {
136 ksmbd_debug(AUTH, "Could not init md4 shash\n");
137 goto out;
138 }
139
140 rc = crypto_shash_update(CRYPTO_MD4(ctx), link_str, link_len);
141 if (rc) {
142 ksmbd_debug(AUTH, "Could not update with link_str\n");
143 goto out;
144 }
145
146 rc = crypto_shash_final(CRYPTO_MD4(ctx), md4_hash);
147 if (rc)
148 ksmbd_debug(AUTH, "Could not generate md4 hash\n");
149out:
150 ksmbd_release_crypto_ctx(ctx);
151 return rc;
152}
153
64b39f4a
NJ
154static int ksmbd_enc_update_sess_key(unsigned char *md5_hash, char *nonce,
155 char *server_challenge, int len)
e2f34481
NJ
156{
157 int rc;
158 struct ksmbd_crypto_ctx *ctx;
159
160 ctx = ksmbd_crypto_ctx_find_md5();
161 if (!ctx) {
162 ksmbd_debug(AUTH, "Crypto md5 allocation error\n");
163 return -EINVAL;
164 }
165
166 rc = crypto_shash_init(CRYPTO_MD5(ctx));
167 if (rc) {
168 ksmbd_debug(AUTH, "Could not init md5 shash\n");
169 goto out;
170 }
171
172 rc = crypto_shash_update(CRYPTO_MD5(ctx), server_challenge, len);
173 if (rc) {
174 ksmbd_debug(AUTH, "Could not update with challenge\n");
175 goto out;
176 }
177
178 rc = crypto_shash_update(CRYPTO_MD5(ctx), nonce, len);
179 if (rc) {
180 ksmbd_debug(AUTH, "Could not update with nonce\n");
181 goto out;
182 }
183
184 rc = crypto_shash_final(CRYPTO_MD5(ctx), md5_hash);
185 if (rc)
186 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
187out:
188 ksmbd_release_crypto_ctx(ctx);
189 return rc;
190}
191
192/**
193 * ksmbd_gen_sess_key() - function to generate session key
194 * @sess: session of connection
195 * @hash: source hash value to be used for find session key
196 * @hmac: source hmac value to be used for finding session key
197 *
198 */
64b39f4a
NJ
199static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
200 char *hmac)
e2f34481
NJ
201{
202 struct ksmbd_crypto_ctx *ctx;
203 int rc = -EINVAL;
204
205 ctx = ksmbd_crypto_ctx_find_hmacmd5();
206 if (!ctx)
207 goto out;
208
209 rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
210 hash,
211 CIFS_HMAC_MD5_HASH_SIZE);
212 if (rc) {
213 ksmbd_debug(AUTH, "hmacmd5 set key fail error %d\n", rc);
214 goto out;
215 }
216
217 rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
218 if (rc) {
219 ksmbd_debug(AUTH, "could not init hmacmd5 error %d\n", rc);
220 goto out;
221 }
222
223 rc = crypto_shash_update(CRYPTO_HMACMD5(ctx),
224 hmac,
225 SMB2_NTLMV2_SESSKEY_SIZE);
226 if (rc) {
227 ksmbd_debug(AUTH, "Could not update with response error %d\n",
228 rc);
229 goto out;
230 }
231
232 rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key);
233 if (rc) {
234 ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
235 rc);
236 goto out;
237 }
238
239out:
240 ksmbd_release_crypto_ctx(ctx);
241 return rc;
242}
243
244static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
64b39f4a 245 char *dname)
e2f34481
NJ
246{
247 int ret = -EINVAL, len;
248 wchar_t *domain = NULL;
249 __le16 *uniname = NULL;
250 struct ksmbd_crypto_ctx *ctx;
251
252 ctx = ksmbd_crypto_ctx_find_hmacmd5();
253 if (!ctx) {
254 ksmbd_debug(AUTH, "can't generate ntlmv2 hash\n");
255 goto out;
256 }
257
258 ret = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
259 user_passkey(sess->user),
260 CIFS_ENCPWD_SIZE);
261 if (ret) {
262 ksmbd_debug(AUTH, "Could not set NT Hash as a key\n");
263 goto out;
264 }
265
266 ret = crypto_shash_init(CRYPTO_HMACMD5(ctx));
267 if (ret) {
268 ksmbd_debug(AUTH, "could not init hmacmd5\n");
269 goto out;
270 }
271
272 /* convert user_name to unicode */
273 len = strlen(user_name(sess->user));
274 uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
275 if (!uniname) {
276 ret = -ENOMEM;
277 goto out;
278 }
279
280 if (len) {
281 len = smb_strtoUTF16(uniname, user_name(sess->user), len,
282 sess->conn->local_nls);
283 UniStrupr(uniname);
284 }
285
286 ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
287 (char *)uniname,
288 UNICODE_LEN(len));
289 if (ret) {
290 ksmbd_debug(AUTH, "Could not update with user\n");
291 goto out;
292 }
293
294 /* Convert domain name or conn name to unicode and uppercase */
295 len = strlen(dname);
296 domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
297 if (!domain) {
298 ret = -ENOMEM;
299 goto out;
300 }
301
302 len = smb_strtoUTF16((__le16 *)domain, dname, len,
303 sess->conn->local_nls);
304
305 ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
306 (char *)domain,
307 UNICODE_LEN(len));
308 if (ret) {
309 ksmbd_debug(AUTH, "Could not update with domain\n");
310 goto out;
311 }
312
313 ret = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_hash);
e2f34481
NJ
314 if (ret)
315 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
7e38ea25 316out:
e2f34481
NJ
317 kfree(uniname);
318 kfree(domain);
319 ksmbd_release_crypto_ctx(ctx);
320 return ret;
321}
322
323/**
324 * ksmbd_auth_ntlm() - NTLM authentication handler
325 * @sess: session of connection
326 * @pw_buf: NTLM challenge response
327 * @passkey: user password
328 *
329 * Return: 0 on success, error number on error
330 */
331int ksmbd_auth_ntlm(struct ksmbd_session *sess, char *pw_buf)
332{
333 int rc;
334 unsigned char p21[21];
335 char key[CIFS_AUTH_RESP_SIZE];
336
337 memset(p21, '\0', 21);
338 memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE);
339 rc = ksmbd_enc_p24(p21, sess->ntlmssp.cryptkey, key);
340 if (rc) {
341 ksmbd_err("password processing failed\n");
342 return rc;
343 }
344
345 ksmbd_enc_md4(sess->sess_key,
346 user_passkey(sess->user),
347 CIFS_SMB1_SESSKEY_SIZE);
348 memcpy(sess->sess_key + CIFS_SMB1_SESSKEY_SIZE, key,
349 CIFS_AUTH_RESP_SIZE);
350 sess->sequence_number = 1;
351
352 if (strncmp(pw_buf, key, CIFS_AUTH_RESP_SIZE) != 0) {
353 ksmbd_debug(AUTH, "ntlmv1 authentication failed\n");
4a6b0228 354 return -EINVAL;
64b39f4a 355 }
e2f34481 356
4a6b0228
NJ
357 ksmbd_debug(AUTH, "ntlmv1 authentication pass\n");
358 return 0;
e2f34481
NJ
359}
360
361/**
362 * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
363 * @sess: session of connection
364 * @ntlmv2: NTLMv2 challenge response
365 * @blen: NTLMv2 blob length
366 * @domain_name: domain name
367 *
368 * Return: 0 on success, error number on error
369 */
64b39f4a
NJ
370int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2,
371 int blen, char *domain_name)
e2f34481
NJ
372{
373 char ntlmv2_hash[CIFS_ENCPWD_SIZE];
374 char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
375 struct ksmbd_crypto_ctx *ctx;
376 char *construct = NULL;
377 int rc = -EINVAL, len;
378
379 ctx = ksmbd_crypto_ctx_find_hmacmd5();
380 if (!ctx) {
381 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5 rc %d\n", rc);
382 goto out;
383 }
384
385 rc = calc_ntlmv2_hash(sess, ntlmv2_hash, domain_name);
386 if (rc) {
387 ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
388 goto out;
389 }
390
391 rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
392 ntlmv2_hash,
393 CIFS_HMAC_MD5_HASH_SIZE);
394 if (rc) {
395 ksmbd_debug(AUTH, "Could not set NTLMV2 Hash as a key\n");
396 goto out;
397 }
398
399 rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
400 if (rc) {
401 ksmbd_debug(AUTH, "Could not init hmacmd5\n");
402 goto out;
403 }
404
405 len = CIFS_CRYPTO_KEY_SIZE + blen;
406 construct = kzalloc(len, GFP_KERNEL);
407 if (!construct) {
408 rc = -ENOMEM;
409 goto out;
410 }
411
412 memcpy(construct, sess->ntlmssp.cryptkey, CIFS_CRYPTO_KEY_SIZE);
192cc732 413 memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen);
e2f34481
NJ
414
415 rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len);
416 if (rc) {
417 ksmbd_debug(AUTH, "Could not update with response\n");
418 goto out;
419 }
420
421 rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_rsp);
422 if (rc) {
423 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
424 goto out;
425 }
426
427 rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp);
428 if (rc) {
429 ksmbd_debug(AUTH, "Could not generate sess key\n");
430 goto out;
431 }
432
b72802aa
NJ
433 if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
434 rc = -EINVAL;
e2f34481
NJ
435out:
436 ksmbd_release_crypto_ctx(ctx);
437 kfree(construct);
438 return rc;
439}
440
441/**
442 * __ksmbd_auth_ntlmv2() - NTLM2(extended security) authentication handler
443 * @sess: session of connection
444 * @client_nonce: client nonce from LM response.
445 * @ntlm_resp: ntlm response data from client.
446 *
447 * Return: 0 on success, error number on error
448 */
64b39f4a
NJ
449static int __ksmbd_auth_ntlmv2(struct ksmbd_session *sess, char *client_nonce,
450 char *ntlm_resp)
e2f34481
NJ
451{
452 char sess_key[CIFS_SMB1_SESSKEY_SIZE] = {0};
453 int rc;
454 unsigned char p21[21];
455 char key[CIFS_AUTH_RESP_SIZE];
456
457 rc = ksmbd_enc_update_sess_key(sess_key,
458 client_nonce,
459 (char *)sess->ntlmssp.cryptkey, 8);
460 if (rc) {
461 ksmbd_err("password processing failed\n");
462 goto out;
463 }
464
465 memset(p21, '\0', 21);
466 memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE);
467 rc = ksmbd_enc_p24(p21, sess_key, key);
468 if (rc) {
469 ksmbd_err("password processing failed\n");
470 goto out;
471 }
472
b72802aa
NJ
473 if (memcmp(ntlm_resp, key, CIFS_AUTH_RESP_SIZE) != 0)
474 rc = -EINVAL;
e2f34481
NJ
475out:
476 return rc;
477}
478
479/**
480 * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
481 * authenticate blob
482 * @authblob: authenticate blob source pointer
483 * @usr: user details
484 * @sess: session of connection
485 *
486 * Return: 0 on success, error number on error
487 */
488int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
64b39f4a 489 int blob_len, struct ksmbd_session *sess)
e2f34481
NJ
490{
491 char *domain_name;
492 unsigned int lm_off, nt_off;
493 unsigned short nt_len;
494 int ret;
495
496 if (blob_len < sizeof(struct authenticate_message)) {
497 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
498 blob_len);
499 return -EINVAL;
500 }
501
502 if (memcmp(authblob->Signature, "NTLMSSP", 8)) {
503 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
504 authblob->Signature);
505 return -EINVAL;
506 }
507
508 lm_off = le32_to_cpu(authblob->LmChallengeResponse.BufferOffset);
509 nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
510 nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
511
512 /* process NTLM authentication */
513 if (nt_len == CIFS_AUTH_RESP_SIZE) {
64b39f4a
NJ
514 if (le32_to_cpu(authblob->NegotiateFlags) &
515 NTLMSSP_NEGOTIATE_EXTENDED_SEC)
e2f34481
NJ
516 return __ksmbd_auth_ntlmv2(sess, (char *)authblob +
517 lm_off, (char *)authblob + nt_off);
518 else
519 return ksmbd_auth_ntlm(sess, (char *)authblob +
520 nt_off);
521 }
522
523 /* TODO : use domain name that imported from configuration file */
64b39f4a 524 domain_name = smb_strndup_from_utf16((const char *)authblob +
e2f34481
NJ
525 le32_to_cpu(authblob->DomainName.BufferOffset),
526 le16_to_cpu(authblob->DomainName.Length), true,
527 sess->conn->local_nls);
528 if (IS_ERR(domain_name))
529 return PTR_ERR(domain_name);
530
531 /* process NTLMv2 authentication */
532 ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n",
533 domain_name);
534 ret = ksmbd_auth_ntlmv2(sess,
535 (struct ntlmv2_resp *)((char *)authblob + nt_off),
536 nt_len - CIFS_ENCPWD_SIZE,
537 domain_name);
538 kfree(domain_name);
539 return ret;
540}
541
542/**
543 * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
544 * negotiate blob
545 * @negblob: negotiate blob source pointer
546 * @rsp: response header pointer to be updated
547 * @sess: session of connection
548 *
549 */
550int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
64b39f4a 551 int blob_len, struct ksmbd_session *sess)
e2f34481
NJ
552{
553 if (blob_len < sizeof(struct negotiate_message)) {
554 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
555 blob_len);
556 return -EINVAL;
557 }
558
559 if (memcmp(negblob->Signature, "NTLMSSP", 8)) {
560 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
561 negblob->Signature);
562 return -EINVAL;
563 }
564
565 sess->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags);
566 return 0;
567}
568
569/**
570 * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
571 * challenge blob
572 * @chgblob: challenge blob source pointer to initialize
573 * @rsp: response header pointer to be updated
574 * @sess: session of connection
575 *
576 */
577unsigned int
578ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
579 struct ksmbd_session *sess)
580{
581 struct target_info *tinfo;
582 wchar_t *name;
583 __u8 *target_name;
584 unsigned int len, flags, blob_off, blob_len, type, target_info_len = 0;
585 int cflags = sess->ntlmssp.client_flags;
586
587 memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
588 chgblob->MessageType = NtLmChallenge;
589
590 flags = NTLMSSP_NEGOTIATE_UNICODE |
591 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_TARGET_TYPE_SERVER |
592 NTLMSSP_NEGOTIATE_TARGET_INFO;
593
594 if (cflags & NTLMSSP_NEGOTIATE_SIGN) {
595 flags |= NTLMSSP_NEGOTIATE_SIGN;
596 flags |= cflags & (NTLMSSP_NEGOTIATE_128 |
597 NTLMSSP_NEGOTIATE_56);
598 }
599
600 if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
601 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
602
603 if (cflags & NTLMSSP_REQUEST_TARGET)
604 flags |= NTLMSSP_REQUEST_TARGET;
605
606 if (sess->conn->use_spnego &&
64b39f4a 607 (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
e2f34481
NJ
608 flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
609
610 chgblob->NegotiateFlags = cpu_to_le32(flags);
611 len = strlen(ksmbd_netbios_name());
612 name = kmalloc(2 + (len * 2), GFP_KERNEL);
613 if (!name)
614 return -ENOMEM;
615
616 len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
617 sess->conn->local_nls);
618 len = UNICODE_LEN(len);
619
620 blob_off = sizeof(struct challenge_message);
621 blob_len = blob_off + len;
622
623 chgblob->TargetName.Length = cpu_to_le16(len);
624 chgblob->TargetName.MaximumLength = cpu_to_le16(len);
625 chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
626
627 /* Initialize random conn challenge */
628 get_random_bytes(sess->ntlmssp.cryptkey, sizeof(__u64));
629 memcpy(chgblob->Challenge, sess->ntlmssp.cryptkey,
630 CIFS_CRYPTO_KEY_SIZE);
631
632 /* Add Target Information to security buffer */
633 chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
634
635 target_name = (__u8 *)chgblob + blob_off;
636 memcpy(target_name, name, len);
637 tinfo = (struct target_info *)(target_name + len);
638
639 chgblob->TargetInfoArray.Length = 0;
640 /* Add target info list for NetBIOS/DNS settings */
641 for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
642 type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
643 tinfo->Type = cpu_to_le16(type);
644 tinfo->Length = cpu_to_le16(len);
645 memcpy(tinfo->Content, name, len);
646 tinfo = (struct target_info *)((char *)tinfo + 4 + len);
647 target_info_len += 4 + len;
648 }
649
650 /* Add terminator subblock */
651 tinfo->Type = 0;
652 tinfo->Length = 0;
653 target_info_len += 4;
654
655 chgblob->TargetInfoArray.Length = cpu_to_le16(target_info_len);
656 chgblob->TargetInfoArray.MaximumLength = cpu_to_le16(target_info_len);
657 blob_len += target_info_len;
658 kfree(name);
659 ksmbd_debug(AUTH, "NTLMSSP SecurityBufferLength %d\n", blob_len);
660 return blob_len;
661}
662
663#ifdef CONFIG_SMB_SERVER_KERBEROS5
64b39f4a
NJ
664int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
665 int in_len, char *out_blob, int *out_len)
e2f34481
NJ
666{
667 struct ksmbd_spnego_authen_response *resp;
668 struct ksmbd_user *user = NULL;
669 int retval;
670
671 resp = ksmbd_ipc_spnego_authen_request(in_blob, in_len);
672 if (!resp) {
673 ksmbd_debug(AUTH, "SPNEGO_AUTHEN_REQUEST failure\n");
674 return -EINVAL;
675 }
676
677 if (!(resp->login_response.status & KSMBD_USER_FLAG_OK)) {
678 ksmbd_debug(AUTH, "krb5 authentication failure\n");
679 retval = -EPERM;
680 goto out;
681 }
682
683 if (*out_len <= resp->spnego_blob_len) {
684 ksmbd_debug(AUTH, "buf len %d, but blob len %d\n",
685 *out_len, resp->spnego_blob_len);
686 retval = -EINVAL;
687 goto out;
688 }
689
690 if (resp->session_key_len > sizeof(sess->sess_key)) {
691 ksmbd_debug(AUTH, "session key is too long\n");
692 retval = -EINVAL;
693 goto out;
694 }
695
696 user = ksmbd_alloc_user(&resp->login_response);
697 if (!user) {
698 ksmbd_debug(AUTH, "login failure\n");
699 retval = -ENOMEM;
700 goto out;
701 }
702 sess->user = user;
703
704 memcpy(sess->sess_key, resp->payload, resp->session_key_len);
705 memcpy(out_blob, resp->payload + resp->session_key_len,
706 resp->spnego_blob_len);
707 *out_len = resp->spnego_blob_len;
708 retval = 0;
709out:
79f6b11a 710 kvfree(resp);
e2f34481
NJ
711 return retval;
712}
713#else
64b39f4a
NJ
714int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
715 int in_len, char *out_blob, int *out_len)
e2f34481
NJ
716{
717 return -EOPNOTSUPP;
718}
719#endif
720
721/**
722 * ksmbd_sign_smb2_pdu() - function to generate packet signing
723 * @conn: connection
724 * @key: signing key
725 * @iov: buffer iov array
726 * @n_vec: number of iovecs
727 * @sig: signature value generated for client request packet
728 *
729 */
64b39f4a
NJ
730int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
731 int n_vec, char *sig)
e2f34481
NJ
732{
733 struct ksmbd_crypto_ctx *ctx;
734 int rc = -EINVAL;
735 int i;
736
737 ctx = ksmbd_crypto_ctx_find_hmacsha256();
738 if (!ctx) {
739 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5 rc %d\n", rc);
740 goto out;
741 }
742
743 rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
744 key,
745 SMB2_NTLMV2_SESSKEY_SIZE);
746 if (rc)
747 goto out;
748
749 rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
750 if (rc) {
751 ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
752 goto out;
753 }
754
755 for (i = 0; i < n_vec; i++) {
756 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
757 iov[i].iov_base,
758 iov[i].iov_len);
759 if (rc) {
760 ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc);
761 goto out;
762 }
763 }
764
765 rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig);
766 if (rc)
767 ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc);
768out:
769 ksmbd_release_crypto_ctx(ctx);
770 return rc;
771}
772
773/**
774 * ksmbd_sign_smb3_pdu() - function to generate packet signing
775 * @conn: connection
776 * @key: signing key
777 * @iov: buffer iov array
778 * @n_vec: number of iovecs
779 * @sig: signature value generated for client request packet
780 *
781 */
64b39f4a
NJ
782int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
783 int n_vec, char *sig)
e2f34481
NJ
784{
785 struct ksmbd_crypto_ctx *ctx;
786 int rc = -EINVAL;
787 int i;
788
789 ctx = ksmbd_crypto_ctx_find_cmacaes();
790 if (!ctx) {
791 ksmbd_debug(AUTH, "could not crypto alloc cmac rc %d\n", rc);
792 goto out;
793 }
794
795 rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx),
796 key,
797 SMB2_CMACAES_SIZE);
798 if (rc)
799 goto out;
800
801 rc = crypto_shash_init(CRYPTO_CMACAES(ctx));
802 if (rc) {
803 ksmbd_debug(AUTH, "cmaces init error %d\n", rc);
804 goto out;
805 }
806
807 for (i = 0; i < n_vec; i++) {
808 rc = crypto_shash_update(CRYPTO_CMACAES(ctx),
809 iov[i].iov_base,
810 iov[i].iov_len);
811 if (rc) {
812 ksmbd_debug(AUTH, "cmaces update error %d\n", rc);
813 goto out;
814 }
815 }
816
817 rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig);
818 if (rc)
819 ksmbd_debug(AUTH, "cmaces generation error %d\n", rc);
820out:
821 ksmbd_release_crypto_ctx(ctx);
822 return rc;
823}
824
825struct derivation {
826 struct kvec label;
827 struct kvec context;
828 bool binding;
829};
830
831static int generate_key(struct ksmbd_session *sess, struct kvec label,
64b39f4a 832 struct kvec context, __u8 *key, unsigned int key_size)
e2f34481
NJ
833{
834 unsigned char zero = 0x0;
835 __u8 i[4] = {0, 0, 0, 1};
5a0ca770
NJ
836 __u8 L128[4] = {0, 0, 0, 128};
837 __u8 L256[4] = {0, 0, 1, 0};
e2f34481
NJ
838 int rc = -EINVAL;
839 unsigned char prfhash[SMB2_HMACSHA256_SIZE];
840 unsigned char *hashptr = prfhash;
841 struct ksmbd_crypto_ctx *ctx;
842
843 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
844 memset(key, 0x0, key_size);
845
846 ctx = ksmbd_crypto_ctx_find_hmacsha256();
847 if (!ctx) {
848 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5 rc %d\n", rc);
849 goto smb3signkey_ret;
850 }
851
852 rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
853 sess->sess_key,
854 SMB2_NTLMV2_SESSKEY_SIZE);
855 if (rc)
856 goto smb3signkey_ret;
857
858 rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
859 if (rc) {
860 ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
861 goto smb3signkey_ret;
862 }
863
864 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4);
865 if (rc) {
866 ksmbd_debug(AUTH, "could not update with n\n");
867 goto smb3signkey_ret;
868 }
869
870 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
871 label.iov_base,
872 label.iov_len);
873 if (rc) {
874 ksmbd_debug(AUTH, "could not update with label\n");
875 goto smb3signkey_ret;
876 }
877
878 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1);
879 if (rc) {
880 ksmbd_debug(AUTH, "could not update with zero\n");
881 goto smb3signkey_ret;
882 }
883
884 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
885 context.iov_base,
886 context.iov_len);
887 if (rc) {
888 ksmbd_debug(AUTH, "could not update with context\n");
889 goto smb3signkey_ret;
890 }
891
5a0ca770
NJ
892 if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
893 sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
894 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
895 else
896 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
e2f34481
NJ
897 if (rc) {
898 ksmbd_debug(AUTH, "could not update with L\n");
899 goto smb3signkey_ret;
900 }
901
902 rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr);
903 if (rc) {
904 ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
905 rc);
906 goto smb3signkey_ret;
907 }
908
909 memcpy(key, hashptr, key_size);
910
911smb3signkey_ret:
912 ksmbd_release_crypto_ctx(ctx);
913 return rc;
914}
915
916static int generate_smb3signingkey(struct ksmbd_session *sess,
64b39f4a 917 const struct derivation *signing)
e2f34481
NJ
918{
919 int rc;
920 struct channel *chann;
921 char *key;
922
923 chann = lookup_chann_list(sess);
924 if (!chann)
925 return 0;
926
927 if (sess->conn->dialect >= SMB30_PROT_ID && signing->binding)
928 key = chann->smb3signingkey;
929 else
930 key = sess->smb3signingkey;
931
932 rc = generate_key(sess, signing->label, signing->context, key,
933 SMB3_SIGN_KEY_SIZE);
934 if (rc)
935 return rc;
936
937 if (!(sess->conn->dialect >= SMB30_PROT_ID && signing->binding))
938 memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
939
940 ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
941 ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
942 ksmbd_debug(AUTH, "Session Key %*ph\n",
943 SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
944 ksmbd_debug(AUTH, "Signing Key %*ph\n",
945 SMB3_SIGN_KEY_SIZE, key);
876edcc4 946 return 0;
e2f34481
NJ
947}
948
949int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess)
950{
951 struct derivation d;
952
953 d.label.iov_base = "SMB2AESCMAC";
954 d.label.iov_len = 12;
955 d.context.iov_base = "SmbSign";
956 d.context.iov_len = 8;
957 d.binding = false;
958
959 return generate_smb3signingkey(sess, &d);
960}
961
962int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess)
963{
964 struct derivation d;
965
966 d.label.iov_base = "SMBSigningKey";
967 d.label.iov_len = 14;
968 d.context.iov_base = sess->Preauth_HashValue;
969 d.context.iov_len = 64;
970 d.binding = false;
971
972 return generate_smb3signingkey(sess, &d);
973}
974
975struct derivation_twin {
976 struct derivation encryption;
977 struct derivation decryption;
978};
979
980static int generate_smb3encryptionkey(struct ksmbd_session *sess,
64b39f4a 981 const struct derivation_twin *ptwin)
e2f34481
NJ
982{
983 int rc;
984
985 rc = generate_key(sess, ptwin->encryption.label,
986 ptwin->encryption.context, sess->smb3encryptionkey,
5a0ca770 987 SMB3_ENC_DEC_KEY_SIZE);
e2f34481
NJ
988 if (rc)
989 return rc;
990
991 rc = generate_key(sess, ptwin->decryption.label,
992 ptwin->decryption.context,
5a0ca770 993 sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
e2f34481
NJ
994 if (rc)
995 return rc;
996
997 ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
5a0ca770 998 ksmbd_debug(AUTH, "Cipher type %d\n", sess->conn->cipher_type);
e2f34481
NJ
999 ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
1000 ksmbd_debug(AUTH, "Session Key %*ph\n",
1001 SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
5a0ca770
NJ
1002 if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
1003 sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
1004 ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
1005 SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
1006 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
1007 SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
1008 } else {
1009 ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
1010 SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
1011 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
1012 SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
1013 }
876edcc4 1014 return 0;
e2f34481
NJ
1015}
1016
1017int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess)
1018{
1019 struct derivation_twin twin;
1020 struct derivation *d;
1021
1022 d = &twin.encryption;
1023 d->label.iov_base = "SMB2AESCCM";
1024 d->label.iov_len = 11;
1025 d->context.iov_base = "ServerOut";
1026 d->context.iov_len = 10;
1027
1028 d = &twin.decryption;
1029 d->label.iov_base = "SMB2AESCCM";
1030 d->label.iov_len = 11;
1031 d->context.iov_base = "ServerIn ";
1032 d->context.iov_len = 10;
1033
1034 return generate_smb3encryptionkey(sess, &twin);
1035}
1036
1037int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess)
1038{
1039 struct derivation_twin twin;
1040 struct derivation *d;
1041
1042 d = &twin.encryption;
1043 d->label.iov_base = "SMBS2CCipherKey";
1044 d->label.iov_len = 16;
1045 d->context.iov_base = sess->Preauth_HashValue;
1046 d->context.iov_len = 64;
1047
1048 d = &twin.decryption;
1049 d->label.iov_base = "SMBC2SCipherKey";
1050 d->label.iov_len = 16;
1051 d->context.iov_base = sess->Preauth_HashValue;
1052 d->context.iov_len = 64;
1053
1054 return generate_smb3encryptionkey(sess, &twin);
1055}
1056
64b39f4a
NJ
1057int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
1058 __u8 *pi_hash)
e2f34481
NJ
1059{
1060 int rc = -1;
1061 struct smb2_hdr *rcv_hdr = (struct smb2_hdr *)buf;
1062 char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
1063 int msg_size = be32_to_cpu(rcv_hdr->smb2_buf_length);
1064 struct ksmbd_crypto_ctx *ctx = NULL;
1065
d3cd8c49
NJ
1066 if (conn->preauth_info->Preauth_HashId !=
1067 SMB2_PREAUTH_INTEGRITY_SHA512)
1068 return -EINVAL;
1069
1070 ctx = ksmbd_crypto_ctx_find_sha512();
1071 if (!ctx) {
1072 ksmbd_debug(AUTH, "could not alloc sha512 rc %d\n", rc);
e2f34481 1073 goto out;
64b39f4a 1074 }
e2f34481
NJ
1075
1076 rc = crypto_shash_init(CRYPTO_SHA512(ctx));
1077 if (rc) {
1078 ksmbd_debug(AUTH, "could not init shashn");
1079 goto out;
1080 }
1081
1082 rc = crypto_shash_update(CRYPTO_SHA512(ctx), pi_hash, 64);
1083 if (rc) {
1084 ksmbd_debug(AUTH, "could not update with n\n");
1085 goto out;
1086 }
1087
1088 rc = crypto_shash_update(CRYPTO_SHA512(ctx), all_bytes_msg, msg_size);
1089 if (rc) {
1090 ksmbd_debug(AUTH, "could not update with n\n");
1091 goto out;
1092 }
1093
1094 rc = crypto_shash_final(CRYPTO_SHA512(ctx), pi_hash);
1095 if (rc) {
1096 ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
1097 goto out;
1098 }
1099out:
1100 ksmbd_release_crypto_ctx(ctx);
1101 return rc;
1102}
1103
1104int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
1105 __u8 *pi_hash)
1106{
1107 int rc = -1;
1108 struct ksmbd_crypto_ctx *ctx = NULL;
1109
1110 ctx = ksmbd_crypto_ctx_find_sha256();
1111 if (!ctx) {
1112 ksmbd_debug(AUTH, "could not alloc sha256 rc %d\n", rc);
1113 goto out;
1114 }
1115
1116 rc = crypto_shash_init(CRYPTO_SHA256(ctx));
1117 if (rc) {
1118 ksmbd_debug(AUTH, "could not init shashn");
1119 goto out;
1120 }
1121
1122 rc = crypto_shash_update(CRYPTO_SHA256(ctx), sd_buf, len);
1123 if (rc) {
1124 ksmbd_debug(AUTH, "could not update with n\n");
1125 goto out;
1126 }
1127
1128 rc = crypto_shash_final(CRYPTO_SHA256(ctx), pi_hash);
1129 if (rc) {
1130 ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
1131 goto out;
1132 }
1133out:
1134 ksmbd_release_crypto_ctx(ctx);
1135 return rc;
1136}
1137
64b39f4a
NJ
1138static int ksmbd_get_encryption_key(struct ksmbd_conn *conn, __u64 ses_id,
1139 int enc, u8 *key)
e2f34481
NJ
1140{
1141 struct ksmbd_session *sess;
1142 u8 *ses_enc_key;
1143
1144 sess = ksmbd_session_lookup(conn, ses_id);
1145 if (!sess)
522dcc76 1146 return -EINVAL;
e2f34481
NJ
1147
1148 ses_enc_key = enc ? sess->smb3encryptionkey :
1149 sess->smb3decryptionkey;
5a0ca770 1150 memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
e2f34481
NJ
1151
1152 return 0;
1153}
1154
1155static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
1156 unsigned int buflen)
1157{
1158 void *addr;
1159
1160 if (is_vmalloc_addr(buf))
1161 addr = vmalloc_to_page(buf);
1162 else
1163 addr = virt_to_page(buf);
1164 sg_set_page(sg, addr, buflen, offset_in_page(buf));
1165}
1166
64b39f4a
NJ
1167static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
1168 u8 *sign)
e2f34481
NJ
1169{
1170 struct scatterlist *sg;
1171 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
1172 int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
1173
41a7848a
NJ
1174 if (!nvec)
1175 return NULL;
1176
e2f34481
NJ
1177 for (i = 0; i < nvec - 1; i++) {
1178 unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
1179
1180 if (is_vmalloc_addr(iov[i + 1].iov_base)) {
1181 nr_entries[i] = ((kaddr + iov[i + 1].iov_len +
1182 PAGE_SIZE - 1) >> PAGE_SHIFT) -
1183 (kaddr >> PAGE_SHIFT);
64b39f4a 1184 } else {
e2f34481 1185 nr_entries[i]++;
64b39f4a 1186 }
e2f34481
NJ
1187 total_entries += nr_entries[i];
1188 }
1189
1190 /* Add two entries for transform header and signature */
1191 total_entries += 2;
1192
1193 sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
1194 if (!sg)
1195 return NULL;
1196
1197 sg_init_table(sg, total_entries);
1198 smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
1199 for (i = 0; i < nvec - 1; i++) {
1200 void *data = iov[i + 1].iov_base;
1201 int len = iov[i + 1].iov_len;
1202
1203 if (is_vmalloc_addr(data)) {
1204 int j, offset = offset_in_page(data);
1205
1206 for (j = 0; j < nr_entries[i]; j++) {
1207 unsigned int bytes = PAGE_SIZE - offset;
1208
08591ccf 1209 if (!len)
e2f34481
NJ
1210 break;
1211
1212 if (bytes > len)
1213 bytes = len;
1214
1215 sg_set_page(&sg[sg_idx++],
1216 vmalloc_to_page(data), bytes,
1217 offset_in_page(data));
1218
1219 data += bytes;
1220 len -= bytes;
1221 offset = 0;
1222 }
1223 } else {
1224 sg_set_page(&sg[sg_idx++], virt_to_page(data), len,
1225 offset_in_page(data));
1226 }
e2f34481
NJ
1227 }
1228 smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
1229 return sg;
1230}
1231
64b39f4a
NJ
1232int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
1233 unsigned int nvec, int enc)
e2f34481
NJ
1234{
1235 struct smb2_transform_hdr *tr_hdr =
1236 (struct smb2_transform_hdr *)iov[0].iov_base;
1237 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
03f1c3d3 1238 int rc;
e2f34481
NJ
1239 struct scatterlist *sg;
1240 u8 sign[SMB2_SIGNATURE_SIZE] = {};
5a0ca770 1241 u8 key[SMB3_ENC_DEC_KEY_SIZE];
e2f34481
NJ
1242 struct aead_request *req;
1243 char *iv;
1244 unsigned int iv_len;
1245 struct crypto_aead *tfm;
1246 unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
1247 struct ksmbd_crypto_ctx *ctx;
1248
1249 rc = ksmbd_get_encryption_key(conn,
1250 le64_to_cpu(tr_hdr->SessionId),
1251 enc,
1252 key);
1253 if (rc) {
1254 ksmbd_err("Could not get %scryption key\n", enc ? "en" : "de");
27aa646d 1255 return rc;
e2f34481
NJ
1256 }
1257
5a0ca770
NJ
1258 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1259 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
e2f34481
NJ
1260 ctx = ksmbd_crypto_ctx_find_gcm();
1261 else
1262 ctx = ksmbd_crypto_ctx_find_ccm();
1263 if (!ctx) {
1264 ksmbd_err("crypto alloc failed\n");
1265 return -EINVAL;
1266 }
1267
5a0ca770
NJ
1268 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1269 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
e2f34481
NJ
1270 tfm = CRYPTO_GCM(ctx);
1271 else
1272 tfm = CRYPTO_CCM(ctx);
1273
5a0ca770
NJ
1274 if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
1275 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
1276 rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
1277 else
1278 rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
e2f34481
NJ
1279 if (rc) {
1280 ksmbd_err("Failed to set aead key %d\n", rc);
1281 goto free_ctx;
1282 }
1283
1284 rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
1285 if (rc) {
1286 ksmbd_err("Failed to set authsize %d\n", rc);
1287 goto free_ctx;
1288 }
1289
1290 req = aead_request_alloc(tfm, GFP_KERNEL);
1291 if (!req) {
1292 ksmbd_err("Failed to alloc aead request\n");
1293 rc = -ENOMEM;
1294 goto free_ctx;
1295 }
1296
1297 if (!enc) {
1298 memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
1299 crypt_len += SMB2_SIGNATURE_SIZE;
1300 }
1301
1302 sg = ksmbd_init_sg(iov, nvec, sign);
1303 if (!sg) {
1304 ksmbd_err("Failed to init sg\n");
1305 rc = -ENOMEM;
1306 goto free_req;
1307 }
1308
1309 iv_len = crypto_aead_ivsize(tfm);
1310 iv = kzalloc(iv_len, GFP_KERNEL);
1311 if (!iv) {
1312 ksmbd_err("Failed to alloc IV\n");
1313 rc = -ENOMEM;
1314 goto free_sg;
1315 }
1316
5a0ca770
NJ
1317 if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1318 conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
1319 memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
64b39f4a 1320 } else {
e2f34481 1321 iv[0] = 3;
5a0ca770 1322 memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
e2f34481
NJ
1323 }
1324
1325 aead_request_set_crypt(req, sg, sg, crypt_len, iv);
1326 aead_request_set_ad(req, assoc_data_len);
1327 aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
1328
1329 if (enc)
1330 rc = crypto_aead_encrypt(req);
1331 else
1332 rc = crypto_aead_decrypt(req);
73b8b085
NJ
1333 if (rc)
1334 goto free_iv;
1335
1336 if (enc)
e2f34481
NJ
1337 memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
1338
73b8b085 1339free_iv:
e2f34481
NJ
1340 kfree(iv);
1341free_sg:
1342 kfree(sg);
1343free_req:
1344 kfree(req);
1345free_ctx:
1346 ksmbd_release_crypto_ctx(ctx);
1347 return rc;
1348}