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 |