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 <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 typedef scoped_ptr<const CERT_CONTEXT, FreeCertContextFunctor> | 67 typedef scoped_ptr<const CERT_CONTEXT, FreeCertContextFunctor> |
68 ScopedPCCERT_CONTEXT; | 68 ScopedPCCERT_CONTEXT; |
69 | 69 |
70 //----------------------------------------------------------------------------- | 70 //----------------------------------------------------------------------------- |
71 | 71 |
72 int MapSecurityError(SECURITY_STATUS err) { | 72 int MapSecurityError(SECURITY_STATUS err) { |
73 // There are numerous security error codes, but these are the ones we thus | 73 // There are numerous security error codes, but these are the ones we thus |
74 // far find interesting. | 74 // far find interesting. |
75 switch (err) { | 75 switch (err) { |
76 case SEC_E_WRONG_PRINCIPAL: // Schannel | 76 case SEC_E_WRONG_PRINCIPAL: // Schannel |
77 case CERT_E_CN_NO_MATCH: // CryptoAPI | 77 case CERT_E_CN_NO_MATCH: // CryptoAPI |
78 return ERR_CERT_COMMON_NAME_INVALID; | 78 return ERR_CERT_COMMON_NAME_INVALID; |
79 case SEC_E_UNTRUSTED_ROOT: // Schannel | 79 case SEC_E_UNTRUSTED_ROOT: // Schannel |
80 case CERT_E_UNTRUSTEDROOT: // CryptoAPI | 80 case CERT_E_UNTRUSTEDROOT: // CryptoAPI |
81 return ERR_CERT_AUTHORITY_INVALID; | 81 return ERR_CERT_AUTHORITY_INVALID; |
82 case SEC_E_CERT_EXPIRED: // Schannel | 82 case SEC_E_CERT_EXPIRED: // Schannel |
83 case CERT_E_EXPIRED: // CryptoAPI | 83 case CERT_E_EXPIRED: // CryptoAPI |
84 return ERR_CERT_DATE_INVALID; | 84 return ERR_CERT_DATE_INVALID; |
85 case CRYPT_E_NO_REVOCATION_CHECK: | 85 case CRYPT_E_NO_REVOCATION_CHECK: |
86 return ERR_CERT_NO_REVOCATION_MECHANISM; | 86 return ERR_CERT_NO_REVOCATION_MECHANISM; |
87 case CRYPT_E_REVOCATION_OFFLINE: | 87 case CRYPT_E_REVOCATION_OFFLINE: |
88 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; | 88 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; |
89 case CRYPT_E_REVOKED: // Schannel and CryptoAPI | 89 case CRYPT_E_REVOKED: // Schannel and CryptoAPI |
90 return ERR_CERT_REVOKED; | 90 return ERR_CERT_REVOKED; |
91 case SEC_E_CERT_UNKNOWN: | 91 case SEC_E_CERT_UNKNOWN: |
92 case CERT_E_ROLE: | 92 case CERT_E_ROLE: |
93 return ERR_CERT_INVALID; | 93 return ERR_CERT_INVALID; |
(...skipping 16 matching lines...) Expand all Loading... |
110 } | 110 } |
111 } | 111 } |
112 | 112 |
113 // Map the errors in the chain_context->TrustStatus.dwErrorStatus returned by | 113 // Map the errors in the chain_context->TrustStatus.dwErrorStatus returned by |
114 // CertGetCertificateChain to our certificate status flags. | 114 // CertGetCertificateChain to our certificate status flags. |
115 int MapCertChainErrorStatusToCertStatus(DWORD error_status) { | 115 int MapCertChainErrorStatusToCertStatus(DWORD error_status) { |
116 CertStatus cert_status = 0; | 116 CertStatus cert_status = 0; |
117 | 117 |
118 // We don't include CERT_TRUST_IS_NOT_TIME_NESTED because it's obsolete and | 118 // We don't include CERT_TRUST_IS_NOT_TIME_NESTED because it's obsolete and |
119 // we wouldn't consider it an error anyway | 119 // we wouldn't consider it an error anyway |
120 const DWORD kDateInvalidErrors = CERT_TRUST_IS_NOT_TIME_VALID | | 120 const DWORD kDateInvalidErrors = |
121 CERT_TRUST_CTL_IS_NOT_TIME_VALID; | 121 CERT_TRUST_IS_NOT_TIME_VALID | CERT_TRUST_CTL_IS_NOT_TIME_VALID; |
122 if (error_status & kDateInvalidErrors) | 122 if (error_status & kDateInvalidErrors) |
123 cert_status |= CERT_STATUS_DATE_INVALID; | 123 cert_status |= CERT_STATUS_DATE_INVALID; |
124 | 124 |
125 const DWORD kAuthorityInvalidErrors = CERT_TRUST_IS_UNTRUSTED_ROOT | | 125 const DWORD kAuthorityInvalidErrors = CERT_TRUST_IS_UNTRUSTED_ROOT | |
126 CERT_TRUST_IS_EXPLICIT_DISTRUST | | 126 CERT_TRUST_IS_EXPLICIT_DISTRUST | |
127 CERT_TRUST_IS_PARTIAL_CHAIN; | 127 CERT_TRUST_IS_PARTIAL_CHAIN; |
128 if (error_status & kAuthorityInvalidErrors) | 128 if (error_status & kAuthorityInvalidErrors) |
129 cert_status |= CERT_STATUS_AUTHORITY_INVALID; | 129 cert_status |= CERT_STATUS_AUTHORITY_INVALID; |
130 | 130 |
131 if ((error_status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) && | 131 if ((error_status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) && |
132 !(error_status & CERT_TRUST_IS_OFFLINE_REVOCATION)) | 132 !(error_status & CERT_TRUST_IS_OFFLINE_REVOCATION)) |
133 cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM; | 133 cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM; |
134 | 134 |
135 if (error_status & CERT_TRUST_IS_OFFLINE_REVOCATION) | 135 if (error_status & CERT_TRUST_IS_OFFLINE_REVOCATION) |
136 cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; | 136 cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; |
137 | 137 |
138 if (error_status & CERT_TRUST_IS_REVOKED) | 138 if (error_status & CERT_TRUST_IS_REVOKED) |
139 cert_status |= CERT_STATUS_REVOKED; | 139 cert_status |= CERT_STATUS_REVOKED; |
140 | 140 |
141 const DWORD kWrongUsageErrors = CERT_TRUST_IS_NOT_VALID_FOR_USAGE | | 141 const DWORD kWrongUsageErrors = |
142 CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE; | 142 CERT_TRUST_IS_NOT_VALID_FOR_USAGE | CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE; |
143 if (error_status & kWrongUsageErrors) { | 143 if (error_status & kWrongUsageErrors) { |
144 // TODO(wtc): Should we add CERT_STATUS_WRONG_USAGE? | 144 // TODO(wtc): Should we add CERT_STATUS_WRONG_USAGE? |
145 cert_status |= CERT_STATUS_INVALID; | 145 cert_status |= CERT_STATUS_INVALID; |
146 } | 146 } |
147 | 147 |
148 if (error_status & CERT_TRUST_IS_NOT_SIGNATURE_VALID) { | 148 if (error_status & CERT_TRUST_IS_NOT_SIGNATURE_VALID) { |
149 // Check for a signature that does not meet the OS criteria for strong | 149 // Check for a signature that does not meet the OS criteria for strong |
150 // signatures. | 150 // signatures. |
151 // Note: These checks may be more restrictive than the current weak key | 151 // Note: These checks may be more restrictive than the current weak key |
152 // criteria implemented within CertVerifier, such as excluding SHA-1 or | 152 // criteria implemented within CertVerifier, such as excluding SHA-1 or |
153 // excluding RSA keys < 2048 bits. However, if the user has configured | 153 // excluding RSA keys < 2048 bits. However, if the user has configured |
154 // these more stringent checks, respect that configuration and err on the | 154 // these more stringent checks, respect that configuration and err on the |
155 // more restrictive criteria. | 155 // more restrictive criteria. |
156 if (error_status & CERT_TRUST_HAS_WEAK_SIGNATURE) { | 156 if (error_status & CERT_TRUST_HAS_WEAK_SIGNATURE) { |
157 cert_status |= CERT_STATUS_WEAK_KEY; | 157 cert_status |= CERT_STATUS_WEAK_KEY; |
158 } else { | 158 } else { |
159 cert_status |= CERT_STATUS_INVALID; | 159 cert_status |= CERT_STATUS_INVALID; |
160 } | 160 } |
161 } | 161 } |
162 | 162 |
163 // The rest of the errors. | 163 // The rest of the errors. |
164 const DWORD kCertInvalidErrors = | 164 const DWORD kCertInvalidErrors = |
165 CERT_TRUST_IS_CYCLIC | | 165 CERT_TRUST_IS_CYCLIC | CERT_TRUST_INVALID_EXTENSION | |
166 CERT_TRUST_INVALID_EXTENSION | | |
167 CERT_TRUST_INVALID_POLICY_CONSTRAINTS | | 166 CERT_TRUST_INVALID_POLICY_CONSTRAINTS | |
168 CERT_TRUST_INVALID_BASIC_CONSTRAINTS | | 167 CERT_TRUST_INVALID_BASIC_CONSTRAINTS | |
169 CERT_TRUST_INVALID_NAME_CONSTRAINTS | | 168 CERT_TRUST_INVALID_NAME_CONSTRAINTS | |
170 CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID | | 169 CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID | |
171 CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT | | 170 CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT | |
172 CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT | | 171 CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT | |
173 CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT | | 172 CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT | |
174 CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT | | 173 CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT | |
175 CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY | | 174 CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY | |
176 CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT; | 175 CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 reinterpret_cast<wchar_t*>(rdn_attr->Value.pbData); | 243 reinterpret_cast<wchar_t*>(rdn_attr->Value.pbData); |
245 for (DWORD k = 0; k < num_wchars; ++k) { | 244 for (DWORD k = 0; k < num_wchars; ++k) { |
246 if (common_name[k] == L'\0') | 245 if (common_name[k] == L'\0') |
247 return true; | 246 return true; |
248 } | 247 } |
249 break; | 248 break; |
250 } | 249 } |
251 // Array of ints (32-bit). | 250 // Array of ints (32-bit). |
252 case CERT_RDN_UNIVERSAL_STRING: { | 251 case CERT_RDN_UNIVERSAL_STRING: { |
253 DWORD num_ints = rdn_attr->Value.cbData / 4; | 252 DWORD num_ints = rdn_attr->Value.cbData / 4; |
254 int* common_name = | 253 int* common_name = reinterpret_cast<int*>(rdn_attr->Value.pbData); |
255 reinterpret_cast<int*>(rdn_attr->Value.pbData); | |
256 for (DWORD k = 0; k < num_ints; ++k) { | 254 for (DWORD k = 0; k < num_ints; ++k) { |
257 if (common_name[k] == 0) | 255 if (common_name[k] == 0) |
258 return true; | 256 return true; |
259 } | 257 } |
260 break; | 258 break; |
261 } | 259 } |
262 default: | 260 default: |
263 NOTREACHED(); | 261 NOTREACHED(); |
264 break; | 262 break; |
265 } | 263 } |
(...skipping 28 matching lines...) Expand all Loading... |
294 if (chain_context->cChain == 0) | 292 if (chain_context->cChain == 0) |
295 return; | 293 return; |
296 | 294 |
297 PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0]; | 295 PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0]; |
298 int num_elements = first_chain->cElement; | 296 int num_elements = first_chain->cElement; |
299 PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement; | 297 PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement; |
300 | 298 |
301 PCCERT_CONTEXT verified_cert = NULL; | 299 PCCERT_CONTEXT verified_cert = NULL; |
302 std::vector<PCCERT_CONTEXT> verified_chain; | 300 std::vector<PCCERT_CONTEXT> verified_chain; |
303 | 301 |
304 bool has_root_ca = num_elements > 1 && | 302 bool has_root_ca = |
305 !(chain_context->TrustStatus.dwErrorStatus & | 303 num_elements > 1 && |
306 CERT_TRUST_IS_PARTIAL_CHAIN); | 304 !(chain_context->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN); |
307 | 305 |
308 // Each chain starts with the end entity certificate (i = 0) and ends with | 306 // Each chain starts with the end entity certificate (i = 0) and ends with |
309 // either the root CA certificate or the last available intermediate. If a | 307 // either the root CA certificate or the last available intermediate. If a |
310 // root CA certificate is present, do not inspect the signature algorithm of | 308 // root CA certificate is present, do not inspect the signature algorithm of |
311 // the root CA certificate because the signature on the trust anchor is not | 309 // the root CA certificate because the signature on the trust anchor is not |
312 // important. | 310 // important. |
313 if (has_root_ca) { | 311 if (has_root_ca) { |
314 // If a full chain was constructed, regardless of whether it was trusted, | 312 // If a full chain was constructed, regardless of whether it was trusted, |
315 // don't inspect the root's signature algorithm. | 313 // don't inspect the root's signature algorithm. |
316 num_elements -= 1; | 314 num_elements -= 1; |
(...skipping 18 matching lines...) Expand all Loading... |
335 // md4WithRSAEncryption: 1.2.840.113549.1.1.3 | 333 // md4WithRSAEncryption: 1.2.840.113549.1.1.3 |
336 verify_result->has_md4 = true; | 334 verify_result->has_md4 = true; |
337 } | 335 } |
338 } | 336 } |
339 | 337 |
340 if (verified_cert) { | 338 if (verified_cert) { |
341 // Add the root certificate, if present, as it was not added above. | 339 // Add the root certificate, if present, as it was not added above. |
342 if (has_root_ca) | 340 if (has_root_ca) |
343 verified_chain.push_back(element[num_elements]->pCertContext); | 341 verified_chain.push_back(element[num_elements]->pCertContext); |
344 verify_result->verified_cert = | 342 verify_result->verified_cert = |
345 X509Certificate::CreateFromHandle(verified_cert, verified_chain); | 343 X509Certificate::CreateFromHandle(verified_cert, verified_chain); |
346 } | 344 } |
347 } | 345 } |
348 | 346 |
349 // Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO | 347 // Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO |
350 // structure and stores it in *output. | 348 // structure and stores it in *output. |
351 void GetCertPoliciesInfo( | 349 void GetCertPoliciesInfo( |
352 PCCERT_CONTEXT cert, | 350 PCCERT_CONTEXT cert, |
353 scoped_ptr<CERT_POLICIES_INFO, base::FreeDeleter>* output) { | 351 scoped_ptr<CERT_POLICIES_INFO, base::FreeDeleter>* output) { |
354 PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES, | 352 PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES, |
355 cert->pCertInfo->cExtension, | 353 cert->pCertInfo->cExtension, |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 | 469 |
472 base::StringPiece der_bytes( | 470 base::StringPiece der_bytes( |
473 reinterpret_cast<const char*>(cert->pbCertEncoded), | 471 reinterpret_cast<const char*>(cert->pbCertEncoded), |
474 cert->cbCertEncoded); | 472 cert->cbCertEncoded); |
475 base::StringPiece spki_bytes; | 473 base::StringPiece spki_bytes; |
476 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) | 474 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) |
477 continue; | 475 continue; |
478 | 476 |
479 HashValue sha1(HASH_VALUE_SHA1); | 477 HashValue sha1(HASH_VALUE_SHA1); |
480 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), | 478 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), |
481 spki_bytes.size(), sha1.data()); | 479 spki_bytes.size(), |
| 480 sha1.data()); |
482 hashes->push_back(sha1); | 481 hashes->push_back(sha1); |
483 | 482 |
484 HashValue sha256(HASH_VALUE_SHA256); | 483 HashValue sha256(HASH_VALUE_SHA256); |
485 crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length); | 484 crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length); |
486 hashes->push_back(sha256); | 485 hashes->push_back(sha256); |
487 } | 486 } |
488 } | 487 } |
489 | 488 |
490 // Returns true if the certificate is an extended-validation certificate. | 489 // Returns true if the certificate is an extended-validation certificate. |
491 // | 490 // |
(...skipping 25 matching lines...) Expand all Loading... |
517 // Check the end certificate simple chain (chain_context->rgpChain[0]). | 516 // Check the end certificate simple chain (chain_context->rgpChain[0]). |
518 // If the end certificate's certificatePolicies extension contains the | 517 // If the end certificate's certificatePolicies extension contains the |
519 // EV policy OID of the root CA, return true. | 518 // EV policy OID of the root CA, return true. |
520 PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement; | 519 PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement; |
521 int num_elements = chain_context->rgpChain[0]->cElement; | 520 int num_elements = chain_context->rgpChain[0]->cElement; |
522 if (num_elements < 2) | 521 if (num_elements < 2) |
523 return false; | 522 return false; |
524 | 523 |
525 // Look up the EV policy OID of the root CA. | 524 // Look up the EV policy OID of the root CA. |
526 PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext; | 525 PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext; |
527 SHA1HashValue fingerprint = | 526 SHA1HashValue fingerprint = X509Certificate::CalculateFingerprint(root_cert); |
528 X509Certificate::CalculateFingerprint(root_cert); | |
529 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); | 527 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); |
530 return metadata->HasEVPolicyOID(fingerprint, policy_oid); | 528 return metadata->HasEVPolicyOID(fingerprint, policy_oid); |
531 } | 529 } |
532 | 530 |
533 } // namespace | 531 } // namespace |
534 | 532 |
535 CertVerifyProcWin::CertVerifyProcWin() {} | 533 CertVerifyProcWin::CertVerifyProcWin() { |
| 534 } |
536 | 535 |
537 CertVerifyProcWin::~CertVerifyProcWin() {} | 536 CertVerifyProcWin::~CertVerifyProcWin() { |
| 537 } |
538 | 538 |
539 bool CertVerifyProcWin::SupportsAdditionalTrustAnchors() const { | 539 bool CertVerifyProcWin::SupportsAdditionalTrustAnchors() const { |
540 return false; | 540 return false; |
541 } | 541 } |
542 | 542 |
543 int CertVerifyProcWin::VerifyInternal( | 543 int CertVerifyProcWin::VerifyInternal( |
544 X509Certificate* cert, | 544 X509Certificate* cert, |
545 const std::string& hostname, | 545 const std::string& hostname, |
546 int flags, | 546 int flags, |
547 CRLSet* crl_set, | 547 CRLSet* crl_set, |
548 const CertificateList& additional_trust_anchors, | 548 const CertificateList& additional_trust_anchors, |
549 CertVerifyResult* verify_result) { | 549 CertVerifyResult* verify_result) { |
550 PCCERT_CONTEXT cert_handle = cert->os_cert_handle(); | 550 PCCERT_CONTEXT cert_handle = cert->os_cert_handle(); |
551 if (!cert_handle) | 551 if (!cert_handle) |
552 return ERR_UNEXPECTED; | 552 return ERR_UNEXPECTED; |
553 | 553 |
554 // Build and validate certificate chain. | 554 // Build and validate certificate chain. |
555 CERT_CHAIN_PARA chain_para; | 555 CERT_CHAIN_PARA chain_para; |
556 memset(&chain_para, 0, sizeof(chain_para)); | 556 memset(&chain_para, 0, sizeof(chain_para)); |
557 chain_para.cbSize = sizeof(chain_para); | 557 chain_para.cbSize = sizeof(chain_para); |
558 // ExtendedKeyUsage. | 558 // ExtendedKeyUsage. |
559 // We still need to request szOID_SERVER_GATED_CRYPTO and szOID_SGC_NETSCAPE | 559 // We still need to request szOID_SERVER_GATED_CRYPTO and szOID_SGC_NETSCAPE |
560 // today because some certificate chains need them. IE also requests these | 560 // today because some certificate chains need them. IE also requests these |
561 // two usages. | 561 // two usages. |
562 static const LPSTR usage[] = { | 562 static const LPSTR usage[] = {szOID_PKIX_KP_SERVER_AUTH, |
563 szOID_PKIX_KP_SERVER_AUTH, | 563 szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE}; |
564 szOID_SERVER_GATED_CRYPTO, | |
565 szOID_SGC_NETSCAPE | |
566 }; | |
567 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; | 564 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; |
568 chain_para.RequestedUsage.Usage.cUsageIdentifier = arraysize(usage); | 565 chain_para.RequestedUsage.Usage.cUsageIdentifier = arraysize(usage); |
569 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = | 566 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = |
570 const_cast<LPSTR*>(usage); | 567 const_cast<LPSTR*>(usage); |
571 | 568 |
572 // Get the certificatePolicies extension of the certificate. | 569 // Get the certificatePolicies extension of the certificate. |
573 scoped_ptr<CERT_POLICIES_INFO, base::FreeDeleter> policies_info; | 570 scoped_ptr<CERT_POLICIES_INFO, base::FreeDeleter> policies_info; |
574 LPSTR ev_policy_oid = NULL; | 571 LPSTR ev_policy_oid = NULL; |
575 if (flags & CertVerifier::VERIFY_EV_CERT) { | 572 if (flags & CertVerifier::VERIFY_EV_CERT) { |
576 GetCertPoliciesInfo(cert_handle, &policies_info); | 573 GetCertPoliciesInfo(cert_handle, &policies_info); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 // certificate. | 608 // certificate. |
612 ScopedHCERTCHAINENGINE chain_engine(NULL); | 609 ScopedHCERTCHAINENGINE chain_engine(NULL); |
613 if (TestRootCerts::HasInstance()) | 610 if (TestRootCerts::HasInstance()) |
614 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); | 611 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); |
615 | 612 |
616 ScopedPCCERT_CONTEXT cert_list(cert->CreateOSCertChainForCert()); | 613 ScopedPCCERT_CONTEXT cert_list(cert->CreateOSCertChainForCert()); |
617 PCCERT_CHAIN_CONTEXT chain_context; | 614 PCCERT_CHAIN_CONTEXT chain_context; |
618 // IE passes a non-NULL pTime argument that specifies the current system | 615 // IE passes a non-NULL pTime argument that specifies the current system |
619 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the | 616 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the |
620 // chain_flags argument. | 617 // chain_flags argument. |
621 if (!CertGetCertificateChain( | 618 if (!CertGetCertificateChain(chain_engine, |
622 chain_engine, | 619 cert_list.get(), |
623 cert_list.get(), | 620 NULL, // current system time |
624 NULL, // current system time | 621 cert_list->hCertStore, |
625 cert_list->hCertStore, | 622 &chain_para, |
626 &chain_para, | 623 chain_flags, |
627 chain_flags, | 624 NULL, // reserved |
628 NULL, // reserved | 625 &chain_context)) { |
629 &chain_context)) { | |
630 verify_result->cert_status |= CERT_STATUS_INVALID; | 626 verify_result->cert_status |= CERT_STATUS_INVALID; |
631 return MapSecurityError(GetLastError()); | 627 return MapSecurityError(GetLastError()); |
632 } | 628 } |
633 | 629 |
634 CRLSetResult crl_set_result = kCRLSetUnknown; | 630 CRLSetResult crl_set_result = kCRLSetUnknown; |
635 if (crl_set) | 631 if (crl_set) |
636 crl_set_result = CheckRevocationWithCRLSet(chain_context, crl_set); | 632 crl_set_result = CheckRevocationWithCRLSet(chain_context, crl_set); |
637 | 633 |
638 if (crl_set_result == kCRLSetRevoked) { | 634 if (crl_set_result == kCRLSetRevoked) { |
639 verify_result->cert_status |= CERT_STATUS_REVOKED; | 635 verify_result->cert_status |= CERT_STATUS_REVOKED; |
640 } else if (crl_set_result == kCRLSetUnknown && | 636 } else if (crl_set_result == kCRLSetUnknown && |
641 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY) && | 637 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY) && |
642 !rev_checking_enabled && | 638 !rev_checking_enabled && ev_policy_oid != NULL) { |
643 ev_policy_oid != NULL) { | |
644 // We don't have fresh information about this chain from the CRLSet and | 639 // We don't have fresh information about this chain from the CRLSet and |
645 // it's probably an EV certificate. Retry with online revocation checking. | 640 // it's probably an EV certificate. Retry with online revocation checking. |
646 rev_checking_enabled = true; | 641 rev_checking_enabled = true; |
647 chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; | 642 chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; |
648 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 643 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
649 | 644 |
650 CertFreeCertificateChain(chain_context); | 645 CertFreeCertificateChain(chain_context); |
651 if (!CertGetCertificateChain( | 646 if (!CertGetCertificateChain(chain_engine, |
652 chain_engine, | 647 cert_list.get(), |
653 cert_list.get(), | 648 NULL, // current system time |
654 NULL, // current system time | 649 cert_list->hCertStore, |
655 cert_list->hCertStore, | 650 &chain_para, |
656 &chain_para, | 651 chain_flags, |
657 chain_flags, | 652 NULL, // reserved |
658 NULL, // reserved | 653 &chain_context)) { |
659 &chain_context)) { | |
660 verify_result->cert_status |= CERT_STATUS_INVALID; | 654 verify_result->cert_status |= CERT_STATUS_INVALID; |
661 return MapSecurityError(GetLastError()); | 655 return MapSecurityError(GetLastError()); |
662 } | 656 } |
663 } | 657 } |
664 | 658 |
665 if (chain_context->TrustStatus.dwErrorStatus & | 659 if (chain_context->TrustStatus.dwErrorStatus & |
666 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { | 660 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { |
667 ev_policy_oid = NULL; | 661 ev_policy_oid = NULL; |
668 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; | 662 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; |
669 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; | 663 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; |
670 CertFreeCertificateChain(chain_context); | 664 CertFreeCertificateChain(chain_context); |
671 if (!CertGetCertificateChain( | 665 if (!CertGetCertificateChain(chain_engine, |
672 chain_engine, | 666 cert_list.get(), |
673 cert_list.get(), | 667 NULL, // current system time |
674 NULL, // current system time | 668 cert_list->hCertStore, |
675 cert_list->hCertStore, | 669 &chain_para, |
676 &chain_para, | 670 chain_flags, |
677 chain_flags, | 671 NULL, // reserved |
678 NULL, // reserved | 672 &chain_context)) { |
679 &chain_context)) { | |
680 verify_result->cert_status |= CERT_STATUS_INVALID; | 673 verify_result->cert_status |= CERT_STATUS_INVALID; |
681 return MapSecurityError(GetLastError()); | 674 return MapSecurityError(GetLastError()); |
682 } | 675 } |
683 } | 676 } |
684 | 677 |
685 CertVerifyResult temp_verify_result = *verify_result; | 678 CertVerifyResult temp_verify_result = *verify_result; |
686 GetCertChainInfo(chain_context, verify_result); | 679 GetCertChainInfo(chain_context, verify_result); |
687 if (!verify_result->is_issued_by_known_root && | 680 if (!verify_result->is_issued_by_known_root && |
688 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS)) { | 681 (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS)) { |
689 *verify_result = temp_verify_result; | 682 *verify_result = temp_verify_result; |
690 | 683 |
691 rev_checking_enabled = true; | 684 rev_checking_enabled = true; |
692 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 685 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
693 chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; | 686 chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; |
694 | 687 |
695 CertFreeCertificateChain(chain_context); | 688 CertFreeCertificateChain(chain_context); |
696 if (!CertGetCertificateChain( | 689 if (!CertGetCertificateChain(chain_engine, |
697 chain_engine, | 690 cert_list.get(), |
698 cert_list.get(), | 691 NULL, // current system time |
699 NULL, // current system time | 692 cert_list->hCertStore, |
700 cert_list->hCertStore, | 693 &chain_para, |
701 &chain_para, | 694 chain_flags, |
702 chain_flags, | 695 NULL, // reserved |
703 NULL, // reserved | 696 &chain_context)) { |
704 &chain_context)) { | |
705 verify_result->cert_status |= CERT_STATUS_INVALID; | 697 verify_result->cert_status |= CERT_STATUS_INVALID; |
706 return MapSecurityError(GetLastError()); | 698 return MapSecurityError(GetLastError()); |
707 } | 699 } |
708 GetCertChainInfo(chain_context, verify_result); | 700 GetCertChainInfo(chain_context, verify_result); |
709 | 701 |
710 if (chain_context->TrustStatus.dwErrorStatus & | 702 if (chain_context->TrustStatus.dwErrorStatus & |
711 CERT_TRUST_IS_OFFLINE_REVOCATION) { | 703 CERT_TRUST_IS_OFFLINE_REVOCATION) { |
712 verify_result->cert_status |= CERT_STATUS_REVOKED; | 704 verify_result->cert_status |= CERT_STATUS_REVOKED; |
713 } | 705 } |
714 } | 706 } |
(...skipping 24 matching lines...) Expand all Loading... |
739 memset(&policy_para, 0, sizeof(policy_para)); | 731 memset(&policy_para, 0, sizeof(policy_para)); |
740 policy_para.cbSize = sizeof(policy_para); | 732 policy_para.cbSize = sizeof(policy_para); |
741 policy_para.dwFlags = 0; | 733 policy_para.dwFlags = 0; |
742 policy_para.pvExtraPolicyPara = &extra_policy_para; | 734 policy_para.pvExtraPolicyPara = &extra_policy_para; |
743 | 735 |
744 CERT_CHAIN_POLICY_STATUS policy_status; | 736 CERT_CHAIN_POLICY_STATUS policy_status; |
745 memset(&policy_status, 0, sizeof(policy_status)); | 737 memset(&policy_status, 0, sizeof(policy_status)); |
746 policy_status.cbSize = sizeof(policy_status); | 738 policy_status.cbSize = sizeof(policy_status); |
747 | 739 |
748 if (!CertVerifyCertificateChainPolicy( | 740 if (!CertVerifyCertificateChainPolicy( |
749 CERT_CHAIN_POLICY_SSL, | 741 CERT_CHAIN_POLICY_SSL, chain_context, &policy_para, &policy_status)) { |
750 chain_context, | |
751 &policy_para, | |
752 &policy_status)) { | |
753 return MapSecurityError(GetLastError()); | 742 return MapSecurityError(GetLastError()); |
754 } | 743 } |
755 | 744 |
756 if (policy_status.dwError) { | 745 if (policy_status.dwError) { |
757 verify_result->cert_status |= MapNetErrorToCertStatus( | 746 verify_result->cert_status |= |
758 MapSecurityError(policy_status.dwError)); | 747 MapNetErrorToCertStatus(MapSecurityError(policy_status.dwError)); |
759 } | 748 } |
760 | 749 |
761 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be | 750 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be |
762 // compatible with WinHTTP, which doesn't report this error (bug 3004). | 751 // compatible with WinHTTP, which doesn't report this error (bug 3004). |
763 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; | 752 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; |
764 | 753 |
765 // Perform hostname verification independent of | 754 // Perform hostname verification independent of |
766 // CertVerifyCertificateChainPolicy. | 755 // CertVerifyCertificateChainPolicy. |
767 if (!cert->VerifyNameMatch(hostname, | 756 if (!cert->VerifyNameMatch(hostname, |
768 &verify_result->common_name_fallback_used)) { | 757 &verify_result->common_name_fallback_used)) { |
(...skipping 15 matching lines...) Expand all Loading... |
784 return MapCertStatusToNetError(verify_result->cert_status); | 773 return MapCertStatusToNetError(verify_result->cert_status); |
785 | 774 |
786 if (ev_policy_oid && | 775 if (ev_policy_oid && |
787 CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) { | 776 CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) { |
788 verify_result->cert_status |= CERT_STATUS_IS_EV; | 777 verify_result->cert_status |= CERT_STATUS_IS_EV; |
789 } | 778 } |
790 return OK; | 779 return OK; |
791 } | 780 } |
792 | 781 |
793 } // namespace net | 782 } // namespace net |
OLD | NEW |