blob: 6679e07e533e8504981a1d6af211e270b2a3afff [file] [log] [blame]
Steve French929be902021-06-18 00:31:49 -05001// SPDX-License-Identifier: LGPL-2.1
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * fs/cifs/cifsencrypt.c
4 *
Steve French8b7a4542015-03-30 16:58:17 -05005 * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP
6 * for more detailed information
7 *
Steve French95dc8dd2013-07-04 10:35:21 -05008 * Copyright (C) International Business Machines Corp., 2005,2013
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * Author(s): Steve French (sfrench@us.ibm.com)
10 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
12
13#include <linux/fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090014#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include "cifspdu.h"
Steve Frenchffdd6e42007-06-24 21:15:44 +000016#include "cifsglob.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include "cifs_debug.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include "cifs_unicode.h"
19#include "cifsproto.h"
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -050020#include "ntlmssp.h"
Steve French7c7b25b2006-06-01 19:20:10 +000021#include <linux/ctype.h>
Steve French6d027cf2006-06-05 16:26:05 +000022#include <linux/random.h>
Jeff Laytonfb308a62012-09-18 16:20:35 -070023#include <linux/highmem.h>
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +020024#include <linux/fips.h>
Ronnie Sahlberg71c02862021-08-19 20:34:59 +100025#include "../cifs_common/arc4.h"
Pavel Shilovsky026e93d2016-11-03 16:47:37 -070026#include <crypto/aead.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Al Viro16c568e2015-11-12 22:46:49 -050028int __cifs_calc_signature(struct smb_rqst *rqst,
29 struct TCP_Server_Info *server, char *signature,
30 struct shash_desc *shash)
31{
32 int i;
33 int rc;
34 struct kvec *iov = rqst->rq_iov;
35 int n_vec = rqst->rq_nvec;
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100036 int is_smb2 = server->vals->header_preamble_size == 0;
Al Viro16c568e2015-11-12 22:46:49 -050037
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100038 /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
39 if (is_smb2) {
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030040 if (iov[0].iov_len <= 4)
41 return -EIO;
42 i = 0;
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100043 } else {
44 if (n_vec < 2 || iov[0].iov_len != 4)
45 return -EIO;
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030046 i = 1; /* skip rfc1002 length */
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100047 }
48
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030049 for (; i < n_vec; i++) {
Al Viro16c568e2015-11-12 22:46:49 -050050 if (iov[i].iov_len == 0)
51 continue;
52 if (iov[i].iov_base == NULL) {
53 cifs_dbg(VFS, "null iovec entry\n");
54 return -EIO;
55 }
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030056
Pavel Shilovsky738f9de2016-11-23 15:14:57 -080057 rc = crypto_shash_update(shash,
58 iov[i].iov_base, iov[i].iov_len);
Al Viro16c568e2015-11-12 22:46:49 -050059 if (rc) {
60 cifs_dbg(VFS, "%s: Could not update with payload\n",
61 __func__);
62 return rc;
63 }
64 }
65
66 /* now hash over the rq_pages array */
67 for (i = 0; i < rqst->rq_npages; i++) {
Long Li4c0d2a52018-05-30 12:48:03 -070068 void *kaddr;
69 unsigned int len, offset;
Al Viro16c568e2015-11-12 22:46:49 -050070
Long Li4c0d2a52018-05-30 12:48:03 -070071 rqst_page_get_length(rqst, i, &len, &offset);
72
73 kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
Al Viro16c568e2015-11-12 22:46:49 -050074
Paulo Alcantaraa12d0c52018-06-23 14:52:25 -030075 rc = crypto_shash_update(shash, kaddr, len);
76 if (rc) {
77 cifs_dbg(VFS, "%s: Could not update with payload\n",
78 __func__);
79 kunmap(rqst->rq_pages[i]);
80 return rc;
81 }
Al Viro16c568e2015-11-12 22:46:49 -050082
83 kunmap(rqst->rq_pages[i]);
84 }
85
86 rc = crypto_shash_final(shash, signature);
87 if (rc)
88 cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
89
90 return rc;
91}
92
Jeff Layton157c2492011-04-02 07:34:30 -040093/*
94 * Calculate and return the CIFS signature based on the mac key and SMB PDU.
95 * The 16 byte signature must be allocated by the caller. Note we only use the
96 * 1st eight bytes and that the smb header signature field on input contains
97 * the sequence number before this function is called. Also, this function
98 * should be called with the server->srv_mutex held.
99 */
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700100static int cifs_calc_signature(struct smb_rqst *rqst,
Jeff Layton826a95e2011-10-11 06:41:32 -0400101 struct TCP_Server_Info *server, char *signature)
Steve French84afc292005-12-02 13:32:45 -0800102{
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500103 int rc;
Steve French84afc292005-12-02 13:32:45 -0800104
Al Viro16c568e2015-11-12 22:46:49 -0500105 if (!rqst->rq_iov || !signature || !server)
Steve Frenche9917a02006-03-31 21:22:00 +0000106 return -EINVAL;
Steve French84afc292005-12-02 13:32:45 -0800107
Aurelien Aptel82fb82b2018-02-16 19:19:27 +0100108 rc = cifs_alloc_hash("md5", &server->secmech.md5,
109 &server->secmech.sdescmd5);
110 if (rc)
111 return -1;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500112
113 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
114 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500115 cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500116 return rc;
117 }
118
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500119 rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500120 server->session_key.response, server->session_key.len);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500121 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500122 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500123 return rc;
124 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500125
Ronnie Sahlbergc713c872018-06-12 08:00:58 +1000126 return __cifs_calc_signature(rqst, server, signature,
Al Viro16c568e2015-11-12 22:46:49 -0500127 &server->secmech.sdescmd5->shash);
Steve French84afc292005-12-02 13:32:45 -0800128}
129
Jeff Laytona0f8b4f2011-01-07 11:30:28 -0500130/* must be called with server->srv_mutex held */
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700131int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
Steve French63d25832007-11-05 21:46:10 +0000132 __u32 *pexpected_response_sequence_number)
Steve French84afc292005-12-02 13:32:45 -0800133{
134 int rc = 0;
135 char smb_signature[20];
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700136 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
Steve French84afc292005-12-02 13:32:45 -0800137
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800138 if (rqst->rq_iov[0].iov_len != 4 ||
139 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
140 return -EIO;
141
Steve Frenchffdd6e42007-06-24 21:15:44 +0000142 if ((cifs_pdu == NULL) || (server == NULL))
Steve French84afc292005-12-02 13:32:45 -0800143 return -EINVAL;
144
Jeff Layton998d6fc2011-07-26 12:21:17 -0400145 if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
146 server->tcpStatus == CifsNeedNegotiate)
Steve French84afc292005-12-02 13:32:45 -0800147 return rc;
148
Jeff Layton998d6fc2011-07-26 12:21:17 -0400149 if (!server->session_estab) {
Jeff Laytonb4dacbc2011-10-11 06:41:32 -0400150 memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
Jeff Layton998d6fc2011-07-26 12:21:17 -0400151 return rc;
152 }
153
Steve Frenchffdd6e42007-06-24 21:15:44 +0000154 cifs_pdu->Signature.Sequence.SequenceNumber =
Steve French84afc292005-12-02 13:32:45 -0800155 cpu_to_le32(server->sequence_number);
Steve Frenchffdd6e42007-06-24 21:15:44 +0000156 cifs_pdu->Signature.Sequence.Reserved = 0;
Steve French84afc292005-12-02 13:32:45 -0800157
Jeff Layton0124cc42013-04-03 11:55:03 -0400158 *pexpected_response_sequence_number = ++server->sequence_number;
159 ++server->sequence_number;
Steve French84afc292005-12-02 13:32:45 -0800160
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700161 rc = cifs_calc_signature(rqst, server, smb_signature);
Steve Frenchffdd6e42007-06-24 21:15:44 +0000162 if (rc)
163 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
164 else
165 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
Steve French84afc292005-12-02 13:32:45 -0800166
Steve Frenchffdd6e42007-06-24 21:15:44 +0000167 return rc;
Steve French84afc292005-12-02 13:32:45 -0800168}
169
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700170int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
171 __u32 *pexpected_response_sequence)
172{
173 struct smb_rqst rqst = { .rq_iov = iov,
174 .rq_nvec = n_vec };
175
176 return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
177}
178
Jeff Layton826a95e2011-10-11 06:41:32 -0400179/* must be called with server->srv_mutex held */
180int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
181 __u32 *pexpected_response_sequence_number)
182{
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800183 struct kvec iov[2];
Jeff Layton826a95e2011-10-11 06:41:32 -0400184
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800185 iov[0].iov_base = cifs_pdu;
186 iov[0].iov_len = 4;
187 iov[1].iov_base = (char *)cifs_pdu + 4;
188 iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
Jeff Layton826a95e2011-10-11 06:41:32 -0400189
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800190 return cifs_sign_smbv(iov, 2, server,
Jeff Layton826a95e2011-10-11 06:41:32 -0400191 pexpected_response_sequence_number);
192}
193
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700194int cifs_verify_signature(struct smb_rqst *rqst,
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500195 struct TCP_Server_Info *server,
Steve Frenchffdd6e42007-06-24 21:15:44 +0000196 __u32 expected_sequence_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197{
Steve Frenchc8e56f12010-09-08 21:10:58 +0000198 unsigned int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 char server_response_sig[8];
200 char what_we_think_sig_should_be[20];
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700201 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800203 if (rqst->rq_iov[0].iov_len != 4 ||
204 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
205 return -EIO;
206
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500207 if (cifs_pdu == NULL || server == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 return -EINVAL;
209
Jeff Layton9c4843e2011-06-06 15:40:23 -0400210 if (!server->session_estab)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 return 0;
212
213 if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
Steve French50c2f752007-07-13 00:33:32 +0000214 struct smb_com_lock_req *pSMB =
Steve Frenchffdd6e42007-06-24 21:15:44 +0000215 (struct smb_com_lock_req *)cifs_pdu;
Colin Ian King58902552018-11-03 15:59:44 +0000216 if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 return 0;
218 }
219
Steve French50c2f752007-07-13 00:33:32 +0000220 /* BB what if signatures are supposed to be on for session but
221 server does not send one? BB */
222
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 /* Do not need to verify session setups with signature "BSRSPYL " */
Steve French50c2f752007-07-13 00:33:32 +0000224 if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
Joe Perchesf96637b2013-05-04 22:12:25 -0500225 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
226 cifs_pdu->Command);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228 /* save off the origiginal signature so we can modify the smb and check
229 its signature against what the server sent */
Steve French50c2f752007-07-13 00:33:32 +0000230 memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
Steve French50c2f752007-07-13 00:33:32 +0000232 cifs_pdu->Signature.Sequence.SequenceNumber =
233 cpu_to_le32(expected_sequence_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 cifs_pdu->Signature.Sequence.Reserved = 0;
235
Jeff Layton157c2492011-04-02 07:34:30 -0400236 mutex_lock(&server->srv_mutex);
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700237 rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
Jeff Layton157c2492011-04-02 07:34:30 -0400238 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
Steve French50c2f752007-07-13 00:33:32 +0000240 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 return rc;
242
Steve French50c2f752007-07-13 00:33:32 +0000243/* cifs_dump_mem("what we think it should be: ",
244 what_we_think_sig_should_be, 16); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
Steve French50c2f752007-07-13 00:33:32 +0000246 if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 return -EACCES;
248 else
249 return 0;
250
251}
252
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500253/* Build a proper attribute value/target info pairs blob.
254 * Fill in netbios and dns domain name and workstation name
255 * and client time (total five av pairs and + one end of fields indicator.
256 * Allocate domain name which gets freed when session struct is deallocated.
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500257 */
258static int
Steve French96daf2b2011-05-27 04:34:02 +0000259build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500260{
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500261 unsigned int dlen;
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500262 unsigned int size = 2 * sizeof(struct ntlmssp2_name);
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500263 char *defdmname = "WORKGROUP";
264 unsigned char *blobptr;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500265 struct ntlmssp2_name *attrptr;
266
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500267 if (!ses->domainName) {
268 ses->domainName = kstrdup(defdmname, GFP_KERNEL);
269 if (!ses->domainName)
270 return -ENOMEM;
271 }
272
273 dlen = strlen(ses->domainName);
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500274
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500275 /*
276 * The length of this blob is two times the size of a
277 * structure (av pair) which holds name/size
278 * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
279 * unicode length of a netbios domain name
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500280 */
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500281 ses->auth_key.len = size + 2 * dlen;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500282 ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
283 if (!ses->auth_key.response) {
284 ses->auth_key.len = 0;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500285 return -ENOMEM;
286 }
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500287
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500288 blobptr = ses->auth_key.response;
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500289 attrptr = (struct ntlmssp2_name *) blobptr;
290
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500291 /*
292 * As defined in MS-NTLM 3.3.2, just this av pair field
293 * is sufficient as part of the temp
294 */
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500295 attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
296 attrptr->length = cpu_to_le16(2 * dlen);
297 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
Steve Frenchacbbb762012-01-18 22:32:33 -0600298 cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500299
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500300 return 0;
301}
302
303/* Server has provided av pairs/target info in the type 2 challenge
304 * packet and we have plucked it and stored within smb session.
305 * We parse that blob here to find netbios domain name to be used
306 * as part of ntlmv2 authentication (in Target String), if not already
307 * specified on the command line.
308 * If this function returns without any error but without fetching
309 * domain name, authentication may fail against some server but
310 * may not fail against other (those who are not very particular
311 * about target string i.e. for some, just user name might suffice.
312 */
313static int
Steve French96daf2b2011-05-27 04:34:02 +0000314find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500315{
316 unsigned int attrsize;
317 unsigned int type;
318 unsigned int onesize = sizeof(struct ntlmssp2_name);
319 unsigned char *blobptr;
320 unsigned char *blobend;
321 struct ntlmssp2_name *attrptr;
322
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500323 if (!ses->auth_key.len || !ses->auth_key.response)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500324 return 0;
325
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500326 blobptr = ses->auth_key.response;
327 blobend = blobptr + ses->auth_key.len;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500328
329 while (blobptr + onesize < blobend) {
330 attrptr = (struct ntlmssp2_name *) blobptr;
331 type = le16_to_cpu(attrptr->type);
332 if (type == NTLMSSP_AV_EOL)
333 break;
334 blobptr += 2; /* advance attr type */
335 attrsize = le16_to_cpu(attrptr->length);
336 blobptr += 2; /* advance attr size */
337 if (blobptr + attrsize > blobend)
338 break;
339 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
Chen Gang057d6332013-07-19 09:01:36 +0800340 if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500341 break;
342 if (!ses->domainName) {
343 ses->domainName =
344 kmalloc(attrsize + 1, GFP_KERNEL);
345 if (!ses->domainName)
346 return -ENOMEM;
Steve Frenchacbbb762012-01-18 22:32:33 -0600347 cifs_from_utf16(ses->domainName,
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500348 (__le16 *)blobptr, attrsize, attrsize,
Steve Frenchb6938552014-09-25 13:20:05 -0500349 nls_cp, NO_MAP_UNI_RSVD);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500350 break;
351 }
352 }
353 blobptr += attrsize; /* advance attr value */
354 }
355
356 return 0;
357}
358
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200359/* Server has provided av pairs/target info in the type 2 challenge
360 * packet and we have plucked it and stored within smb session.
361 * We parse that blob here to find the server given timestamp
362 * as part of ntlmv2 authentication (or local current time as
363 * default in case of failure)
364 */
365static __le64
366find_timestamp(struct cifs_ses *ses)
367{
368 unsigned int attrsize;
369 unsigned int type;
370 unsigned int onesize = sizeof(struct ntlmssp2_name);
371 unsigned char *blobptr;
372 unsigned char *blobend;
373 struct ntlmssp2_name *attrptr;
Arnd Bergmann95390202018-06-19 17:27:58 +0200374 struct timespec64 ts;
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200375
376 if (!ses->auth_key.len || !ses->auth_key.response)
377 return 0;
378
379 blobptr = ses->auth_key.response;
380 blobend = blobptr + ses->auth_key.len;
381
382 while (blobptr + onesize < blobend) {
383 attrptr = (struct ntlmssp2_name *) blobptr;
384 type = le16_to_cpu(attrptr->type);
385 if (type == NTLMSSP_AV_EOL)
386 break;
387 blobptr += 2; /* advance attr type */
388 attrsize = le16_to_cpu(attrptr->length);
389 blobptr += 2; /* advance attr size */
390 if (blobptr + attrsize > blobend)
391 break;
392 if (type == NTLMSSP_AV_TIMESTAMP) {
393 if (attrsize == sizeof(u64))
394 return *((__le64 *)blobptr);
395 }
396 blobptr += attrsize; /* advance attr value */
397 }
398
Arnd Bergmann95390202018-06-19 17:27:58 +0200399 ktime_get_real_ts64(&ts);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700400 return cpu_to_le64(cifs_UnixTimeToNT(ts));
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200401}
402
Steve French96daf2b2011-05-27 04:34:02 +0000403static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
Steve French50c2f752007-07-13 00:33:32 +0000404 const struct nls_table *nls_cp)
Steve Frencha8ee0342006-06-05 23:34:19 +0000405{
406 int rc = 0;
407 int len;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500408 char nt_hash[CIFS_NTHASH_SIZE];
Steve Frenchfdf96a92013-06-25 14:03:16 -0500409 __le16 *user;
Steve French50c2f752007-07-13 00:33:32 +0000410 wchar_t *domain;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500411 wchar_t *server;
Steve Frenchc8e56f12010-09-08 21:10:58 +0000412
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500413 if (!ses->server->secmech.sdeschmacmd5) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500414 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500415 return -1;
416 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000417
418 /* calculate md4 hash of password */
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -0500419 E_md4hash(ses->password, nt_hash, nls_cp);
Steve Frencha8ee0342006-06-05 23:34:19 +0000420
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500421 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500422 CIFS_NTHASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500423 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500424 cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500425 return rc;
426 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500427
428 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
429 if (rc) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700430 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500431 return rc;
432 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000433
Steve Frenchfdf96a92013-06-25 14:03:16 -0500434 /* convert ses->user_name to unicode */
Jeff Layton04febab2012-01-17 16:09:15 -0500435 len = ses->user_name ? strlen(ses->user_name) : 0;
Steve French1717ffc2006-06-08 05:41:32 +0000436 user = kmalloc(2 + (len * 2), GFP_KERNEL);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500437 if (user == NULL) {
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500438 rc = -ENOMEM;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500439 return rc;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500440 }
Jeff Layton04febab2012-01-17 16:09:15 -0500441
442 if (len) {
Steve Frenchfdf96a92013-06-25 14:03:16 -0500443 len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
Jeff Layton04febab2012-01-17 16:09:15 -0500444 UniStrupr(user);
445 } else {
446 memset(user, '\0', 2);
447 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500448
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500449 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500450 (char *)user, 2 * len);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500451 kfree(user);
452 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500453 cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500454 return rc;
455 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000456
457 /* convert ses->domainName to unicode and uppercase */
Steve French50c2f752007-07-13 00:33:32 +0000458 if (ses->domainName) {
Steve French1717ffc2006-06-08 05:41:32 +0000459 len = strlen(ses->domainName);
Steve Frencha8ee0342006-06-05 23:34:19 +0000460
Steve French50c2f752007-07-13 00:33:32 +0000461 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500462 if (domain == NULL) {
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500463 rc = -ENOMEM;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500464 return rc;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500465 }
Steve Frenchacbbb762012-01-18 22:32:33 -0600466 len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
467 nls_cp);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500468 rc =
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500469 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
470 (char *)domain, 2 * len);
Steve French1717ffc2006-06-08 05:41:32 +0000471 kfree(domain);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500472 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500473 cifs_dbg(VFS, "%s: Could not update with domain\n",
474 __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500475 return rc;
476 }
Steve French8b7a4542015-03-30 16:58:17 -0500477 } else {
Steve Frenchb438fcf2021-02-20 19:24:11 -0600478 /* We use ses->ip_addr if no domain name available */
479 len = strlen(ses->ip_addr);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500480
481 server = kmalloc(2 + (len * 2), GFP_KERNEL);
482 if (server == NULL) {
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500483 rc = -ENOMEM;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500484 return rc;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500485 }
Steve Frenchb438fcf2021-02-20 19:24:11 -0600486 len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500487 nls_cp);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500488 rc =
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500489 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
490 (char *)server, 2 * len);
491 kfree(server);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500492 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500493 cifs_dbg(VFS, "%s: Could not update with server\n",
494 __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500495 return rc;
496 }
Steve French1717ffc2006-06-08 05:41:32 +0000497 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500498
499 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500500 ntlmv2_hash);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500501 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500502 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500503
Steve Frencha8ee0342006-06-05 23:34:19 +0000504 return rc;
505}
506
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500507static int
Steve French96daf2b2011-05-27 04:34:02 +0000508CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500509{
510 int rc;
Tim Gardner2c957dd2013-11-07 16:40:57 -0700511 struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
512 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
513 unsigned int hash_len;
514
515 /* The MD5 hash starts at challenge_key.key */
516 hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
517 offsetof(struct ntlmv2_resp, challenge.key[0]));
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500518
519 if (!ses->server->secmech.sdeschmacmd5) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500520 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500521 return -1;
522 }
523
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500524 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700525 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500526 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500527 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
528 __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500529 return rc;
530 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500531
532 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
533 if (rc) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700534 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500535 return rc;
536 }
537
Jeff Layton3f618222013-06-12 19:52:14 -0500538 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
Tim Gardner2c957dd2013-11-07 16:40:57 -0700539 memcpy(ntlmv2->challenge.key,
540 ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -0500541 else
Tim Gardner2c957dd2013-11-07 16:40:57 -0700542 memcpy(ntlmv2->challenge.key,
543 ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500544 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700545 ntlmv2->challenge.key, hash_len);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500546 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500547 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500548 return rc;
549 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500550
Tim Gardner2c957dd2013-11-07 16:40:57 -0700551 /* Note that the MD5 digest over writes anon.challenge_key.key */
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500552 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700553 ntlmv2->ntlmv2_hash);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500554 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500555 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500556
557 return rc;
558}
559
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500560int
Steve French96daf2b2011-05-27 04:34:02 +0000561setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
Steve French9fbc5902010-08-20 20:42:26 +0000562{
Steve Frenchc8e56f12010-09-08 21:10:58 +0000563 int rc;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500564 int baselen;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500565 unsigned int tilen;
Tim Gardner2c957dd2013-11-07 16:40:57 -0700566 struct ntlmv2_resp *ntlmv2;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500567 char ntlmv2_hash[16];
568 unsigned char *tiblob = NULL; /* target info blob */
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200569 __le64 rsp_timestamp;
Steve French6d027cf2006-06-05 16:26:05 +0000570
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600571 if (nls_cp == NULL) {
572 cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
573 return -EINVAL;
574 }
575
Jeff Layton3f618222013-06-12 19:52:14 -0500576 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500577 if (!ses->domainName) {
Germano Percossi39566442016-12-15 12:31:18 +0530578 if (ses->domainAuto) {
579 rc = find_domain_name(ses, nls_cp);
580 if (rc) {
581 cifs_dbg(VFS, "error %d finding domain name\n",
582 rc);
583 goto setup_ntlmv2_rsp_ret;
584 }
585 } else {
586 ses->domainName = kstrdup("", GFP_KERNEL);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500587 }
588 }
589 } else {
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500590 rc = build_avpair_blob(ses, nls_cp);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500591 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500592 cifs_dbg(VFS, "error %d building av pair blob\n", rc);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500593 goto setup_ntlmv2_rsp_ret;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500594 }
595 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000596
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200597 /* Must be within 5 minutes of the server (or in range +/-2h
598 * in case of Mac OS X), so simply carry over server timestamp
599 * (as Windows 7 does)
600 */
601 rsp_timestamp = find_timestamp(ses);
602
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500603 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500604 tilen = ses->auth_key.len;
605 tiblob = ses->auth_key.response;
606
607 ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500608 if (!ses->auth_key.response) {
Anton Protopopov4b550af2016-02-10 12:50:21 -0500609 rc = -ENOMEM;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500610 ses->auth_key.len = 0;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500611 goto setup_ntlmv2_rsp_ret;
612 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500613 ses->auth_key.len += baselen;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500614
Tim Gardner2c957dd2013-11-07 16:40:57 -0700615 ntlmv2 = (struct ntlmv2_resp *)
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500616 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
Tim Gardner2c957dd2013-11-07 16:40:57 -0700617 ntlmv2->blob_signature = cpu_to_le32(0x00000101);
618 ntlmv2->reserved = 0;
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200619 ntlmv2->time = rsp_timestamp;
620
Tim Gardner2c957dd2013-11-07 16:40:57 -0700621 get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
622 ntlmv2->reserved2 = 0;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500623
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500624 memcpy(ses->auth_key.response + baselen, tiblob, tilen);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500625
Rabin Vincentbd975d12016-07-19 09:26:21 +0200626 mutex_lock(&ses->server->srv_mutex);
627
Aurelien Aptel82fb82b2018-02-16 19:19:27 +0100628 rc = cifs_alloc_hash("hmac(md5)",
629 &ses->server->secmech.hmacmd5,
630 &ses->server->secmech.sdeschmacmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500631 if (rc) {
Rabin Vincentbd975d12016-07-19 09:26:21 +0200632 goto unlock;
Steve French95dc8dd2013-07-04 10:35:21 -0500633 }
634
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -0500635 /* calculate ntlmv2_hash */
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500636 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500637 if (rc) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700638 cifs_dbg(VFS, "Could not get v2 hash rc %d\n", rc);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200639 goto unlock;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500640 }
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -0500641
642 /* calculate first part of the client response (CR1) */
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500643 rc = CalcNTLMv2_response(ses, ntlmv2_hash);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500644 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500645 cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200646 goto unlock;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500647 }
Steve Frenchb609f062007-07-09 07:55:14 +0000648
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500649 /* now calculate the session key for NTLMv2 */
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500650 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500651 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500652 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500653 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
654 __func__);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200655 goto unlock;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500656 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500657
658 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
659 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500660 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200661 goto unlock;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500662 }
663
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500664 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700665 ntlmv2->ntlmv2_hash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500666 CIFS_HMAC_MD5_HASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500667 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500668 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200669 goto unlock;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500670 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500671
672 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
673 ses->auth_key.response);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500674 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500675 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500676
Rabin Vincentbd975d12016-07-19 09:26:21 +0200677unlock:
678 mutex_unlock(&ses->server->srv_mutex);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500679setup_ntlmv2_rsp_ret:
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500680 kfree(tiblob);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500681
682 return rc;
Steve French6d027cf2006-06-05 16:26:05 +0000683}
684
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500685int
Steve French96daf2b2011-05-27 04:34:02 +0000686calc_seckey(struct cifs_ses *ses)
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500687{
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200688 unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
689 struct arc4_ctx *ctx_arc4;
Sachin Prabhu5f4b5562016-10-17 16:40:22 -0400690
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200691 if (fips_enabled)
692 return -ENODEV;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500693
694 get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
695
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200696 ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
697 if (!ctx_arc4) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700698 cifs_dbg(VFS, "Could not allocate arc4 context\n");
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200699 return -ENOMEM;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500700 }
701
Ronnie Sahlberg71c02862021-08-19 20:34:59 +1000702 cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
703 cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
704 CIFS_CPHTXT_SIZE);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500705
706 /* make secondary_key/nonce as session key */
707 memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
708 /* and make len as that of session key only */
709 ses->auth_key.len = CIFS_SESS_KEY_SIZE;
710
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200711 memzero_explicit(sec_key, CIFS_SESS_KEY_SIZE);
Waiman Long453431a2020-08-06 23:18:13 -0700712 kfree_sensitive(ctx_arc4);
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200713 return 0;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500714}
715
716void
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700717cifs_crypto_secmech_release(struct TCP_Server_Info *server)
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500718{
Steve French95dc8dd2013-07-04 10:35:21 -0500719 if (server->secmech.cmacaes) {
Steve French429b46f2013-06-26 23:45:05 -0500720 crypto_free_shash(server->secmech.cmacaes);
Steve French95dc8dd2013-07-04 10:35:21 -0500721 server->secmech.cmacaes = NULL;
722 }
Steve French429b46f2013-06-26 23:45:05 -0500723
Steve French95dc8dd2013-07-04 10:35:21 -0500724 if (server->secmech.hmacsha256) {
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700725 crypto_free_shash(server->secmech.hmacsha256);
Steve French95dc8dd2013-07-04 10:35:21 -0500726 server->secmech.hmacsha256 = NULL;
727 }
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700728
Steve French95dc8dd2013-07-04 10:35:21 -0500729 if (server->secmech.md5) {
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500730 crypto_free_shash(server->secmech.md5);
Steve French95dc8dd2013-07-04 10:35:21 -0500731 server->secmech.md5 = NULL;
732 }
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500733
Gustavo A. R. Silva70e80652018-02-19 11:11:13 -0600734 if (server->secmech.sha512) {
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +0100735 crypto_free_shash(server->secmech.sha512);
736 server->secmech.sha512 = NULL;
737 }
738
Steve French95dc8dd2013-07-04 10:35:21 -0500739 if (server->secmech.hmacmd5) {
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500740 crypto_free_shash(server->secmech.hmacmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500741 server->secmech.hmacmd5 = NULL;
742 }
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500743
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700744 if (server->secmech.ccmaesencrypt) {
745 crypto_free_aead(server->secmech.ccmaesencrypt);
746 server->secmech.ccmaesencrypt = NULL;
747 }
748
749 if (server->secmech.ccmaesdecrypt) {
750 crypto_free_aead(server->secmech.ccmaesdecrypt);
751 server->secmech.ccmaesdecrypt = NULL;
752 }
753
Steve French429b46f2013-06-26 23:45:05 -0500754 kfree(server->secmech.sdesccmacaes);
Steve French95dc8dd2013-07-04 10:35:21 -0500755 server->secmech.sdesccmacaes = NULL;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700756 kfree(server->secmech.sdeschmacsha256);
Steve French95dc8dd2013-07-04 10:35:21 -0500757 server->secmech.sdeschmacsha256 = NULL;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500758 kfree(server->secmech.sdeschmacmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500759 server->secmech.sdeschmacmd5 = NULL;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500760 kfree(server->secmech.sdescmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500761 server->secmech.sdescmd5 = NULL;
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +0100762 kfree(server->secmech.sdescsha512);
763 server->secmech.sdescsha512 = NULL;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500764}