blob: 0912d8bbbac14aa5419b6d7c91f4272ba258a09e [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/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Steve French8b7a4542015-03-30 16:58:17 -05004 * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP
5 * for more detailed information
6 *
Steve French95dc8dd2013-07-04 10:35:21 -05007 * Copyright (C) International Business Machines Corp., 2005,2013
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Author(s): Steve French (sfrench@us.ibm.com)
9 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 */
11
12#include <linux/fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include "cifspdu.h"
Steve Frenchffdd6e42007-06-24 21:15:44 +000015#include "cifsglob.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include "cifs_debug.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include "cifs_unicode.h"
18#include "cifsproto.h"
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -050019#include "ntlmssp.h"
Steve French7c7b25b2006-06-01 19:20:10 +000020#include <linux/ctype.h>
Steve French6d027cf2006-06-05 16:26:05 +000021#include <linux/random.h>
Jeff Laytonfb308a62012-09-18 16:20:35 -070022#include <linux/highmem.h>
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +020023#include <linux/fips.h>
Steve French23e91d82021-09-08 23:59:26 -050024#include "../smbfs_common/arc4.h"
Pavel Shilovsky026e93d2016-11-03 16:47:37 -070025#include <crypto/aead.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
Al Viro16c568e2015-11-12 22:46:49 -050027int __cifs_calc_signature(struct smb_rqst *rqst,
28 struct TCP_Server_Info *server, char *signature,
29 struct shash_desc *shash)
30{
31 int i;
32 int rc;
33 struct kvec *iov = rqst->rq_iov;
34 int n_vec = rqst->rq_nvec;
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100035 int is_smb2 = server->vals->header_preamble_size == 0;
Al Viro16c568e2015-11-12 22:46:49 -050036
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100037 /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
38 if (is_smb2) {
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030039 if (iov[0].iov_len <= 4)
40 return -EIO;
41 i = 0;
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100042 } else {
43 if (n_vec < 2 || iov[0].iov_len != 4)
44 return -EIO;
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030045 i = 1; /* skip rfc1002 length */
Ronnie Sahlbergc713c872018-06-12 08:00:58 +100046 }
47
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030048 for (; i < n_vec; i++) {
Al Viro16c568e2015-11-12 22:46:49 -050049 if (iov[i].iov_len == 0)
50 continue;
51 if (iov[i].iov_base == NULL) {
52 cifs_dbg(VFS, "null iovec entry\n");
53 return -EIO;
54 }
Paulo Alcantara83ffdea2018-06-15 15:58:00 -030055
Pavel Shilovsky738f9de2016-11-23 15:14:57 -080056 rc = crypto_shash_update(shash,
57 iov[i].iov_base, iov[i].iov_len);
Al Viro16c568e2015-11-12 22:46:49 -050058 if (rc) {
59 cifs_dbg(VFS, "%s: Could not update with payload\n",
60 __func__);
61 return rc;
62 }
63 }
64
65 /* now hash over the rq_pages array */
66 for (i = 0; i < rqst->rq_npages; i++) {
Long Li4c0d2a52018-05-30 12:48:03 -070067 void *kaddr;
68 unsigned int len, offset;
Al Viro16c568e2015-11-12 22:46:49 -050069
Long Li4c0d2a52018-05-30 12:48:03 -070070 rqst_page_get_length(rqst, i, &len, &offset);
71
72 kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
Al Viro16c568e2015-11-12 22:46:49 -050073
Paulo Alcantaraa12d0c52018-06-23 14:52:25 -030074 rc = crypto_shash_update(shash, kaddr, len);
75 if (rc) {
76 cifs_dbg(VFS, "%s: Could not update with payload\n",
77 __func__);
78 kunmap(rqst->rq_pages[i]);
79 return rc;
80 }
Al Viro16c568e2015-11-12 22:46:49 -050081
82 kunmap(rqst->rq_pages[i]);
83 }
84
85 rc = crypto_shash_final(shash, signature);
86 if (rc)
87 cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
88
89 return rc;
90}
91
Jeff Layton157c2492011-04-02 07:34:30 -040092/*
93 * Calculate and return the CIFS signature based on the mac key and SMB PDU.
94 * The 16 byte signature must be allocated by the caller. Note we only use the
95 * 1st eight bytes and that the smb header signature field on input contains
96 * the sequence number before this function is called. Also, this function
97 * should be called with the server->srv_mutex held.
98 */
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -070099static int cifs_calc_signature(struct smb_rqst *rqst,
Jeff Layton826a95e2011-10-11 06:41:32 -0400100 struct TCP_Server_Info *server, char *signature)
Steve French84afc292005-12-02 13:32:45 -0800101{
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500102 int rc;
Steve French84afc292005-12-02 13:32:45 -0800103
Al Viro16c568e2015-11-12 22:46:49 -0500104 if (!rqst->rq_iov || !signature || !server)
Steve Frenche9917a02006-03-31 21:22:00 +0000105 return -EINVAL;
Steve French84afc292005-12-02 13:32:45 -0800106
Aurelien Aptel82fb82b2018-02-16 19:19:27 +0100107 rc = cifs_alloc_hash("md5", &server->secmech.md5,
108 &server->secmech.sdescmd5);
109 if (rc)
110 return -1;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500111
112 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
113 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500114 cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500115 return rc;
116 }
117
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500118 rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500119 server->session_key.response, server->session_key.len);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500120 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500121 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500122 return rc;
123 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500124
Ronnie Sahlbergc713c872018-06-12 08:00:58 +1000125 return __cifs_calc_signature(rqst, server, signature,
Al Viro16c568e2015-11-12 22:46:49 -0500126 &server->secmech.sdescmd5->shash);
Steve French84afc292005-12-02 13:32:45 -0800127}
128
Jeff Laytona0f8b4f2011-01-07 11:30:28 -0500129/* must be called with server->srv_mutex held */
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700130int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
Steve French63d25832007-11-05 21:46:10 +0000131 __u32 *pexpected_response_sequence_number)
Steve French84afc292005-12-02 13:32:45 -0800132{
133 int rc = 0;
134 char smb_signature[20];
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700135 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
Steve French84afc292005-12-02 13:32:45 -0800136
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800137 if (rqst->rq_iov[0].iov_len != 4 ||
138 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
139 return -EIO;
140
Steve Frenchffdd6e42007-06-24 21:15:44 +0000141 if ((cifs_pdu == NULL) || (server == NULL))
Steve French84afc292005-12-02 13:32:45 -0800142 return -EINVAL;
143
Shyam Prasad N080dc5e2021-07-19 17:05:53 +0000144 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton998d6fc2011-07-26 12:21:17 -0400145 if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
Shyam Prasad N080dc5e2021-07-19 17:05:53 +0000146 server->tcpStatus == CifsNeedNegotiate) {
147 spin_unlock(&cifs_tcp_ses_lock);
Steve French84afc292005-12-02 13:32:45 -0800148 return rc;
Shyam Prasad N080dc5e2021-07-19 17:05:53 +0000149 }
150 spin_unlock(&cifs_tcp_ses_lock);
Steve French84afc292005-12-02 13:32:45 -0800151
Jeff Layton998d6fc2011-07-26 12:21:17 -0400152 if (!server->session_estab) {
Jeff Laytonb4dacbc2011-10-11 06:41:32 -0400153 memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
Jeff Layton998d6fc2011-07-26 12:21:17 -0400154 return rc;
155 }
156
Steve Frenchffdd6e42007-06-24 21:15:44 +0000157 cifs_pdu->Signature.Sequence.SequenceNumber =
Steve French84afc292005-12-02 13:32:45 -0800158 cpu_to_le32(server->sequence_number);
Steve Frenchffdd6e42007-06-24 21:15:44 +0000159 cifs_pdu->Signature.Sequence.Reserved = 0;
Steve French84afc292005-12-02 13:32:45 -0800160
Jeff Layton0124cc42013-04-03 11:55:03 -0400161 *pexpected_response_sequence_number = ++server->sequence_number;
162 ++server->sequence_number;
Steve French84afc292005-12-02 13:32:45 -0800163
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700164 rc = cifs_calc_signature(rqst, server, smb_signature);
Steve Frenchffdd6e42007-06-24 21:15:44 +0000165 if (rc)
166 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
167 else
168 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
Steve French84afc292005-12-02 13:32:45 -0800169
Steve Frenchffdd6e42007-06-24 21:15:44 +0000170 return rc;
Steve French84afc292005-12-02 13:32:45 -0800171}
172
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700173int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
174 __u32 *pexpected_response_sequence)
175{
176 struct smb_rqst rqst = { .rq_iov = iov,
177 .rq_nvec = n_vec };
178
179 return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
180}
181
Jeff Layton826a95e2011-10-11 06:41:32 -0400182/* must be called with server->srv_mutex held */
183int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
184 __u32 *pexpected_response_sequence_number)
185{
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800186 struct kvec iov[2];
Jeff Layton826a95e2011-10-11 06:41:32 -0400187
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800188 iov[0].iov_base = cifs_pdu;
189 iov[0].iov_len = 4;
190 iov[1].iov_base = (char *)cifs_pdu + 4;
191 iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
Jeff Layton826a95e2011-10-11 06:41:32 -0400192
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800193 return cifs_sign_smbv(iov, 2, server,
Jeff Layton826a95e2011-10-11 06:41:32 -0400194 pexpected_response_sequence_number);
195}
196
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700197int cifs_verify_signature(struct smb_rqst *rqst,
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500198 struct TCP_Server_Info *server,
Steve Frenchffdd6e42007-06-24 21:15:44 +0000199 __u32 expected_sequence_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
Steve Frenchc8e56f12010-09-08 21:10:58 +0000201 unsigned int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 char server_response_sig[8];
203 char what_we_think_sig_should_be[20];
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700204 struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Pavel Shilovsky738f9de2016-11-23 15:14:57 -0800206 if (rqst->rq_iov[0].iov_len != 4 ||
207 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
208 return -EIO;
209
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500210 if (cifs_pdu == NULL || server == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 return -EINVAL;
212
Jeff Layton9c4843e2011-06-06 15:40:23 -0400213 if (!server->session_estab)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 return 0;
215
216 if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
Steve French50c2f752007-07-13 00:33:32 +0000217 struct smb_com_lock_req *pSMB =
Steve Frenchffdd6e42007-06-24 21:15:44 +0000218 (struct smb_com_lock_req *)cifs_pdu;
Colin Ian King58902552018-11-03 15:59:44 +0000219 if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 return 0;
221 }
222
Steve French50c2f752007-07-13 00:33:32 +0000223 /* BB what if signatures are supposed to be on for session but
224 server does not send one? BB */
225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 /* Do not need to verify session setups with signature "BSRSPYL " */
Steve French50c2f752007-07-13 00:33:32 +0000227 if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
Joe Perchesf96637b2013-05-04 22:12:25 -0500228 cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
229 cifs_pdu->Command);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231 /* save off the origiginal signature so we can modify the smb and check
232 its signature against what the server sent */
Steve French50c2f752007-07-13 00:33:32 +0000233 memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Steve French50c2f752007-07-13 00:33:32 +0000235 cifs_pdu->Signature.Sequence.SequenceNumber =
236 cpu_to_le32(expected_sequence_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 cifs_pdu->Signature.Sequence.Reserved = 0;
238
Jeff Layton157c2492011-04-02 07:34:30 -0400239 mutex_lock(&server->srv_mutex);
Jeff Laytonbf5ea0e2012-09-18 16:20:34 -0700240 rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
Jeff Layton157c2492011-04-02 07:34:30 -0400241 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
Steve French50c2f752007-07-13 00:33:32 +0000243 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 return rc;
245
Steve French50c2f752007-07-13 00:33:32 +0000246/* cifs_dump_mem("what we think it should be: ",
247 what_we_think_sig_should_be, 16); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Steve French50c2f752007-07-13 00:33:32 +0000249 if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 return -EACCES;
251 else
252 return 0;
253
254}
255
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500256/* Build a proper attribute value/target info pairs blob.
257 * Fill in netbios and dns domain name and workstation name
258 * and client time (total five av pairs and + one end of fields indicator.
259 * Allocate domain name which gets freed when session struct is deallocated.
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500260 */
261static int
Steve French96daf2b2011-05-27 04:34:02 +0000262build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500263{
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500264 unsigned int dlen;
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500265 unsigned int size = 2 * sizeof(struct ntlmssp2_name);
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500266 char *defdmname = "WORKGROUP";
267 unsigned char *blobptr;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500268 struct ntlmssp2_name *attrptr;
269
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500270 if (!ses->domainName) {
271 ses->domainName = kstrdup(defdmname, GFP_KERNEL);
272 if (!ses->domainName)
273 return -ENOMEM;
274 }
275
276 dlen = strlen(ses->domainName);
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500277
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500278 /*
279 * The length of this blob is two times the size of a
280 * structure (av pair) which holds name/size
281 * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
282 * unicode length of a netbios domain name
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500283 */
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500284 ses->auth_key.len = size + 2 * dlen;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500285 ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
286 if (!ses->auth_key.response) {
287 ses->auth_key.len = 0;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500288 return -ENOMEM;
289 }
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500290
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500291 blobptr = ses->auth_key.response;
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500292 attrptr = (struct ntlmssp2_name *) blobptr;
293
Shirish Pargaonkarcfbd6f82011-08-24 23:05:46 -0500294 /*
295 * As defined in MS-NTLM 3.3.2, just this av pair field
296 * is sufficient as part of the temp
297 */
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500298 attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
299 attrptr->length = cpu_to_le16(2 * dlen);
300 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
Steve Frenchacbbb762012-01-18 22:32:33 -0600301 cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500302
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500303 return 0;
304}
305
306/* Server has provided av pairs/target info in the type 2 challenge
307 * packet and we have plucked it and stored within smb session.
308 * We parse that blob here to find netbios domain name to be used
309 * as part of ntlmv2 authentication (in Target String), if not already
310 * specified on the command line.
311 * If this function returns without any error but without fetching
312 * domain name, authentication may fail against some server but
313 * may not fail against other (those who are not very particular
314 * about target string i.e. for some, just user name might suffice.
315 */
316static int
Steve French96daf2b2011-05-27 04:34:02 +0000317find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500318{
319 unsigned int attrsize;
320 unsigned int type;
321 unsigned int onesize = sizeof(struct ntlmssp2_name);
322 unsigned char *blobptr;
323 unsigned char *blobend;
324 struct ntlmssp2_name *attrptr;
325
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500326 if (!ses->auth_key.len || !ses->auth_key.response)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500327 return 0;
328
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500329 blobptr = ses->auth_key.response;
330 blobend = blobptr + ses->auth_key.len;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500331
332 while (blobptr + onesize < blobend) {
333 attrptr = (struct ntlmssp2_name *) blobptr;
334 type = le16_to_cpu(attrptr->type);
335 if (type == NTLMSSP_AV_EOL)
336 break;
337 blobptr += 2; /* advance attr type */
338 attrsize = le16_to_cpu(attrptr->length);
339 blobptr += 2; /* advance attr size */
340 if (blobptr + attrsize > blobend)
341 break;
342 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
Chen Gang057d6332013-07-19 09:01:36 +0800343 if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500344 break;
345 if (!ses->domainName) {
346 ses->domainName =
347 kmalloc(attrsize + 1, GFP_KERNEL);
348 if (!ses->domainName)
349 return -ENOMEM;
Steve Frenchacbbb762012-01-18 22:32:33 -0600350 cifs_from_utf16(ses->domainName,
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500351 (__le16 *)blobptr, attrsize, attrsize,
Steve Frenchb6938552014-09-25 13:20:05 -0500352 nls_cp, NO_MAP_UNI_RSVD);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500353 break;
354 }
355 }
356 blobptr += attrsize; /* advance attr value */
357 }
358
359 return 0;
360}
361
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200362/* Server has provided av pairs/target info in the type 2 challenge
363 * packet and we have plucked it and stored within smb session.
364 * We parse that blob here to find the server given timestamp
365 * as part of ntlmv2 authentication (or local current time as
366 * default in case of failure)
367 */
368static __le64
369find_timestamp(struct cifs_ses *ses)
370{
371 unsigned int attrsize;
372 unsigned int type;
373 unsigned int onesize = sizeof(struct ntlmssp2_name);
374 unsigned char *blobptr;
375 unsigned char *blobend;
376 struct ntlmssp2_name *attrptr;
Arnd Bergmann95390202018-06-19 17:27:58 +0200377 struct timespec64 ts;
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200378
379 if (!ses->auth_key.len || !ses->auth_key.response)
380 return 0;
381
382 blobptr = ses->auth_key.response;
383 blobend = blobptr + ses->auth_key.len;
384
385 while (blobptr + onesize < blobend) {
386 attrptr = (struct ntlmssp2_name *) blobptr;
387 type = le16_to_cpu(attrptr->type);
388 if (type == NTLMSSP_AV_EOL)
389 break;
390 blobptr += 2; /* advance attr type */
391 attrsize = le16_to_cpu(attrptr->length);
392 blobptr += 2; /* advance attr size */
393 if (blobptr + attrsize > blobend)
394 break;
395 if (type == NTLMSSP_AV_TIMESTAMP) {
396 if (attrsize == sizeof(u64))
397 return *((__le64 *)blobptr);
398 }
399 blobptr += attrsize; /* advance attr value */
400 }
401
Arnd Bergmann95390202018-06-19 17:27:58 +0200402 ktime_get_real_ts64(&ts);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700403 return cpu_to_le64(cifs_UnixTimeToNT(ts));
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200404}
405
Steve French96daf2b2011-05-27 04:34:02 +0000406static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
Steve French50c2f752007-07-13 00:33:32 +0000407 const struct nls_table *nls_cp)
Steve Frencha8ee0342006-06-05 23:34:19 +0000408{
409 int rc = 0;
410 int len;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500411 char nt_hash[CIFS_NTHASH_SIZE];
Steve Frenchfdf96a92013-06-25 14:03:16 -0500412 __le16 *user;
Steve French50c2f752007-07-13 00:33:32 +0000413 wchar_t *domain;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500414 wchar_t *server;
Steve Frenchc8e56f12010-09-08 21:10:58 +0000415
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500416 if (!ses->server->secmech.sdeschmacmd5) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500417 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500418 return -1;
419 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000420
421 /* calculate md4 hash of password */
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -0500422 E_md4hash(ses->password, nt_hash, nls_cp);
Steve Frencha8ee0342006-06-05 23:34:19 +0000423
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500424 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500425 CIFS_NTHASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500426 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500427 cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500428 return rc;
429 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500430
431 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
432 if (rc) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700433 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500434 return rc;
435 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000436
Steve Frenchfdf96a92013-06-25 14:03:16 -0500437 /* convert ses->user_name to unicode */
Jeff Layton04febab2012-01-17 16:09:15 -0500438 len = ses->user_name ? strlen(ses->user_name) : 0;
Steve French1717ffc2006-06-08 05:41:32 +0000439 user = kmalloc(2 + (len * 2), GFP_KERNEL);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500440 if (user == NULL) {
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500441 rc = -ENOMEM;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500442 return rc;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500443 }
Jeff Layton04febab2012-01-17 16:09:15 -0500444
445 if (len) {
Steve Frenchfdf96a92013-06-25 14:03:16 -0500446 len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
Jeff Layton04febab2012-01-17 16:09:15 -0500447 UniStrupr(user);
448 } else {
449 memset(user, '\0', 2);
450 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500451
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500452 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500453 (char *)user, 2 * len);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500454 kfree(user);
455 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500456 cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500457 return rc;
458 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000459
460 /* convert ses->domainName to unicode and uppercase */
Steve French50c2f752007-07-13 00:33:32 +0000461 if (ses->domainName) {
Steve French1717ffc2006-06-08 05:41:32 +0000462 len = strlen(ses->domainName);
Steve Frencha8ee0342006-06-05 23:34:19 +0000463
Steve French50c2f752007-07-13 00:33:32 +0000464 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500465 if (domain == NULL) {
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500466 rc = -ENOMEM;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500467 return rc;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500468 }
Steve Frenchacbbb762012-01-18 22:32:33 -0600469 len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
470 nls_cp);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500471 rc =
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500472 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
473 (char *)domain, 2 * len);
Steve French1717ffc2006-06-08 05:41:32 +0000474 kfree(domain);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500475 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500476 cifs_dbg(VFS, "%s: Could not update with domain\n",
477 __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500478 return rc;
479 }
Steve French8b7a4542015-03-30 16:58:17 -0500480 } else {
Steve Frenchb438fcf2021-02-20 19:24:11 -0600481 /* We use ses->ip_addr if no domain name available */
482 len = strlen(ses->ip_addr);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500483
484 server = kmalloc(2 + (len * 2), GFP_KERNEL);
485 if (server == NULL) {
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500486 rc = -ENOMEM;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500487 return rc;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500488 }
Steve Frenchb438fcf2021-02-20 19:24:11 -0600489 len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500490 nls_cp);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500491 rc =
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500492 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
493 (char *)server, 2 * len);
494 kfree(server);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500495 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500496 cifs_dbg(VFS, "%s: Could not update with server\n",
497 __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500498 return rc;
499 }
Steve French1717ffc2006-06-08 05:41:32 +0000500 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500501
502 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500503 ntlmv2_hash);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500504 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500505 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500506
Steve Frencha8ee0342006-06-05 23:34:19 +0000507 return rc;
508}
509
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500510static int
Steve French96daf2b2011-05-27 04:34:02 +0000511CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500512{
513 int rc;
Tim Gardner2c957dd2013-11-07 16:40:57 -0700514 struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
515 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
516 unsigned int hash_len;
517
518 /* The MD5 hash starts at challenge_key.key */
519 hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
520 offsetof(struct ntlmv2_resp, challenge.key[0]));
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500521
522 if (!ses->server->secmech.sdeschmacmd5) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500523 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500524 return -1;
525 }
526
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500527 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700528 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500529 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500530 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
531 __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500532 return rc;
533 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500534
535 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
536 if (rc) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700537 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500538 return rc;
539 }
540
Jeff Layton3f618222013-06-12 19:52:14 -0500541 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
Tim Gardner2c957dd2013-11-07 16:40:57 -0700542 memcpy(ntlmv2->challenge.key,
543 ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -0500544 else
Tim Gardner2c957dd2013-11-07 16:40:57 -0700545 memcpy(ntlmv2->challenge.key,
546 ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500547 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700548 ntlmv2->challenge.key, hash_len);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500549 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500550 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500551 return rc;
552 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500553
Tim Gardner2c957dd2013-11-07 16:40:57 -0700554 /* Note that the MD5 digest over writes anon.challenge_key.key */
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500555 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700556 ntlmv2->ntlmv2_hash);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500557 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500558 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500559
560 return rc;
561}
562
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500563int
Steve French96daf2b2011-05-27 04:34:02 +0000564setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
Steve French9fbc5902010-08-20 20:42:26 +0000565{
Steve Frenchc8e56f12010-09-08 21:10:58 +0000566 int rc;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500567 int baselen;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500568 unsigned int tilen;
Tim Gardner2c957dd2013-11-07 16:40:57 -0700569 struct ntlmv2_resp *ntlmv2;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500570 char ntlmv2_hash[16];
571 unsigned char *tiblob = NULL; /* target info blob */
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200572 __le64 rsp_timestamp;
Steve French6d027cf2006-06-05 16:26:05 +0000573
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600574 if (nls_cp == NULL) {
575 cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
576 return -EINVAL;
577 }
578
Jeff Layton3f618222013-06-12 19:52:14 -0500579 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500580 if (!ses->domainName) {
Germano Percossi39566442016-12-15 12:31:18 +0530581 if (ses->domainAuto) {
582 rc = find_domain_name(ses, nls_cp);
583 if (rc) {
584 cifs_dbg(VFS, "error %d finding domain name\n",
585 rc);
586 goto setup_ntlmv2_rsp_ret;
587 }
588 } else {
589 ses->domainName = kstrdup("", GFP_KERNEL);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500590 }
591 }
592 } else {
Shirish Pargaonkar9daa42e2010-10-10 13:21:05 -0500593 rc = build_avpair_blob(ses, nls_cp);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500594 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500595 cifs_dbg(VFS, "error %d building av pair blob\n", rc);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500596 goto setup_ntlmv2_rsp_ret;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500597 }
598 }
Steve Frencha8ee0342006-06-05 23:34:19 +0000599
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200600 /* Must be within 5 minutes of the server (or in range +/-2h
601 * in case of Mac OS X), so simply carry over server timestamp
602 * (as Windows 7 does)
603 */
604 rsp_timestamp = find_timestamp(ses);
605
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500606 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500607 tilen = ses->auth_key.len;
608 tiblob = ses->auth_key.response;
609
610 ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500611 if (!ses->auth_key.response) {
Anton Protopopov4b550af2016-02-10 12:50:21 -0500612 rc = -ENOMEM;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500613 ses->auth_key.len = 0;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500614 goto setup_ntlmv2_rsp_ret;
615 }
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500616 ses->auth_key.len += baselen;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500617
Tim Gardner2c957dd2013-11-07 16:40:57 -0700618 ntlmv2 = (struct ntlmv2_resp *)
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500619 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
Tim Gardner2c957dd2013-11-07 16:40:57 -0700620 ntlmv2->blob_signature = cpu_to_le32(0x00000101);
621 ntlmv2->reserved = 0;
Peter Seiderer98ce94c2015-09-17 21:40:12 +0200622 ntlmv2->time = rsp_timestamp;
623
Tim Gardner2c957dd2013-11-07 16:40:57 -0700624 get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
625 ntlmv2->reserved2 = 0;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500626
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500627 memcpy(ses->auth_key.response + baselen, tiblob, tilen);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500628
Rabin Vincentbd975d12016-07-19 09:26:21 +0200629 mutex_lock(&ses->server->srv_mutex);
630
Aurelien Aptel82fb82b2018-02-16 19:19:27 +0100631 rc = cifs_alloc_hash("hmac(md5)",
632 &ses->server->secmech.hmacmd5,
633 &ses->server->secmech.sdeschmacmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500634 if (rc) {
Rabin Vincentbd975d12016-07-19 09:26:21 +0200635 goto unlock;
Steve French95dc8dd2013-07-04 10:35:21 -0500636 }
637
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -0500638 /* calculate ntlmv2_hash */
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500639 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500640 if (rc) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700641 cifs_dbg(VFS, "Could not get v2 hash rc %d\n", rc);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200642 goto unlock;
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500643 }
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -0500644
645 /* calculate first part of the client response (CR1) */
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500646 rc = CalcNTLMv2_response(ses, ntlmv2_hash);
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500647 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500648 cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200649 goto unlock;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500650 }
Steve Frenchb609f062007-07-09 07:55:14 +0000651
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500652 /* now calculate the session key for NTLMv2 */
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500653 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500654 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500655 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500656 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
657 __func__);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200658 goto unlock;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500659 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500660
661 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
662 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500663 cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200664 goto unlock;
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500665 }
666
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500667 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
Tim Gardner2c957dd2013-11-07 16:40:57 -0700668 ntlmv2->ntlmv2_hash,
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500669 CIFS_HMAC_MD5_HASH_SIZE);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500670 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500671 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
Rabin Vincentbd975d12016-07-19 09:26:21 +0200672 goto unlock;
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500673 }
Shirish Pargaonkar307fbd32010-10-21 14:25:17 -0500674
675 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
676 ses->auth_key.response);
Shirish Pargaonkar14cae322011-06-20 16:14:03 -0500677 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500678 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500679
Rabin Vincentbd975d12016-07-19 09:26:21 +0200680unlock:
681 mutex_unlock(&ses->server->srv_mutex);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500682setup_ntlmv2_rsp_ret:
Shirish Pargaonkard3686d52010-10-28 09:53:07 -0500683 kfree(tiblob);
Shirish Pargaonkar2b149f12010-09-18 22:02:18 -0500684
685 return rc;
Steve French6d027cf2006-06-05 16:26:05 +0000686}
687
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500688int
Steve French96daf2b2011-05-27 04:34:02 +0000689calc_seckey(struct cifs_ses *ses)
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500690{
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200691 unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
692 struct arc4_ctx *ctx_arc4;
Sachin Prabhu5f4b5562016-10-17 16:40:22 -0400693
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200694 if (fips_enabled)
695 return -ENODEV;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500696
697 get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
698
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200699 ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
700 if (!ctx_arc4) {
Joe Perchesa0a30362020-04-14 22:42:53 -0700701 cifs_dbg(VFS, "Could not allocate arc4 context\n");
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200702 return -ENOMEM;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500703 }
704
Ronnie Sahlberg71c02862021-08-19 20:34:59 +1000705 cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
706 cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
707 CIFS_CPHTXT_SIZE);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500708
709 /* make secondary_key/nonce as session key */
710 memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
711 /* and make len as that of session key only */
712 ses->auth_key.len = CIFS_SESS_KEY_SIZE;
713
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200714 memzero_explicit(sec_key, CIFS_SESS_KEY_SIZE);
Waiman Long453431a2020-08-06 23:18:13 -0700715 kfree_sensitive(ctx_arc4);
Ard Biesheuvel97a5fee2019-06-12 18:19:59 +0200716 return 0;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500717}
718
719void
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700720cifs_crypto_secmech_release(struct TCP_Server_Info *server)
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500721{
Steve French95dc8dd2013-07-04 10:35:21 -0500722 if (server->secmech.cmacaes) {
Steve French429b46f2013-06-26 23:45:05 -0500723 crypto_free_shash(server->secmech.cmacaes);
Steve French95dc8dd2013-07-04 10:35:21 -0500724 server->secmech.cmacaes = NULL;
725 }
Steve French429b46f2013-06-26 23:45:05 -0500726
Steve French95dc8dd2013-07-04 10:35:21 -0500727 if (server->secmech.hmacsha256) {
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700728 crypto_free_shash(server->secmech.hmacsha256);
Steve French95dc8dd2013-07-04 10:35:21 -0500729 server->secmech.hmacsha256 = NULL;
730 }
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700731
Steve French95dc8dd2013-07-04 10:35:21 -0500732 if (server->secmech.md5) {
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500733 crypto_free_shash(server->secmech.md5);
Steve French95dc8dd2013-07-04 10:35:21 -0500734 server->secmech.md5 = NULL;
735 }
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500736
Gustavo A. R. Silva70e80652018-02-19 11:11:13 -0600737 if (server->secmech.sha512) {
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +0100738 crypto_free_shash(server->secmech.sha512);
739 server->secmech.sha512 = NULL;
740 }
741
Steve French95dc8dd2013-07-04 10:35:21 -0500742 if (server->secmech.hmacmd5) {
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500743 crypto_free_shash(server->secmech.hmacmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500744 server->secmech.hmacmd5 = NULL;
745 }
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500746
Pavel Shilovsky026e93d2016-11-03 16:47:37 -0700747 if (server->secmech.ccmaesencrypt) {
748 crypto_free_aead(server->secmech.ccmaesencrypt);
749 server->secmech.ccmaesencrypt = NULL;
750 }
751
752 if (server->secmech.ccmaesdecrypt) {
753 crypto_free_aead(server->secmech.ccmaesdecrypt);
754 server->secmech.ccmaesdecrypt = NULL;
755 }
756
Steve French429b46f2013-06-26 23:45:05 -0500757 kfree(server->secmech.sdesccmacaes);
Steve French95dc8dd2013-07-04 10:35:21 -0500758 server->secmech.sdesccmacaes = NULL;
Pavel Shilovsky3c1bf7e2012-09-18 16:20:30 -0700759 kfree(server->secmech.sdeschmacsha256);
Steve French95dc8dd2013-07-04 10:35:21 -0500760 server->secmech.sdeschmacsha256 = NULL;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500761 kfree(server->secmech.sdeschmacmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500762 server->secmech.sdeschmacmd5 = NULL;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500763 kfree(server->secmech.sdescmd5);
Steve French95dc8dd2013-07-04 10:35:21 -0500764 server->secmech.sdescmd5 = NULL;
Aurelien Aptel5fcd7f32018-02-16 19:19:28 +0100765 kfree(server->secmech.sdescsha512);
766 server->secmech.sdescsha512 = NULL;
Shirish Pargaonkard2b91522010-10-21 14:25:08 -0500767}