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

TOMOYO Linux Cross Reference
Linux/fs/cifs/cifsencrypt.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *   fs/cifs/cifsencrypt.c
  3  *
  4  *   Copyright (C) International Business Machines  Corp., 2005,2013
  5  *   Author(s): Steve French (sfrench@us.ibm.com)
  6  *
  7  *   This library is free software; you can redistribute it and/or modify
  8  *   it under the terms of the GNU Lesser General Public License as published
  9  *   by the Free Software Foundation; either version 2.1 of the License, or
 10  *   (at your option) any later version.
 11  *
 12  *   This library is distributed in the hope that it will be useful,
 13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 15  *   the GNU Lesser General Public License for more details.
 16  *
 17  *   You should have received a copy of the GNU Lesser General Public License
 18  *   along with this library; if not, write to the Free Software
 19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 20  */
 21 
 22 #include <linux/fs.h>
 23 #include <linux/slab.h>
 24 #include "cifspdu.h"
 25 #include "cifsglob.h"
 26 #include "cifs_debug.h"
 27 #include "cifs_unicode.h"
 28 #include "cifsproto.h"
 29 #include "ntlmssp.h"
 30 #include <linux/ctype.h>
 31 #include <linux/random.h>
 32 #include <linux/highmem.h>
 33 
 34 static int
 35 cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
 36 {
 37         int rc;
 38         unsigned int size;
 39 
 40         if (server->secmech.sdescmd5 != NULL)
 41                 return 0; /* already allocated */
 42 
 43         server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
 44         if (IS_ERR(server->secmech.md5)) {
 45                 cifs_dbg(VFS, "could not allocate crypto md5\n");
 46                 rc = PTR_ERR(server->secmech.md5);
 47                 server->secmech.md5 = NULL;
 48                 return rc;
 49         }
 50 
 51         size = sizeof(struct shash_desc) +
 52                         crypto_shash_descsize(server->secmech.md5);
 53         server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
 54         if (!server->secmech.sdescmd5) {
 55                 crypto_free_shash(server->secmech.md5);
 56                 server->secmech.md5 = NULL;
 57                 return -ENOMEM;
 58         }
 59         server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
 60         server->secmech.sdescmd5->shash.flags = 0x0;
 61 
 62         return 0;
 63 }
 64 
 65 /*
 66  * Calculate and return the CIFS signature based on the mac key and SMB PDU.
 67  * The 16 byte signature must be allocated by the caller. Note we only use the
 68  * 1st eight bytes and that the smb header signature field on input contains
 69  * the sequence number before this function is called. Also, this function
 70  * should be called with the server->srv_mutex held.
 71  */
 72 static int cifs_calc_signature(struct smb_rqst *rqst,
 73                         struct TCP_Server_Info *server, char *signature)
 74 {
 75         int i;
 76         int rc;
 77         struct kvec *iov = rqst->rq_iov;
 78         int n_vec = rqst->rq_nvec;
 79 
 80         if (iov == NULL || signature == NULL || server == NULL)
 81                 return -EINVAL;
 82 
 83         if (!server->secmech.sdescmd5) {
 84                 rc = cifs_crypto_shash_md5_allocate(server);
 85                 if (rc) {
 86                         cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
 87                         return -1;
 88                 }
 89         }
 90 
 91         rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
 92         if (rc) {
 93                 cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
 94                 return rc;
 95         }
 96 
 97         rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
 98                 server->session_key.response, server->session_key.len);
 99         if (rc) {
100                 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
101                 return rc;
102         }
103 
104         for (i = 0; i < n_vec; i++) {
105                 if (iov[i].iov_len == 0)
106                         continue;
107                 if (iov[i].iov_base == NULL) {
108                         cifs_dbg(VFS, "null iovec entry\n");
109                         return -EIO;
110                 }
111                 /* The first entry includes a length field (which does not get
112                    signed that occupies the first 4 bytes before the header */
113                 if (i == 0) {
114                         if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
115                                 break; /* nothing to sign or corrupt header */
116                         rc =
117                         crypto_shash_update(&server->secmech.sdescmd5->shash,
118                                 iov[i].iov_base + 4, iov[i].iov_len - 4);
119                 } else {
120                         rc =
121                         crypto_shash_update(&server->secmech.sdescmd5->shash,
122                                 iov[i].iov_base, iov[i].iov_len);
123                 }
124                 if (rc) {
125                         cifs_dbg(VFS, "%s: Could not update with payload\n",
126                                  __func__);
127                         return rc;
128                 }
129         }
130 
131         /* now hash over the rq_pages array */
132         for (i = 0; i < rqst->rq_npages; i++) {
133                 struct kvec p_iov;
134 
135                 cifs_rqst_page_to_kvec(rqst, i, &p_iov);
136                 crypto_shash_update(&server->secmech.sdescmd5->shash,
137                                         p_iov.iov_base, p_iov.iov_len);
138                 kunmap(rqst->rq_pages[i]);
139         }
140 
141         rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
142         if (rc)
143                 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
144 
145         return rc;
146 }
147 
148 /* must be called with server->srv_mutex held */
149 int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
150                    __u32 *pexpected_response_sequence_number)
151 {
152         int rc = 0;
153         char smb_signature[20];
154         struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
155 
156         if ((cifs_pdu == NULL) || (server == NULL))
157                 return -EINVAL;
158 
159         if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
160             server->tcpStatus == CifsNeedNegotiate)
161                 return rc;
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;
198 
199         iov.iov_base = cifs_pdu;
200         iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
201 
202         return cifs_sign_smbv(&iov, 1, server,
203                               pexpected_response_sequence_number);
204 }
205 
206 int cifs_verify_signature(struct smb_rqst *rqst,
207                           struct TCP_Server_Info *server,
208                           __u32 expected_sequence_number)
209 {
210         unsigned int rc;
211         char server_response_sig[8];
212         char what_we_think_sig_should_be[20];
213         struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
214 
215         if (cifs_pdu == NULL || server == NULL)
216                 return -EINVAL;
217 
218         if (!server->session_estab)
219                 return 0;
220 
221         if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
222                 struct smb_com_lock_req *pSMB =
223                         (struct smb_com_lock_req *)cifs_pdu;
224             if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
225                         return 0;
226         }
227 
228         /* BB what if signatures are supposed to be on for session but
229            server does not send one? BB */
230 
231         /* Do not need to verify session setups with signature "BSRSPYL "  */
232         if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
233                 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
234                          cifs_pdu->Command);
235 
236         /* save off the origiginal signature so we can modify the smb and check
237                 its signature against what the server sent */
238         memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
239 
240         cifs_pdu->Signature.Sequence.SequenceNumber =
241                                         cpu_to_le32(expected_sequence_number);
242         cifs_pdu->Signature.Sequence.Reserved = 0;
243 
244         mutex_lock(&server->srv_mutex);
245         rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
246         mutex_unlock(&server->srv_mutex);
247 
248         if (rc)
249                 return rc;
250 
251 /*      cifs_dump_mem("what we think it should be: ",
252                       what_we_think_sig_should_be, 16); */
253 
254         if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
255                 return -EACCES;
256         else
257                 return 0;
258 
259 }
260 
261 /* first calculate 24 bytes ntlm response and then 16 byte session key */
262 int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
263 {
264         int rc = 0;
265         unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
266         char temp_key[CIFS_SESS_KEY_SIZE];
267 
268         if (!ses)
269                 return -EINVAL;
270 
271         ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
272         if (!ses->auth_key.response)
273                 return -ENOMEM;
274 
275         ses->auth_key.len = temp_len;
276 
277         rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
278                         ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
279         if (rc) {
280                 cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n",
281                          __func__, rc);
282                 return rc;
283         }
284 
285         rc = E_md4hash(ses->password, temp_key, nls_cp);
286         if (rc) {
287                 cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
288                          __func__, rc);
289                 return rc;
290         }
291 
292         rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
293         if (rc)
294                 cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n",
295                          __func__, rc);
296 
297         return rc;
298 }
299 
300 #ifdef CONFIG_CIFS_WEAK_PW_HASH
301 int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
302                         char *lnm_session_key)
303 {
304         int i;
305         int rc;
306         char password_with_pad[CIFS_ENCPWD_SIZE] = {0};
307 
308         if (password)
309                 strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
310 
311         if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) {
312                 memcpy(lnm_session_key, password_with_pad,
313                         CIFS_ENCPWD_SIZE);
314                 return 0;
315         }
316 
317         /* calculate old style session key */
318         /* calling toupper is less broken than repeatedly
319         calling nls_toupper would be since that will never
320         work for UTF8, but neither handles multibyte code pages
321         but the only alternative would be converting to UCS-16 (Unicode)
322         (using a routine something like UniStrupr) then
323         uppercasing and then converting back from Unicode - which
324         would only worth doing it if we knew it were utf8. Basically
325         utf8 and other multibyte codepages each need their own strupper
326         function since a byte at a time will ont work. */
327 
328         for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
329                 password_with_pad[i] = toupper(password_with_pad[i]);
330 
331         rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key);
332 
333         return rc;
334 }
335 #endif /* CIFS_WEAK_PW_HASH */
336 
337 /* Build a proper attribute value/target info pairs blob.
338  * Fill in netbios and dns domain name and workstation name
339  * and client time (total five av pairs and + one end of fields indicator.
340  * Allocate domain name which gets freed when session struct is deallocated.
341  */
342 static int
343 build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
344 {
345         unsigned int dlen;
346         unsigned int size = 2 * sizeof(struct ntlmssp2_name);
347         char *defdmname = "WORKGROUP";
348         unsigned char *blobptr;
349         struct ntlmssp2_name *attrptr;
350 
351         if (!ses->domainName) {
352                 ses->domainName = kstrdup(defdmname, GFP_KERNEL);
353                 if (!ses->domainName)
354                         return -ENOMEM;
355         }
356 
357         dlen = strlen(ses->domainName);
358 
359         /*
360          * The length of this blob is two times the size of a
361          * structure (av pair) which holds name/size
362          * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
363          * unicode length of a netbios domain name
364          */
365         ses->auth_key.len = size + 2 * dlen;
366         ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
367         if (!ses->auth_key.response) {
368                 ses->auth_key.len = 0;
369                 return -ENOMEM;
370         }
371 
372         blobptr = ses->auth_key.response;
373         attrptr = (struct ntlmssp2_name *) blobptr;
374 
375         /*
376          * As defined in MS-NTLM 3.3.2, just this av pair field
377          * is sufficient as part of the temp
378          */
379         attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
380         attrptr->length = cpu_to_le16(2 * dlen);
381         blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
382         cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
383 
384         return 0;
385 }
386 
387 /* Server has provided av pairs/target info in the type 2 challenge
388  * packet and we have plucked it and stored within smb session.
389  * We parse that blob here to find netbios domain name to be used
390  * as part of ntlmv2 authentication (in Target String), if not already
391  * specified on the command line.
392  * If this function returns without any error but without fetching
393  * domain name, authentication may fail against some server but
394  * may not fail against other (those who are not very particular
395  * about target string i.e. for some, just user name might suffice.
396  */
397 static int
398 find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
399 {
400         unsigned int attrsize;
401         unsigned int type;
402         unsigned int onesize = sizeof(struct ntlmssp2_name);
403         unsigned char *blobptr;
404         unsigned char *blobend;
405         struct ntlmssp2_name *attrptr;
406 
407         if (!ses->auth_key.len || !ses->auth_key.response)
408                 return 0;
409 
410         blobptr = ses->auth_key.response;
411         blobend = blobptr + ses->auth_key.len;
412 
413         while (blobptr + onesize < blobend) {
414                 attrptr = (struct ntlmssp2_name *) blobptr;
415                 type = le16_to_cpu(attrptr->type);
416                 if (type == NTLMSSP_AV_EOL)
417                         break;
418                 blobptr += 2; /* advance attr type */
419                 attrsize = le16_to_cpu(attrptr->length);
420                 blobptr += 2; /* advance attr size */
421                 if (blobptr + attrsize > blobend)
422                         break;
423                 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
424                         if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
425                                 break;
426                         if (!ses->domainName) {
427                                 ses->domainName =
428                                         kmalloc(attrsize + 1, GFP_KERNEL);
429                                 if (!ses->domainName)
430                                                 return -ENOMEM;
431                                 cifs_from_utf16(ses->domainName,
432                                         (__le16 *)blobptr, attrsize, attrsize,
433                                         nls_cp, false);
434                                 break;
435                         }
436                 }
437                 blobptr += attrsize; /* advance attr  value */
438         }
439 
440         return 0;
441 }
442 
443 /* Server has provided av pairs/target info in the type 2 challenge
444  * packet and we have plucked it and stored within smb session.
445  * We parse that blob here to find the server given timestamp
446  * as part of ntlmv2 authentication (or local current time as
447  * default in case of failure)
448  */
449 static __le64
450 find_timestamp(struct cifs_ses *ses)
451 {
452         unsigned int attrsize;
453         unsigned int type;
454         unsigned int onesize = sizeof(struct ntlmssp2_name);
455         unsigned char *blobptr;
456         unsigned char *blobend;
457         struct ntlmssp2_name *attrptr;
458 
459         if (!ses->auth_key.len || !ses->auth_key.response)
460                 return 0;
461 
462         blobptr = ses->auth_key.response;
463         blobend = blobptr + ses->auth_key.len;
464 
465         while (blobptr + onesize < blobend) {
466                 attrptr = (struct ntlmssp2_name *) blobptr;
467                 type = le16_to_cpu(attrptr->type);
468                 if (type == NTLMSSP_AV_EOL)
469                         break;
470                 blobptr += 2; /* advance attr type */
471                 attrsize = le16_to_cpu(attrptr->length);
472                 blobptr += 2; /* advance attr size */
473                 if (blobptr + attrsize > blobend)
474                         break;
475                 if (type == NTLMSSP_AV_TIMESTAMP) {
476                         if (attrsize == sizeof(u64))
477                                 return *((__le64 *)blobptr);
478                 }
479                 blobptr += attrsize; /* advance attr value */
480         }
481 
482         return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
483 }
484 
485 static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
486                             const struct nls_table *nls_cp)
487 {
488         int rc = 0;
489         int len;
490         char nt_hash[CIFS_NTHASH_SIZE];
491         __le16 *user;
492         wchar_t *domain;
493         wchar_t *server;
494 
495         if (!ses->server->secmech.sdeschmacmd5) {
496                 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
497                 return -1;
498         }
499 
500         /* calculate md4 hash of password */
501         E_md4hash(ses->password, nt_hash, nls_cp);
502 
503         rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
504                                 CIFS_NTHASH_SIZE);
505         if (rc) {
506                 cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
507                 return rc;
508         }
509 
510         rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
511         if (rc) {
512                 cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
513                 return rc;
514         }
515 
516         /* convert ses->user_name to unicode */
517         len = ses->user_name ? strlen(ses->user_name) : 0;
518         user = kmalloc(2 + (len * 2), GFP_KERNEL);
519         if (user == NULL) {
520                 rc = -ENOMEM;
521                 return rc;
522         }
523 
524         if (len) {
525                 len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
526                 UniStrupr(user);
527         } else {
528                 memset(user, '\0', 2);
529         }
530 
531         rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
532                                 (char *)user, 2 * len);
533         kfree(user);
534         if (rc) {
535                 cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
536                 return rc;
537         }
538 
539         /* convert ses->domainName to unicode and uppercase */
540         if (ses->domainName) {
541                 len = strlen(ses->domainName);
542 
543                 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
544                 if (domain == NULL) {
545                         rc = -ENOMEM;
546                         return rc;
547                 }
548                 len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
549                                       nls_cp);
550                 rc =
551                 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
552                                         (char *)domain, 2 * len);
553                 kfree(domain);
554                 if (rc) {
555                         cifs_dbg(VFS, "%s: Could not update with domain\n",
556                                  __func__);
557                         return rc;
558                 }
559         } else if (ses->serverName) {
560                 len = strlen(ses->serverName);
561 
562                 server = kmalloc(2 + (len * 2), GFP_KERNEL);
563                 if (server == NULL) {
564                         rc = -ENOMEM;
565                         return rc;
566                 }
567                 len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
568                                         nls_cp);
569                 rc =
570                 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
571                                         (char *)server, 2 * len);
572                 kfree(server);
573                 if (rc) {
574                         cifs_dbg(VFS, "%s: Could not update with server\n",
575                                  __func__);
576                         return rc;
577                 }
578         }
579 
580         rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
581                                         ntlmv2_hash);
582         if (rc)
583                 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
584 
585         return rc;
586 }
587 
588 static int
589 CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
590 {
591         int rc;
592         struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
593             (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
594         unsigned int hash_len;
595 
596         /* The MD5 hash starts at challenge_key.key */
597         hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
598                 offsetof(struct ntlmv2_resp, challenge.key[0]));
599 
600         if (!ses->server->secmech.sdeschmacmd5) {
601                 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
602                 return -1;
603         }
604 
605         rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
606                                  ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
607         if (rc) {
608                 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
609                          __func__);
610                 return rc;
611         }
612 
613         rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
614         if (rc) {
615                 cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
616                 return rc;
617         }
618 
619         if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
620                 memcpy(ntlmv2->challenge.key,
621                        ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
622         else
623                 memcpy(ntlmv2->challenge.key,
624                        ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
625         rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
626                                  ntlmv2->challenge.key, hash_len);
627         if (rc) {
628                 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
629                 return rc;
630         }
631 
632         /* Note that the MD5 digest over writes anon.challenge_key.key */
633         rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
634                                 ntlmv2->ntlmv2_hash);
635         if (rc)
636                 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
637 
638         return rc;
639 }
640 
641 static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
642 {
643         int rc;
644         unsigned int size;
645 
646         /* check if already allocated */
647         if (server->secmech.sdeschmacmd5)
648                 return 0;
649 
650         server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
651         if (IS_ERR(server->secmech.hmacmd5)) {
652                 cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
653                 rc = PTR_ERR(server->secmech.hmacmd5);
654                 server->secmech.hmacmd5 = NULL;
655                 return rc;
656         }
657 
658         size = sizeof(struct shash_desc) +
659                         crypto_shash_descsize(server->secmech.hmacmd5);
660         server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
661         if (!server->secmech.sdeschmacmd5) {
662                 crypto_free_shash(server->secmech.hmacmd5);
663                 server->secmech.hmacmd5 = NULL;
664                 return -ENOMEM;
665         }
666         server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
667         server->secmech.sdeschmacmd5->shash.flags = 0x0;
668 
669         return 0;
670 }
671 
672 int
673 setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
674 {
675         int rc;
676         int baselen;
677         unsigned int tilen;
678         struct ntlmv2_resp *ntlmv2;
679         char ntlmv2_hash[16];
680         unsigned char *tiblob = NULL; /* target info blob */
681         __le64 rsp_timestamp;
682 
683         if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
684                 if (!ses->domainName) {
685                         rc = find_domain_name(ses, nls_cp);
686                         if (rc) {
687                                 cifs_dbg(VFS, "error %d finding domain name\n",
688                                          rc);
689                                 goto setup_ntlmv2_rsp_ret;
690                         }
691                 }
692         } else {
693                 rc = build_avpair_blob(ses, nls_cp);
694                 if (rc) {
695                         cifs_dbg(VFS, "error %d building av pair blob\n", rc);
696                         goto setup_ntlmv2_rsp_ret;
697                 }
698         }
699 
700         /* Must be within 5 minutes of the server (or in range +/-2h
701          * in case of Mac OS X), so simply carry over server timestamp
702          * (as Windows 7 does)
703          */
704         rsp_timestamp = find_timestamp(ses);
705 
706         baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
707         tilen = ses->auth_key.len;
708         tiblob = ses->auth_key.response;
709 
710         ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
711         if (!ses->auth_key.response) {
712                 rc = -ENOMEM;
713                 ses->auth_key.len = 0;
714                 goto setup_ntlmv2_rsp_ret;
715         }
716         ses->auth_key.len += baselen;
717 
718         ntlmv2 = (struct ntlmv2_resp *)
719                         (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
720         ntlmv2->blob_signature = cpu_to_le32(0x00000101);
721         ntlmv2->reserved = 0;
722         ntlmv2->time = rsp_timestamp;
723 
724         get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
725         ntlmv2->reserved2 = 0;
726 
727         memcpy(ses->auth_key.response + baselen, tiblob, tilen);
728 
729         mutex_lock(&ses->server->srv_mutex);
730 
731         rc = crypto_hmacmd5_alloc(ses->server);
732         if (rc) {
733                 cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
734                 goto unlock;
735         }
736 
737         /* calculate ntlmv2_hash */
738         rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
739         if (rc) {
740                 cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
741                 goto unlock;
742         }
743 
744         /* calculate first part of the client response (CR1) */
745         rc = CalcNTLMv2_response(ses, ntlmv2_hash);
746         if (rc) {
747                 cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
748                 goto unlock;
749         }
750 
751         /* now calculate the session key for NTLMv2 */
752         rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
753                 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
754         if (rc) {
755                 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
756                          __func__);
757                 goto unlock;
758         }
759 
760         rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
761         if (rc) {
762                 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
763                 goto unlock;
764         }
765 
766         rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
767                 ntlmv2->ntlmv2_hash,
768                 CIFS_HMAC_MD5_HASH_SIZE);
769         if (rc) {
770                 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
771                 goto unlock;
772         }
773 
774         rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
775                 ses->auth_key.response);
776         if (rc)
777                 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
778 
779 unlock:
780         mutex_unlock(&ses->server->srv_mutex);
781 setup_ntlmv2_rsp_ret:
782         kfree(tiblob);
783 
784         return rc;
785 }
786 
787 int
788 calc_seckey(struct cifs_ses *ses)
789 {
790         int rc;
791         struct crypto_blkcipher *tfm_arc4;
792         struct scatterlist sgin, sgout;
793         struct blkcipher_desc desc;
794         unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
795 
796         get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
797 
798         tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
799         if (IS_ERR(tfm_arc4)) {
800                 rc = PTR_ERR(tfm_arc4);
801                 cifs_dbg(VFS, "could not allocate crypto API arc4\n");
802                 return rc;
803         }
804 
805         desc.tfm = tfm_arc4;
806 
807         rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
808                                         CIFS_SESS_KEY_SIZE);
809         if (rc) {
810                 cifs_dbg(VFS, "%s: Could not set response as a key\n",
811                          __func__);
812                 return rc;
813         }
814 
815         sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
816         sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
817 
818         rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
819         if (rc) {
820                 cifs_dbg(VFS, "could not encrypt session key rc: %d\n", rc);
821                 crypto_free_blkcipher(tfm_arc4);
822                 return rc;
823         }
824 
825         /* make secondary_key/nonce as session key */
826         memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
827         /* and make len as that of session key only */
828         ses->auth_key.len = CIFS_SESS_KEY_SIZE;
829 
830         crypto_free_blkcipher(tfm_arc4);
831 
832         return rc;
833 }
834 
835 void
836 cifs_crypto_shash_release(struct TCP_Server_Info *server)
837 {
838         if (server->secmech.cmacaes) {
839                 crypto_free_shash(server->secmech.cmacaes);
840                 server->secmech.cmacaes = NULL;
841         }
842 
843         if (server->secmech.hmacsha256) {
844                 crypto_free_shash(server->secmech.hmacsha256);
845                 server->secmech.hmacsha256 = NULL;
846         }
847 
848         if (server->secmech.md5) {
849                 crypto_free_shash(server->secmech.md5);
850                 server->secmech.md5 = NULL;
851         }
852 
853         if (server->secmech.hmacmd5) {
854                 crypto_free_shash(server->secmech.hmacmd5);
855                 server->secmech.hmacmd5 = NULL;
856         }
857 
858         kfree(server->secmech.sdesccmacaes);
859         server->secmech.sdesccmacaes = NULL;
860         kfree(server->secmech.sdeschmacsha256);
861         server->secmech.sdeschmacsha256 = NULL;
862         kfree(server->secmech.sdeschmacmd5);
863         server->secmech.sdeschmacmd5 = NULL;
864         kfree(server->secmech.sdescmd5);
865         server->secmech.sdescmd5 = NULL;
866 }
867 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp