]> Git Repo - J-linux.git/blob - fs/smb/client/cifsencrypt.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / fs / smb / client / cifsencrypt.c
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3  *
4  *   Encryption and hashing operations relating to NTLM, NTLMv2.  See MS-NLMP
5  *   for more detailed information
6  *
7  *   Copyright (C) International Business Machines  Corp., 2005,2013
8  *   Author(s): Steve French ([email protected])
9  *
10  */
11
12 #include <linux/fs.h>
13 #include <linux/slab.h>
14 #include "cifspdu.h"
15 #include "cifsglob.h"
16 #include "cifs_debug.h"
17 #include "cifs_unicode.h"
18 #include "cifsproto.h"
19 #include "ntlmssp.h"
20 #include <linux/ctype.h>
21 #include <linux/random.h>
22 #include <linux/highmem.h>
23 #include <linux/fips.h>
24 #include <linux/iov_iter.h>
25 #include "../common/arc4.h"
26 #include <crypto/aead.h>
27
28 static size_t cifs_shash_step(void *iter_base, size_t progress, size_t len,
29                               void *priv, void *priv2)
30 {
31         struct shash_desc *shash = priv;
32         int ret, *pret = priv2;
33
34         ret = crypto_shash_update(shash, iter_base, len);
35         if (ret < 0) {
36                 *pret = ret;
37                 return len;
38         }
39         return 0;
40 }
41
42 /*
43  * Pass the data from an iterator into a hash.
44  */
45 static int cifs_shash_iter(const struct iov_iter *iter, size_t maxsize,
46                            struct shash_desc *shash)
47 {
48         struct iov_iter tmp_iter = *iter;
49         int err = -EIO;
50
51         if (iterate_and_advance_kernel(&tmp_iter, maxsize, shash, &err,
52                                        cifs_shash_step) != maxsize)
53                 return err;
54         return 0;
55 }
56
57 int __cifs_calc_signature(struct smb_rqst *rqst,
58                           struct TCP_Server_Info *server, char *signature,
59                           struct shash_desc *shash)
60 {
61         int i;
62         ssize_t rc;
63         struct kvec *iov = rqst->rq_iov;
64         int n_vec = rqst->rq_nvec;
65
66         /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
67         if (!is_smb1(server)) {
68                 if (iov[0].iov_len <= 4)
69                         return -EIO;
70                 i = 0;
71         } else {
72                 if (n_vec < 2 || iov[0].iov_len != 4)
73                         return -EIO;
74                 i = 1; /* skip rfc1002 length */
75         }
76
77         for (; i < n_vec; i++) {
78                 if (iov[i].iov_len == 0)
79                         continue;
80                 if (iov[i].iov_base == NULL) {
81                         cifs_dbg(VFS, "null iovec entry\n");
82                         return -EIO;
83                 }
84
85                 rc = crypto_shash_update(shash,
86                                          iov[i].iov_base, iov[i].iov_len);
87                 if (rc) {
88                         cifs_dbg(VFS, "%s: Could not update with payload\n",
89                                  __func__);
90                         return rc;
91                 }
92         }
93
94         rc = cifs_shash_iter(&rqst->rq_iter, iov_iter_count(&rqst->rq_iter), shash);
95         if (rc < 0)
96                 return rc;
97
98         rc = crypto_shash_final(shash, signature);
99         if (rc)
100                 cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
101
102         return rc;
103 }
104
105 /*
106  * Calculate and return the CIFS signature based on the mac key and SMB PDU.
107  * The 16 byte signature must be allocated by the caller. Note we only use the
108  * 1st eight bytes and that the smb header signature field on input contains
109  * the sequence number before this function is called. Also, this function
110  * should be called with the server->srv_mutex held.
111  */
112 static int cifs_calc_signature(struct smb_rqst *rqst,
113                         struct TCP_Server_Info *server, char *signature)
114 {
115         int rc;
116
117         if (!rqst->rq_iov || !signature || !server)
118                 return -EINVAL;
119
120         rc = cifs_alloc_hash("md5", &server->secmech.md5);
121         if (rc)
122                 return -1;
123
124         rc = crypto_shash_init(server->secmech.md5);
125         if (rc) {
126                 cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
127                 return rc;
128         }
129
130         rc = crypto_shash_update(server->secmech.md5,
131                 server->session_key.response, server->session_key.len);
132         if (rc) {
133                 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
134                 return rc;
135         }
136
137         return __cifs_calc_signature(rqst, server, signature, server->secmech.md5);
138 }
139
140 /* must be called with server->srv_mutex held */
141 int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
142                    __u32 *pexpected_response_sequence_number)
143 {
144         int rc = 0;
145         char smb_signature[20];
146         struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
147
148         if (rqst->rq_iov[0].iov_len != 4 ||
149             rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
150                 return -EIO;
151
152         if ((cifs_pdu == NULL) || (server == NULL))
153                 return -EINVAL;
154
155         spin_lock(&server->srv_lock);
156         if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
157             server->tcpStatus == CifsNeedNegotiate) {
158                 spin_unlock(&server->srv_lock);
159                 return rc;
160         }
161         spin_unlock(&server->srv_lock);
162
163         if (!server->session_estab) {
164                 memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
165                 return rc;
166         }
167
168         cifs_pdu->Signature.Sequence.SequenceNumber =
169                                 cpu_to_le32(server->sequence_number);
170         cifs_pdu->Signature.Sequence.Reserved = 0;
171
172         *pexpected_response_sequence_number = ++server->sequence_number;
173         ++server->sequence_number;
174
175         rc = cifs_calc_signature(rqst, server, smb_signature);
176         if (rc)
177                 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
178         else
179                 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
180
181         return rc;
182 }
183
184 int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
185                    __u32 *pexpected_response_sequence)
186 {
187         struct smb_rqst rqst = { .rq_iov = iov,
188                                  .rq_nvec = n_vec };
189
190         return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
191 }
192
193 /* must be called with server->srv_mutex held */
194 int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
195                   __u32 *pexpected_response_sequence_number)
196 {
197         struct kvec iov[2];
198
199         iov[0].iov_base = cifs_pdu;
200         iov[0].iov_len = 4;
201         iov[1].iov_base = (char *)cifs_pdu + 4;
202         iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
203
204         return cifs_sign_smbv(iov, 2, server,
205                               pexpected_response_sequence_number);
206 }
207
208 int cifs_verify_signature(struct smb_rqst *rqst,
209                           struct TCP_Server_Info *server,
210                           __u32 expected_sequence_number)
211 {
212         unsigned int rc;
213         char server_response_sig[8];
214         char what_we_think_sig_should_be[20];
215         struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
216
217         if (rqst->rq_iov[0].iov_len != 4 ||
218             rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
219                 return -EIO;
220
221         if (cifs_pdu == NULL || server == NULL)
222                 return -EINVAL;
223
224         if (!server->session_estab)
225                 return 0;
226
227         if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
228                 struct smb_com_lock_req *pSMB =
229                         (struct smb_com_lock_req *)cifs_pdu;
230                 if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
231                         return 0;
232         }
233
234         /* BB what if signatures are supposed to be on for session but
235            server does not send one? BB */
236
237         /* Do not need to verify session setups with signature "BSRSPYL "  */
238         if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
239                 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
240                          cifs_pdu->Command);
241
242         /* save off the original signature so we can modify the smb and check
243                 its signature against what the server sent */
244         memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
245
246         cifs_pdu->Signature.Sequence.SequenceNumber =
247                                         cpu_to_le32(expected_sequence_number);
248         cifs_pdu->Signature.Sequence.Reserved = 0;
249
250         cifs_server_lock(server);
251         rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
252         cifs_server_unlock(server);
253
254         if (rc)
255                 return rc;
256
257 /*      cifs_dump_mem("what we think it should be: ",
258                       what_we_think_sig_should_be, 16); */
259
260         if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
261                 return -EACCES;
262         else
263                 return 0;
264
265 }
266
267 /* Build a proper attribute value/target info pairs blob.
268  * Fill in netbios and dns domain name and workstation name
269  * and client time (total five av pairs and + one end of fields indicator.
270  * Allocate domain name which gets freed when session struct is deallocated.
271  */
272 static int
273 build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
274 {
275         unsigned int dlen;
276         unsigned int size = 2 * sizeof(struct ntlmssp2_name);
277         char *defdmname = "WORKGROUP";
278         unsigned char *blobptr;
279         struct ntlmssp2_name *attrptr;
280
281         if (!ses->domainName) {
282                 ses->domainName = kstrdup(defdmname, GFP_KERNEL);
283                 if (!ses->domainName)
284                         return -ENOMEM;
285         }
286
287         dlen = strlen(ses->domainName);
288
289         /*
290          * The length of this blob is two times the size of a
291          * structure (av pair) which holds name/size
292          * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
293          * unicode length of a netbios domain name
294          */
295         kfree_sensitive(ses->auth_key.response);
296         ses->auth_key.len = size + 2 * dlen;
297         ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
298         if (!ses->auth_key.response) {
299                 ses->auth_key.len = 0;
300                 return -ENOMEM;
301         }
302
303         blobptr = ses->auth_key.response;
304         attrptr = (struct ntlmssp2_name *) blobptr;
305
306         /*
307          * As defined in MS-NTLM 3.3.2, just this av pair field
308          * is sufficient as part of the temp
309          */
310         attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
311         attrptr->length = cpu_to_le16(2 * dlen);
312         blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
313         cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
314
315         return 0;
316 }
317
318 /* Server has provided av pairs/target info in the type 2 challenge
319  * packet and we have plucked it and stored within smb session.
320  * We parse that blob here to find netbios domain name to be used
321  * as part of ntlmv2 authentication (in Target String), if not already
322  * specified on the command line.
323  * If this function returns without any error but without fetching
324  * domain name, authentication may fail against some server but
325  * may not fail against other (those who are not very particular
326  * about target string i.e. for some, just user name might suffice.
327  */
328 static int
329 find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
330 {
331         unsigned int attrsize;
332         unsigned int type;
333         unsigned int onesize = sizeof(struct ntlmssp2_name);
334         unsigned char *blobptr;
335         unsigned char *blobend;
336         struct ntlmssp2_name *attrptr;
337
338         if (!ses->auth_key.len || !ses->auth_key.response)
339                 return 0;
340
341         blobptr = ses->auth_key.response;
342         blobend = blobptr + ses->auth_key.len;
343
344         while (blobptr + onesize < blobend) {
345                 attrptr = (struct ntlmssp2_name *) blobptr;
346                 type = le16_to_cpu(attrptr->type);
347                 if (type == NTLMSSP_AV_EOL)
348                         break;
349                 blobptr += 2; /* advance attr type */
350                 attrsize = le16_to_cpu(attrptr->length);
351                 blobptr += 2; /* advance attr size */
352                 if (blobptr + attrsize > blobend)
353                         break;
354                 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
355                         if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
356                                 break;
357                         if (!ses->domainName) {
358                                 ses->domainName =
359                                         kmalloc(attrsize + 1, GFP_KERNEL);
360                                 if (!ses->domainName)
361                                                 return -ENOMEM;
362                                 cifs_from_utf16(ses->domainName,
363                                         (__le16 *)blobptr, attrsize, attrsize,
364                                         nls_cp, NO_MAP_UNI_RSVD);
365                                 break;
366                         }
367                 }
368                 blobptr += attrsize; /* advance attr  value */
369         }
370
371         return 0;
372 }
373
374 /* Server has provided av pairs/target info in the type 2 challenge
375  * packet and we have plucked it and stored within smb session.
376  * We parse that blob here to find the server given timestamp
377  * as part of ntlmv2 authentication (or local current time as
378  * default in case of failure)
379  */
380 static __le64
381 find_timestamp(struct cifs_ses *ses)
382 {
383         unsigned int attrsize;
384         unsigned int type;
385         unsigned int onesize = sizeof(struct ntlmssp2_name);
386         unsigned char *blobptr;
387         unsigned char *blobend;
388         struct ntlmssp2_name *attrptr;
389         struct timespec64 ts;
390
391         if (!ses->auth_key.len || !ses->auth_key.response)
392                 return 0;
393
394         blobptr = ses->auth_key.response;
395         blobend = blobptr + ses->auth_key.len;
396
397         while (blobptr + onesize < blobend) {
398                 attrptr = (struct ntlmssp2_name *) blobptr;
399                 type = le16_to_cpu(attrptr->type);
400                 if (type == NTLMSSP_AV_EOL)
401                         break;
402                 blobptr += 2; /* advance attr type */
403                 attrsize = le16_to_cpu(attrptr->length);
404                 blobptr += 2; /* advance attr size */
405                 if (blobptr + attrsize > blobend)
406                         break;
407                 if (type == NTLMSSP_AV_TIMESTAMP) {
408                         if (attrsize == sizeof(u64))
409                                 return *((__le64 *)blobptr);
410                 }
411                 blobptr += attrsize; /* advance attr value */
412         }
413
414         ktime_get_real_ts64(&ts);
415         return cpu_to_le64(cifs_UnixTimeToNT(ts));
416 }
417
418 static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
419                             const struct nls_table *nls_cp, struct shash_desc *hmacmd5)
420 {
421         int rc = 0;
422         int len;
423         char nt_hash[CIFS_NTHASH_SIZE];
424         __le16 *user;
425         wchar_t *domain;
426         wchar_t *server;
427
428         /* calculate md4 hash of password */
429         E_md4hash(ses->password, nt_hash, nls_cp);
430
431         rc = crypto_shash_setkey(hmacmd5->tfm, nt_hash, CIFS_NTHASH_SIZE);
432         if (rc) {
433                 cifs_dbg(VFS, "%s: Could not set NT hash as a key, rc=%d\n", __func__, rc);
434                 return rc;
435         }
436
437         rc = crypto_shash_init(hmacmd5);
438         if (rc) {
439                 cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
440                 return rc;
441         }
442
443         /* convert ses->user_name to unicode */
444         len = ses->user_name ? strlen(ses->user_name) : 0;
445         user = kmalloc(2 + (len * 2), GFP_KERNEL);
446         if (user == NULL)
447                 return -ENOMEM;
448
449         if (len) {
450                 len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
451                 UniStrupr(user);
452         } else {
453                 *(u16 *)user = 0;
454         }
455
456         rc = crypto_shash_update(hmacmd5, (char *)user, 2 * len);
457         kfree(user);
458         if (rc) {
459                 cifs_dbg(VFS, "%s: Could not update with user, rc=%d\n", __func__, rc);
460                 return rc;
461         }
462
463         /* convert ses->domainName to unicode and uppercase */
464         if (ses->domainName) {
465                 len = strlen(ses->domainName);
466
467                 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
468                 if (domain == NULL)
469                         return -ENOMEM;
470
471                 len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
472                                       nls_cp);
473                 rc = crypto_shash_update(hmacmd5, (char *)domain, 2 * len);
474                 kfree(domain);
475                 if (rc) {
476                         cifs_dbg(VFS, "%s: Could not update with domain, rc=%d\n", __func__, rc);
477                         return rc;
478                 }
479         } else {
480                 /* We use ses->ip_addr if no domain name available */
481                 len = strlen(ses->ip_addr);
482
483                 server = kmalloc(2 + (len * 2), GFP_KERNEL);
484                 if (server == NULL)
485                         return -ENOMEM;
486
487                 len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len, nls_cp);
488                 rc = crypto_shash_update(hmacmd5, (char *)server, 2 * len);
489                 kfree(server);
490                 if (rc) {
491                         cifs_dbg(VFS, "%s: Could not update with server, rc=%d\n", __func__, rc);
492                         return rc;
493                 }
494         }
495
496         rc = crypto_shash_final(hmacmd5, ntlmv2_hash);
497         if (rc)
498                 cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
499
500         return rc;
501 }
502
503 static int
504 CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_desc *hmacmd5)
505 {
506         int rc;
507         struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
508             (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
509         unsigned int hash_len;
510
511         /* The MD5 hash starts at challenge_key.key */
512         hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
513                 offsetof(struct ntlmv2_resp, challenge.key[0]));
514
515         rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
516         if (rc) {
517                 cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
518                 return rc;
519         }
520
521         rc = crypto_shash_init(hmacmd5);
522         if (rc) {
523                 cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
524                 return rc;
525         }
526
527         if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
528                 memcpy(ntlmv2->challenge.key, ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
529         else
530                 memcpy(ntlmv2->challenge.key, ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
531
532         rc = crypto_shash_update(hmacmd5, ntlmv2->challenge.key, hash_len);
533         if (rc) {
534                 cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
535                 return rc;
536         }
537
538         /* Note that the MD5 digest over writes anon.challenge_key.key */
539         rc = crypto_shash_final(hmacmd5, ntlmv2->ntlmv2_hash);
540         if (rc)
541                 cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
542
543         return rc;
544 }
545
546 int
547 setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
548 {
549         struct shash_desc *hmacmd5 = NULL;
550         int rc;
551         int baselen;
552         unsigned int tilen;
553         struct ntlmv2_resp *ntlmv2;
554         char ntlmv2_hash[16];
555         unsigned char *tiblob = NULL; /* target info blob */
556         __le64 rsp_timestamp;
557
558         if (nls_cp == NULL) {
559                 cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
560                 return -EINVAL;
561         }
562
563         if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
564                 if (!ses->domainName) {
565                         if (ses->domainAuto) {
566                                 rc = find_domain_name(ses, nls_cp);
567                                 if (rc) {
568                                         cifs_dbg(VFS, "error %d finding domain name\n",
569                                                  rc);
570                                         goto setup_ntlmv2_rsp_ret;
571                                 }
572                         } else {
573                                 ses->domainName = kstrdup("", GFP_KERNEL);
574                         }
575                 }
576         } else {
577                 rc = build_avpair_blob(ses, nls_cp);
578                 if (rc) {
579                         cifs_dbg(VFS, "error %d building av pair blob\n", rc);
580                         goto setup_ntlmv2_rsp_ret;
581                 }
582         }
583
584         /* Must be within 5 minutes of the server (or in range +/-2h
585          * in case of Mac OS X), so simply carry over server timestamp
586          * (as Windows 7 does)
587          */
588         rsp_timestamp = find_timestamp(ses);
589
590         baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
591         tilen = ses->auth_key.len;
592         tiblob = ses->auth_key.response;
593
594         ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
595         if (!ses->auth_key.response) {
596                 rc = -ENOMEM;
597                 ses->auth_key.len = 0;
598                 goto setup_ntlmv2_rsp_ret;
599         }
600         ses->auth_key.len += baselen;
601
602         ntlmv2 = (struct ntlmv2_resp *)
603                         (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
604         ntlmv2->blob_signature = cpu_to_le32(0x00000101);
605         ntlmv2->reserved = 0;
606         ntlmv2->time = rsp_timestamp;
607
608         get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
609         ntlmv2->reserved2 = 0;
610
611         memcpy(ses->auth_key.response + baselen, tiblob, tilen);
612
613         cifs_server_lock(ses->server);
614
615         rc = cifs_alloc_hash("hmac(md5)", &hmacmd5);
616         if (rc) {
617                 cifs_dbg(VFS, "Could not allocate HMAC-MD5, rc=%d\n", rc);
618                 goto unlock;
619         }
620
621         /* calculate ntlmv2_hash */
622         rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp, hmacmd5);
623         if (rc) {
624                 cifs_dbg(VFS, "Could not get NTLMv2 hash, rc=%d\n", rc);
625                 goto unlock;
626         }
627
628         /* calculate first part of the client response (CR1) */
629         rc = CalcNTLMv2_response(ses, ntlmv2_hash, hmacmd5);
630         if (rc) {
631                 cifs_dbg(VFS, "Could not calculate CR1, rc=%d\n", rc);
632                 goto unlock;
633         }
634
635         /* now calculate the session key for NTLMv2 */
636         rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
637         if (rc) {
638                 cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
639                 goto unlock;
640         }
641
642         rc = crypto_shash_init(hmacmd5);
643         if (rc) {
644                 cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
645                 goto unlock;
646         }
647
648         rc = crypto_shash_update(hmacmd5, ntlmv2->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
649         if (rc) {
650                 cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
651                 goto unlock;
652         }
653
654         rc = crypto_shash_final(hmacmd5, ses->auth_key.response);
655         if (rc)
656                 cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
657 unlock:
658         cifs_server_unlock(ses->server);
659         cifs_free_hash(&hmacmd5);
660 setup_ntlmv2_rsp_ret:
661         kfree_sensitive(tiblob);
662
663         return rc;
664 }
665
666 int
667 calc_seckey(struct cifs_ses *ses)
668 {
669         unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
670         struct arc4_ctx *ctx_arc4;
671
672         if (fips_enabled)
673                 return -ENODEV;
674
675         get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
676
677         ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
678         if (!ctx_arc4) {
679                 cifs_dbg(VFS, "Could not allocate arc4 context\n");
680                 return -ENOMEM;
681         }
682
683         cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
684         cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
685                         CIFS_CPHTXT_SIZE);
686
687         /* make secondary_key/nonce as session key */
688         memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
689         /* and make len as that of session key only */
690         ses->auth_key.len = CIFS_SESS_KEY_SIZE;
691
692         memzero_explicit(sec_key, CIFS_SESS_KEY_SIZE);
693         kfree_sensitive(ctx_arc4);
694         return 0;
695 }
696
697 void
698 cifs_crypto_secmech_release(struct TCP_Server_Info *server)
699 {
700         cifs_free_hash(&server->secmech.aes_cmac);
701         cifs_free_hash(&server->secmech.hmacsha256);
702         cifs_free_hash(&server->secmech.md5);
703         cifs_free_hash(&server->secmech.sha512);
704
705         if (!SERVER_IS_CHAN(server)) {
706                 if (server->secmech.enc) {
707                         crypto_free_aead(server->secmech.enc);
708                         server->secmech.enc = NULL;
709                 }
710
711                 if (server->secmech.dec) {
712                         crypto_free_aead(server->secmech.dec);
713                         server->secmech.dec = NULL;
714                 }
715         } else {
716                 server->secmech.enc = NULL;
717                 server->secmech.dec = NULL;
718         }
719 }
This page took 0.119538 seconds and 4 git commands to generate.