~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/smb/server/auth.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 "../common/arc4.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  */
 39 static 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 
 67 void ksmbd_copy_gss_neg_header(void *buf)
 68 {
 69         memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
 70 }
 71 
 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  */
 79 static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
 80                               char *hmac)
 81 {
 82         struct ksmbd_crypto_ctx *ctx;
 83         int rc;
 84 
 85         ctx = ksmbd_crypto_ctx_find_hmacmd5();
 86         if (!ctx) {
 87                 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
 88                 return -ENOMEM;
 89         }
 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) {
109                 ksmbd_debug(AUTH, "Could not update with response error %d\n", rc);
110                 goto out;
111         }
112 
113         rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key);
114         if (rc) {
115                 ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", rc);
116                 goto out;
117         }
118 
119 out:
120         ksmbd_release_crypto_ctx(ctx);
121         return rc;
122 }
123 
124 static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
125                             char *ntlmv2_hash, char *dname)
126 {
127         int ret, len, conv_len;
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");
135                 return -ENOMEM;
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 
160         conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
161                                   conn->local_nls);
162         if (conv_len < 0 || conv_len > len) {
163                 ret = -EINVAL;
164                 goto out;
165         }
166         UniStrupr(uniname);
167 
168         ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
169                                   (char *)uniname,
170                                   UNICODE_LEN(conv_len));
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 
184         conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
185                                   conn->local_nls);
186         if (conv_len < 0 || conv_len > len) {
187                 ret = -EINVAL;
188                 goto out;
189         }
190 
191         ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
192                                   (char *)domain,
193                                   UNICODE_LEN(conv_len));
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);
200         if (ret)
201                 ksmbd_debug(AUTH, "Could not generate md5 hash\n");
202 out:
203         kfree(uniname);
204         kfree(domain);
205         ksmbd_release_crypto_ctx(ctx);
206         return ret;
207 }
208 
209 /**
210  * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
211  * @conn:               connection
212  * @sess:               session of connection
213  * @ntlmv2:             NTLMv2 challenge response
214  * @blen:               NTLMv2 blob length
215  * @domain_name:        domain name
216  * @cryptkey:           session crypto key
217  *
218  * Return:      0 on success, error number on error
219  */
220 int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
221                       struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
222                       char *cryptkey)
223 {
224         char ntlmv2_hash[CIFS_ENCPWD_SIZE];
225         char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
226         struct ksmbd_crypto_ctx *ctx = NULL;
227         char *construct = NULL;
228         int rc, len;
229 
230         rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name);
231         if (rc) {
232                 ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
233                 goto out;
234         }
235 
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 
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 
263         memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE);
264         memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen);
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         }
277         ksmbd_release_crypto_ctx(ctx);
278         ctx = NULL;
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 
286         if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
287                 rc = -EINVAL;
288 out:
289         if (ctx)
290                 ksmbd_release_crypto_ctx(ctx);
291         kfree(construct);
292         return rc;
293 }
294 
295 /**
296  * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
297  * authenticate blob
298  * @authblob:   authenticate blob source pointer
299  * @blob_len:   length of the @authblob message
300  * @conn:       connection
301  * @sess:       session of connection
302  *
303  * Return:      0 on success, error number on error
304  */
305 int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
306                                    int blob_len, struct ksmbd_conn *conn,
307                                    struct ksmbd_session *sess)
308 {
309         char *domain_name;
310         unsigned int nt_off, dn_off;
311         unsigned short nt_len, dn_len;
312         int ret;
313 
314         if (blob_len < sizeof(struct authenticate_message)) {
315                 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
316                             blob_len);
317                 return -EINVAL;
318         }
319 
320         if (memcmp(authblob->Signature, "NTLMSSP", 8)) {
321                 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
322                             authblob->Signature);
323                 return -EINVAL;
324         }
325 
326         nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
327         nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
328         dn_off = le32_to_cpu(authblob->DomainName.BufferOffset);
329         dn_len = le16_to_cpu(authblob->DomainName.Length);
330 
331         if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len ||
332             nt_len < CIFS_ENCPWD_SIZE)
333                 return -EINVAL;
334 
335         /* TODO : use domain name that imported from configuration file */
336         domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off,
337                                              dn_len, true, conn->local_nls);
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",
343                     domain_name);
344         ret = ksmbd_auth_ntlmv2(conn, sess,
345                                 (struct ntlmv2_resp *)((char *)authblob + nt_off),
346                                 nt_len - CIFS_ENCPWD_SIZE,
347                                 domain_name, conn->ntlmssp.cryptkey);
348         kfree(domain_name);
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;
360 
361                 if (sess_key_len > CIFS_KEY_SIZE)
362                         return -EINVAL;
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 
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
382  * @blob_len:   length of the @authblob message
383  * @conn:       connection
384  *
385  */
386 int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
387                                   int blob_len, struct ksmbd_conn *conn)
388 {
389         if (blob_len < sizeof(struct negotiate_message)) {
390                 ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
391                             blob_len);
392                 return -EINVAL;
393         }
394 
395         if (memcmp(negblob->Signature, "NTLMSSP", 8)) {
396                 ksmbd_debug(AUTH, "blob signature incorrect %s\n",
397                             negblob->Signature);
398                 return -EINVAL;
399         }
400 
401         conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags);
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
409  * @conn:       connection
410  *
411  */
412 unsigned int
413 ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
414                                    struct ksmbd_conn *conn)
415 {
416         struct target_info *tinfo;
417         wchar_t *name;
418         __u8 *target_name;
419         unsigned int flags, blob_off, blob_len, type, target_info_len = 0;
420         int len, uni_len, conv_len;
421         int cflags = conn->ntlmssp.client_flags;
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 |
433                                    NTLMSSP_NEGOTIATE_56);
434         }
435 
436         if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn))
437                 flags |= NTLMSSP_NEGOTIATE_SEAL;
438 
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 
445         if (conn->use_spnego &&
446             (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
447                 flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
448 
449         if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
450                 flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
451 
452         chgblob->NegotiateFlags = cpu_to_le32(flags);
453         len = strlen(ksmbd_netbios_name());
454         name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
455         if (!name)
456                 return -ENOMEM;
457 
458         conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
459                                   conn->local_nls);
460         if (conv_len < 0 || conv_len > len) {
461                 kfree(name);
462                 return -EINVAL;
463         }
464 
465         uni_len = UNICODE_LEN(conv_len);
466 
467         blob_off = sizeof(struct challenge_message);
468         blob_len = blob_off + uni_len;
469 
470         chgblob->TargetName.Length = cpu_to_le16(uni_len);
471         chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len);
472         chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
473 
474         /* Initialize random conn challenge */
475         get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64));
476         memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey,
477                CIFS_CRYPTO_KEY_SIZE);
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;
483         memcpy(target_name, name, uni_len);
484         tinfo = (struct target_info *)(target_name + uni_len);
485 
486         chgblob->TargetInfoArray.Length = 0;
487         /* Add target info list for NetBIOS/DNS settings */
488         for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
489              type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
490                 tinfo->Type = cpu_to_le16(type);
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;
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
511 int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
512                             int in_len, char *out_blob, int *out_len)
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",
532                             *out_len, resp->spnego_blob_len);
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,
553                resp->spnego_blob_len);
554         *out_len = resp->spnego_blob_len;
555         retval = 0;
556 out:
557         kvfree(resp);
558         return retval;
559 }
560 #else
561 int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
562                             int in_len, char *out_blob, int *out_len)
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  */
577 int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
578                         int n_vec, char *sig)
579 {
580         struct ksmbd_crypto_ctx *ctx;
581         int rc, i;
582 
583         ctx = ksmbd_crypto_ctx_find_hmacsha256();
584         if (!ctx) {
585                 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
586                 return -ENOMEM;
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);
614 out:
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  */
628 int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
629                         int n_vec, char *sig)
630 {
631         struct ksmbd_crypto_ctx *ctx;
632         int rc, i;
633 
634         ctx = ksmbd_crypto_ctx_find_cmacaes();
635         if (!ctx) {
636                 ksmbd_debug(AUTH, "could not crypto alloc cmac\n");
637                 return -ENOMEM;
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);
665 out:
666         ksmbd_release_crypto_ctx(ctx);
667         return rc;
668 }
669 
670 struct derivation {
671         struct kvec label;
672         struct kvec context;
673         bool binding;
674 };
675 
676 static 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)
679 {
680         unsigned char zero = 0x0;
681         __u8 i[4] = {0, 0, 0, 1};
682         __u8 L128[4] = {0, 0, 0, 128};
683         __u8 L256[4] = {0, 0, 1, 0};
684         int rc;
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) {
694                 ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
695                 return -ENOMEM;
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 
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))
741                 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
742         else
743                 rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
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",
752                             rc);
753                 goto smb3signkey_ret;
754         }
755 
756         memcpy(key, hashptr, key_size);
757 
758 smb3signkey_ret:
759         ksmbd_release_crypto_ctx(ctx);
760         return rc;
761 }
762 
763 static int generate_smb3signingkey(struct ksmbd_session *sess,
764                                    struct ksmbd_conn *conn,
765                                    const struct derivation *signing)
766 {
767         int rc;
768         struct channel *chann;
769         char *key;
770 
771         chann = lookup_chann_list(sess, conn);
772         if (!chann)
773                 return 0;
774 
775         if (conn->dialect >= SMB30_PROT_ID && signing->binding)
776                 key = chann->smb3signingkey;
777         else
778                 key = sess->smb3signingkey;
779 
780         rc = generate_key(conn, sess, signing->label, signing->context, key,
781                           SMB3_SIGN_KEY_SIZE);
782         if (rc)
783                 return rc;
784 
785         if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
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",
791                     SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
792         ksmbd_debug(AUTH, "Signing Key   %*ph\n",
793                     SMB3_SIGN_KEY_SIZE, key);
794         return 0;
795 }
796 
797 int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
798                                struct ksmbd_conn *conn)
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;
806         d.binding = conn->binding;
807 
808         return generate_smb3signingkey(sess, conn, &d);
809 }
810 
811 int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
812                                 struct ksmbd_conn *conn)
813 {
814         struct derivation d;
815 
816         d.label.iov_base = "SMBSigningKey";
817         d.label.iov_len = 14;
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         }
828         d.context.iov_len = 64;
829         d.binding = conn->binding;
830 
831         return generate_smb3signingkey(sess, conn, &d);
832 }
833 
834 struct derivation_twin {
835         struct derivation encryption;
836         struct derivation decryption;
837 };
838 
839 static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
840                                       struct ksmbd_session *sess,
841                                       const struct derivation_twin *ptwin)
842 {
843         int rc;
844 
845         rc = generate_key(conn, sess, ptwin->encryption.label,
846                           ptwin->encryption.context, sess->smb3encryptionkey,
847                           SMB3_ENC_DEC_KEY_SIZE);
848         if (rc)
849                 return rc;
850 
851         rc = generate_key(conn, sess, ptwin->decryption.label,
852                           ptwin->decryption.context,
853                           sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
854         if (rc)
855                 return rc;
856 
857         ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
858         ksmbd_debug(AUTH, "Cipher type   %d\n", conn->cipher_type);
859         ksmbd_debug(AUTH, "Session Id    %llu\n", sess->id);
860         ksmbd_debug(AUTH, "Session Key   %*ph\n",
861                     SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
862         if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
863             conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
864                 ksmbd_debug(AUTH, "ServerIn Key  %*ph\n",
865                             SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
866                 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
867                             SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
868         } else {
869                 ksmbd_debug(AUTH, "ServerIn Key  %*ph\n",
870                             SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
871                 ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
872                             SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
873         }
874         return 0;
875 }
876 
877 int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
878                                   struct ksmbd_session *sess)
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 
895         return generate_smb3encryptionkey(conn, sess, &twin);
896 }
897 
898 int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
899                                    struct ksmbd_session *sess)
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 
916         return generate_smb3encryptionkey(conn, sess, &twin);
917 }
918 
919 int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
920                                      __u8 *pi_hash)
921 {
922         int rc;
923         struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
924         char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
925         int msg_size = get_rfc1002_len(buf);
926         struct ksmbd_crypto_ctx *ctx = NULL;
927 
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) {
934                 ksmbd_debug(AUTH, "could not alloc sha512\n");
935                 return -ENOMEM;
936         }
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         }
961 out:
962         ksmbd_release_crypto_ctx(ctx);
963         return rc;
964 }
965 
966 int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
967                       __u8 *pi_hash)
968 {
969         int rc;
970         struct ksmbd_crypto_ctx *ctx = NULL;
971 
972         ctx = ksmbd_crypto_ctx_find_sha256();
973         if (!ctx) {
974                 ksmbd_debug(AUTH, "could not alloc sha256\n");
975                 return -ENOMEM;
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         }
995 out:
996         ksmbd_release_crypto_ctx(ctx);
997         return rc;
998 }
999 
1000 static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
1001                                     int enc, u8 *key)
1002 {
1003         struct ksmbd_session *sess;
1004         u8 *ses_enc_key;
1005 
1006         if (enc)
1007                 sess = work->sess;
1008         else
1009                 sess = ksmbd_session_lookup_all(work->conn, ses_id);
1010         if (!sess)
1011                 return -EINVAL;
1012 
1013         ses_enc_key = enc ? sess->smb3encryptionkey :
1014                 sess->smb3decryptionkey;
1015         memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
1016 
1017         return 0;
1018 }
1019 
1020 static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
1021                                    unsigned int buflen)
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 
1032 static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
1033                                          u8 *sign)
1034 {
1035         struct scatterlist *sg;
1036         unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
1037         int i, *nr_entries, total_entries = 0, sg_idx = 0;
1038 
1039         if (!nvec)
1040                 return NULL;
1041 
1042         nr_entries = kcalloc(nvec, sizeof(int), GFP_KERNEL);
1043         if (!nr_entries)
1044                 return NULL;
1045 
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);
1053                 } else {
1054                         nr_entries[i]++;
1055                 }
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);
1063         if (!sg) {
1064                 kfree(nr_entries);
1065                 return NULL;
1066         }
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 
1080                                 if (!len)
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                 }
1098         }
1099         smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
1100         kfree(nr_entries);
1101         return sg;
1102 }
1103 
1104 int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
1105                         unsigned int nvec, int enc)
1106 {
1107         struct ksmbd_conn *conn = work->conn;
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;
1110         int rc;
1111         struct scatterlist *sg;
1112         u8 sign[SMB2_SIGNATURE_SIZE] = {};
1113         u8 key[SMB3_ENC_DEC_KEY_SIZE];
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 
1121         rc = ksmbd_get_encryption_key(work,
1122                                       le64_to_cpu(tr_hdr->SessionId),
1123                                       enc,
1124                                       key);
1125         if (rc) {
1126                 pr_err("Could not get %scryption key\n", enc ? "en" : "de");
1127                 return rc;
1128         }
1129 
1130         if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1131             conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
1132                 ctx = ksmbd_crypto_ctx_find_gcm();
1133         else
1134                 ctx = ksmbd_crypto_ctx_find_ccm();
1135         if (!ctx) {
1136                 pr_err("crypto alloc failed\n");
1137                 return -ENOMEM;
1138         }
1139 
1140         if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
1141             conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
1142                 tfm = CRYPTO_GCM(ctx);
1143         else
1144                 tfm = CRYPTO_CCM(ctx);
1145 
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);
1151         if (rc) {
1152                 pr_err("Failed to set aead key %d\n", rc);
1153                 goto free_ctx;
1154         }
1155 
1156         rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
1157         if (rc) {
1158                 pr_err("Failed to set authsize %d\n", rc);
1159                 goto free_ctx;
1160         }
1161 
1162         req = aead_request_alloc(tfm, GFP_KERNEL);
1163         if (!req) {
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) {
1175                 pr_err("Failed to init sg\n");
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) {
1183                 rc = -ENOMEM;
1184                 goto free_sg;
1185         }
1186 
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);
1190         } else {
1191                 iv[0] = 3;
1192                 memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
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);
1203         if (rc)
1204                 goto free_iv;
1205 
1206         if (enc)
1207                 memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
1208 
1209 free_iv:
1210         kfree(iv);
1211 free_sg:
1212         kfree(sg);
1213 free_req:
1214         kfree(req);
1215 free_ctx:
1216         ksmbd_release_crypto_ctx(ctx);
1217         return rc;
1218 }
1219 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php