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.c195
1 files changed, 136 insertions, 59 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index eaa2327ee7af..96908874a45c 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -45,17 +45,30 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
46 struct TCP_Server_Info *server, char *signature) 46 struct TCP_Server_Info *server, char *signature)
47{ 47{
48 struct MD5Context context; 48 int rc;
49 49
50 if (cifs_pdu == NULL || signature == NULL || server == NULL) 50 if (cifs_pdu == NULL || signature == NULL || server == NULL)
51 return -EINVAL; 51 return -EINVAL;
52 52
53 cifs_MD5_init(&context); 53 if (!server->secmech.sdescmd5) {
54 cifs_MD5_update(&context, server->session_key.response, 54 cERROR(1, "%s: Can't generate signature\n", __func__);
55 server->session_key.len); 55 return -1;
56 cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); 56 }
57
58 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
59 if (rc) {
60 cERROR(1, "%s: Oould not init md5\n", __func__);
61 return rc;
62 }
63
64 crypto_shash_update(&server->secmech.sdescmd5->shash,
65 server->session_key.response, server->session_key.len);
66
67 crypto_shash_update(&server->secmech.sdescmd5->shash,
68 cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
69
70 rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
57 71
58 cifs_MD5_final(signature, &context);
59 return 0; 72 return 0;
60} 73}
61 74
@@ -92,15 +105,26 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
92static int cifs_calc_signature2(const struct kvec *iov, int n_vec, 105static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
93 struct TCP_Server_Info *server, char *signature) 106 struct TCP_Server_Info *server, char *signature)
94{ 107{
95 struct MD5Context context;
96 int i; 108 int i;
109 int rc;
97 110
98 if (iov == NULL || signature == NULL || server == NULL) 111 if (iov == NULL || signature == NULL || server == NULL)
99 return -EINVAL; 112 return -EINVAL;
100 113
101 cifs_MD5_init(&context); 114 if (!server->secmech.sdescmd5) {
102 cifs_MD5_update(&context, server->session_key.response, 115 cERROR(1, "%s: Can't generate signature\n", __func__);
103 server->session_key.len); 116 return -1;
117 }
118
119 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
120 if (rc) {
121 cERROR(1, "%s: Oould not init md5\n", __func__);
122 return rc;
123 }
124
125 crypto_shash_update(&server->secmech.sdescmd5->shash,
126 server->session_key.response, server->session_key.len);
127
104 for (i = 0; i < n_vec; i++) { 128 for (i = 0; i < n_vec; i++) {
105 if (iov[i].iov_len == 0) 129 if (iov[i].iov_len == 0)
106 continue; 130 continue;
@@ -113,18 +137,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
113 if (i == 0) { 137 if (i == 0) {
114 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ 138 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
115 break; /* nothing to sign or corrupt header */ 139 break; /* nothing to sign or corrupt header */
116 cifs_MD5_update(&context, iov[0].iov_base+4, 140 crypto_shash_update(&server->secmech.sdescmd5->shash,
117 iov[0].iov_len-4); 141 iov[i].iov_base + 4, iov[i].iov_len - 4);
118 } else 142 } else
119 cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); 143 crypto_shash_update(&server->secmech.sdescmd5->shash,
144 iov[i].iov_base, iov[i].iov_len);
120 } 145 }
121 146
122 cifs_MD5_final(signature, &context); 147 rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
123 148
124 return 0; 149 return rc;
125} 150}
126 151
127
128int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, 152int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
129 __u32 *pexpected_response_sequence_number) 153 __u32 *pexpected_response_sequence_number)
130{ 154{
@@ -420,67 +444,120 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
420{ 444{
421 int rc = 0; 445 int rc = 0;
422 int len; 446 int len;
423 char nt_hash[16]; 447 char nt_hash[CIFS_NTHASH_SIZE];
424 struct HMACMD5Context *pctxt;
425 wchar_t *user; 448 wchar_t *user;
426 wchar_t *domain; 449 wchar_t *domain;
450 wchar_t *server;
427 451
428 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); 452 if (!ses->server->secmech.sdeschmacmd5) {
429 453 cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
430 if (pctxt == NULL) 454 return -1;
431 return -ENOMEM; 455 }
432 456
433 /* calculate md4 hash of password */ 457 /* calculate md4 hash of password */
434 E_md4hash(ses->password, nt_hash); 458 E_md4hash(ses->password, nt_hash);
435 459
436 /* convert Domainname to unicode and uppercase */ 460 crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
437 hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); 461 CIFS_NTHASH_SIZE);
462
463 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
464 if (rc) {
465 cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n");
466 return rc;
467 }
438 468
439 /* convert ses->userName to unicode and uppercase */ 469 /* convert ses->userName to unicode and uppercase */
440 len = strlen(ses->userName); 470 len = strlen(ses->userName);
441 user = kmalloc(2 + (len * 2), GFP_KERNEL); 471 user = kmalloc(2 + (len * 2), GFP_KERNEL);
442 if (user == NULL) 472 if (user == NULL) {
473 cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
474 rc = -ENOMEM;
443 goto calc_exit_2; 475 goto calc_exit_2;
476 }
444 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); 477 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
445 UniStrupr(user); 478 UniStrupr(user);
446 hmac_md5_update((char *)user, 2*len, pctxt); 479
480 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
481 (char *)user, 2 * len);
447 482
448 /* convert ses->domainName to unicode and uppercase */ 483 /* convert ses->domainName to unicode and uppercase */
449 if (ses->domainName) { 484 if (ses->domainName) {
450 len = strlen(ses->domainName); 485 len = strlen(ses->domainName);
451 486
452 domain = kmalloc(2 + (len * 2), GFP_KERNEL); 487 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
453 if (domain == NULL) 488 if (domain == NULL) {
489 cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
490 rc = -ENOMEM;
454 goto calc_exit_1; 491 goto calc_exit_1;
492 }
455 len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, 493 len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
456 nls_cp); 494 nls_cp);
457 /* the following line was removed since it didn't work well 495 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
458 with lower cased domain name that passed as an option. 496 (char *)domain, 2 * len);
459 Maybe converting the domain name earlier makes sense */
460 /* UniStrupr(domain); */
461
462 hmac_md5_update((char *)domain, 2*len, pctxt);
463
464 kfree(domain); 497 kfree(domain);
498 } else if (ses->serverName) {
499 len = strlen(ses->serverName);
500
501 server = kmalloc(2 + (len * 2), GFP_KERNEL);
502 if (server == NULL) {
503 cERROR(1, "calc_ntlmv2_hash: server mem alloc failure");
504 rc = -ENOMEM;
505 goto calc_exit_1;
506 }
507 len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
508 nls_cp);
509 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
510 (char *)server, 2 * len);
511 kfree(server);
465 } 512 }
513
514 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
515 ses->ntlmv2_hash);
516
466calc_exit_1: 517calc_exit_1:
467 kfree(user); 518 kfree(user);
468calc_exit_2: 519calc_exit_2:
469 /* BB FIXME what about bytes 24 through 40 of the signing key? 520 return rc;
470 compare with the NTLM example */ 521}
471 hmac_md5_final(ses->ntlmv2_hash, pctxt); 522
523static int
524CalcNTLMv2_response(const struct cifsSesInfo *ses)
525{
526 int rc;
527 unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
528
529 if (!ses->server->secmech.sdeschmacmd5) {
530 cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
531 return -1;
532 }
533
534 crypto_shash_setkey(ses->server->secmech.hmacmd5,
535 ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
536
537 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
538 if (rc) {
539 cERROR(1, "CalcNTLMv2_response: could not init hmacmd5");
540 return rc;
541 }
542
543 memcpy(ses->auth_key.response + offset,
544 ses->cryptKey, CIFS_SERVER_CHALLENGE_SIZE);
545 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
546 ses->auth_key.response + offset, ses->auth_key.len - offset);
547
548 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
549 ses->auth_key.response + CIFS_SESS_KEY_SIZE);
472 550
473 kfree(pctxt);
474 return rc; 551 return rc;
475} 552}
476 553
554
477int 555int
478setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp) 556setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
479{ 557{
480 int rc; 558 int rc;
481 int baselen; 559 int baselen;
482 struct ntlmv2_resp *buf; 560 struct ntlmv2_resp *buf;
483 struct HMACMD5Context context;
484 561
485 if (ses->server->secType == RawNTLMSSP) { 562 if (ses->server->secType == RawNTLMSSP) {
486 if (!ses->domainName) { 563 if (!ses->domainName) {
@@ -523,13 +600,28 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
523 cERROR(1, "could not get v2 hash rc %d", rc); 600 cERROR(1, "could not get v2 hash rc %d", rc);
524 goto setup_ntlmv2_rsp_ret; 601 goto setup_ntlmv2_rsp_ret;
525 } 602 }
526 CalcNTLMv2_response(ses); 603 rc = CalcNTLMv2_response(ses);
604 if (rc) {
605 cERROR(1, "Could not calculate CR1 rc: %d", rc);
606 goto setup_ntlmv2_rsp_ret;
607 }
527 608
528 /* now calculate the session key for NTLMv2 */ 609 /* now calculate the session key for NTLMv2 */
529 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context); 610 crypto_shash_setkey(ses->server->secmech.hmacmd5,
530 hmac_md5_update(ses->auth_key.response + CIFS_SESS_KEY_SIZE, 611 ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
531 16, &context); 612
532 hmac_md5_final(ses->auth_key.response, &context); 613 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
614 if (rc) {
615 cERROR(1, "%s: Could not init hmacmd5\n", __func__);
616 goto setup_ntlmv2_rsp_ret;
617 }
618
619 crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
620 ses->auth_key.response + CIFS_SESS_KEY_SIZE,
621 CIFS_HMAC_MD5_HASH_SIZE);
622
623 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
624 ses->auth_key.response);
533 625
534 return 0; 626 return 0;
535 627
@@ -653,18 +745,3 @@ crypto_allocate_md5_fail:
653 745
654 return rc; 746 return rc;
655} 747}
656
657void CalcNTLMv2_response(const struct cifsSesInfo *ses)
658{
659 unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
660 struct HMACMD5Context context;
661
662 /* rest of v2 struct already generated */
663 memcpy(ses->auth_key.response + offset, ses->cryptKey, 8);
664 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
665
666 hmac_md5_update(ses->auth_key.response + offset,
667 ses->auth_key.len - offset, &context);
668
669 hmac_md5_final(ses->auth_key.response + CIFS_SESS_KEY_SIZE, &context);
670}