diff options
Diffstat (limited to 'fs/cifs/cifsencrypt.c')
-rw-r--r-- | fs/cifs/cifsencrypt.c | 189 |
1 files changed, 98 insertions, 91 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 71436d1fca13..fc6f4f3a1a9d 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/cifsencrypt.c | 2 | * fs/cifs/cifsencrypt.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2005,2006 | 4 | * Copyright (C) International Business Machines Corp., 2005,2013 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -31,6 +31,37 @@ | |||
31 | #include <linux/random.h> | 31 | #include <linux/random.h> |
32 | #include <linux/highmem.h> | 32 | #include <linux/highmem.h> |
33 | 33 | ||
34 | static int | ||
35 | cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) | ||
36 | { | ||
37 | int rc; | ||
38 | unsigned int size; | ||
39 | |||
40 | if (server->secmech.sdescmd5 != NULL) | ||
41 | return 0; /* already allocated */ | ||
42 | |||
43 | server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); | ||
44 | if (IS_ERR(server->secmech.md5)) { | ||
45 | cifs_dbg(VFS, "could not allocate crypto md5\n"); | ||
46 | rc = PTR_ERR(server->secmech.md5); | ||
47 | server->secmech.md5 = NULL; | ||
48 | return rc; | ||
49 | } | ||
50 | |||
51 | size = sizeof(struct shash_desc) + | ||
52 | crypto_shash_descsize(server->secmech.md5); | ||
53 | server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); | ||
54 | if (!server->secmech.sdescmd5) { | ||
55 | crypto_free_shash(server->secmech.md5); | ||
56 | server->secmech.md5 = NULL; | ||
57 | return -ENOMEM; | ||
58 | } | ||
59 | server->secmech.sdescmd5->shash.tfm = server->secmech.md5; | ||
60 | server->secmech.sdescmd5->shash.flags = 0x0; | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
34 | /* | 65 | /* |
35 | * Calculate and return the CIFS signature based on the mac key and SMB PDU. | 66 | * Calculate and return the CIFS signature based on the mac key and SMB PDU. |
36 | * The 16 byte signature must be allocated by the caller. Note we only use the | 67 | * The 16 byte signature must be allocated by the caller. Note we only use the |
@@ -50,8 +81,11 @@ static int cifs_calc_signature(struct smb_rqst *rqst, | |||
50 | return -EINVAL; | 81 | return -EINVAL; |
51 | 82 | ||
52 | if (!server->secmech.sdescmd5) { | 83 | if (!server->secmech.sdescmd5) { |
53 | cifs_dbg(VFS, "%s: Can't generate signature\n", __func__); | 84 | rc = cifs_crypto_shash_md5_allocate(server); |
54 | return -1; | 85 | if (rc) { |
86 | cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); | ||
87 | return -1; | ||
88 | } | ||
55 | } | 89 | } |
56 | 90 | ||
57 | rc = crypto_shash_init(&server->secmech.sdescmd5->shash); | 91 | rc = crypto_shash_init(&server->secmech.sdescmd5->shash); |
@@ -276,7 +310,6 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | |||
276 | strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); | 310 | strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); |
277 | 311 | ||
278 | if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { | 312 | if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { |
279 | memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); | ||
280 | memcpy(lnm_session_key, password_with_pad, | 313 | memcpy(lnm_session_key, password_with_pad, |
281 | CIFS_ENCPWD_SIZE); | 314 | CIFS_ENCPWD_SIZE); |
282 | return 0; | 315 | return 0; |
@@ -389,7 +422,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) | |||
389 | if (blobptr + attrsize > blobend) | 422 | if (blobptr + attrsize > blobend) |
390 | break; | 423 | break; |
391 | if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { | 424 | if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { |
392 | if (!attrsize) | 425 | if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN) |
393 | break; | 426 | break; |
394 | if (!ses->domainName) { | 427 | if (!ses->domainName) { |
395 | ses->domainName = | 428 | ses->domainName = |
@@ -414,7 +447,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, | |||
414 | int rc = 0; | 447 | int rc = 0; |
415 | int len; | 448 | int len; |
416 | char nt_hash[CIFS_NTHASH_SIZE]; | 449 | char nt_hash[CIFS_NTHASH_SIZE]; |
417 | wchar_t *user; | 450 | __le16 *user; |
418 | wchar_t *domain; | 451 | wchar_t *domain; |
419 | wchar_t *server; | 452 | wchar_t *server; |
420 | 453 | ||
@@ -439,7 +472,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, | |||
439 | return rc; | 472 | return rc; |
440 | } | 473 | } |
441 | 474 | ||
442 | /* convert ses->user_name to unicode and uppercase */ | 475 | /* convert ses->user_name to unicode */ |
443 | len = ses->user_name ? strlen(ses->user_name) : 0; | 476 | len = ses->user_name ? strlen(ses->user_name) : 0; |
444 | user = kmalloc(2 + (len * 2), GFP_KERNEL); | 477 | user = kmalloc(2 + (len * 2), GFP_KERNEL); |
445 | if (user == NULL) { | 478 | if (user == NULL) { |
@@ -448,7 +481,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, | |||
448 | } | 481 | } |
449 | 482 | ||
450 | if (len) { | 483 | if (len) { |
451 | len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp); | 484 | len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp); |
452 | UniStrupr(user); | 485 | UniStrupr(user); |
453 | } else { | 486 | } else { |
454 | memset(user, '\0', 2); | 487 | memset(user, '\0', 2); |
@@ -536,7 +569,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) | |||
536 | return rc; | 569 | return rc; |
537 | } | 570 | } |
538 | 571 | ||
539 | if (ses->server->secType == RawNTLMSSP) | 572 | if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) |
540 | memcpy(ses->auth_key.response + offset, | 573 | memcpy(ses->auth_key.response + offset, |
541 | ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); | 574 | ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); |
542 | else | 575 | else |
@@ -557,6 +590,36 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) | |||
557 | return rc; | 590 | return rc; |
558 | } | 591 | } |
559 | 592 | ||
593 | static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) | ||
594 | { | ||
595 | int rc; | ||
596 | unsigned int size; | ||
597 | |||
598 | /* check if already allocated */ | ||
599 | if (server->secmech.sdeschmacmd5) | ||
600 | return 0; | ||
601 | |||
602 | server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); | ||
603 | if (IS_ERR(server->secmech.hmacmd5)) { | ||
604 | cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); | ||
605 | rc = PTR_ERR(server->secmech.hmacmd5); | ||
606 | server->secmech.hmacmd5 = NULL; | ||
607 | return rc; | ||
608 | } | ||
609 | |||
610 | size = sizeof(struct shash_desc) + | ||
611 | crypto_shash_descsize(server->secmech.hmacmd5); | ||
612 | server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); | ||
613 | if (!server->secmech.sdeschmacmd5) { | ||
614 | crypto_free_shash(server->secmech.hmacmd5); | ||
615 | server->secmech.hmacmd5 = NULL; | ||
616 | return -ENOMEM; | ||
617 | } | ||
618 | server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; | ||
619 | server->secmech.sdeschmacmd5->shash.flags = 0x0; | ||
620 | |||
621 | return 0; | ||
622 | } | ||
560 | 623 | ||
561 | int | 624 | int |
562 | setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) | 625 | setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) |
@@ -568,7 +631,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) | |||
568 | char ntlmv2_hash[16]; | 631 | char ntlmv2_hash[16]; |
569 | unsigned char *tiblob = NULL; /* target info blob */ | 632 | unsigned char *tiblob = NULL; /* target info blob */ |
570 | 633 | ||
571 | if (ses->server->secType == RawNTLMSSP) { | 634 | if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { |
572 | if (!ses->domainName) { | 635 | if (!ses->domainName) { |
573 | rc = find_domain_name(ses, nls_cp); | 636 | rc = find_domain_name(ses, nls_cp); |
574 | if (rc) { | 637 | if (rc) { |
@@ -607,6 +670,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) | |||
607 | 670 | ||
608 | memcpy(ses->auth_key.response + baselen, tiblob, tilen); | 671 | memcpy(ses->auth_key.response + baselen, tiblob, tilen); |
609 | 672 | ||
673 | rc = crypto_hmacmd5_alloc(ses->server); | ||
674 | if (rc) { | ||
675 | cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc); | ||
676 | goto setup_ntlmv2_rsp_ret; | ||
677 | } | ||
678 | |||
610 | /* calculate ntlmv2_hash */ | 679 | /* calculate ntlmv2_hash */ |
611 | rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); | 680 | rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); |
612 | if (rc) { | 681 | if (rc) { |
@@ -706,94 +775,32 @@ calc_seckey(struct cifs_ses *ses) | |||
706 | void | 775 | void |
707 | cifs_crypto_shash_release(struct TCP_Server_Info *server) | 776 | cifs_crypto_shash_release(struct TCP_Server_Info *server) |
708 | { | 777 | { |
709 | if (server->secmech.hmacsha256) | 778 | if (server->secmech.cmacaes) { |
710 | crypto_free_shash(server->secmech.hmacsha256); | 779 | crypto_free_shash(server->secmech.cmacaes); |
711 | 780 | server->secmech.cmacaes = NULL; | |
712 | if (server->secmech.md5) | ||
713 | crypto_free_shash(server->secmech.md5); | ||
714 | |||
715 | if (server->secmech.hmacmd5) | ||
716 | crypto_free_shash(server->secmech.hmacmd5); | ||
717 | |||
718 | kfree(server->secmech.sdeschmacsha256); | ||
719 | |||
720 | kfree(server->secmech.sdeschmacmd5); | ||
721 | |||
722 | kfree(server->secmech.sdescmd5); | ||
723 | } | ||
724 | |||
725 | int | ||
726 | cifs_crypto_shash_allocate(struct TCP_Server_Info *server) | ||
727 | { | ||
728 | int rc; | ||
729 | unsigned int size; | ||
730 | |||
731 | server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); | ||
732 | if (IS_ERR(server->secmech.hmacmd5)) { | ||
733 | cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); | ||
734 | return PTR_ERR(server->secmech.hmacmd5); | ||
735 | } | ||
736 | |||
737 | server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); | ||
738 | if (IS_ERR(server->secmech.md5)) { | ||
739 | cifs_dbg(VFS, "could not allocate crypto md5\n"); | ||
740 | rc = PTR_ERR(server->secmech.md5); | ||
741 | goto crypto_allocate_md5_fail; | ||
742 | } | 781 | } |
743 | 782 | ||
744 | server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); | 783 | if (server->secmech.hmacsha256) { |
745 | if (IS_ERR(server->secmech.hmacsha256)) { | 784 | crypto_free_shash(server->secmech.hmacsha256); |
746 | cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); | 785 | server->secmech.hmacsha256 = NULL; |
747 | rc = PTR_ERR(server->secmech.hmacsha256); | ||
748 | goto crypto_allocate_hmacsha256_fail; | ||
749 | } | ||
750 | |||
751 | size = sizeof(struct shash_desc) + | ||
752 | crypto_shash_descsize(server->secmech.hmacmd5); | ||
753 | server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); | ||
754 | if (!server->secmech.sdeschmacmd5) { | ||
755 | rc = -ENOMEM; | ||
756 | goto crypto_allocate_hmacmd5_sdesc_fail; | ||
757 | } | 786 | } |
758 | server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; | ||
759 | server->secmech.sdeschmacmd5->shash.flags = 0x0; | ||
760 | 787 | ||
761 | size = sizeof(struct shash_desc) + | 788 | if (server->secmech.md5) { |
762 | crypto_shash_descsize(server->secmech.md5); | 789 | crypto_free_shash(server->secmech.md5); |
763 | server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); | 790 | server->secmech.md5 = NULL; |
764 | if (!server->secmech.sdescmd5) { | ||
765 | rc = -ENOMEM; | ||
766 | goto crypto_allocate_md5_sdesc_fail; | ||
767 | } | 791 | } |
768 | server->secmech.sdescmd5->shash.tfm = server->secmech.md5; | ||
769 | server->secmech.sdescmd5->shash.flags = 0x0; | ||
770 | 792 | ||
771 | size = sizeof(struct shash_desc) + | 793 | if (server->secmech.hmacmd5) { |
772 | crypto_shash_descsize(server->secmech.hmacsha256); | 794 | crypto_free_shash(server->secmech.hmacmd5); |
773 | server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL); | 795 | server->secmech.hmacmd5 = NULL; |
774 | if (!server->secmech.sdeschmacsha256) { | ||
775 | rc = -ENOMEM; | ||
776 | goto crypto_allocate_hmacsha256_sdesc_fail; | ||
777 | } | 796 | } |
778 | server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256; | ||
779 | server->secmech.sdeschmacsha256->shash.flags = 0x0; | ||
780 | |||
781 | return 0; | ||
782 | |||
783 | crypto_allocate_hmacsha256_sdesc_fail: | ||
784 | kfree(server->secmech.sdescmd5); | ||
785 | 797 | ||
786 | crypto_allocate_md5_sdesc_fail: | 798 | kfree(server->secmech.sdesccmacaes); |
799 | server->secmech.sdesccmacaes = NULL; | ||
800 | kfree(server->secmech.sdeschmacsha256); | ||
801 | server->secmech.sdeschmacsha256 = NULL; | ||
787 | kfree(server->secmech.sdeschmacmd5); | 802 | kfree(server->secmech.sdeschmacmd5); |
788 | 803 | server->secmech.sdeschmacmd5 = NULL; | |
789 | crypto_allocate_hmacmd5_sdesc_fail: | 804 | kfree(server->secmech.sdescmd5); |
790 | crypto_free_shash(server->secmech.hmacsha256); | 805 | server->secmech.sdescmd5 = NULL; |
791 | |||
792 | crypto_allocate_hmacsha256_fail: | ||
793 | crypto_free_shash(server->secmech.md5); | ||
794 | |||
795 | crypto_allocate_md5_fail: | ||
796 | crypto_free_shash(server->secmech.hmacmd5); | ||
797 | |||
798 | return rc; | ||
799 | } | 806 | } |