| 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 |