| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/cert/cert_verify_proc_win.h" | 5 #include "net/cert/cert_verify_proc_win.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/memory/free_deleter.h" | 11 #include "base/memory/free_deleter.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/sha1.h" | 13 #include "base/sha1.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/threading/thread_local.h" | 16 #include "base/threading/thread_local.h" |
| 17 #include "crypto/capi_util.h" | 17 #include "crypto/capi_util.h" |
| 18 #include "crypto/scoped_capi_types.h" | 18 #include "crypto/scoped_capi_types.h" |
| 19 #include "crypto/sha2.h" | 19 #include "crypto/sha2.h" |
| 20 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 21 #include "net/cert/asn1_util.h" | 21 #include "net/cert/asn1_util.h" |
| 22 #include "net/cert/cert_status_flags.h" | 22 #include "net/cert/cert_status_flags.h" |
| 23 #include "net/cert/cert_verifier.h" | 23 #include "net/cert/cert_verifier.h" |
| 24 #include "net/cert/cert_verify_result.h" | 24 #include "net/cert/cert_verify_result.h" |
| 25 #include "net/cert/crl_set.h" | 25 #include "net/cert/crl_set.h" |
| 26 #include "net/cert/ev_root_ca_metadata.h" | 26 #include "net/cert/ev_root_ca_metadata.h" |
| 27 #include "net/cert/known_roots_win.h" | 27 #include "net/cert/known_roots_win.h" |
| 28 #include "net/cert/test_root_certs.h" | 28 #include "net/cert/test_root_certs.h" |
| 29 #include "net/cert/x509_certificate.h" | 29 #include "net/cert/x509_certificate.h" |
| 30 #include "net/cert/x509_util_win.h" |
| 30 | 31 |
| 31 #if !defined(CERT_TRUST_HAS_WEAK_SIGNATURE) | 32 #if !defined(CERT_TRUST_HAS_WEAK_SIGNATURE) |
| 32 // This was introduced in Windows 8 / Windows Server 2012, but retroactively | 33 // This was introduced in Windows 8 / Windows Server 2012, but retroactively |
| 33 // ported as far back as Windows XP via system update. | 34 // ported as far back as Windows XP via system update. |
| 34 #define CERT_TRUST_HAS_WEAK_SIGNATURE 0x00100000 | 35 #define CERT_TRUST_HAS_WEAK_SIGNATURE 0x00100000 |
| 35 #endif | 36 #endif |
| 36 | 37 |
| 37 namespace net { | 38 namespace net { |
| 38 | 39 |
| 39 namespace { | 40 namespace { |
| 40 | 41 |
| 41 struct FreeChainEngineFunctor { | 42 struct FreeChainEngineFunctor { |
| 42 void operator()(HCERTCHAINENGINE engine) const { | 43 void operator()(HCERTCHAINENGINE engine) const { |
| 43 if (engine) | 44 if (engine) |
| 44 CertFreeCertificateChainEngine(engine); | 45 CertFreeCertificateChainEngine(engine); |
| 45 } | 46 } |
| 46 }; | 47 }; |
| 47 | 48 |
| 48 struct FreeCertChainContextFunctor { | 49 struct FreeCertChainContextFunctor { |
| 49 void operator()(PCCERT_CHAIN_CONTEXT chain_context) const { | 50 void operator()(PCCERT_CHAIN_CONTEXT chain_context) const { |
| 50 if (chain_context) | 51 if (chain_context) |
| 51 CertFreeCertificateChain(chain_context); | 52 CertFreeCertificateChain(chain_context); |
| 52 } | 53 } |
| 53 }; | 54 }; |
| 54 | 55 |
| 55 struct FreeCertContextFunctor { | |
| 56 void operator()(PCCERT_CONTEXT context) const { | |
| 57 if (context) | |
| 58 CertFreeCertificateContext(context); | |
| 59 } | |
| 60 }; | |
| 61 | |
| 62 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> | 56 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> |
| 63 ScopedHCERTCHAINENGINE; | 57 ScopedHCERTCHAINENGINE; |
| 64 | 58 |
| 65 typedef std::unique_ptr<const CERT_CHAIN_CONTEXT, FreeCertChainContextFunctor> | 59 typedef std::unique_ptr<const CERT_CHAIN_CONTEXT, FreeCertChainContextFunctor> |
| 66 ScopedPCCERT_CHAIN_CONTEXT; | 60 ScopedPCCERT_CHAIN_CONTEXT; |
| 67 | 61 |
| 68 typedef std::unique_ptr<const CERT_CONTEXT, FreeCertContextFunctor> | |
| 69 ScopedPCCERT_CONTEXT; | |
| 70 | |
| 71 //----------------------------------------------------------------------------- | 62 //----------------------------------------------------------------------------- |
| 72 | 63 |
| 73 int MapSecurityError(SECURITY_STATUS err) { | 64 int MapSecurityError(SECURITY_STATUS err) { |
| 74 // There are numerous security error codes, but these are the ones we thus | 65 // There are numerous security error codes, but these are the ones we thus |
| 75 // far find interesting. | 66 // far find interesting. |
| 76 switch (err) { | 67 switch (err) { |
| 77 case SEC_E_WRONG_PRINCIPAL: // Schannel | 68 case SEC_E_WRONG_PRINCIPAL: // Schannel |
| 78 case CERT_E_CN_NO_MATCH: // CryptoAPI | 69 case CERT_E_CN_NO_MATCH: // CryptoAPI |
| 79 return ERR_CERT_COMMON_NAME_INVALID; | 70 return ERR_CERT_COMMON_NAME_INVALID; |
| 80 case SEC_E_UNTRUSTED_ROOT: // Schannel | 71 case SEC_E_UNTRUSTED_ROOT: // Schannel |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 } else { | 315 } else { |
| 325 verified_chain.push_back(cert); | 316 verified_chain.push_back(cert); |
| 326 } | 317 } |
| 327 } | 318 } |
| 328 | 319 |
| 329 if (verified_cert) { | 320 if (verified_cert) { |
| 330 // Add the root certificate, if present, as it was not added above. | 321 // Add the root certificate, if present, as it was not added above. |
| 331 if (has_root_ca) | 322 if (has_root_ca) |
| 332 verified_chain.push_back(element[num_elements]->pCertContext); | 323 verified_chain.push_back(element[num_elements]->pCertContext); |
| 333 scoped_refptr<X509Certificate> verified_cert_with_chain = | 324 scoped_refptr<X509Certificate> verified_cert_with_chain = |
| 334 X509Certificate::CreateFromHandle(verified_cert, verified_chain); | 325 x509_util::CreateX509CertificateFromCertContexts(verified_cert, |
| 326 verified_chain); |
| 335 if (verified_cert_with_chain) | 327 if (verified_cert_with_chain) |
| 336 verify_result->verified_cert = std::move(verified_cert_with_chain); | 328 verify_result->verified_cert = std::move(verified_cert_with_chain); |
| 337 else | 329 else |
| 338 verify_result->cert_status |= CERT_STATUS_INVALID; | 330 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 339 } | 331 } |
| 340 } | 332 } |
| 341 | 333 |
| 342 // Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO | 334 // Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO |
| 343 // structure and stores it in *output. | 335 // structure and stores it in *output. |
| 344 void GetCertPoliciesInfo( | 336 void GetCertPoliciesInfo( |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 const std::string& hostname, | 855 const std::string& hostname, |
| 864 const std::string& ocsp_response, | 856 const std::string& ocsp_response, |
| 865 int flags, | 857 int flags, |
| 866 CRLSet* crl_set, | 858 CRLSet* crl_set, |
| 867 const CertificateList& additional_trust_anchors, | 859 const CertificateList& additional_trust_anchors, |
| 868 CertVerifyResult* verify_result) { | 860 CertVerifyResult* verify_result) { |
| 869 // Ensure the Revocation Provider has been installed and configured for this | 861 // Ensure the Revocation Provider has been installed and configured for this |
| 870 // CRLSet. | 862 // CRLSet. |
| 871 ScopedThreadLocalCRLSet thread_local_crlset(crl_set); | 863 ScopedThreadLocalCRLSet thread_local_crlset(crl_set); |
| 872 | 864 |
| 873 PCCERT_CONTEXT cert_handle = cert->os_cert_handle(); | 865 ScopedPCCERT_CONTEXT cert_list = x509_util::CreateCertContextWithChain(cert); |
| 874 if (!cert_handle) | 866 if (!cert_list) { |
| 875 return ERR_UNEXPECTED; | 867 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 868 return ERR_CERT_INVALID; |
| 869 } |
| 876 | 870 |
| 877 // Build and validate certificate chain. | 871 // Build and validate certificate chain. |
| 878 CERT_CHAIN_PARA chain_para; | 872 CERT_CHAIN_PARA chain_para; |
| 879 memset(&chain_para, 0, sizeof(chain_para)); | 873 memset(&chain_para, 0, sizeof(chain_para)); |
| 880 chain_para.cbSize = sizeof(chain_para); | 874 chain_para.cbSize = sizeof(chain_para); |
| 881 // ExtendedKeyUsage. | 875 // ExtendedKeyUsage. |
| 882 // We still need to request szOID_SERVER_GATED_CRYPTO and szOID_SGC_NETSCAPE | 876 // We still need to request szOID_SERVER_GATED_CRYPTO and szOID_SGC_NETSCAPE |
| 883 // today because some certificate chains need them. IE also requests these | 877 // today because some certificate chains need them. IE also requests these |
| 884 // two usages. | 878 // two usages. |
| 885 static const LPCSTR usage[] = { | 879 static const LPCSTR usage[] = { |
| 886 szOID_PKIX_KP_SERVER_AUTH, | 880 szOID_PKIX_KP_SERVER_AUTH, |
| 887 szOID_SERVER_GATED_CRYPTO, | 881 szOID_SERVER_GATED_CRYPTO, |
| 888 szOID_SGC_NETSCAPE | 882 szOID_SGC_NETSCAPE |
| 889 }; | 883 }; |
| 890 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; | 884 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; |
| 891 chain_para.RequestedUsage.Usage.cUsageIdentifier = arraysize(usage); | 885 chain_para.RequestedUsage.Usage.cUsageIdentifier = arraysize(usage); |
| 892 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = | 886 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = |
| 893 const_cast<LPSTR*>(usage); | 887 const_cast<LPSTR*>(usage); |
| 894 | 888 |
| 895 // Get the certificatePolicies extension of the certificate. | 889 // Get the certificatePolicies extension of the certificate. |
| 896 std::unique_ptr<CERT_POLICIES_INFO, base::FreeDeleter> policies_info; | 890 std::unique_ptr<CERT_POLICIES_INFO, base::FreeDeleter> policies_info; |
| 897 LPSTR ev_policy_oid = NULL; | 891 LPSTR ev_policy_oid = NULL; |
| 898 if (flags & CertVerifier::VERIFY_EV_CERT) { | 892 if (flags & CertVerifier::VERIFY_EV_CERT) { |
| 899 GetCertPoliciesInfo(cert_handle, &policies_info); | 893 GetCertPoliciesInfo(cert_list.get(), &policies_info); |
| 900 if (policies_info.get()) { | 894 if (policies_info.get()) { |
| 901 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); | 895 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); |
| 902 for (DWORD i = 0; i < policies_info->cPolicyInfo; ++i) { | 896 for (DWORD i = 0; i < policies_info->cPolicyInfo; ++i) { |
| 903 LPSTR policy_oid = policies_info->rgPolicyInfo[i].pszPolicyIdentifier; | 897 LPSTR policy_oid = policies_info->rgPolicyInfo[i].pszPolicyIdentifier; |
| 904 if (metadata->IsEVPolicyOID(policy_oid)) { | 898 if (metadata->IsEVPolicyOID(policy_oid)) { |
| 905 ev_policy_oid = policy_oid; | 899 ev_policy_oid = policy_oid; |
| 906 chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_AND; | 900 chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_AND; |
| 907 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 1; | 901 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 1; |
| 908 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = | 902 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = |
| 909 &ev_policy_oid; | 903 &ev_policy_oid; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 940 // cache between runs. | 934 // cache between runs. |
| 941 // | 935 // |
| 942 // This is not the most efficient means of doing so; it's possible to mark the | 936 // This is not the most efficient means of doing so; it's possible to mark the |
| 943 // Root store used by TestRootCerts as changed, via CertControlStore with the | 937 // Root store used by TestRootCerts as changed, via CertControlStore with the |
| 944 // CERT_STORE_CTRL_NOTIFY_CHANGE / CERT_STORE_CTRL_RESYNC, but that's more | 938 // CERT_STORE_CTRL_NOTIFY_CHANGE / CERT_STORE_CTRL_RESYNC, but that's more |
| 945 // complexity for what is test-only code. | 939 // complexity for what is test-only code. |
| 946 ScopedHCERTCHAINENGINE chain_engine(NULL); | 940 ScopedHCERTCHAINENGINE chain_engine(NULL); |
| 947 if (TestRootCerts::HasInstance()) | 941 if (TestRootCerts::HasInstance()) |
| 948 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); | 942 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); |
| 949 | 943 |
| 950 ScopedPCCERT_CONTEXT cert_list(cert->CreateOSCertChainForCert()); | |
| 951 | |
| 952 // Add stapled OCSP response data, which will be preferred over online checks | 944 // Add stapled OCSP response data, which will be preferred over online checks |
| 953 // and used when in cache-only mode. | 945 // and used when in cache-only mode. |
| 954 if (!ocsp_response.empty()) { | 946 if (!ocsp_response.empty()) { |
| 955 CRYPT_DATA_BLOB ocsp_response_blob; | 947 CRYPT_DATA_BLOB ocsp_response_blob; |
| 956 ocsp_response_blob.cbData = ocsp_response.size(); | 948 ocsp_response_blob.cbData = ocsp_response.size(); |
| 957 ocsp_response_blob.pbData = | 949 ocsp_response_blob.pbData = |
| 958 reinterpret_cast<BYTE*>(const_cast<char*>(ocsp_response.data())); | 950 reinterpret_cast<BYTE*>(const_cast<char*>(ocsp_response.data())); |
| 959 CertSetCertificateContextProperty( | 951 CertSetCertificateContextProperty( |
| 960 cert_list.get(), CERT_OCSP_RESPONSE_PROP_ID, | 952 cert_list.get(), CERT_OCSP_RESPONSE_PROP_ID, |
| 961 CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, &ocsp_response_blob); | 953 CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, &ocsp_response_blob); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 verify_result->cert_status |= CERT_STATUS_REVOKED; | 1104 verify_result->cert_status |= CERT_STATUS_REVOKED; |
| 1113 } | 1105 } |
| 1114 } | 1106 } |
| 1115 | 1107 |
| 1116 ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context); | 1108 ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context); |
| 1117 | 1109 |
| 1118 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( | 1110 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( |
| 1119 chain_context->TrustStatus.dwErrorStatus); | 1111 chain_context->TrustStatus.dwErrorStatus); |
| 1120 | 1112 |
| 1121 // Flag certificates that have a Subject common name with a NULL character. | 1113 // Flag certificates that have a Subject common name with a NULL character. |
| 1122 if (CertSubjectCommonNameHasNull(cert_handle)) | 1114 if (CertSubjectCommonNameHasNull(cert_list.get())) |
| 1123 verify_result->cert_status |= CERT_STATUS_INVALID; | 1115 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 1124 | 1116 |
| 1125 base::string16 hostname16 = base::ASCIIToUTF16(hostname); | 1117 base::string16 hostname16 = base::ASCIIToUTF16(hostname); |
| 1126 | 1118 |
| 1127 SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para; | 1119 SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para; |
| 1128 memset(&extra_policy_para, 0, sizeof(extra_policy_para)); | 1120 memset(&extra_policy_para, 0, sizeof(extra_policy_para)); |
| 1129 extra_policy_para.cbSize = sizeof(extra_policy_para); | 1121 extra_policy_para.cbSize = sizeof(extra_policy_para); |
| 1130 extra_policy_para.dwAuthType = AUTHTYPE_SERVER; | 1122 extra_policy_para.dwAuthType = AUTHTYPE_SERVER; |
| 1131 // Certificate name validation happens separately, later, using an internal | 1123 // Certificate name validation happens separately, later, using an internal |
| 1132 // routine that has better support for RFC 6125 name matching. | 1124 // routine that has better support for RFC 6125 name matching. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 return MapCertStatusToNetError(verify_result->cert_status); | 1169 return MapCertStatusToNetError(verify_result->cert_status); |
| 1178 | 1170 |
| 1179 if (ev_policy_oid && | 1171 if (ev_policy_oid && |
| 1180 CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) { | 1172 CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) { |
| 1181 verify_result->cert_status |= CERT_STATUS_IS_EV; | 1173 verify_result->cert_status |= CERT_STATUS_IS_EV; |
| 1182 } | 1174 } |
| 1183 return OK; | 1175 return OK; |
| 1184 } | 1176 } |
| 1185 | 1177 |
| 1186 } // namespace net | 1178 } // namespace net |
| OLD | NEW |