aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsencrypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifsencrypt.c')
-rw-r--r--fs/cifs/cifsencrypt.c475
1 files changed, 349 insertions, 126 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 847628dfdc44..709f2296bdb4 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -27,6 +27,7 @@
27#include "md5.h" 27#include "md5.h"
28#include "cifs_unicode.h" 28#include "cifs_unicode.h"
29#include "cifsproto.h" 29#include "cifsproto.h"
30#include "ntlmssp.h"
30#include <linux/ctype.h> 31#include <linux/ctype.h>
31#include <linux/random.h> 32#include <linux/random.h>
32 33
@@ -42,21 +43,43 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
42 unsigned char *p24); 43 unsigned char *p24);
43 44
44static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
45 const struct mac_key *key, char *signature) 46 struct TCP_Server_Info *server, char *signature)
46{ 47{
47 struct MD5Context context; 48 int rc;
48 49
49 if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) 50 if (cifs_pdu == NULL || server == NULL || signature == NULL)
50 return -EINVAL; 51 return -EINVAL;
51 52
52 cifs_MD5_init(&context); 53 if (!server->ntlmssp.sdescmd5) {
53 cifs_MD5_update(&context, (char *)&key->data, key->len); 54 cERROR(1,
54 cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); 55 "cifs_calculate_signature: can't generate signature\n");
56 return -1;
57 }
55 58
56 cifs_MD5_final(signature, &context); 59 rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash);
57 return 0; 60 if (rc) {
61 cERROR(1, "cifs_calculate_signature: oould not init md5\n");
62 return rc;
63 }
64
65 if (server->secType == RawNTLMSSP)
66 crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
67 server->session_key.data.ntlmv2.key,
68 CIFS_NTLMV2_SESSKEY_SIZE);
69 else
70 crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
71 (char *)&server->session_key.data,
72 server->session_key.len);
73
74 crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
75 cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
76
77 rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature);
78
79 return rc;
58} 80}
59 81
82
60int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, 83int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
61 __u32 *pexpected_response_sequence_number) 84 __u32 *pexpected_response_sequence_number)
62{ 85{
@@ -78,8 +101,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
78 server->sequence_number++; 101 server->sequence_number++;
79 spin_unlock(&GlobalMid_Lock); 102 spin_unlock(&GlobalMid_Lock);
80 103
81 rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, 104 rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
82 smb_signature);
83 if (rc) 105 if (rc)
84 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 106 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
85 else 107 else
@@ -89,21 +111,39 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
89} 111}
90 112
91static int cifs_calc_signature2(const struct kvec *iov, int n_vec, 113static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
92 const struct mac_key *key, char *signature) 114 struct TCP_Server_Info *server, char *signature)
93{ 115{
94 struct MD5Context context;
95 int i; 116 int i;
117 int rc;
96 118
97 if ((iov == NULL) || (signature == NULL) || (key == NULL)) 119 if (iov == NULL || server == NULL || signature == NULL)
98 return -EINVAL; 120 return -EINVAL;
99 121
100 cifs_MD5_init(&context); 122 if (!server->ntlmssp.sdescmd5) {
101 cifs_MD5_update(&context, (char *)&key->data, key->len); 123 cERROR(1, "cifs_calc_signature2: can't generate signature\n");
124 return -1;
125 }
126
127 rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash);
128 if (rc) {
129 cERROR(1, "cifs_calc_signature2: oould not init md5\n");
130 return rc;
131 }
132
133 if (server->secType == RawNTLMSSP)
134 crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
135 server->session_key.data.ntlmv2.key,
136 CIFS_NTLMV2_SESSKEY_SIZE);
137 else
138 crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
139 (char *)&server->session_key.data,
140 server->session_key.len);
141
102 for (i = 0; i < n_vec; i++) { 142 for (i = 0; i < n_vec; i++) {
103 if (iov[i].iov_len == 0) 143 if (iov[i].iov_len == 0)
104 continue; 144 continue;
105 if (iov[i].iov_base == NULL) { 145 if (iov[i].iov_base == NULL) {
106 cERROR(1, "null iovec entry"); 146 cERROR(1, "cifs_calc_signature2: null iovec entry");
107 return -EIO; 147 return -EIO;
108 } 148 }
109 /* The first entry includes a length field (which does not get 149 /* The first entry includes a length field (which does not get
@@ -111,18 +151,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
111 if (i == 0) { 151 if (i == 0) {
112 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ 152 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
113 break; /* nothing to sign or corrupt header */ 153 break; /* nothing to sign or corrupt header */
114 cifs_MD5_update(&context, iov[0].iov_base+4, 154 crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
115 iov[0].iov_len-4); 155 iov[i].iov_base + 4, iov[i].iov_len - 4);
116 } else 156 } else
117 cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); 157 crypto_shash_update(&server->ntlmssp.sdescmd5->shash,
158 iov[i].iov_base, iov[i].iov_len);
118 } 159 }
119 160
120 cifs_MD5_final(signature, &context); 161 rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature);
121 162
122 return 0; 163 return rc;
123} 164}
124 165
125
126int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, 166int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
127 __u32 *pexpected_response_sequence_number) 167 __u32 *pexpected_response_sequence_number)
128{ 168{
@@ -145,8 +185,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
145 server->sequence_number++; 185 server->sequence_number++;
146 spin_unlock(&GlobalMid_Lock); 186 spin_unlock(&GlobalMid_Lock);
147 187
148 rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, 188 rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
149 smb_signature);
150 if (rc) 189 if (rc)
151 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 190 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
152 else 191 else
@@ -156,14 +195,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
156} 195}
157 196
158int cifs_verify_signature(struct smb_hdr *cifs_pdu, 197int cifs_verify_signature(struct smb_hdr *cifs_pdu,
159 const struct mac_key *mac_key, 198 struct TCP_Server_Info *server,
160 __u32 expected_sequence_number) 199 __u32 expected_sequence_number)
161{ 200{
162 unsigned int rc; 201 int rc;
163 char server_response_sig[8]; 202 char server_response_sig[8];
164 char what_we_think_sig_should_be[20]; 203 char what_we_think_sig_should_be[20];
165 204
166 if ((cifs_pdu == NULL) || (mac_key == NULL)) 205 if (cifs_pdu == NULL || server == NULL)
167 return -EINVAL; 206 return -EINVAL;
168 207
169 if (cifs_pdu->Command == SMB_COM_NEGOTIATE) 208 if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
@@ -192,7 +231,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
192 cpu_to_le32(expected_sequence_number); 231 cpu_to_le32(expected_sequence_number);
193 cifs_pdu->Signature.Sequence.Reserved = 0; 232 cifs_pdu->Signature.Sequence.Reserved = 0;
194 233
195 rc = cifs_calculate_signature(cifs_pdu, mac_key, 234 rc = cifs_calculate_signature(cifs_pdu, server,
196 what_we_think_sig_should_be); 235 what_we_think_sig_should_be);
197 236
198 if (rc) 237 if (rc)
@@ -209,7 +248,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
209} 248}
210 249
211/* We fill in key by putting in 40 byte array which was allocated by caller */ 250/* We fill in key by putting in 40 byte array which was allocated by caller */
212int cifs_calculate_mac_key(struct mac_key *key, const char *rn, 251int cifs_calculate_session_key(struct session_key *key, const char *rn,
213 const char *password) 252 const char *password)
214{ 253{
215 char temp_key[16]; 254 char temp_key[16];
@@ -223,63 +262,6 @@ int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
223 return 0; 262 return 0;
224} 263}
225 264
226int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
227 const struct nls_table *nls_info)
228{
229 char temp_hash[16];
230 struct HMACMD5Context ctx;
231 char *ucase_buf;
232 __le16 *unicode_buf;
233 unsigned int i, user_name_len, dom_name_len;
234
235 if (ses == NULL)
236 return -EINVAL;
237
238 E_md4hash(ses->password, temp_hash);
239
240 hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
241 user_name_len = strlen(ses->userName);
242 if (user_name_len > MAX_USERNAME_SIZE)
243 return -EINVAL;
244 if (ses->domainName == NULL)
245 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
246 dom_name_len = strlen(ses->domainName);
247 if (dom_name_len > MAX_USERNAME_SIZE)
248 return -EINVAL;
249
250 ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
251 if (ucase_buf == NULL)
252 return -ENOMEM;
253 unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
254 if (unicode_buf == NULL) {
255 kfree(ucase_buf);
256 return -ENOMEM;
257 }
258
259 for (i = 0; i < user_name_len; i++)
260 ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
261 ucase_buf[i] = 0;
262 user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
263 MAX_USERNAME_SIZE*2, nls_info);
264 unicode_buf[user_name_len] = 0;
265 user_name_len++;
266
267 for (i = 0; i < dom_name_len; i++)
268 ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
269 ucase_buf[i] = 0;
270 dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
271 MAX_USERNAME_SIZE*2, nls_info);
272
273 unicode_buf[user_name_len + dom_name_len] = 0;
274 hmac_md5_update((const unsigned char *) unicode_buf,
275 (user_name_len+dom_name_len)*2, &ctx);
276
277 hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
278 kfree(ucase_buf);
279 kfree(unicode_buf);
280 return 0;
281}
282
283#ifdef CONFIG_CIFS_WEAK_PW_HASH 265#ifdef CONFIG_CIFS_WEAK_PW_HASH
284void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, 266void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
285 char *lnm_session_key) 267 char *lnm_session_key)
@@ -324,38 +306,52 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
324{ 306{
325 int rc = 0; 307 int rc = 0;
326 int len; 308 int len;
327 char nt_hash[16]; 309 char nt_hash[CIFS_NTHASH_SIZE];
328 struct HMACMD5Context *pctxt;
329 wchar_t *user; 310 wchar_t *user;
330 wchar_t *domain; 311 wchar_t *domain;
312 wchar_t *server;
331 313
332 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); 314 if (!ses->server->ntlmssp.sdeschmacmd5) {
333 315 cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
334 if (pctxt == NULL) 316 return -1;
335 return -ENOMEM; 317 }
336 318
337 /* calculate md4 hash of password */ 319 /* calculate md4 hash of password */
338 E_md4hash(ses->password, nt_hash); 320 E_md4hash(ses->password, nt_hash);
339 321
340 /* convert Domainname to unicode and uppercase */ 322 crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash,
341 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); 323 CIFS_NTHASH_SIZE);
324
325 rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash);
326 if (rc) {
327 cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n");
328 return rc;
329 }
342 330
343 /* convert ses->userName to unicode and uppercase */ 331 /* convert ses->userName to unicode and uppercase */
344 len = strlen(ses->userName); 332 len = strlen(ses->userName);
345 user = kmalloc(2 + (len * 2), GFP_KERNEL); 333 user = kmalloc(2 + (len * 2), GFP_KERNEL);
346 if (user == NULL) 334 if (user == NULL) {
335 cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
336 rc = -ENOMEM;
347 goto calc_exit_2; 337 goto calc_exit_2;
338 }
348 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); 339 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
349 UniStrupr(user); 340 UniStrupr(user);
350 hmac_md5_update((char *)user, 2*len, pctxt); 341
342 crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
343 (char *)user, 2 * len);
351 344
352 /* convert ses->domainName to unicode and uppercase */ 345 /* convert ses->domainName to unicode and uppercase */
353 if (ses->domainName) { 346 if (ses->domainName) {
354 len = strlen(ses->domainName); 347 len = strlen(ses->domainName);
355 348
356 domain = kmalloc(2 + (len * 2), GFP_KERNEL); 349 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
357 if (domain == NULL) 350 if (domain == NULL) {
351 cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
352 rc = -ENOMEM;
358 goto calc_exit_1; 353 goto calc_exit_1;
354 }
359 len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, 355 len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
360 nls_cp); 356 nls_cp);
361 /* the following line was removed since it didn't work well 357 /* the following line was removed since it didn't work well
@@ -363,65 +359,292 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
363 Maybe converting the domain name earlier makes sense */ 359 Maybe converting the domain name earlier makes sense */
364 /* UniStrupr(domain); */ 360 /* UniStrupr(domain); */
365 361
366 hmac_md5_update((char *)domain, 2*len, pctxt); 362 crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
363 (char *)domain, 2 * len);
367 364
368 kfree(domain); 365 kfree(domain);
366 } else if (ses->serverName) {
367 len = strlen(ses->serverName);
368
369 server = kmalloc(2 + (len * 2), GFP_KERNEL);
370 if (server == NULL) {
371 cERROR(1, "calc_ntlmv2_hash: server mem alloc failure");
372 rc = -ENOMEM;
373 goto calc_exit_1;
374 }
375 len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
376 nls_cp);
377 /* the following line was removed since it didn't work well
378 with lower cased domain name that passed as an option.
379 Maybe converting the domain name earlier makes sense */
380 /* UniStrupr(domain); */
381
382 crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
383 (char *)server, 2 * len);
384
385 kfree(server);
369 } 386 }
387
388 rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash,
389 ses->server->ntlmv2_hash);
390
370calc_exit_1: 391calc_exit_1:
371 kfree(user); 392 kfree(user);
372calc_exit_2: 393calc_exit_2:
373 /* BB FIXME what about bytes 24 through 40 of the signing key? 394 /* BB FIXME what about bytes 24 through 40 of the signing key?
374 compare with the NTLM example */ 395 compare with the NTLM example */
375 hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
376 396
377 kfree(pctxt);
378 return rc; 397 return rc;
379} 398}
380 399
381void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, 400static int
382 const struct nls_table *nls_cp) 401find_domain_name(struct cifsSesInfo *ses)
402{
403 int rc = 0;
404 unsigned int attrsize;
405 unsigned int type;
406 unsigned char *blobptr;
407 struct ntlmssp2_name *attrptr;
408
409 if (ses->server->tiblob) {
410 blobptr = ses->server->tiblob;
411 attrptr = (struct ntlmssp2_name *) blobptr;
412
413 while ((type = attrptr->type) != 0) {
414 blobptr += 2; /* advance attr type */
415 attrsize = attrptr->length;
416 blobptr += 2; /* advance attr size */
417 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
418 if (!ses->domainName) {
419 ses->domainName =
420 kmalloc(attrptr->length + 1,
421 GFP_KERNEL);
422 if (!ses->domainName)
423 return -ENOMEM;
424 cifs_from_ucs2(ses->domainName,
425 (__le16 *)blobptr,
426 attrptr->length,
427 attrptr->length,
428 load_nls_default(), false);
429 }
430 }
431 blobptr += attrsize; /* advance attr value */
432 attrptr = (struct ntlmssp2_name *) blobptr;
433 }
434 } else {
435 ses->server->tilen = 2 * sizeof(struct ntlmssp2_name);
436 ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL);
437 if (!ses->server->tiblob) {
438 ses->server->tilen = 0;
439 cERROR(1, "Challenge target info allocation failure");
440 return -ENOMEM;
441 }
442 memset(ses->server->tiblob, 0x0, ses->server->tilen);
443 attrptr = (struct ntlmssp2_name *) ses->server->tiblob;
444 attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
445 }
446
447 return rc;
448}
449
450static int
451CalcNTLMv2_response(const struct TCP_Server_Info *server,
452 char *v2_session_response)
383{ 453{
384 int rc; 454 int rc;
455
456 if (!server->ntlmssp.sdeschmacmd5) {
457 cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
458 return -1;
459 }
460
461 crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash,
462 CIFS_HMAC_MD5_HASH_SIZE);
463
464 rc = crypto_shash_init(&server->ntlmssp.sdeschmacmd5->shash);
465 if (rc) {
466 cERROR(1, "CalcNTLMv2_response: could not init hmacmd5");
467 return rc;
468 }
469
470 memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE,
471 server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE);
472 crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash,
473 v2_session_response + CIFS_SERVER_CHALLENGE_SIZE,
474 sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE);
475
476 if (server->tilen)
477 crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash,
478 server->tiblob, server->tilen);
479
480 rc = crypto_shash_final(&server->ntlmssp.sdeschmacmd5->shash,
481 v2_session_response);
482
483 return rc;
484}
485
486int
487setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
488 const struct nls_table *nls_cp)
489{
490 int rc = 0;
385 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; 491 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
386 struct HMACMD5Context context;
387 492
388 buf->blob_signature = cpu_to_le32(0x00000101); 493 buf->blob_signature = cpu_to_le32(0x00000101);
389 buf->reserved = 0; 494 buf->reserved = 0;
390 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 495 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
391 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 496 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
392 buf->reserved2 = 0; 497 buf->reserved2 = 0;
393 buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); 498
394 buf->names[0].length = 0; 499 if (!ses->domainName) {
395 buf->names[1].type = 0; 500 rc = find_domain_name(ses);
396 buf->names[1].length = 0; 501 if (rc) {
502 cERROR(1, "could not get domain/server name rc %d", rc);
503 return rc;
504 }
505 }
397 506
398 /* calculate buf->ntlmv2_hash */ 507 /* calculate buf->ntlmv2_hash */
399 rc = calc_ntlmv2_hash(ses, nls_cp); 508 rc = calc_ntlmv2_hash(ses, nls_cp);
400 if (rc) 509 if (rc) {
401 cERROR(1, "could not get v2 hash rc %d", rc); 510 cERROR(1, "could not get v2 hash rc %d", rc);
402 CalcNTLMv2_response(ses, resp_buf); 511 return rc;
512 }
513 rc = CalcNTLMv2_response(ses->server, resp_buf);
514 if (rc) {
515 cERROR(1, "could not get v2 hash rc %d", rc);
516 return rc;
517 }
403 518
404 /* now calculate the MAC key for NTLMv2 */ 519 if (!ses->server->ntlmssp.sdeschmacmd5) {
405 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 520 cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
406 hmac_md5_update(resp_buf, 16, &context); 521 return -1;
407 hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); 522 }
408 523
409 memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, 524 crypto_shash_setkey(ses->server->ntlmssp.hmacmd5,
410 sizeof(struct ntlmv2_resp)); 525 ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
411 ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); 526
527 rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash);
528 if (rc) {
529 cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n");
530 return rc;
531 }
532
533 crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
534 resp_buf, CIFS_HMAC_MD5_HASH_SIZE);
535
536 rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash,
537 ses->server->session_key.data.ntlmv2.key);
538
539 memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf,
540 sizeof(struct ntlmv2_resp));
541 ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp);
542
543 return rc;
412} 544}
413 545
414void CalcNTLMv2_response(const struct cifsSesInfo *ses, 546int
415 char *v2_session_response) 547calc_seckey(struct TCP_Server_Info *server)
416{ 548{
417 struct HMACMD5Context context; 549 int rc;
418 /* rest of v2 struct already generated */ 550 unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE];
419 memcpy(v2_session_response + 8, ses->server->cryptKey, 8); 551 struct crypto_blkcipher *tfm_arc4;
420 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 552 struct scatterlist sgin, sgout;
553 struct blkcipher_desc desc;
554
555 get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE);
556
557 tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)",
558 0, CRYPTO_ALG_ASYNC);
559 if (!tfm_arc4 || IS_ERR(tfm_arc4)) {
560 cERROR(1, "could not allocate " "master crypto API arc4\n");
561 return 1;
562 }
563
564 desc.tfm = tfm_arc4;
565
566 crypto_blkcipher_setkey(tfm_arc4,
567 server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE);
568 sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE);
569 sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
570 rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
421 571
422 hmac_md5_update(v2_session_response+8, 572 if (!rc)
423 sizeof(struct ntlmv2_resp) - 8, &context); 573 memcpy(server->session_key.data.ntlmv2.key,
574 sec_key, CIFS_NTLMV2_SESSKEY_SIZE);
575
576 crypto_free_blkcipher(tfm_arc4);
577
578 return 0;
579}
424 580
425 hmac_md5_final(v2_session_response, &context); 581void
426/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ 582cifs_crypto_shash_release(struct TCP_Server_Info *server)
583{
584 if (server->ntlmssp.md5)
585 crypto_free_shash(server->ntlmssp.md5);
586
587 if (server->ntlmssp.hmacmd5)
588 crypto_free_shash(server->ntlmssp.hmacmd5);
589
590 kfree(server->ntlmssp.sdeschmacmd5);
591
592 kfree(server->ntlmssp.sdescmd5);
593}
594
595int
596cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
597{
598 int rc;
599 unsigned int size;
600
601 server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
602 if (!server->ntlmssp.hmacmd5 ||
603 IS_ERR(server->ntlmssp.hmacmd5)) {
604 cERROR(1, "could not allocate crypto hmacmd5\n");
605 return 1;
606 }
607
608 server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0);
609 if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) {
610 cERROR(1, "could not allocate crypto md5\n");
611 rc = 1;
612 goto cifs_crypto_shash_allocate_ret1;
613 }
614
615 size = sizeof(struct shash_desc) +
616 crypto_shash_descsize(server->ntlmssp.hmacmd5);
617 server->ntlmssp.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
618 if (!server->ntlmssp.sdeschmacmd5) {
619 cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n");
620 rc = -ENOMEM;
621 goto cifs_crypto_shash_allocate_ret2;
622 }
623 server->ntlmssp.sdeschmacmd5->shash.tfm = server->ntlmssp.hmacmd5;
624 server->ntlmssp.sdeschmacmd5->shash.flags = 0x0;
625
626
627 size = sizeof(struct shash_desc) +
628 crypto_shash_descsize(server->ntlmssp.md5);
629 server->ntlmssp.sdescmd5 = kmalloc(size, GFP_KERNEL);
630 if (!server->ntlmssp.sdescmd5) {
631 cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n");
632 rc = -ENOMEM;
633 goto cifs_crypto_shash_allocate_ret3;
634 }
635 server->ntlmssp.sdescmd5->shash.tfm = server->ntlmssp.md5;
636 server->ntlmssp.sdescmd5->shash.flags = 0x0;
637
638 return 0;
639
640cifs_crypto_shash_allocate_ret3:
641 kfree(server->ntlmssp.sdeschmacmd5);
642
643cifs_crypto_shash_allocate_ret2:
644 crypto_free_shash(server->ntlmssp.md5);
645
646cifs_crypto_shash_allocate_ret1:
647 crypto_free_shash(server->ntlmssp.hmacmd5);
648
649 return rc;
427} 650}