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 #define PRArenaPool PLArenaPool // Required by <blapi.h>. | 7 #define PRArenaPool PLArenaPool // Required by <blapi.h>. |
8 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. | 8 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. |
9 | 9 |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" |
12 #include "base/pickle.h" | 13 #include "base/pickle.h" |
13 #include "base/sha1.h" | 14 #include "base/sha1.h" |
14 #include "base/string_tokenizer.h" | 15 #include "base/string_tokenizer.h" |
15 #include "base/string_util.h" | 16 #include "base/string_util.h" |
16 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
17 #include "crypto/rsa_private_key.h" | 18 #include "crypto/rsa_private_key.h" |
18 #include "crypto/scoped_capi_types.h" | 19 #include "crypto/scoped_capi_types.h" |
19 #include "net/base/asn1_util.h" | 20 #include "net/base/asn1_util.h" |
20 #include "net/base/cert_status_flags.h" | 21 #include "net/base/cert_status_flags.h" |
21 #include "net/base/cert_verify_result.h" | 22 #include "net/base/cert_verify_result.h" |
22 #include "net/base/ev_root_ca_metadata.h" | 23 #include "net/base/ev_root_ca_metadata.h" |
23 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
24 #include "net/base/scoped_cert_chain_context.h" | |
25 #include "net/base/test_root_certs.h" | 25 #include "net/base/test_root_certs.h" |
26 #include "net/base/x509_certificate_known_roots_win.h" | 26 #include "net/base/x509_certificate_known_roots_win.h" |
27 | 27 |
28 #pragma comment(lib, "crypt32.lib") | 28 #pragma comment(lib, "crypt32.lib") |
29 | 29 |
30 using base::Time; | 30 using base::Time; |
31 | 31 |
32 namespace net { | 32 namespace net { |
33 | 33 |
34 namespace { | 34 namespace { |
35 | 35 |
36 typedef crypto::ScopedCAPIHandle< | |
37 HCERTSTORE, | |
38 crypto::CAPIDestroyerWithFlags<HCERTSTORE, | |
39 CertCloseStore, 0> > ScopedHCERTSTORE; | |
40 | |
41 struct FreeChainEngineFunctor { | 36 struct FreeChainEngineFunctor { |
42 void operator()(HCERTCHAINENGINE engine) const { | 37 void operator()(HCERTCHAINENGINE engine) const { |
43 if (engine) | 38 if (engine) |
44 CertFreeCertificateChainEngine(engine); | 39 CertFreeCertificateChainEngine(engine); |
45 } | 40 } |
46 }; | 41 }; |
47 | 42 |
| 43 struct FreeCertContextFunctor { |
| 44 void operator()(PCCERT_CONTEXT context) const { |
| 45 if (context) |
| 46 CertFreeCertificateContext(context); |
| 47 } |
| 48 }; |
| 49 |
| 50 struct FreeCertChainContextFunctor { |
| 51 void operator()(PCCERT_CHAIN_CONTEXT chain_context) const { |
| 52 if (chain_context) |
| 53 CertFreeCertificateChain(chain_context); |
| 54 } |
| 55 }; |
| 56 |
48 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> | 57 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> |
49 ScopedHCERTCHAINENGINE; | 58 ScopedHCERTCHAINENGINE; |
50 | 59 |
| 60 typedef crypto::ScopedCAPIHandle< |
| 61 HCERTSTORE, |
| 62 crypto::CAPIDestroyerWithFlags<HCERTSTORE, |
| 63 CertCloseStore, 0> > ScopedHCERTSTORE; |
| 64 |
| 65 typedef scoped_ptr_malloc<const CERT_CONTEXT, |
| 66 FreeCertContextFunctor> ScopedPCCERT_CONTEXT; |
| 67 |
| 68 typedef scoped_ptr_malloc<const CERT_CHAIN_CONTEXT, |
| 69 FreeCertChainContextFunctor> |
| 70 ScopedPCCERT_CHAIN_CONTEXT; |
| 71 |
51 //----------------------------------------------------------------------------- | 72 //----------------------------------------------------------------------------- |
52 | 73 |
53 // TODO(wtc): This is a copy of the MapSecurityError function in | 74 // TODO(wtc): This is a copy of the MapSecurityError function in |
54 // ssl_client_socket_win.cc. Another function that maps Windows error codes | 75 // ssl_client_socket_win.cc. Another function that maps Windows error codes |
55 // to our network error codes is WinInetUtil::OSErrorToNetError. We should | 76 // to our network error codes is WinInetUtil::OSErrorToNetError. We should |
56 // eliminate the code duplication. | 77 // eliminate the code duplication. |
57 int MapSecurityError(SECURITY_STATUS err) { | 78 int MapSecurityError(SECURITY_STATUS err) { |
58 // There are numerous security error codes, but these are the ones we thus | 79 // There are numerous security error codes, but these are the ones we thus |
59 // far find interesting. | 80 // far find interesting. |
60 switch (err) { | 81 switch (err) { |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 | 709 |
689 static base::LazyInstance<GlobalCertStore, | 710 static base::LazyInstance<GlobalCertStore, |
690 base::LeakyLazyInstanceTraits<GlobalCertStore> > | 711 base::LeakyLazyInstanceTraits<GlobalCertStore> > |
691 g_cert_store(base::LINKER_INITIALIZED); | 712 g_cert_store(base::LINKER_INITIALIZED); |
692 | 713 |
693 // static | 714 // static |
694 HCERTSTORE X509Certificate::cert_store() { | 715 HCERTSTORE X509Certificate::cert_store() { |
695 return g_cert_store.Get().cert_store(); | 716 return g_cert_store.Get().cert_store(); |
696 } | 717 } |
697 | 718 |
| 719 PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const { |
| 720 // Create an in-memory certificate store to hold this certificate and |
| 721 // any intermediate certificates in |intermediate_ca_certs_|. The store |
| 722 // will be referenced in the returned PCCERT_CONTEXT, and will not be freed |
| 723 // until the PCCERT_CONTEXT is freed. |
| 724 ScopedHCERTSTORE store(CertOpenStore( |
| 725 CERT_STORE_PROV_MEMORY, 0, NULL, |
| 726 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL)); |
| 727 if (!store.get()) |
| 728 return NULL; |
| 729 |
| 730 // NOTE: This preserves all of the properties of |os_cert_handle()| except |
| 731 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two |
| 732 // properties that hold access to already-opened private keys. If a handle |
| 733 // has already been unlocked (eg: PIN prompt), then the first time that the |
| 734 // identity is used for client auth, it may prompt the user again. |
| 735 PCCERT_CONTEXT primary_cert; |
| 736 BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(), |
| 737 CERT_STORE_ADD_ALWAYS, |
| 738 &primary_cert); |
| 739 if (!ok || !primary_cert) |
| 740 return NULL; |
| 741 |
| 742 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { |
| 743 CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i], |
| 744 CERT_STORE_ADD_ALWAYS, NULL); |
| 745 } |
| 746 |
| 747 // Note: |store| is explicitly not released, as the call to CertCloseStore() |
| 748 // when |store| goes out of scope will not actually free the store. Instead, |
| 749 // the store will be freed when |primary_cert| is freed. |
| 750 return primary_cert; |
| 751 } |
| 752 |
698 int X509Certificate::VerifyInternal(const std::string& hostname, | 753 int X509Certificate::VerifyInternal(const std::string& hostname, |
699 int flags, | 754 int flags, |
700 CRLSet* crl_set, | 755 CRLSet* crl_set, |
701 CertVerifyResult* verify_result) const { | 756 CertVerifyResult* verify_result) const { |
702 if (!cert_handle_) | 757 if (!cert_handle_) |
703 return ERR_UNEXPECTED; | 758 return ERR_UNEXPECTED; |
704 | 759 |
705 // Build and validate certificate chain. | 760 // Build and validate certificate chain. |
706 CERT_CHAIN_PARA chain_para; | 761 CERT_CHAIN_PARA chain_para; |
707 memset(&chain_para, 0, sizeof(chain_para)); | 762 memset(&chain_para, 0, sizeof(chain_para)); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by | 810 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by |
756 // crypt32. However, when testing, it is necessary to create a new | 811 // crypt32. However, when testing, it is necessary to create a new |
757 // HCERTCHAINENGINE and use that instead. This is because each | 812 // HCERTCHAINENGINE and use that instead. This is because each |
758 // HCERTCHAINENGINE maintains a cache of information about certificates | 813 // HCERTCHAINENGINE maintains a cache of information about certificates |
759 // encountered, and each test run may modify the trust status of a | 814 // encountered, and each test run may modify the trust status of a |
760 // certificate. | 815 // certificate. |
761 ScopedHCERTCHAINENGINE chain_engine(NULL); | 816 ScopedHCERTCHAINENGINE chain_engine(NULL); |
762 if (TestRootCerts::HasInstance()) | 817 if (TestRootCerts::HasInstance()) |
763 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); | 818 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); |
764 | 819 |
| 820 ScopedPCCERT_CONTEXT cert_list(CreateOSCertChainForCert()); |
765 PCCERT_CHAIN_CONTEXT chain_context; | 821 PCCERT_CHAIN_CONTEXT chain_context; |
766 // IE passes a non-NULL pTime argument that specifies the current system | 822 // IE passes a non-NULL pTime argument that specifies the current system |
767 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the | 823 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the |
768 // chain_flags argument. | 824 // chain_flags argument. |
769 if (!CertGetCertificateChain( | 825 if (!CertGetCertificateChain( |
770 chain_engine, | 826 chain_engine, |
771 cert_handle_, | 827 cert_list.get(), |
772 NULL, // current system time | 828 NULL, // current system time |
773 cert_handle_->hCertStore, | 829 cert_list->hCertStore, |
774 &chain_para, | 830 &chain_para, |
775 chain_flags, | 831 chain_flags, |
776 NULL, // reserved | 832 NULL, // reserved |
777 &chain_context)) { | 833 &chain_context)) { |
778 return MapSecurityError(GetLastError()); | 834 return MapSecurityError(GetLastError()); |
779 } | 835 } |
| 836 |
780 if (chain_context->TrustStatus.dwErrorStatus & | 837 if (chain_context->TrustStatus.dwErrorStatus & |
781 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { | 838 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { |
782 ev_policy_oid = NULL; | 839 ev_policy_oid = NULL; |
783 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; | 840 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; |
784 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; | 841 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; |
785 CertFreeCertificateChain(chain_context); | 842 CertFreeCertificateChain(chain_context); |
786 if (!CertGetCertificateChain( | 843 if (!CertGetCertificateChain( |
787 chain_engine, | 844 chain_engine, |
788 cert_handle_, | 845 cert_list.get(), |
789 NULL, // current system time | 846 NULL, // current system time |
790 cert_handle_->hCertStore, | 847 cert_list->hCertStore, |
791 &chain_para, | 848 &chain_para, |
792 chain_flags, | 849 chain_flags, |
793 NULL, // reserved | 850 NULL, // reserved |
794 &chain_context)) { | 851 &chain_context)) { |
795 return MapSecurityError(GetLastError()); | 852 return MapSecurityError(GetLastError()); |
796 } | 853 } |
797 } | 854 } |
798 ScopedCertChainContext scoped_chain_context(chain_context); | 855 |
| 856 ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context); |
799 | 857 |
800 GetCertChainInfo(chain_context, verify_result); | 858 GetCertChainInfo(chain_context, verify_result); |
801 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( | 859 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( |
802 chain_context->TrustStatus.dwErrorStatus); | 860 chain_context->TrustStatus.dwErrorStatus); |
803 | 861 |
804 // Treat certificates signed using broken signature algorithms as invalid. | 862 // Treat certificates signed using broken signature algorithms as invalid. |
805 if (verify_result->has_md4) | 863 if (verify_result->has_md4) |
806 verify_result->cert_status |= CERT_STATUS_INVALID; | 864 verify_result->cert_status |= CERT_STATUS_INVALID; |
807 | 865 |
808 // Flag certificates signed using weak signature algorithms. | 866 // Flag certificates signed using weak signature algorithms. |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], | 1135 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], |
1078 &length)) { | 1136 &length)) { |
1079 return false; | 1137 return false; |
1080 } | 1138 } |
1081 | 1139 |
1082 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), | 1140 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), |
1083 length); | 1141 length); |
1084 } | 1142 } |
1085 | 1143 |
1086 } // namespace net | 1144 } // namespace net |
OLD | NEW |