linux/fs/cifs/cifsencrypt.c
<<
>>
Prefs
   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
  34static int
  35cifs_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 */
  72static 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 */
 149int 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
 184int 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 */
 194int 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
 206int 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 */
 262int 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
 301int 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];
 307
 308        memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
 309        if (password)
 310                strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
 311
 312        if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) {
 313                memcpy(lnm_session_key, password_with_pad,
 314                        CIFS_ENCPWD_SIZE);
 315                return 0;
 316        }
 317
 318        /* calculate old style session key */
 319        /* calling toupper is less broken than repeatedly
 320        calling nls_toupper would be since that will never
 321        work for UTF8, but neither handles multibyte code pages
 322        but the only alternative would be converting to UCS-16 (Unicode)
 323        (using a routine something like UniStrupr) then
 324        uppercasing and then converting back from Unicode - which
 325        would only worth doing it if we knew it were utf8. Basically
 326        utf8 and other multibyte codepages each need their own strupper
 327        function since a byte at a time will ont work. */
 328
 329        for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
 330                password_with_pad[i] = toupper(password_with_pad[i]);
 331
 332        rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key);
 333
 334        return rc;
 335}
 336#endif /* CIFS_WEAK_PW_HASH */
 337
 338/* Build a proper attribute value/target info pairs blob.
 339 * Fill in netbios and dns domain name and workstation name
 340 * and client time (total five av pairs and + one end of fields indicator.
 341 * Allocate domain name which gets freed when session struct is deallocated.
 342 */
 343static int
 344build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
 345{
 346        unsigned int dlen;
 347        unsigned int size = 2 * sizeof(struct ntlmssp2_name);
 348        char *defdmname = "WORKGROUP";
 349        unsigned char *blobptr;
 350        struct ntlmssp2_name *attrptr;
 351
 352        if (!ses->domainName) {
 353                ses->domainName = kstrdup(defdmname, GFP_KERNEL);
 354                if (!ses->domainName)
 355                        return -ENOMEM;
 356        }
 357
 358        dlen = strlen(ses->domainName);
 359
 360        /*
 361         * The length of this blob is two times the size of a
 362         * structure (av pair) which holds name/size
 363         * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
 364         * unicode length of a netbios domain name
 365         */
 366        ses->auth_key.len = size + 2 * dlen;
 367        ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
 368        if (!ses->auth_key.response) {
 369                ses->auth_key.len = 0;
 370                return -ENOMEM;
 371        }
 372
 373        blobptr = ses->auth_key.response;
 374        attrptr = (struct ntlmssp2_name *) blobptr;
 375
 376        /*
 377         * As defined in MS-NTLM 3.3.2, just this av pair field
 378         * is sufficient as part of the temp
 379         */
 380        attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
 381        attrptr->length = cpu_to_le16(2 * dlen);
 382        blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
 383        cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
 384
 385        return 0;
 386}
 387
 388/* Server has provided av pairs/target info in the type 2 challenge
 389 * packet and we have plucked it and stored within smb session.
 390 * We parse that blob here to find netbios domain name to be used
 391 * as part of ntlmv2 authentication (in Target String), if not already
 392 * specified on the command line.
 393 * If this function returns without any error but without fetching
 394 * domain name, authentication may fail against some server but
 395 * may not fail against other (those who are not very particular
 396 * about target string i.e. for some, just user name might suffice.
 397 */
 398static int
 399find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
 400{
 401        unsigned int attrsize;
 402        unsigned int type;
 403        unsigned int onesize = sizeof(struct ntlmssp2_name);
 404        unsigned char *blobptr;
 405        unsigned char *blobend;
 406        struct ntlmssp2_name *attrptr;
 407
 408        if (!ses->auth_key.len || !ses->auth_key.response)
 409                return 0;
 410
 411        blobptr = ses->auth_key.response;
 412        blobend = blobptr + ses->auth_key.len;
 413
 414        while (blobptr + onesize < blobend) {
 415                attrptr = (struct ntlmssp2_name *) blobptr;
 416                type = le16_to_cpu(attrptr->type);
 417                if (type == NTLMSSP_AV_EOL)
 418                        break;
 419                blobptr += 2; /* advance attr type */
 420                attrsize = le16_to_cpu(attrptr->length);
 421                blobptr += 2; /* advance attr size */
 422                if (blobptr + attrsize > blobend)
 423                        break;
 424                if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
 425                        if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
 426                                break;
 427                        if (!ses->domainName) {
 428                                ses->domainName =
 429                                        kmalloc(attrsize + 1, GFP_KERNEL);
 430                                if (!ses->domainName)
 431                                                return -ENOMEM;
 432                                cifs_from_utf16(ses->domainName,
 433                                        (__le16 *)blobptr, attrsize, attrsize,
 434                                        nls_cp, false);
 435                                break;
 436                        }
 437                }
 438                blobptr += attrsize; /* advance attr  value */
 439        }
 440
 441        return 0;
 442}
 443
 444static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 445                            const struct nls_table *nls_cp)
 446{
 447        int rc = 0;
 448        int len;
 449        char nt_hash[CIFS_NTHASH_SIZE];
 450        __le16 *user;
 451        wchar_t *domain;
 452        wchar_t *server;
 453
 454        if (!ses->server->secmech.sdeschmacmd5) {
 455                cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
 456                return -1;
 457        }
 458
 459        /* calculate md4 hash of password */
 460        E_md4hash(ses->password, nt_hash, nls_cp);
 461
 462        rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
 463                                CIFS_NTHASH_SIZE);
 464        if (rc) {
 465                cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
 466                return rc;
 467        }
 468
 469        rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 470        if (rc) {
 471                cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
 472                return rc;
 473        }
 474
 475        /* convert ses->user_name to unicode */
 476        len = ses->user_name ? strlen(ses->user_name) : 0;
 477        user = kmalloc(2 + (len * 2), GFP_KERNEL);
 478        if (user == NULL) {
 479                rc = -ENOMEM;
 480                return rc;
 481        }
 482
 483        if (len) {
 484                len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
 485                UniStrupr(user);
 486        } else {
 487                memset(user, '\0', 2);
 488        }
 489
 490        rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 491                                (char *)user, 2 * len);
 492        kfree(user);
 493        if (rc) {
 494                cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
 495                return rc;
 496        }
 497
 498        /* convert ses->domainName to unicode and uppercase */
 499        if (ses->domainName) {
 500                len = strlen(ses->domainName);
 501
 502                domain = kmalloc(2 + (len * 2), GFP_KERNEL);
 503                if (domain == NULL) {
 504                        rc = -ENOMEM;
 505                        return rc;
 506                }
 507                len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
 508                                      nls_cp);
 509                rc =
 510                crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 511                                        (char *)domain, 2 * len);
 512                kfree(domain);
 513                if (rc) {
 514                        cifs_dbg(VFS, "%s: Could not update with domain\n",
 515                                 __func__);
 516                        return rc;
 517                }
 518        } else if (ses->serverName) {
 519                len = strlen(ses->serverName);
 520
 521                server = kmalloc(2 + (len * 2), GFP_KERNEL);
 522                if (server == NULL) {
 523                        rc = -ENOMEM;
 524                        return rc;
 525                }
 526                len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
 527                                        nls_cp);
 528                rc =
 529                crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 530                                        (char *)server, 2 * len);
 531                kfree(server);
 532                if (rc) {
 533                        cifs_dbg(VFS, "%s: Could not update with server\n",
 534                                 __func__);
 535                        return rc;
 536                }
 537        }
 538
 539        rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
 540                                        ntlmv2_hash);
 541        if (rc)
 542                cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 543
 544        return rc;
 545}
 546
 547static int
 548CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
 549{
 550        int rc;
 551        unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
 552
 553        if (!ses->server->secmech.sdeschmacmd5) {
 554                cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
 555                return -1;
 556        }
 557
 558        rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
 559                                ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
 560        if (rc) {
 561                cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
 562                         __func__);
 563                return rc;
 564        }
 565
 566        rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 567        if (rc) {
 568                cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__);
 569                return rc;
 570        }
 571
 572        if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
 573                memcpy(ses->auth_key.response + offset,
 574                        ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
 575        else
 576                memcpy(ses->auth_key.response + offset,
 577                        ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
 578        rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 579                ses->auth_key.response + offset, ses->auth_key.len - offset);
 580        if (rc) {
 581                cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
 582                return rc;
 583        }
 584
 585        rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
 586                ses->auth_key.response + CIFS_SESS_KEY_SIZE);
 587        if (rc)
 588                cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 589
 590        return rc;
 591}
 592
 593static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
 594{
 595        int rc;
 596        unsigned int size;
 597
 598        /* check if already allocated */
 599        if (server->secmech.sdeschmacmd5)
 600                return 0;
 601
 602        server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
 603        if (IS_ERR(server->secmech.hmacmd5)) {
 604                cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
 605                rc = PTR_ERR(server->secmech.hmacmd5);
 606                server->secmech.hmacmd5 = NULL;
 607                return rc;
 608        }
 609
 610        size = sizeof(struct shash_desc) +
 611                        crypto_shash_descsize(server->secmech.hmacmd5);
 612        server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
 613        if (!server->secmech.sdeschmacmd5) {
 614                crypto_free_shash(server->secmech.hmacmd5);
 615                server->secmech.hmacmd5 = NULL;
 616                return -ENOMEM;
 617        }
 618        server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
 619        server->secmech.sdeschmacmd5->shash.flags = 0x0;
 620
 621        return 0;
 622}
 623
 624int
 625setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 626{
 627        int rc;
 628        int baselen;
 629        unsigned int tilen;
 630        struct ntlmv2_resp *buf;
 631        char ntlmv2_hash[16];
 632        unsigned char *tiblob = NULL; /* target info blob */
 633
 634        if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
 635                if (!ses->domainName) {
 636                        rc = find_domain_name(ses, nls_cp);
 637                        if (rc) {
 638                                cifs_dbg(VFS, "error %d finding domain name\n",
 639                                         rc);
 640                                goto setup_ntlmv2_rsp_ret;
 641                        }
 642                }
 643        } else {
 644                rc = build_avpair_blob(ses, nls_cp);
 645                if (rc) {
 646                        cifs_dbg(VFS, "error %d building av pair blob\n", rc);
 647                        goto setup_ntlmv2_rsp_ret;
 648                }
 649        }
 650
 651        baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
 652        tilen = ses->auth_key.len;
 653        tiblob = ses->auth_key.response;
 654
 655        ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
 656        if (!ses->auth_key.response) {
 657                rc = ENOMEM;
 658                ses->auth_key.len = 0;
 659                goto setup_ntlmv2_rsp_ret;
 660        }
 661        ses->auth_key.len += baselen;
 662
 663        buf = (struct ntlmv2_resp *)
 664                        (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
 665        buf->blob_signature = cpu_to_le32(0x00000101);
 666        buf->reserved = 0;
 667        buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
 668        get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
 669        buf->reserved2 = 0;
 670
 671        memcpy(ses->auth_key.response + baselen, tiblob, tilen);
 672
 673        rc = crypto_hmacmd5_alloc(ses->server);
 674        if (rc) {
 675                cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
 676                goto setup_ntlmv2_rsp_ret;
 677        }
 678
 679        /* calculate ntlmv2_hash */
 680        rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
 681        if (rc) {
 682                cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
 683                goto setup_ntlmv2_rsp_ret;
 684        }
 685
 686        /* calculate first part of the client response (CR1) */
 687        rc = CalcNTLMv2_response(ses, ntlmv2_hash);
 688        if (rc) {
 689                cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
 690                goto setup_ntlmv2_rsp_ret;
 691        }
 692
 693        /* now calculate the session key for NTLMv2 */
 694        rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
 695                ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
 696        if (rc) {
 697                cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
 698                         __func__);
 699                goto setup_ntlmv2_rsp_ret;
 700        }
 701
 702        rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 703        if (rc) {
 704                cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
 705                goto setup_ntlmv2_rsp_ret;
 706        }
 707
 708        rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 709                ses->auth_key.response + CIFS_SESS_KEY_SIZE,
 710                CIFS_HMAC_MD5_HASH_SIZE);
 711        if (rc) {
 712                cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
 713                goto setup_ntlmv2_rsp_ret;
 714        }
 715
 716        rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
 717                ses->auth_key.response);
 718        if (rc)
 719                cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 720
 721setup_ntlmv2_rsp_ret:
 722        kfree(tiblob);
 723
 724        return rc;
 725}
 726
 727int
 728calc_seckey(struct cifs_ses *ses)
 729{
 730        int rc;
 731        struct crypto_blkcipher *tfm_arc4;
 732        struct scatterlist sgin, sgout;
 733        struct blkcipher_desc desc;
 734        unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
 735
 736        get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
 737
 738        tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
 739        if (IS_ERR(tfm_arc4)) {
 740                rc = PTR_ERR(tfm_arc4);
 741                cifs_dbg(VFS, "could not allocate crypto API arc4\n");
 742                return rc;
 743        }
 744
 745        desc.tfm = tfm_arc4;
 746
 747        rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
 748                                        CIFS_SESS_KEY_SIZE);
 749        if (rc) {
 750                cifs_dbg(VFS, "%s: Could not set response as a key\n",
 751                         __func__);
 752                return rc;
 753        }
 754
 755        sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
 756        sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
 757
 758        rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
 759        if (rc) {
 760                cifs_dbg(VFS, "could not encrypt session key rc: %d\n", rc);
 761                crypto_free_blkcipher(tfm_arc4);
 762                return rc;
 763        }
 764
 765        /* make secondary_key/nonce as session key */
 766        memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
 767        /* and make len as that of session key only */
 768        ses->auth_key.len = CIFS_SESS_KEY_SIZE;
 769
 770        crypto_free_blkcipher(tfm_arc4);
 771
 772        return rc;
 773}
 774
 775void
 776cifs_crypto_shash_release(struct TCP_Server_Info *server)
 777{
 778        if (server->secmech.cmacaes) {
 779                crypto_free_shash(server->secmech.cmacaes);
 780                server->secmech.cmacaes = NULL;
 781        }
 782
 783        if (server->secmech.hmacsha256) {
 784                crypto_free_shash(server->secmech.hmacsha256);
 785                server->secmech.hmacsha256 = NULL;
 786        }
 787
 788        if (server->secmech.md5) {
 789                crypto_free_shash(server->secmech.md5);
 790                server->secmech.md5 = NULL;
 791        }
 792
 793        if (server->secmech.hmacmd5) {
 794                crypto_free_shash(server->secmech.hmacmd5);
 795                server->secmech.hmacmd5 = NULL;
 796        }
 797
 798        kfree(server->secmech.sdesccmacaes);
 799        server->secmech.sdesccmacaes = NULL;
 800        kfree(server->secmech.sdeschmacsha256);
 801        server->secmech.sdeschmacsha256 = NULL;
 802        kfree(server->secmech.sdeschmacmd5);
 803        server->secmech.sdeschmacmd5 = NULL;
 804        kfree(server->secmech.sdescmd5);
 805        server->secmech.sdescmd5 = NULL;
 806}
 807
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.