0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/fs.h>
0013 #include <linux/slab.h>
0014 #include "cifspdu.h"
0015 #include "cifsglob.h"
0016 #include "cifs_debug.h"
0017 #include "cifs_unicode.h"
0018 #include "cifsproto.h"
0019 #include "ntlmssp.h"
0020 #include <linux/ctype.h>
0021 #include <linux/random.h>
0022 #include <linux/highmem.h>
0023 #include <linux/fips.h>
0024 #include "../smbfs_common/arc4.h"
0025 #include <crypto/aead.h>
0026
0027 int __cifs_calc_signature(struct smb_rqst *rqst,
0028 struct TCP_Server_Info *server, char *signature,
0029 struct shash_desc *shash)
0030 {
0031 int i;
0032 int rc;
0033 struct kvec *iov = rqst->rq_iov;
0034 int n_vec = rqst->rq_nvec;
0035
0036
0037 if (!is_smb1(server)) {
0038 if (iov[0].iov_len <= 4)
0039 return -EIO;
0040 i = 0;
0041 } else {
0042 if (n_vec < 2 || iov[0].iov_len != 4)
0043 return -EIO;
0044 i = 1;
0045 }
0046
0047 for (; i < n_vec; i++) {
0048 if (iov[i].iov_len == 0)
0049 continue;
0050 if (iov[i].iov_base == NULL) {
0051 cifs_dbg(VFS, "null iovec entry\n");
0052 return -EIO;
0053 }
0054
0055 rc = crypto_shash_update(shash,
0056 iov[i].iov_base, iov[i].iov_len);
0057 if (rc) {
0058 cifs_dbg(VFS, "%s: Could not update with payload\n",
0059 __func__);
0060 return rc;
0061 }
0062 }
0063
0064
0065 for (i = 0; i < rqst->rq_npages; i++) {
0066 void *kaddr;
0067 unsigned int len, offset;
0068
0069 rqst_page_get_length(rqst, i, &len, &offset);
0070
0071 kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
0072
0073 rc = crypto_shash_update(shash, kaddr, len);
0074 if (rc) {
0075 cifs_dbg(VFS, "%s: Could not update with payload\n",
0076 __func__);
0077 kunmap(rqst->rq_pages[i]);
0078 return rc;
0079 }
0080
0081 kunmap(rqst->rq_pages[i]);
0082 }
0083
0084 rc = crypto_shash_final(shash, signature);
0085 if (rc)
0086 cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
0087
0088 return rc;
0089 }
0090
0091
0092
0093
0094
0095
0096
0097
0098 static int cifs_calc_signature(struct smb_rqst *rqst,
0099 struct TCP_Server_Info *server, char *signature)
0100 {
0101 int rc;
0102
0103 if (!rqst->rq_iov || !signature || !server)
0104 return -EINVAL;
0105
0106 rc = cifs_alloc_hash("md5", &server->secmech.md5,
0107 &server->secmech.sdescmd5);
0108 if (rc)
0109 return -1;
0110
0111 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
0112 if (rc) {
0113 cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
0114 return rc;
0115 }
0116
0117 rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
0118 server->session_key.response, server->session_key.len);
0119 if (rc) {
0120 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
0121 return rc;
0122 }
0123
0124 return __cifs_calc_signature(rqst, server, signature,
0125 &server->secmech.sdescmd5->shash);
0126 }
0127
0128
0129 int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
0130 __u32 *pexpected_response_sequence_number)
0131 {
0132 int rc = 0;
0133 char smb_signature[20];
0134 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
0135
0136 if (rqst->rq_iov[0].iov_len != 4 ||
0137 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
0138 return -EIO;
0139
0140 if ((cifs_pdu == NULL) || (server == NULL))
0141 return -EINVAL;
0142
0143 spin_lock(&server->srv_lock);
0144 if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
0145 server->tcpStatus == CifsNeedNegotiate) {
0146 spin_unlock(&server->srv_lock);
0147 return rc;
0148 }
0149 spin_unlock(&server->srv_lock);
0150
0151 if (!server->session_estab) {
0152 memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
0153 return rc;
0154 }
0155
0156 cifs_pdu->Signature.Sequence.SequenceNumber =
0157 cpu_to_le32(server->sequence_number);
0158 cifs_pdu->Signature.Sequence.Reserved = 0;
0159
0160 *pexpected_response_sequence_number = ++server->sequence_number;
0161 ++server->sequence_number;
0162
0163 rc = cifs_calc_signature(rqst, server, smb_signature);
0164 if (rc)
0165 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
0166 else
0167 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
0168
0169 return rc;
0170 }
0171
0172 int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
0173 __u32 *pexpected_response_sequence)
0174 {
0175 struct smb_rqst rqst = { .rq_iov = iov,
0176 .rq_nvec = n_vec };
0177
0178 return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
0179 }
0180
0181
0182 int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
0183 __u32 *pexpected_response_sequence_number)
0184 {
0185 struct kvec iov[2];
0186
0187 iov[0].iov_base = cifs_pdu;
0188 iov[0].iov_len = 4;
0189 iov[1].iov_base = (char *)cifs_pdu + 4;
0190 iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
0191
0192 return cifs_sign_smbv(iov, 2, server,
0193 pexpected_response_sequence_number);
0194 }
0195
0196 int cifs_verify_signature(struct smb_rqst *rqst,
0197 struct TCP_Server_Info *server,
0198 __u32 expected_sequence_number)
0199 {
0200 unsigned int rc;
0201 char server_response_sig[8];
0202 char what_we_think_sig_should_be[20];
0203 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
0204
0205 if (rqst->rq_iov[0].iov_len != 4 ||
0206 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
0207 return -EIO;
0208
0209 if (cifs_pdu == NULL || server == NULL)
0210 return -EINVAL;
0211
0212 if (!server->session_estab)
0213 return 0;
0214
0215 if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
0216 struct smb_com_lock_req *pSMB =
0217 (struct smb_com_lock_req *)cifs_pdu;
0218 if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
0219 return 0;
0220 }
0221
0222
0223
0224
0225
0226 if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
0227 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
0228 cifs_pdu->Command);
0229
0230
0231
0232 memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
0233
0234 cifs_pdu->Signature.Sequence.SequenceNumber =
0235 cpu_to_le32(expected_sequence_number);
0236 cifs_pdu->Signature.Sequence.Reserved = 0;
0237
0238 cifs_server_lock(server);
0239 rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
0240 cifs_server_unlock(server);
0241
0242 if (rc)
0243 return rc;
0244
0245
0246
0247
0248 if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
0249 return -EACCES;
0250 else
0251 return 0;
0252
0253 }
0254
0255
0256
0257
0258
0259
0260 static int
0261 build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
0262 {
0263 unsigned int dlen;
0264 unsigned int size = 2 * sizeof(struct ntlmssp2_name);
0265 char *defdmname = "WORKGROUP";
0266 unsigned char *blobptr;
0267 struct ntlmssp2_name *attrptr;
0268
0269 if (!ses->domainName) {
0270 ses->domainName = kstrdup(defdmname, GFP_KERNEL);
0271 if (!ses->domainName)
0272 return -ENOMEM;
0273 }
0274
0275 dlen = strlen(ses->domainName);
0276
0277
0278
0279
0280
0281
0282
0283 ses->auth_key.len = size + 2 * dlen;
0284 ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
0285 if (!ses->auth_key.response) {
0286 ses->auth_key.len = 0;
0287 return -ENOMEM;
0288 }
0289
0290 blobptr = ses->auth_key.response;
0291 attrptr = (struct ntlmssp2_name *) blobptr;
0292
0293
0294
0295
0296
0297 attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
0298 attrptr->length = cpu_to_le16(2 * dlen);
0299 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
0300 cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
0301
0302 return 0;
0303 }
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315 static int
0316 find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
0317 {
0318 unsigned int attrsize;
0319 unsigned int type;
0320 unsigned int onesize = sizeof(struct ntlmssp2_name);
0321 unsigned char *blobptr;
0322 unsigned char *blobend;
0323 struct ntlmssp2_name *attrptr;
0324
0325 if (!ses->auth_key.len || !ses->auth_key.response)
0326 return 0;
0327
0328 blobptr = ses->auth_key.response;
0329 blobend = blobptr + ses->auth_key.len;
0330
0331 while (blobptr + onesize < blobend) {
0332 attrptr = (struct ntlmssp2_name *) blobptr;
0333 type = le16_to_cpu(attrptr->type);
0334 if (type == NTLMSSP_AV_EOL)
0335 break;
0336 blobptr += 2;
0337 attrsize = le16_to_cpu(attrptr->length);
0338 blobptr += 2;
0339 if (blobptr + attrsize > blobend)
0340 break;
0341 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
0342 if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
0343 break;
0344 if (!ses->domainName) {
0345 ses->domainName =
0346 kmalloc(attrsize + 1, GFP_KERNEL);
0347 if (!ses->domainName)
0348 return -ENOMEM;
0349 cifs_from_utf16(ses->domainName,
0350 (__le16 *)blobptr, attrsize, attrsize,
0351 nls_cp, NO_MAP_UNI_RSVD);
0352 break;
0353 }
0354 }
0355 blobptr += attrsize;
0356 }
0357
0358 return 0;
0359 }
0360
0361
0362
0363
0364
0365
0366
0367 static __le64
0368 find_timestamp(struct cifs_ses *ses)
0369 {
0370 unsigned int attrsize;
0371 unsigned int type;
0372 unsigned int onesize = sizeof(struct ntlmssp2_name);
0373 unsigned char *blobptr;
0374 unsigned char *blobend;
0375 struct ntlmssp2_name *attrptr;
0376 struct timespec64 ts;
0377
0378 if (!ses->auth_key.len || !ses->auth_key.response)
0379 return 0;
0380
0381 blobptr = ses->auth_key.response;
0382 blobend = blobptr + ses->auth_key.len;
0383
0384 while (blobptr + onesize < blobend) {
0385 attrptr = (struct ntlmssp2_name *) blobptr;
0386 type = le16_to_cpu(attrptr->type);
0387 if (type == NTLMSSP_AV_EOL)
0388 break;
0389 blobptr += 2;
0390 attrsize = le16_to_cpu(attrptr->length);
0391 blobptr += 2;
0392 if (blobptr + attrsize > blobend)
0393 break;
0394 if (type == NTLMSSP_AV_TIMESTAMP) {
0395 if (attrsize == sizeof(u64))
0396 return *((__le64 *)blobptr);
0397 }
0398 blobptr += attrsize;
0399 }
0400
0401 ktime_get_real_ts64(&ts);
0402 return cpu_to_le64(cifs_UnixTimeToNT(ts));
0403 }
0404
0405 static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
0406 const struct nls_table *nls_cp)
0407 {
0408 int rc = 0;
0409 int len;
0410 char nt_hash[CIFS_NTHASH_SIZE];
0411 __le16 *user;
0412 wchar_t *domain;
0413 wchar_t *server;
0414
0415 if (!ses->server->secmech.sdeschmacmd5) {
0416 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
0417 return -1;
0418 }
0419
0420
0421 E_md4hash(ses->password, nt_hash, nls_cp);
0422
0423 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
0424 CIFS_NTHASH_SIZE);
0425 if (rc) {
0426 cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
0427 return rc;
0428 }
0429
0430 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
0431 if (rc) {
0432 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
0433 return rc;
0434 }
0435
0436
0437 len = ses->user_name ? strlen(ses->user_name) : 0;
0438 user = kmalloc(2 + (len * 2), GFP_KERNEL);
0439 if (user == NULL) {
0440 rc = -ENOMEM;
0441 return rc;
0442 }
0443
0444 if (len) {
0445 len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
0446 UniStrupr(user);
0447 } else {
0448 memset(user, '\0', 2);
0449 }
0450
0451 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
0452 (char *)user, 2 * len);
0453 kfree(user);
0454 if (rc) {
0455 cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
0456 return rc;
0457 }
0458
0459
0460 if (ses->domainName) {
0461 len = strlen(ses->domainName);
0462
0463 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
0464 if (domain == NULL) {
0465 rc = -ENOMEM;
0466 return rc;
0467 }
0468 len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
0469 nls_cp);
0470 rc =
0471 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
0472 (char *)domain, 2 * len);
0473 kfree(domain);
0474 if (rc) {
0475 cifs_dbg(VFS, "%s: Could not update with domain\n",
0476 __func__);
0477 return rc;
0478 }
0479 } else {
0480
0481 len = strlen(ses->ip_addr);
0482
0483 server = kmalloc(2 + (len * 2), GFP_KERNEL);
0484 if (server == NULL) {
0485 rc = -ENOMEM;
0486 return rc;
0487 }
0488 len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len,
0489 nls_cp);
0490 rc =
0491 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
0492 (char *)server, 2 * len);
0493 kfree(server);
0494 if (rc) {
0495 cifs_dbg(VFS, "%s: Could not update with server\n",
0496 __func__);
0497 return rc;
0498 }
0499 }
0500
0501 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
0502 ntlmv2_hash);
0503 if (rc)
0504 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
0505
0506 return rc;
0507 }
0508
0509 static int
0510 CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
0511 {
0512 int rc;
0513 struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
0514 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
0515 unsigned int hash_len;
0516
0517
0518 hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
0519 offsetof(struct ntlmv2_resp, challenge.key[0]));
0520
0521 if (!ses->server->secmech.sdeschmacmd5) {
0522 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
0523 return -1;
0524 }
0525
0526 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
0527 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
0528 if (rc) {
0529 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
0530 __func__);
0531 return rc;
0532 }
0533
0534 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
0535 if (rc) {
0536 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
0537 return rc;
0538 }
0539
0540 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
0541 memcpy(ntlmv2->challenge.key,
0542 ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
0543 else
0544 memcpy(ntlmv2->challenge.key,
0545 ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
0546 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
0547 ntlmv2->challenge.key, hash_len);
0548 if (rc) {
0549 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
0550 return rc;
0551 }
0552
0553
0554 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
0555 ntlmv2->ntlmv2_hash);
0556 if (rc)
0557 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
0558
0559 return rc;
0560 }
0561
0562 int
0563 setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
0564 {
0565 int rc;
0566 int baselen;
0567 unsigned int tilen;
0568 struct ntlmv2_resp *ntlmv2;
0569 char ntlmv2_hash[16];
0570 unsigned char *tiblob = NULL;
0571 __le64 rsp_timestamp;
0572
0573 if (nls_cp == NULL) {
0574 cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
0575 return -EINVAL;
0576 }
0577
0578 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
0579 if (!ses->domainName) {
0580 if (ses->domainAuto) {
0581 rc = find_domain_name(ses, nls_cp);
0582 if (rc) {
0583 cifs_dbg(VFS, "error %d finding domain name\n",
0584 rc);
0585 goto setup_ntlmv2_rsp_ret;
0586 }
0587 } else {
0588 ses->domainName = kstrdup("", GFP_KERNEL);
0589 }
0590 }
0591 } else {
0592 rc = build_avpair_blob(ses, nls_cp);
0593 if (rc) {
0594 cifs_dbg(VFS, "error %d building av pair blob\n", rc);
0595 goto setup_ntlmv2_rsp_ret;
0596 }
0597 }
0598
0599
0600
0601
0602
0603 rsp_timestamp = find_timestamp(ses);
0604
0605 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
0606 tilen = ses->auth_key.len;
0607 tiblob = ses->auth_key.response;
0608
0609 ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
0610 if (!ses->auth_key.response) {
0611 rc = -ENOMEM;
0612 ses->auth_key.len = 0;
0613 goto setup_ntlmv2_rsp_ret;
0614 }
0615 ses->auth_key.len += baselen;
0616
0617 ntlmv2 = (struct ntlmv2_resp *)
0618 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
0619 ntlmv2->blob_signature = cpu_to_le32(0x00000101);
0620 ntlmv2->reserved = 0;
0621 ntlmv2->time = rsp_timestamp;
0622
0623 get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
0624 ntlmv2->reserved2 = 0;
0625
0626 memcpy(ses->auth_key.response + baselen, tiblob, tilen);
0627
0628 cifs_server_lock(ses->server);
0629
0630 rc = cifs_alloc_hash("hmac(md5)",
0631 &ses->server->secmech.hmacmd5,
0632 &ses->server->secmech.sdeschmacmd5);
0633 if (rc) {
0634 goto unlock;
0635 }
0636
0637
0638 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
0639 if (rc) {
0640 cifs_dbg(VFS, "Could not get v2 hash rc %d\n", rc);
0641 goto unlock;
0642 }
0643
0644
0645 rc = CalcNTLMv2_response(ses, ntlmv2_hash);
0646 if (rc) {
0647 cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
0648 goto unlock;
0649 }
0650
0651
0652 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
0653 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
0654 if (rc) {
0655 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
0656 __func__);
0657 goto unlock;
0658 }
0659
0660 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
0661 if (rc) {
0662 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
0663 goto unlock;
0664 }
0665
0666 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
0667 ntlmv2->ntlmv2_hash,
0668 CIFS_HMAC_MD5_HASH_SIZE);
0669 if (rc) {
0670 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
0671 goto unlock;
0672 }
0673
0674 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
0675 ses->auth_key.response);
0676 if (rc)
0677 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
0678
0679 unlock:
0680 cifs_server_unlock(ses->server);
0681 setup_ntlmv2_rsp_ret:
0682 kfree(tiblob);
0683
0684 return rc;
0685 }
0686
0687 int
0688 calc_seckey(struct cifs_ses *ses)
0689 {
0690 unsigned char sec_key[CIFS_SESS_KEY_SIZE];
0691 struct arc4_ctx *ctx_arc4;
0692
0693 if (fips_enabled)
0694 return -ENODEV;
0695
0696 get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
0697
0698 ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
0699 if (!ctx_arc4) {
0700 cifs_dbg(VFS, "Could not allocate arc4 context\n");
0701 return -ENOMEM;
0702 }
0703
0704 cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
0705 cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
0706 CIFS_CPHTXT_SIZE);
0707
0708
0709 memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
0710
0711 ses->auth_key.len = CIFS_SESS_KEY_SIZE;
0712
0713 memzero_explicit(sec_key, CIFS_SESS_KEY_SIZE);
0714 kfree_sensitive(ctx_arc4);
0715 return 0;
0716 }
0717
0718 void
0719 cifs_crypto_secmech_release(struct TCP_Server_Info *server)
0720 {
0721 if (server->secmech.cmacaes) {
0722 crypto_free_shash(server->secmech.cmacaes);
0723 server->secmech.cmacaes = NULL;
0724 }
0725
0726 if (server->secmech.hmacsha256) {
0727 crypto_free_shash(server->secmech.hmacsha256);
0728 server->secmech.hmacsha256 = NULL;
0729 }
0730
0731 if (server->secmech.md5) {
0732 crypto_free_shash(server->secmech.md5);
0733 server->secmech.md5 = NULL;
0734 }
0735
0736 if (server->secmech.sha512) {
0737 crypto_free_shash(server->secmech.sha512);
0738 server->secmech.sha512 = NULL;
0739 }
0740
0741 if (server->secmech.hmacmd5) {
0742 crypto_free_shash(server->secmech.hmacmd5);
0743 server->secmech.hmacmd5 = NULL;
0744 }
0745
0746 if (server->secmech.ccmaesencrypt) {
0747 crypto_free_aead(server->secmech.ccmaesencrypt);
0748 server->secmech.ccmaesencrypt = NULL;
0749 }
0750
0751 if (server->secmech.ccmaesdecrypt) {
0752 crypto_free_aead(server->secmech.ccmaesdecrypt);
0753 server->secmech.ccmaesdecrypt = NULL;
0754 }
0755
0756 kfree(server->secmech.sdesccmacaes);
0757 server->secmech.sdesccmacaes = NULL;
0758 kfree(server->secmech.sdeschmacsha256);
0759 server->secmech.sdeschmacsha256 = NULL;
0760 kfree(server->secmech.sdeschmacmd5);
0761 server->secmech.sdeschmacmd5 = NULL;
0762 kfree(server->secmech.sdescmd5);
0763 server->secmech.sdescmd5 = NULL;
0764 kfree(server->secmech.sdescsha512);
0765 server->secmech.sdescsha512 = NULL;
0766 }