OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
6 | 6 |
7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/pickle.h" | 9 #include "base/pickle.h" |
10 #include "base/sha1.h" | 10 #include "base/sha1.h" |
11 #include "base/string_tokenizer.h" | 11 #include "base/string_tokenizer.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
14 #include "crypto/rsa_private_key.h" | 14 #include "crypto/rsa_private_key.h" |
15 #include "crypto/scoped_capi_types.h" | 15 #include "crypto/scoped_capi_types.h" |
16 #include "net/base/asn1_util.h" | 16 #include "net/base/asn1_util.h" |
17 #include "net/base/cert_status_flags.h" | 17 #include "net/base/cert_status_flags.h" |
18 #include "net/base/cert_verify_result.h" | 18 #include "net/base/cert_verify_result.h" |
19 #include "net/base/ev_root_ca_metadata.h" | 19 #include "net/base/ev_root_ca_metadata.h" |
20 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
21 #include "net/base/scoped_cert_chain_context.h" | |
22 #include "net/base/test_root_certs.h" | 21 #include "net/base/test_root_certs.h" |
23 #include "net/base/x509_certificate_known_roots_win.h" | 22 #include "net/base/x509_certificate_known_roots_win.h" |
24 | 23 |
25 #pragma comment(lib, "crypt32.lib") | 24 #pragma comment(lib, "crypt32.lib") |
26 | 25 |
27 using base::Time; | 26 using base::Time; |
28 | 27 |
29 namespace net { | 28 namespace net { |
30 | 29 |
31 namespace { | 30 namespace { |
32 | 31 |
33 typedef crypto::ScopedCAPIHandle< | |
34 HCERTSTORE, | |
35 crypto::CAPIDestroyerWithFlags<HCERTSTORE, | |
36 CertCloseStore, 0> > ScopedHCERTSTORE; | |
37 | |
38 struct FreeChainEngineFunctor { | 32 struct FreeChainEngineFunctor { |
39 void operator()(HCERTCHAINENGINE engine) const { | 33 void operator()(HCERTCHAINENGINE engine) const { |
40 if (engine) | 34 if (engine) |
41 CertFreeCertificateChainEngine(engine); | 35 CertFreeCertificateChainEngine(engine); |
42 } | 36 } |
43 }; | 37 }; |
44 | 38 |
39 struct FreeCertContextFunctor { | |
40 void operator()(PCCERT_CONTEXT context) const { | |
41 if (context) | |
42 CertFreeCertificateContext(context); | |
43 } | |
44 }; | |
45 | |
46 struct FreeCertChainContextFunctor { | |
47 void operator()(PCCERT_CHAIN_CONTEXT chain_context) const { | |
48 if (context) | |
49 CertFreeCertificateChain(context); | |
50 } | |
51 }; | |
52 | |
53 typedef crypto::ScopedCAPIHandle< | |
54 HCERTSTORE, | |
55 crypto::CAPIDestroyerWithFlags<HCERTSTORE, | |
56 CertCloseStore, 0> > ScopedHCERTSTORE; | |
57 | |
45 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> | 58 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> |
46 ScopedHCERTCHAINENGINE; | 59 ScopedHCERTCHAINENGINE; |
47 | 60 |
61 typedef scoped_ptr_malloc<const CERT_CONTEXT, | |
62 FreeCertContextFunctor> ScopedCertContext; | |
63 | |
64 typedef scoped_ptr_malloc<const CERT_CHAIN_CONTEXT, | |
65 FreeCertChainContextFunctor> ScopedCertChainContext; | |
66 | |
wtc
2011/10/04 18:00:52
Nit: delete one blank line.
| |
67 | |
48 //----------------------------------------------------------------------------- | 68 //----------------------------------------------------------------------------- |
49 | 69 |
50 // TODO(wtc): This is a copy of the MapSecurityError function in | 70 // TODO(wtc): This is a copy of the MapSecurityError function in |
51 // ssl_client_socket_win.cc. Another function that maps Windows error codes | 71 // ssl_client_socket_win.cc. Another function that maps Windows error codes |
52 // to our network error codes is WinInetUtil::OSErrorToNetError. We should | 72 // to our network error codes is WinInetUtil::OSErrorToNetError. We should |
53 // eliminate the code duplication. | 73 // eliminate the code duplication. |
54 int MapSecurityError(SECURITY_STATUS err) { | 74 int MapSecurityError(SECURITY_STATUS err) { |
55 // There are numerous security error codes, but these are the ones we thus | 75 // There are numerous security error codes, but these are the ones we thus |
56 // far find interesting. | 76 // far find interesting. |
57 switch (err) { | 77 switch (err) { |
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 | 717 |
698 static base::LazyInstance<GlobalCertStore, | 718 static base::LazyInstance<GlobalCertStore, |
699 base::LeakyLazyInstanceTraits<GlobalCertStore> > | 719 base::LeakyLazyInstanceTraits<GlobalCertStore> > |
700 g_cert_store(base::LINKER_INITIALIZED); | 720 g_cert_store(base::LINKER_INITIALIZED); |
701 | 721 |
702 // static | 722 // static |
703 HCERTSTORE X509Certificate::cert_store() { | 723 HCERTSTORE X509Certificate::cert_store() { |
704 return g_cert_store.Get().cert_store(); | 724 return g_cert_store.Get().cert_store(); |
705 } | 725 } |
706 | 726 |
727 X509Certificate::OSCertListHandle | |
728 X509Certificate::CreateOSCertListHandle() const { | |
729 // Create an in-memory certificate store to hold |cert_handle_| and any | |
730 // associated intermediate certificates. The store will be referenced in the | |
731 // returned OSCertListHandle, and will not be freed until the | |
732 // OSCertListHandle is freed. | |
733 OSCertListHandle cert_list = NULL; | |
734 DWORD flags = CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG; | |
735 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, | |
736 NULL, flags, NULL); | |
737 | |
738 if (store) { | |
739 // NOTE: This preserves all of the properties of |cert_handle_| except for | |
740 // CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two | |
741 // properties that hold access to already-opened private keys. If a handle | |
742 // has already been unlocked (eg: PIN prompt), then the first time that | |
743 // the identity is used for client auth, it may prompt the user again. | |
744 BOOL ok = CertAddCertificateContextToStore(store, cert_handle_, | |
745 CERT_STORE_ADD_ALWAYS, | |
746 &cert_list); | |
747 if (ok && cert_list) { | |
748 for (size_t i = 0; ok && i < intermediate_ca_certs_.size(); ++i) { | |
749 ok = CertAddCertificateContextToStore(store, intermediate_ca_certs_[i], | |
750 CERT_STORE_ADD_ALWAYS, NULL); | |
751 } | |
752 } | |
753 | |
754 // If |cert_list| points to a valid certificate, this will not actually | |
755 // close and free |store| until |cert_list| is freed. | |
756 CertCloseStore(store, 0); | |
757 | |
758 if (!ok) { | |
759 FreeOSCertListHandle(cert_list); | |
760 return NULL; | |
761 } | |
762 } | |
763 | |
764 return cert_list; | |
765 } | |
766 | |
707 int X509Certificate::VerifyInternal(const std::string& hostname, | 767 int X509Certificate::VerifyInternal(const std::string& hostname, |
708 int flags, | 768 int flags, |
709 CertVerifyResult* verify_result) const { | 769 CertVerifyResult* verify_result) const { |
710 if (!cert_handle_) | 770 if (!cert_handle_) |
711 return ERR_UNEXPECTED; | 771 return ERR_UNEXPECTED; |
712 | 772 |
713 // Build and validate certificate chain. | 773 // Build and validate certificate chain. |
714 CERT_CHAIN_PARA chain_para; | 774 CERT_CHAIN_PARA chain_para; |
715 memset(&chain_para, 0, sizeof(chain_para)); | 775 memset(&chain_para, 0, sizeof(chain_para)); |
716 chain_para.cbSize = sizeof(chain_para); | 776 chain_para.cbSize = sizeof(chain_para); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
763 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by | 823 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by |
764 // crypt32. However, when testing, it is necessary to create a new | 824 // crypt32. However, when testing, it is necessary to create a new |
765 // HCERTCHAINENGINE and use that instead. This is because each | 825 // HCERTCHAINENGINE and use that instead. This is because each |
766 // HCERTCHAINENGINE maintains a cache of information about certificates | 826 // HCERTCHAINENGINE maintains a cache of information about certificates |
767 // encountered, and each test run may modify the trust status of a | 827 // encountered, and each test run may modify the trust status of a |
768 // certificate. | 828 // certificate. |
769 ScopedHCERTCHAINENGINE chain_engine(NULL); | 829 ScopedHCERTCHAINENGINE chain_engine(NULL); |
770 if (TestRootCerts::HasInstance()) | 830 if (TestRootCerts::HasInstance()) |
771 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); | 831 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); |
772 | 832 |
833 ScopedPCCERT_CONTEXT cert_list(CreateOSCertListHandle()); | |
wtc
2011/10/04 18:00:52
I don't see where the ScopedPCCERT_CONTEXT type is
| |
773 PCCERT_CHAIN_CONTEXT chain_context; | 834 PCCERT_CHAIN_CONTEXT chain_context; |
774 // IE passes a non-NULL pTime argument that specifies the current system | 835 // IE passes a non-NULL pTime argument that specifies the current system |
775 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the | 836 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the |
776 // chain_flags argument. | 837 // chain_flags argument. |
777 if (!CertGetCertificateChain( | 838 if (!CertGetCertificateChain( |
778 chain_engine, | 839 chain_engine, |
779 cert_handle_, | 840 cert_list, |
780 NULL, // current system time | 841 NULL, // current system time |
781 cert_handle_->hCertStore, | 842 cert_list->hCertStore, |
782 &chain_para, | 843 &chain_para, |
783 chain_flags, | 844 chain_flags, |
784 NULL, // reserved | 845 NULL, // reserved |
785 &chain_context)) { | 846 &chain_context)) { |
786 return MapSecurityError(GetLastError()); | 847 return MapSecurityError(GetLastError()); |
787 } | 848 } |
849 | |
788 if (chain_context->TrustStatus.dwErrorStatus & | 850 if (chain_context->TrustStatus.dwErrorStatus & |
789 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { | 851 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { |
790 ev_policy_oid = NULL; | 852 ev_policy_oid = NULL; |
791 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; | 853 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; |
792 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; | 854 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; |
793 CertFreeCertificateChain(chain_context); | 855 CertFreeCertificateChain(chain_context); |
794 if (!CertGetCertificateChain( | 856 if (!CertGetCertificateChain( |
795 chain_engine, | 857 chain_engine, |
796 cert_handle_, | 858 cert_list, |
797 NULL, // current system time | 859 NULL, // current system time |
798 cert_handle_->hCertStore, | 860 cert_list->hCertStore, |
799 &chain_para, | 861 &chain_para, |
800 chain_flags, | 862 chain_flags, |
801 NULL, // reserved | 863 NULL, // reserved |
802 &chain_context)) { | 864 &chain_context)) { |
803 return MapSecurityError(GetLastError()); | 865 return MapSecurityError(GetLastError()); |
804 } | 866 } |
805 } | 867 } |
868 | |
806 ScopedCertChainContext scoped_chain_context(chain_context); | 869 ScopedCertChainContext scoped_chain_context(chain_context); |
807 | 870 |
808 GetCertChainInfo(chain_context, verify_result); | 871 GetCertChainInfo(chain_context, verify_result); |
809 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( | 872 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( |
810 chain_context->TrustStatus.dwErrorStatus); | 873 chain_context->TrustStatus.dwErrorStatus); |
811 | 874 |
812 // Treat certificates signed using broken signature algorithms as invalid. | 875 // Treat certificates signed using broken signature algorithms as invalid. |
813 if (verify_result->has_md4) | 876 if (verify_result->has_md4) |
814 verify_result->cert_status |= CERT_STATUS_INVALID; | 877 verify_result->cert_status |= CERT_STATUS_INVALID; |
815 | 878 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1004 OSCertHandle cert_handle) { | 1067 OSCertHandle cert_handle) { |
1005 return CertDuplicateCertificateContext(cert_handle); | 1068 return CertDuplicateCertificateContext(cert_handle); |
1006 } | 1069 } |
1007 | 1070 |
1008 // static | 1071 // static |
1009 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 1072 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
1010 CertFreeCertificateContext(cert_handle); | 1073 CertFreeCertificateContext(cert_handle); |
1011 } | 1074 } |
1012 | 1075 |
1013 // static | 1076 // static |
1077 void X509Certificate::FreeOSCertListHandle(OSCertListHandle cert_list) { | |
1078 CertFreeCertificateContext(cert_list); | |
1079 } | |
1080 | |
1081 // static | |
1014 SHA1Fingerprint X509Certificate::CalculateFingerprint( | 1082 SHA1Fingerprint X509Certificate::CalculateFingerprint( |
1015 OSCertHandle cert) { | 1083 OSCertHandle cert) { |
1016 DCHECK(NULL != cert->pbCertEncoded); | 1084 DCHECK(NULL != cert->pbCertEncoded); |
1017 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); | 1085 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); |
1018 | 1086 |
1019 BOOL rv; | 1087 BOOL rv; |
1020 SHA1Fingerprint sha1; | 1088 SHA1Fingerprint sha1; |
1021 DWORD sha1_size = sizeof(sha1.data); | 1089 DWORD sha1_size = sizeof(sha1.data); |
1022 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, | 1090 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, |
1023 cert->cbCertEncoded, sha1.data, &sha1_size); | 1091 cert->cbCertEncoded, sha1.data, &sha1_size); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1061 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], | 1129 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], |
1062 &length)) { | 1130 &length)) { |
1063 return false; | 1131 return false; |
1064 } | 1132 } |
1065 | 1133 |
1066 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), | 1134 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), |
1067 length); | 1135 length); |
1068 } | 1136 } |
1069 | 1137 |
1070 } // namespace net | 1138 } // namespace net |
OLD | NEW |