aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsencrypt.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-10-11 07:45:22 -0400
committerTakashi Iwai <tiwai@suse.de>2010-10-11 07:45:22 -0400
commit4e83998f5af010a928495988c586ea2926624db9 (patch)
treee72d346172a30bbee165d7f585784724906da416 /fs/cifs/cifsencrypt.c
parentdd1d3a49db4ae5c6afffadaff526b96c7993c7dd (diff)
parentd4cfa4d12f46e2520f4c1d1a92e891ce068b7464 (diff)
Merge branch 'fix/misc' into topic/misc
Diffstat (limited to 'fs/cifs/cifsencrypt.c')
-rw-r--r--fs/cifs/cifsencrypt.c418
1 files changed, 69 insertions, 349 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 709f2296bdb4..35042d8f7338 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -27,7 +27,6 @@
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"
31#include <linux/ctype.h> 30#include <linux/ctype.h>
32#include <linux/random.h> 31#include <linux/random.h>
33 32
@@ -43,43 +42,21 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
43 unsigned char *p24); 42 unsigned char *p24);
44 43
45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 44static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
46 struct TCP_Server_Info *server, char *signature) 45 const struct mac_key *key, char *signature)
47{ 46{
48 int rc; 47 struct MD5Context context;
49 48
50 if (cifs_pdu == NULL || server == NULL || signature == NULL) 49 if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
51 return -EINVAL; 50 return -EINVAL;
52 51
53 if (!server->ntlmssp.sdescmd5) { 52 cifs_MD5_init(&context);
54 cERROR(1, 53 cifs_MD5_update(&context, (char *)&key->data, key->len);
55 "cifs_calculate_signature: can't generate signature\n"); 54 cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
56 return -1;
57 }
58
59 rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash);
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 55
77 rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); 56 cifs_MD5_final(signature, &context);
78 57 return 0;
79 return rc;
80} 58}
81 59
82
83int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, 60int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
84 __u32 *pexpected_response_sequence_number) 61 __u32 *pexpected_response_sequence_number)
85{ 62{
@@ -101,7 +78,8 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
101 server->sequence_number++; 78 server->sequence_number++;
102 spin_unlock(&GlobalMid_Lock); 79 spin_unlock(&GlobalMid_Lock);
103 80
104 rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); 81 rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key,
82 smb_signature);
105 if (rc) 83 if (rc)
106 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 84 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
107 else 85 else
@@ -111,39 +89,21 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
111} 89}
112 90
113static int cifs_calc_signature2(const struct kvec *iov, int n_vec, 91static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
114 struct TCP_Server_Info *server, char *signature) 92 const struct mac_key *key, char *signature)
115{ 93{
94 struct MD5Context context;
116 int i; 95 int i;
117 int rc;
118 96
119 if (iov == NULL || server == NULL || signature == NULL) 97 if ((iov == NULL) || (signature == NULL) || (key == NULL))
120 return -EINVAL; 98 return -EINVAL;
121 99
122 if (!server->ntlmssp.sdescmd5) { 100 cifs_MD5_init(&context);
123 cERROR(1, "cifs_calc_signature2: can't generate signature\n"); 101 cifs_MD5_update(&context, (char *)&key->data, key->len);
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
142 for (i = 0; i < n_vec; i++) { 102 for (i = 0; i < n_vec; i++) {
143 if (iov[i].iov_len == 0) 103 if (iov[i].iov_len == 0)
144 continue; 104 continue;
145 if (iov[i].iov_base == NULL) { 105 if (iov[i].iov_base == NULL) {
146 cERROR(1, "cifs_calc_signature2: null iovec entry"); 106 cERROR(1, "null iovec entry");
147 return -EIO; 107 return -EIO;
148 } 108 }
149 /* The first entry includes a length field (which does not get 109 /* The first entry includes a length field (which does not get
@@ -151,18 +111,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
151 if (i == 0) { 111 if (i == 0) {
152 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ 112 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
153 break; /* nothing to sign or corrupt header */ 113 break; /* nothing to sign or corrupt header */
154 crypto_shash_update(&server->ntlmssp.sdescmd5->shash, 114 cifs_MD5_update(&context, iov[0].iov_base+4,
155 iov[i].iov_base + 4, iov[i].iov_len - 4); 115 iov[0].iov_len-4);
156 } else 116 } else
157 crypto_shash_update(&server->ntlmssp.sdescmd5->shash, 117 cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len);
158 iov[i].iov_base, iov[i].iov_len);
159 } 118 }
160 119
161 rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); 120 cifs_MD5_final(signature, &context);
162 121
163 return rc; 122 return 0;
164} 123}
165 124
125
166int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, 126int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
167 __u32 *pexpected_response_sequence_number) 127 __u32 *pexpected_response_sequence_number)
168{ 128{
@@ -185,7 +145,8 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
185 server->sequence_number++; 145 server->sequence_number++;
186 spin_unlock(&GlobalMid_Lock); 146 spin_unlock(&GlobalMid_Lock);
187 147
188 rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); 148 rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key,
149 smb_signature);
189 if (rc) 150 if (rc)
190 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 151 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
191 else 152 else
@@ -195,14 +156,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
195} 156}
196 157
197int cifs_verify_signature(struct smb_hdr *cifs_pdu, 158int cifs_verify_signature(struct smb_hdr *cifs_pdu,
198 struct TCP_Server_Info *server, 159 const struct mac_key *mac_key,
199 __u32 expected_sequence_number) 160 __u32 expected_sequence_number)
200{ 161{
201 int rc; 162 unsigned int rc;
202 char server_response_sig[8]; 163 char server_response_sig[8];
203 char what_we_think_sig_should_be[20]; 164 char what_we_think_sig_should_be[20];
204 165
205 if (cifs_pdu == NULL || server == NULL) 166 if ((cifs_pdu == NULL) || (mac_key == NULL))
206 return -EINVAL; 167 return -EINVAL;
207 168
208 if (cifs_pdu->Command == SMB_COM_NEGOTIATE) 169 if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
@@ -231,7 +192,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
231 cpu_to_le32(expected_sequence_number); 192 cpu_to_le32(expected_sequence_number);
232 cifs_pdu->Signature.Sequence.Reserved = 0; 193 cifs_pdu->Signature.Sequence.Reserved = 0;
233 194
234 rc = cifs_calculate_signature(cifs_pdu, server, 195 rc = cifs_calculate_signature(cifs_pdu, mac_key,
235 what_we_think_sig_should_be); 196 what_we_think_sig_should_be);
236 197
237 if (rc) 198 if (rc)
@@ -248,7 +209,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
248} 209}
249 210
250/* We fill in key by putting in 40 byte array which was allocated by caller */ 211/* We fill in key by putting in 40 byte array which was allocated by caller */
251int cifs_calculate_session_key(struct session_key *key, const char *rn, 212int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
252 const char *password) 213 const char *password)
253{ 214{
254 char temp_key[16]; 215 char temp_key[16];
@@ -306,52 +267,38 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
306{ 267{
307 int rc = 0; 268 int rc = 0;
308 int len; 269 int len;
309 char nt_hash[CIFS_NTHASH_SIZE]; 270 char nt_hash[16];
271 struct HMACMD5Context *pctxt;
310 wchar_t *user; 272 wchar_t *user;
311 wchar_t *domain; 273 wchar_t *domain;
312 wchar_t *server;
313 274
314 if (!ses->server->ntlmssp.sdeschmacmd5) { 275 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
315 cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); 276
316 return -1; 277 if (pctxt == NULL)
317 } 278 return -ENOMEM;
318 279
319 /* calculate md4 hash of password */ 280 /* calculate md4 hash of password */
320 E_md4hash(ses->password, nt_hash); 281 E_md4hash(ses->password, nt_hash);
321 282
322 crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash, 283 /* convert Domainname to unicode and uppercase */
323 CIFS_NTHASH_SIZE); 284 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
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 }
330 285
331 /* convert ses->userName to unicode and uppercase */ 286 /* convert ses->userName to unicode and uppercase */
332 len = strlen(ses->userName); 287 len = strlen(ses->userName);
333 user = kmalloc(2 + (len * 2), GFP_KERNEL); 288 user = kmalloc(2 + (len * 2), GFP_KERNEL);
334 if (user == NULL) { 289 if (user == NULL)
335 cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
336 rc = -ENOMEM;
337 goto calc_exit_2; 290 goto calc_exit_2;
338 }
339 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); 291 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
340 UniStrupr(user); 292 UniStrupr(user);
341 293 hmac_md5_update((char *)user, 2*len, pctxt);
342 crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash,
343 (char *)user, 2 * len);
344 294
345 /* convert ses->domainName to unicode and uppercase */ 295 /* convert ses->domainName to unicode and uppercase */
346 if (ses->domainName) { 296 if (ses->domainName) {
347 len = strlen(ses->domainName); 297 len = strlen(ses->domainName);
348 298
349 domain = kmalloc(2 + (len * 2), GFP_KERNEL); 299 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
350 if (domain == NULL) { 300 if (domain == NULL)
351 cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
352 rc = -ENOMEM;
353 goto calc_exit_1; 301 goto calc_exit_1;
354 }
355 len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, 302 len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
356 nls_cp); 303 nls_cp);
357 /* the following line was removed since it didn't work well 304 /* the following line was removed since it didn't work well
@@ -359,292 +306,65 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
359 Maybe converting the domain name earlier makes sense */ 306 Maybe converting the domain name earlier makes sense */
360 /* UniStrupr(domain); */ 307 /* UniStrupr(domain); */
361 308
362 crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, 309 hmac_md5_update((char *)domain, 2*len, pctxt);
363 (char *)domain, 2 * len);
364 310
365 kfree(domain); 311 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);
386 } 312 }
387
388 rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash,
389 ses->server->ntlmv2_hash);
390
391calc_exit_1: 313calc_exit_1:
392 kfree(user); 314 kfree(user);
393calc_exit_2: 315calc_exit_2:
394 /* BB FIXME what about bytes 24 through 40 of the signing key? 316 /* BB FIXME what about bytes 24 through 40 of the signing key?
395 compare with the NTLM example */ 317 compare with the NTLM example */
318 hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
396 319
320 kfree(pctxt);
397 return rc; 321 return rc;
398} 322}
399 323
400static int 324void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
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)
453{
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) 325 const struct nls_table *nls_cp)
489{ 326{
490 int rc = 0; 327 int rc;
491 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; 328 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
329 struct HMACMD5Context context;
492 330
493 buf->blob_signature = cpu_to_le32(0x00000101); 331 buf->blob_signature = cpu_to_le32(0x00000101);
494 buf->reserved = 0; 332 buf->reserved = 0;
495 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 333 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
496 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 334 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
497 buf->reserved2 = 0; 335 buf->reserved2 = 0;
498 336 buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
499 if (!ses->domainName) { 337 buf->names[0].length = 0;
500 rc = find_domain_name(ses); 338 buf->names[1].type = 0;
501 if (rc) { 339 buf->names[1].length = 0;
502 cERROR(1, "could not get domain/server name rc %d", rc);
503 return rc;
504 }
505 }
506 340
507 /* calculate buf->ntlmv2_hash */ 341 /* calculate buf->ntlmv2_hash */
508 rc = calc_ntlmv2_hash(ses, nls_cp); 342 rc = calc_ntlmv2_hash(ses, nls_cp);
509 if (rc) { 343 if (rc)
510 cERROR(1, "could not get v2 hash rc %d", rc);
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); 344 cERROR(1, "could not get v2 hash rc %d", rc);
516 return rc; 345 CalcNTLMv2_response(ses, resp_buf);
517 }
518
519 if (!ses->server->ntlmssp.sdeschmacmd5) {
520 cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
521 return -1;
522 }
523
524 crypto_shash_setkey(ses->server->ntlmssp.hmacmd5,
525 ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
526 346
527 rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); 347 /* now calculate the MAC key for NTLMv2 */
528 if (rc) { 348 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
529 cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n"); 349 hmac_md5_update(resp_buf, 16, &context);
530 return rc; 350 hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
531 }
532 351
533 crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, 352 memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf,
534 resp_buf, CIFS_HMAC_MD5_HASH_SIZE); 353 sizeof(struct ntlmv2_resp));
535 354 ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
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;
544} 355}
545 356
546int 357void CalcNTLMv2_response(const struct cifsSesInfo *ses,
547calc_seckey(struct TCP_Server_Info *server) 358 char *v2_session_response)
548{
549 int rc;
550 unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE];
551 struct crypto_blkcipher *tfm_arc4;
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);
571
572 if (!rc)
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}
580
581void
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{ 359{
598 int rc; 360 struct HMACMD5Context context;
599 unsigned int size; 361 /* rest of v2 struct already generated */
600 362 memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
601 server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); 363 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
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 364
365 hmac_md5_update(v2_session_response+8,
366 sizeof(struct ntlmv2_resp) - 8, &context);
626 367
627 size = sizeof(struct shash_desc) + 368 hmac_md5_final(v2_session_response, &context);
628 crypto_shash_descsize(server->ntlmssp.md5); 369/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
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;
650} 370}