linux/fs/cifs/smb2transport.c
<<
>>
Prefs
   1/*
   2 *   fs/cifs/smb2transport.c
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2002, 2011
   5 *                 Etersoft, 2012
   6 *   Author(s): Steve French (sfrench@us.ibm.com)
   7 *              Jeremy Allison (jra@samba.org) 2006
   8 *              Pavel Shilovsky (pshilovsky@samba.org) 2012
   9 *
  10 *   This library is free software; you can redistribute it and/or modify
  11 *   it under the terms of the GNU Lesser General Public License as published
  12 *   by the Free Software Foundation; either version 2.1 of the License, or
  13 *   (at your option) any later version.
  14 *
  15 *   This library is distributed in the hope that it will be useful,
  16 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  18 *   the GNU Lesser General Public License for more details.
  19 *
  20 *   You should have received a copy of the GNU Lesser General Public License
  21 *   along with this library; if not, write to the Free Software
  22 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23 */
  24
  25#include <linux/fs.h>
  26#include <linux/list.h>
  27#include <linux/wait.h>
  28#include <linux/net.h>
  29#include <linux/delay.h>
  30#include <linux/uaccess.h>
  31#include <asm/processor.h>
  32#include <linux/mempool.h>
  33#include <linux/highmem.h>
  34#include <crypto/aead.h>
  35#include "smb2pdu.h"
  36#include "cifsglob.h"
  37#include "cifsproto.h"
  38#include "smb2proto.h"
  39#include "cifs_debug.h"
  40#include "smb2status.h"
  41#include "smb2glob.h"
  42
  43static int
  44smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
  45{
  46        int rc;
  47        unsigned int size;
  48
  49        if (server->secmech.sdeschmacsha256 != NULL)
  50                return 0; /* already allocated */
  51
  52        server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
  53        if (IS_ERR(server->secmech.hmacsha256)) {
  54                cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
  55                rc = PTR_ERR(server->secmech.hmacsha256);
  56                server->secmech.hmacsha256 = NULL;
  57                return rc;
  58        }
  59
  60        size = sizeof(struct shash_desc) +
  61                        crypto_shash_descsize(server->secmech.hmacsha256);
  62        server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
  63        if (!server->secmech.sdeschmacsha256) {
  64                crypto_free_shash(server->secmech.hmacsha256);
  65                server->secmech.hmacsha256 = NULL;
  66                return -ENOMEM;
  67        }
  68        server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
  69        server->secmech.sdeschmacsha256->shash.flags = 0x0;
  70
  71        return 0;
  72}
  73
  74static int
  75smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
  76{
  77        unsigned int size;
  78        int rc;
  79
  80        if (server->secmech.sdesccmacaes != NULL)
  81                return 0;  /* already allocated */
  82
  83        rc = smb2_crypto_shash_allocate(server);
  84        if (rc)
  85                return rc;
  86
  87        server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
  88        if (IS_ERR(server->secmech.cmacaes)) {
  89                cifs_dbg(VFS, "could not allocate crypto cmac-aes");
  90                kfree(server->secmech.sdeschmacsha256);
  91                server->secmech.sdeschmacsha256 = NULL;
  92                crypto_free_shash(server->secmech.hmacsha256);
  93                server->secmech.hmacsha256 = NULL;
  94                rc = PTR_ERR(server->secmech.cmacaes);
  95                server->secmech.cmacaes = NULL;
  96                return rc;
  97        }
  98
  99        size = sizeof(struct shash_desc) +
 100                        crypto_shash_descsize(server->secmech.cmacaes);
 101        server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
 102        if (!server->secmech.sdesccmacaes) {
 103                cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
 104                kfree(server->secmech.sdeschmacsha256);
 105                server->secmech.sdeschmacsha256 = NULL;
 106                crypto_free_shash(server->secmech.hmacsha256);
 107                crypto_free_shash(server->secmech.cmacaes);
 108                server->secmech.hmacsha256 = NULL;
 109                server->secmech.cmacaes = NULL;
 110                return -ENOMEM;
 111        }
 112        server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
 113        server->secmech.sdesccmacaes->shash.flags = 0x0;
 114
 115        return 0;
 116}
 117
 118static struct cifs_ses *
 119smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
 120{
 121        struct cifs_ses *ses;
 122
 123        list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
 124                if (ses->Suid != ses_id)
 125                        continue;
 126                return ses;
 127        }
 128
 129        return NULL;
 130}
 131
 132struct cifs_ses *
 133smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
 134{
 135        struct cifs_ses *ses;
 136
 137        spin_lock(&cifs_tcp_ses_lock);
 138        ses = smb2_find_smb_ses_unlocked(server, ses_id);
 139        spin_unlock(&cifs_tcp_ses_lock);
 140
 141        return ses;
 142}
 143
 144static struct cifs_tcon *
 145smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
 146{
 147        struct cifs_tcon *tcon;
 148
 149        list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
 150                if (tcon->tid != tid)
 151                        continue;
 152                ++tcon->tc_count;
 153                return tcon;
 154        }
 155
 156        return NULL;
 157}
 158
 159/*
 160 * Obtain tcon corresponding to the tid in the given
 161 * cifs_ses
 162 */
 163
 164struct cifs_tcon *
 165smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32  tid)
 166{
 167        struct cifs_ses *ses;
 168        struct cifs_tcon *tcon;
 169
 170        spin_lock(&cifs_tcp_ses_lock);
 171        ses = smb2_find_smb_ses_unlocked(server, ses_id);
 172        if (!ses) {
 173                spin_unlock(&cifs_tcp_ses_lock);
 174                return NULL;
 175        }
 176        tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
 177        spin_unlock(&cifs_tcp_ses_lock);
 178
 179        return tcon;
 180}
 181
 182int
 183smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 184{
 185        int rc;
 186        unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
 187        unsigned char *sigptr = smb2_signature;
 188        struct kvec *iov = rqst->rq_iov;
 189        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
 190        struct cifs_ses *ses;
 191
 192        ses = smb2_find_smb_ses(server, shdr->SessionId);
 193        if (!ses) {
 194                cifs_dbg(VFS, "%s: Could not find session\n", __func__);
 195                return 0;
 196        }
 197
 198        memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
 199        memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
 200
 201        rc = smb2_crypto_shash_allocate(server);
 202        if (rc) {
 203                cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__);
 204                return rc;
 205        }
 206
 207        rc = crypto_shash_setkey(server->secmech.hmacsha256,
 208                ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
 209        if (rc) {
 210                cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
 211                return rc;
 212        }
 213
 214        rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
 215        if (rc) {
 216                cifs_dbg(VFS, "%s: Could not init sha256", __func__);
 217                return rc;
 218        }
 219
 220        rc = __cifs_calc_signature(rqst, server, sigptr,
 221                &server->secmech.sdeschmacsha256->shash);
 222
 223        if (!rc)
 224                memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
 225
 226        return rc;
 227}
 228
 229static int generate_key(struct cifs_ses *ses, struct kvec label,
 230                        struct kvec context, __u8 *key, unsigned int key_size)
 231{
 232        unsigned char zero = 0x0;
 233        __u8 i[4] = {0, 0, 0, 1};
 234        __u8 L[4] = {0, 0, 0, 128};
 235        int rc = 0;
 236        unsigned char prfhash[SMB2_HMACSHA256_SIZE];
 237        unsigned char *hashptr = prfhash;
 238
 239        memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
 240        memset(key, 0x0, key_size);
 241
 242        rc = smb3_crypto_shash_allocate(ses->server);
 243        if (rc) {
 244                cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
 245                goto smb3signkey_ret;
 246        }
 247
 248        rc = crypto_shash_setkey(ses->server->secmech.hmacsha256,
 249                ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
 250        if (rc) {
 251                cifs_dbg(VFS, "%s: Could not set with session key\n", __func__);
 252                goto smb3signkey_ret;
 253        }
 254
 255        rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash);
 256        if (rc) {
 257                cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
 258                goto smb3signkey_ret;
 259        }
 260
 261        rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
 262                                i, 4);
 263        if (rc) {
 264                cifs_dbg(VFS, "%s: Could not update with n\n", __func__);
 265                goto smb3signkey_ret;
 266        }
 267
 268        rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
 269                                label.iov_base, label.iov_len);
 270        if (rc) {
 271                cifs_dbg(VFS, "%s: Could not update with label\n", __func__);
 272                goto smb3signkey_ret;
 273        }
 274
 275        rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
 276                                &zero, 1);
 277        if (rc) {
 278                cifs_dbg(VFS, "%s: Could not update with zero\n", __func__);
 279                goto smb3signkey_ret;
 280        }
 281
 282        rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
 283                                context.iov_base, context.iov_len);
 284        if (rc) {
 285                cifs_dbg(VFS, "%s: Could not update with context\n", __func__);
 286                goto smb3signkey_ret;
 287        }
 288
 289        rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
 290                                L, 4);
 291        if (rc) {
 292                cifs_dbg(VFS, "%s: Could not update with L\n", __func__);
 293                goto smb3signkey_ret;
 294        }
 295
 296        rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash,
 297                                hashptr);
 298        if (rc) {
 299                cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
 300                goto smb3signkey_ret;
 301        }
 302
 303        memcpy(key, hashptr, key_size);
 304
 305smb3signkey_ret:
 306        return rc;
 307}
 308
 309struct derivation {
 310        struct kvec label;
 311        struct kvec context;
 312};
 313
 314struct derivation_triplet {
 315        struct derivation signing;
 316        struct derivation encryption;
 317        struct derivation decryption;
 318};
 319
 320static int
 321generate_smb3signingkey(struct cifs_ses *ses,
 322                        const struct derivation_triplet *ptriplet)
 323{
 324        int rc;
 325
 326        rc = generate_key(ses, ptriplet->signing.label,
 327                          ptriplet->signing.context, ses->smb3signingkey,
 328                          SMB3_SIGN_KEY_SIZE);
 329        if (rc)
 330                return rc;
 331
 332        rc = generate_key(ses, ptriplet->encryption.label,
 333                          ptriplet->encryption.context, ses->smb3encryptionkey,
 334                          SMB3_SIGN_KEY_SIZE);
 335        if (rc)
 336                return rc;
 337
 338        return generate_key(ses, ptriplet->decryption.label,
 339                            ptriplet->decryption.context,
 340                            ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);
 341}
 342
 343int
 344generate_smb30signingkey(struct cifs_ses *ses)
 345
 346{
 347        struct derivation_triplet triplet;
 348        struct derivation *d;
 349
 350        d = &triplet.signing;
 351        d->label.iov_base = "SMB2AESCMAC";
 352        d->label.iov_len = 12;
 353        d->context.iov_base = "SmbSign";
 354        d->context.iov_len = 8;
 355
 356        d = &triplet.encryption;
 357        d->label.iov_base = "SMB2AESCCM";
 358        d->label.iov_len = 11;
 359        d->context.iov_base = "ServerIn ";
 360        d->context.iov_len = 10;
 361
 362        d = &triplet.decryption;
 363        d->label.iov_base = "SMB2AESCCM";
 364        d->label.iov_len = 11;
 365        d->context.iov_base = "ServerOut";
 366        d->context.iov_len = 10;
 367
 368        return generate_smb3signingkey(ses, &triplet);
 369}
 370
 371int
 372generate_smb311signingkey(struct cifs_ses *ses)
 373
 374{
 375        struct derivation_triplet triplet;
 376        struct derivation *d;
 377
 378        d = &triplet.signing;
 379        d->label.iov_base = "SMB2AESCMAC";
 380        d->label.iov_len = 12;
 381        d->context.iov_base = "SmbSign";
 382        d->context.iov_len = 8;
 383
 384        d = &triplet.encryption;
 385        d->label.iov_base = "SMB2AESCCM";
 386        d->label.iov_len = 11;
 387        d->context.iov_base = "ServerIn ";
 388        d->context.iov_len = 10;
 389
 390        d = &triplet.decryption;
 391        d->label.iov_base = "SMB2AESCCM";
 392        d->label.iov_len = 11;
 393        d->context.iov_base = "ServerOut";
 394        d->context.iov_len = 10;
 395
 396        return generate_smb3signingkey(ses, &triplet);
 397}
 398
 399int
 400smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 401{
 402        int rc = 0;
 403        unsigned char smb3_signature[SMB2_CMACAES_SIZE];
 404        unsigned char *sigptr = smb3_signature;
 405        struct kvec *iov = rqst->rq_iov;
 406        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
 407        struct cifs_ses *ses;
 408
 409        ses = smb2_find_smb_ses(server, shdr->SessionId);
 410        if (!ses) {
 411                cifs_dbg(VFS, "%s: Could not find session\n", __func__);
 412                return 0;
 413        }
 414
 415        memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
 416        memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
 417
 418        rc = crypto_shash_setkey(server->secmech.cmacaes,
 419                ses->smb3signingkey, SMB2_CMACAES_SIZE);
 420
 421        if (rc) {
 422                cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
 423                return rc;
 424        }
 425
 426        /*
 427         * we already allocate sdesccmacaes when we init smb3 signing key,
 428         * so unlike smb2 case we do not have to check here if secmech are
 429         * initialized
 430         */
 431        rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
 432        if (rc) {
 433                cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
 434                return rc;
 435        }
 436        
 437        rc = __cifs_calc_signature(rqst, server, sigptr,
 438                                   &server->secmech.sdesccmacaes->shash);
 439
 440        if (!rc)
 441                memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
 442
 443        return rc;
 444}
 445
 446/* must be called with server->srv_mutex held */
 447static int
 448smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 449{
 450        int rc = 0;
 451        struct smb2_sync_hdr *shdr =
 452                        (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
 453
 454        if (!(shdr->Flags & SMB2_FLAGS_SIGNED) ||
 455            server->tcpStatus == CifsNeedNegotiate)
 456                return rc;
 457
 458        if (!server->session_estab) {
 459                strncpy(shdr->Signature, "BSRSPYL", 8);
 460                return rc;
 461        }
 462
 463        rc = server->ops->calc_signature(rqst, server);
 464
 465        return rc;
 466}
 467
 468int
 469smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 470{
 471        unsigned int rc;
 472        char server_response_sig[16];
 473        struct smb2_sync_hdr *shdr =
 474                        (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
 475
 476        if ((shdr->Command == SMB2_NEGOTIATE) ||
 477            (shdr->Command == SMB2_SESSION_SETUP) ||
 478            (shdr->Command == SMB2_OPLOCK_BREAK) ||
 479            (!server->session_estab))
 480                return 0;
 481
 482        /*
 483         * BB what if signatures are supposed to be on for session but
 484         * server does not send one? BB
 485         */
 486
 487        /* Do not need to verify session setups with signature "BSRSPYL " */
 488        if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
 489                cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
 490                         shdr->Command);
 491
 492        /*
 493         * Save off the origiginal signature so we can modify the smb and check
 494         * our calculated signature against what the server sent.
 495         */
 496        memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
 497
 498        memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
 499
 500        mutex_lock(&server->srv_mutex);
 501        rc = server->ops->calc_signature(rqst, server);
 502        mutex_unlock(&server->srv_mutex);
 503
 504        if (rc)
 505                return rc;
 506
 507        if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE))
 508                return -EACCES;
 509        else
 510                return 0;
 511}
 512
 513/*
 514 * Set message id for the request. Should be called after wait_for_free_request
 515 * and when srv_mutex is held.
 516 */
 517static inline void
 518smb2_seq_num_into_buf(struct TCP_Server_Info *server,
 519                      struct smb2_sync_hdr *shdr)
 520{
 521        unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
 522
 523        shdr->MessageId = get_next_mid64(server);
 524        /* skip message numbers according to CreditCharge field */
 525        for (i = 1; i < num; i++)
 526                get_next_mid(server);
 527}
 528
 529static struct mid_q_entry *
 530smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
 531                     struct TCP_Server_Info *server)
 532{
 533        struct mid_q_entry *temp;
 534
 535        if (server == NULL) {
 536                cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
 537                return NULL;
 538        }
 539
 540        temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
 541        if (temp == NULL)
 542                return temp;
 543        else {
 544                memset(temp, 0, sizeof(struct mid_q_entry));
 545                temp->mid = le64_to_cpu(shdr->MessageId);
 546                temp->pid = current->pid;
 547                temp->command = shdr->Command; /* Always LE */
 548                temp->when_alloc = jiffies;
 549                temp->server = server;
 550
 551                /*
 552                 * The default is for the mid to be synchronous, so the
 553                 * default callback just wakes up the current task.
 554                 */
 555                temp->callback = cifs_wake_up_task;
 556                temp->callback_data = current;
 557        }
 558
 559        atomic_inc(&midCount);
 560        temp->mid_state = MID_REQUEST_ALLOCATED;
 561        return temp;
 562}
 563
 564static int
 565smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_sync_hdr *shdr,
 566                   struct mid_q_entry **mid)
 567{
 568        if (ses->server->tcpStatus == CifsExiting)
 569                return -ENOENT;
 570
 571        if (ses->server->tcpStatus == CifsNeedReconnect) {
 572                cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
 573                return -EAGAIN;
 574        }
 575
 576        if (ses->status == CifsNew) {
 577                if ((shdr->Command != SMB2_SESSION_SETUP) &&
 578                    (shdr->Command != SMB2_NEGOTIATE))
 579                        return -EAGAIN;
 580                /* else ok - we are setting up session */
 581        }
 582
 583        if (ses->status == CifsExiting) {
 584                if (shdr->Command != SMB2_LOGOFF)
 585                        return -EAGAIN;
 586                /* else ok - we are shutting down the session */
 587        }
 588
 589        *mid = smb2_mid_entry_alloc(shdr, ses->server);
 590        if (*mid == NULL)
 591                return -ENOMEM;
 592        spin_lock(&GlobalMid_Lock);
 593        list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
 594        spin_unlock(&GlobalMid_Lock);
 595        return 0;
 596}
 597
 598int
 599smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 600                   bool log_error)
 601{
 602        unsigned int len = get_rfc1002_length(mid->resp_buf);
 603        struct kvec iov[2];
 604        struct smb_rqst rqst = { .rq_iov = iov,
 605                                 .rq_nvec = 2 };
 606
 607        iov[0].iov_base = (char *)mid->resp_buf;
 608        iov[0].iov_len = 4;
 609        iov[1].iov_base = (char *)mid->resp_buf + 4;
 610        iov[1].iov_len = len;
 611
 612        dump_smb(mid->resp_buf, min_t(u32, 80, len));
 613        /* convert the length into a more usable form */
 614        if (len > 24 && server->sign && !mid->decrypted) {
 615                int rc;
 616
 617                rc = smb2_verify_signature(&rqst, server);
 618                if (rc)
 619                        cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
 620                                 rc);
 621        }
 622
 623        return map_smb2_to_linux_error(mid->resp_buf, log_error);
 624}
 625
 626struct mid_q_entry *
 627smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
 628{
 629        int rc;
 630        struct smb2_sync_hdr *shdr =
 631                        (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
 632        struct mid_q_entry *mid;
 633
 634        smb2_seq_num_into_buf(ses->server, shdr);
 635
 636        rc = smb2_get_mid_entry(ses, shdr, &mid);
 637        if (rc)
 638                return ERR_PTR(rc);
 639        rc = smb2_sign_rqst(rqst, ses->server);
 640        if (rc) {
 641                cifs_delete_mid(mid);
 642                return ERR_PTR(rc);
 643        }
 644        return mid;
 645}
 646
 647struct mid_q_entry *
 648smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 649{
 650        int rc;
 651        struct smb2_sync_hdr *shdr =
 652                        (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
 653        struct mid_q_entry *mid;
 654
 655        smb2_seq_num_into_buf(server, shdr);
 656
 657        mid = smb2_mid_entry_alloc(shdr, server);
 658        if (mid == NULL)
 659                return ERR_PTR(-ENOMEM);
 660
 661        rc = smb2_sign_rqst(rqst, server);
 662        if (rc) {
 663                DeleteMidQEntry(mid);
 664                return ERR_PTR(rc);
 665        }
 666
 667        return mid;
 668}
 669
 670int
 671smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
 672{
 673        struct crypto_aead *tfm;
 674
 675        if (!server->secmech.ccmaesencrypt) {
 676                tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
 677                if (IS_ERR(tfm)) {
 678                        cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
 679                                 __func__);
 680                        return PTR_ERR(tfm);
 681                }
 682                server->secmech.ccmaesencrypt = tfm;
 683        }
 684
 685        if (!server->secmech.ccmaesdecrypt) {
 686                tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
 687                if (IS_ERR(tfm)) {
 688                        crypto_free_aead(server->secmech.ccmaesencrypt);
 689                        server->secmech.ccmaesencrypt = NULL;
 690                        cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
 691                                 __func__);
 692                        return PTR_ERR(tfm);
 693                }
 694                server->secmech.ccmaesdecrypt = tfm;
 695        }
 696
 697        return 0;
 698}
 699