6d841c417b2cc9ad4fcc2a2eff7e25ea02b57932
[platform/framework/web/crosswalk.git] / src / net / cert / cert_verify_proc_win.cc
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
3 // found in the LICENSE file.
4
5 #include "net/cert/cert_verify_proc_win.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/memory/scoped_ptr.h"
11 #include "base/sha1.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "crypto/capi_util.h"
15 #include "crypto/scoped_capi_types.h"
16 #include "crypto/sha2.h"
17 #include "net/base/net_errors.h"
18 #include "net/cert/asn1_util.h"
19 #include "net/cert/cert_status_flags.h"
20 #include "net/cert/cert_verifier.h"
21 #include "net/cert/cert_verify_result.h"
22 #include "net/cert/crl_set.h"
23 #include "net/cert/ev_root_ca_metadata.h"
24 #include "net/cert/test_root_certs.h"
25 #include "net/cert/x509_certificate.h"
26 #include "net/cert/x509_certificate_known_roots_win.h"
27
28 #pragma comment(lib, "crypt32.lib")
29
30 #if !defined(CERT_TRUST_HAS_WEAK_SIGNATURE)
31 // This was introduced in Windows 8 / Windows Server 2012, but retroactively
32 // ported as far back as Windows XP via system update.
33 #define CERT_TRUST_HAS_WEAK_SIGNATURE 0x00100000
34 #endif
35
36 namespace net {
37
38 namespace {
39
40 struct FreeChainEngineFunctor {
41   void operator()(HCERTCHAINENGINE engine) const {
42     if (engine)
43       CertFreeCertificateChainEngine(engine);
44   }
45 };
46
47 struct FreeCertChainContextFunctor {
48   void operator()(PCCERT_CHAIN_CONTEXT chain_context) const {
49     if (chain_context)
50       CertFreeCertificateChain(chain_context);
51   }
52 };
53
54 struct FreeCertContextFunctor {
55   void operator()(PCCERT_CONTEXT context) const {
56     if (context)
57       CertFreeCertificateContext(context);
58   }
59 };
60
61 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor>
62     ScopedHCERTCHAINENGINE;
63
64 typedef scoped_ptr<const CERT_CHAIN_CONTEXT, FreeCertChainContextFunctor>
65     ScopedPCCERT_CHAIN_CONTEXT;
66
67 typedef scoped_ptr<const CERT_CONTEXT, FreeCertContextFunctor>
68     ScopedPCCERT_CONTEXT;
69
70 //-----------------------------------------------------------------------------
71
72 int MapSecurityError(SECURITY_STATUS err) {
73   // There are numerous security error codes, but these are the ones we thus
74   // far find interesting.
75   switch (err) {
76     case SEC_E_WRONG_PRINCIPAL:  // Schannel
77     case CERT_E_CN_NO_MATCH:  // CryptoAPI
78       return ERR_CERT_COMMON_NAME_INVALID;
79     case SEC_E_UNTRUSTED_ROOT:  // Schannel
80     case CERT_E_UNTRUSTEDROOT:  // CryptoAPI
81       return ERR_CERT_AUTHORITY_INVALID;
82     case SEC_E_CERT_EXPIRED:  // Schannel
83     case CERT_E_EXPIRED:  // CryptoAPI
84       return ERR_CERT_DATE_INVALID;
85     case CRYPT_E_NO_REVOCATION_CHECK:
86       return ERR_CERT_NO_REVOCATION_MECHANISM;
87     case CRYPT_E_REVOCATION_OFFLINE:
88       return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
89     case CRYPT_E_REVOKED:  // Schannel and CryptoAPI
90       return ERR_CERT_REVOKED;
91     case SEC_E_CERT_UNKNOWN:
92     case CERT_E_ROLE:
93       return ERR_CERT_INVALID;
94     case CERT_E_WRONG_USAGE:
95       // TODO(wtc): Should we add ERR_CERT_WRONG_USAGE?
96       return ERR_CERT_INVALID;
97     // We received an unexpected_message or illegal_parameter alert message
98     // from the server.
99     case SEC_E_ILLEGAL_MESSAGE:
100       return ERR_SSL_PROTOCOL_ERROR;
101     case SEC_E_ALGORITHM_MISMATCH:
102       return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
103     case SEC_E_INVALID_HANDLE:
104       return ERR_UNEXPECTED;
105     case SEC_E_OK:
106       return OK;
107     default:
108       LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
109       return ERR_FAILED;
110   }
111 }
112
113 // Map the errors in the chain_context->TrustStatus.dwErrorStatus returned by
114 // CertGetCertificateChain to our certificate status flags.
115 int MapCertChainErrorStatusToCertStatus(DWORD error_status) {
116   CertStatus cert_status = 0;
117
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
120   const DWORD kDateInvalidErrors = CERT_TRUST_IS_NOT_TIME_VALID |
121                                    CERT_TRUST_CTL_IS_NOT_TIME_VALID;
122   if (error_status & kDateInvalidErrors)
123     cert_status |= CERT_STATUS_DATE_INVALID;
124
125   const DWORD kAuthorityInvalidErrors = CERT_TRUST_IS_UNTRUSTED_ROOT |
126                                         CERT_TRUST_IS_EXPLICIT_DISTRUST |
127                                         CERT_TRUST_IS_PARTIAL_CHAIN;
128   if (error_status & kAuthorityInvalidErrors)
129     cert_status |= CERT_STATUS_AUTHORITY_INVALID;
130
131   if ((error_status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) &&
132       !(error_status & CERT_TRUST_IS_OFFLINE_REVOCATION))
133     cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM;
134
135   if (error_status & CERT_TRUST_IS_OFFLINE_REVOCATION)
136     cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
137
138   if (error_status & CERT_TRUST_IS_REVOKED)
139     cert_status |= CERT_STATUS_REVOKED;
140
141   const DWORD kWrongUsageErrors = CERT_TRUST_IS_NOT_VALID_FOR_USAGE |
142                                   CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
143   if (error_status & kWrongUsageErrors) {
144     // TODO(wtc): Should we add CERT_STATUS_WRONG_USAGE?
145     cert_status |= CERT_STATUS_INVALID;
146   }
147
148   if (error_status & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
149     // Check for a signature that does not meet the OS criteria for strong
150     // signatures.
151     // Note: These checks may be more restrictive than the current weak key
152     // criteria implemented within CertVerifier, such as excluding SHA-1 or
153     // excluding RSA keys < 2048 bits. However, if the user has configured
154     // these more stringent checks, respect that configuration and err on the
155     // more restrictive criteria.
156     if (error_status & CERT_TRUST_HAS_WEAK_SIGNATURE) {
157       cert_status |= CERT_STATUS_WEAK_KEY;
158     } else {
159       cert_status |= CERT_STATUS_INVALID;
160     }
161   }
162
163   // The rest of the errors.
164   const DWORD kCertInvalidErrors =
165       CERT_TRUST_IS_CYCLIC |
166       CERT_TRUST_INVALID_EXTENSION |
167       CERT_TRUST_INVALID_POLICY_CONSTRAINTS |
168       CERT_TRUST_INVALID_BASIC_CONSTRAINTS |
169       CERT_TRUST_INVALID_NAME_CONSTRAINTS |
170       CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID |
171       CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT |
172       CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT |
173       CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT |
174       CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT |
175       CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY |
176       CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT;
177   if (error_status & kCertInvalidErrors)
178     cert_status |= CERT_STATUS_INVALID;
179
180   return cert_status;
181 }
182
183 // Returns true if any common name in the certificate's Subject field contains
184 // a NULL character.
185 bool CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert) {
186   CRYPT_DECODE_PARA decode_para;
187   decode_para.cbSize = sizeof(decode_para);
188   decode_para.pfnAlloc = crypto::CryptAlloc;
189   decode_para.pfnFree = crypto::CryptFree;
190   CERT_NAME_INFO* name_info = NULL;
191   DWORD name_info_size = 0;
192   BOOL rv;
193   rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
194                            X509_NAME,
195                            cert->pCertInfo->Subject.pbData,
196                            cert->pCertInfo->Subject.cbData,
197                            CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
198                            &decode_para,
199                            &name_info,
200                            &name_info_size);
201   if (rv) {
202     scoped_ptr<CERT_NAME_INFO, base::FreeDeleter> scoped_name_info(name_info);
203
204     // The Subject field may have multiple common names.  According to the
205     // "PKI Layer Cake" paper, CryptoAPI uses every common name in the
206     // Subject field, so we inspect every common name.
207     //
208     // From RFC 5280:
209     // X520CommonName ::= CHOICE {
210     //       teletexString     TeletexString   (SIZE (1..ub-common-name)),
211     //       printableString   PrintableString (SIZE (1..ub-common-name)),
212     //       universalString   UniversalString (SIZE (1..ub-common-name)),
213     //       utf8String        UTF8String      (SIZE (1..ub-common-name)),
214     //       bmpString         BMPString       (SIZE (1..ub-common-name)) }
215     //
216     // We also check IA5String and VisibleString.
217     for (DWORD i = 0; i < name_info->cRDN; ++i) {
218       PCERT_RDN rdn = &name_info->rgRDN[i];
219       for (DWORD j = 0; j < rdn->cRDNAttr; ++j) {
220         PCERT_RDN_ATTR rdn_attr = &rdn->rgRDNAttr[j];
221         if (strcmp(rdn_attr->pszObjId, szOID_COMMON_NAME) == 0) {
222           switch (rdn_attr->dwValueType) {
223             // After the CryptoAPI ASN.1 security vulnerabilities described in
224             // http://www.microsoft.com/technet/security/Bulletin/MS09-056.mspx
225             // were patched, we get CERT_RDN_ENCODED_BLOB for a common name
226             // that contains a NULL character.
227             case CERT_RDN_ENCODED_BLOB:
228               break;
229             // Array of 8-bit characters.
230             case CERT_RDN_PRINTABLE_STRING:
231             case CERT_RDN_TELETEX_STRING:
232             case CERT_RDN_IA5_STRING:
233             case CERT_RDN_VISIBLE_STRING:
234               for (DWORD k = 0; k < rdn_attr->Value.cbData; ++k) {
235                 if (rdn_attr->Value.pbData[k] == '\0')
236                   return true;
237               }
238               break;
239             // Array of 16-bit characters.
240             case CERT_RDN_BMP_STRING:
241             case CERT_RDN_UTF8_STRING: {
242               DWORD num_wchars = rdn_attr->Value.cbData / 2;
243               wchar_t* common_name =
244                   reinterpret_cast<wchar_t*>(rdn_attr->Value.pbData);
245               for (DWORD k = 0; k < num_wchars; ++k) {
246                 if (common_name[k] == L'\0')
247                   return true;
248               }
249               break;
250             }
251             // Array of ints (32-bit).
252             case CERT_RDN_UNIVERSAL_STRING: {
253               DWORD num_ints = rdn_attr->Value.cbData / 4;
254               int* common_name =
255                   reinterpret_cast<int*>(rdn_attr->Value.pbData);
256               for (DWORD k = 0; k < num_ints; ++k) {
257                 if (common_name[k] == 0)
258                   return true;
259               }
260               break;
261             }
262             default:
263               NOTREACHED();
264               break;
265           }
266         }
267       }
268     }
269   }
270   return false;
271 }
272
273 // IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA
274 // which we recognise as a standard root.
275 // static
276 bool IsIssuedByKnownRoot(PCCERT_CHAIN_CONTEXT chain_context) {
277   PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0];
278   int num_elements = first_chain->cElement;
279   if (num_elements < 1)
280     return false;
281   PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
282   PCCERT_CONTEXT cert = element[num_elements - 1]->pCertContext;
283
284   SHA1HashValue hash = X509Certificate::CalculateFingerprint(cert);
285   return IsSHA1HashInSortedArray(
286       hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes));
287 }
288
289 // Saves some information about the certificate chain |chain_context| in
290 // |*verify_result|. The caller MUST initialize |*verify_result| before
291 // calling this function.
292 void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
293                       CertVerifyResult* verify_result) {
294   if (chain_context->cChain == 0)
295     return;
296
297   PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0];
298   int num_elements = first_chain->cElement;
299   PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
300
301   PCCERT_CONTEXT verified_cert = NULL;
302   std::vector<PCCERT_CONTEXT> verified_chain;
303
304   bool has_root_ca = num_elements > 1 &&
305       !(chain_context->TrustStatus.dwErrorStatus &
306           CERT_TRUST_IS_PARTIAL_CHAIN);
307
308   // 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
310   // 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
312   // important.
313   if (has_root_ca) {
314     // If a full chain was constructed, regardless of whether it was trusted,
315     // don't inspect the root's signature algorithm.
316     num_elements -= 1;
317   }
318
319   for (int i = 0; i < num_elements; ++i) {
320     PCCERT_CONTEXT cert = element[i]->pCertContext;
321     if (i == 0) {
322       verified_cert = cert;
323     } else {
324       verified_chain.push_back(cert);
325     }
326
327     const char* algorithm = cert->pCertInfo->SignatureAlgorithm.pszObjId;
328     if (strcmp(algorithm, szOID_RSA_MD5RSA) == 0) {
329       // md5WithRSAEncryption: 1.2.840.113549.1.1.4
330       verify_result->has_md5 = true;
331     } else if (strcmp(algorithm, szOID_RSA_MD2RSA) == 0) {
332       // md2WithRSAEncryption: 1.2.840.113549.1.1.2
333       verify_result->has_md2 = true;
334     } else if (strcmp(algorithm, szOID_RSA_MD4RSA) == 0) {
335       // md4WithRSAEncryption: 1.2.840.113549.1.1.3
336       verify_result->has_md4 = true;
337     } else if (strcmp(algorithm, szOID_RSA_SHA1RSA) == 0 ||
338                strcmp(algorithm, szOID_X957_SHA1DSA) == 0 ||
339                strcmp(algorithm, szOID_ECDSA_SHA1) == 0) {
340       // sha1WithRSAEncryption: 1.2.840.113549.1.1.5
341       // id-dsa-with-sha1: 1.2.840.10040.4.3
342       // ecdsa-with-SHA1: 1.2.840.10045.4.1
343       verify_result->has_sha1 = true;
344     }
345   }
346
347   if (verified_cert) {
348     // Add the root certificate, if present, as it was not added above.
349     if (has_root_ca)
350       verified_chain.push_back(element[num_elements]->pCertContext);
351     verify_result->verified_cert =
352           X509Certificate::CreateFromHandle(verified_cert, verified_chain);
353   }
354 }
355
356 // Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO
357 // structure and stores it in *output.
358 void GetCertPoliciesInfo(
359     PCCERT_CONTEXT cert,
360     scoped_ptr<CERT_POLICIES_INFO, base::FreeDeleter>* output) {
361   PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES,
362                                                 cert->pCertInfo->cExtension,
363                                                 cert->pCertInfo->rgExtension);
364   if (!extension)
365     return;
366
367   CRYPT_DECODE_PARA decode_para;
368   decode_para.cbSize = sizeof(decode_para);
369   decode_para.pfnAlloc = crypto::CryptAlloc;
370   decode_para.pfnFree = crypto::CryptFree;
371   CERT_POLICIES_INFO* policies_info = NULL;
372   DWORD policies_info_size = 0;
373   BOOL rv;
374   rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
375                            szOID_CERT_POLICIES,
376                            extension->Value.pbData,
377                            extension->Value.cbData,
378                            CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
379                            &decode_para,
380                            &policies_info,
381                            &policies_info_size);
382   if (rv)
383     output->reset(policies_info);
384 }
385
386 enum CRLSetResult {
387   kCRLSetOk,
388   kCRLSetUnknown,
389   kCRLSetRevoked,
390 };
391
392 // CheckRevocationWithCRLSet attempts to check each element of |chain|
393 // against |crl_set|. It returns:
394 //   kCRLSetRevoked: if any element of the chain is known to have been revoked.
395 //   kCRLSetUnknown: if there is no fresh information about the leaf
396 //       certificate in the chain or if the CRLSet has expired.
397 //
398 //       Only the leaf certificate is considered for coverage because some
399 //       intermediates have CRLs with no revocations (after filtering) and
400 //       those CRLs are pruned from the CRLSet at generation time. This means
401 //       that some EV sites would otherwise take the hit of an OCSP lookup for
402 //       no reason.
403 //   kCRLSetOk: otherwise.
404 CRLSetResult CheckRevocationWithCRLSet(PCCERT_CHAIN_CONTEXT chain,
405                                        CRLSet* crl_set) {
406   if (chain->cChain == 0)
407     return kCRLSetOk;
408
409   const PCERT_SIMPLE_CHAIN first_chain = chain->rgpChain[0];
410   const PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
411
412   const int num_elements = first_chain->cElement;
413   if (num_elements == 0)
414     return kCRLSetOk;
415
416   // error is set to true if any errors are found. It causes such chains to be
417   // considered as not covered.
418   bool error = false;
419   // last_covered is set to the coverage state of the previous certificate. The
420   // certificates are iterated over backwards thus, after the iteration,
421   // |last_covered| contains the coverage state of the leaf certificate.
422   bool last_covered = false;
423
424   // We iterate from the root certificate down to the leaf, keeping track of
425   // the issuer's SPKI at each step.
426   std::string issuer_spki_hash;
427   for (int i = num_elements - 1; i >= 0; i--) {
428     PCCERT_CONTEXT cert = element[i]->pCertContext;
429
430     base::StringPiece der_bytes(
431         reinterpret_cast<const char*>(cert->pbCertEncoded),
432         cert->cbCertEncoded);
433
434     base::StringPiece spki;
435     if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki)) {
436       NOTREACHED();
437       error = true;
438       continue;
439     }
440
441     const std::string spki_hash = crypto::SHA256HashString(spki);
442
443     const CRYPT_INTEGER_BLOB* serial_blob = &cert->pCertInfo->SerialNumber;
444     scoped_ptr<uint8[]> serial_bytes(new uint8[serial_blob->cbData]);
445     // The bytes of the serial number are stored little-endian.
446     for (unsigned j = 0; j < serial_blob->cbData; j++)
447       serial_bytes[j] = serial_blob->pbData[serial_blob->cbData - j - 1];
448     base::StringPiece serial(reinterpret_cast<const char*>(serial_bytes.get()),
449                              serial_blob->cbData);
450
451     CRLSet::Result result = crl_set->CheckSPKI(spki_hash);
452
453     if (result != CRLSet::REVOKED && !issuer_spki_hash.empty())
454       result = crl_set->CheckSerial(serial, issuer_spki_hash);
455
456     issuer_spki_hash = spki_hash;
457
458     switch (result) {
459       case CRLSet::REVOKED:
460         return kCRLSetRevoked;
461       case CRLSet::UNKNOWN:
462         last_covered = false;
463         continue;
464       case CRLSet::GOOD:
465         last_covered = true;
466         continue;
467       default:
468         NOTREACHED();
469         error = true;
470         continue;
471     }
472   }
473
474   if (error || !last_covered || crl_set->IsExpired())
475     return kCRLSetUnknown;
476   return kCRLSetOk;
477 }
478
479 void AppendPublicKeyHashes(PCCERT_CHAIN_CONTEXT chain,
480                            HashValueVector* hashes) {
481   if (chain->cChain == 0)
482     return;
483
484   PCERT_SIMPLE_CHAIN first_chain = chain->rgpChain[0];
485   PCERT_CHAIN_ELEMENT* const element = first_chain->rgpElement;
486
487   const DWORD num_elements = first_chain->cElement;
488   for (DWORD i = 0; i < num_elements; i++) {
489     PCCERT_CONTEXT cert = element[i]->pCertContext;
490
491     base::StringPiece der_bytes(
492         reinterpret_cast<const char*>(cert->pbCertEncoded),
493         cert->cbCertEncoded);
494     base::StringPiece spki_bytes;
495     if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
496       continue;
497
498     HashValue sha1(HASH_VALUE_SHA1);
499     base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()),
500                         spki_bytes.size(), sha1.data());
501     hashes->push_back(sha1);
502
503     HashValue sha256(HASH_VALUE_SHA256);
504     crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length);
505     hashes->push_back(sha256);
506   }
507 }
508
509 // Returns true if the certificate is an extended-validation certificate.
510 //
511 // This function checks the certificatePolicies extensions of the
512 // certificates in the certificate chain according to Section 7 (pp. 11-12)
513 // of the EV Certificate Guidelines Version 1.0 at
514 // http://cabforum.org/EV_Certificate_Guidelines.pdf.
515 bool CheckEV(PCCERT_CHAIN_CONTEXT chain_context,
516              bool rev_checking_enabled,
517              const char* policy_oid) {
518   DCHECK_NE(static_cast<DWORD>(0), chain_context->cChain);
519   // If the cert doesn't match any of the policies, the
520   // CERT_TRUST_IS_NOT_VALID_FOR_USAGE bit (0x10) in
521   // chain_context->TrustStatus.dwErrorStatus is set.
522   DWORD error_status = chain_context->TrustStatus.dwErrorStatus;
523
524   if (!rev_checking_enabled) {
525     // If online revocation checking is disabled then we will have still
526     // requested that the revocation cache be checked. However, that will often
527     // cause the following two error bits to be set. These error bits mean that
528     // the local OCSP/CRL is stale or missing entries for these certificates.
529     // Since they are expected, we mask them away.
530     error_status &= ~(CERT_TRUST_IS_OFFLINE_REVOCATION |
531                       CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
532   }
533   if (!chain_context->cChain || error_status != CERT_TRUST_NO_ERROR)
534     return false;
535
536   // Check the end certificate simple chain (chain_context->rgpChain[0]).
537   // If the end certificate's certificatePolicies extension contains the
538   // EV policy OID of the root CA, return true.
539   PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement;
540   int num_elements = chain_context->rgpChain[0]->cElement;
541   if (num_elements < 2)
542     return false;
543
544   // Look up the EV policy OID of the root CA.
545   PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext;
546   SHA1HashValue fingerprint =
547       X509Certificate::CalculateFingerprint(root_cert);
548   EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
549   return metadata->HasEVPolicyOID(fingerprint, policy_oid);
550 }
551
552 }  // namespace
553
554 CertVerifyProcWin::CertVerifyProcWin() {}
555
556 CertVerifyProcWin::~CertVerifyProcWin() {}
557
558 bool CertVerifyProcWin::SupportsAdditionalTrustAnchors() const {
559   return false;
560 }
561
562 int CertVerifyProcWin::VerifyInternal(
563     X509Certificate* cert,
564     const std::string& hostname,
565     int flags,
566     CRLSet* crl_set,
567     const CertificateList& additional_trust_anchors,
568     CertVerifyResult* verify_result) {
569   PCCERT_CONTEXT cert_handle = cert->os_cert_handle();
570   if (!cert_handle)
571     return ERR_UNEXPECTED;
572
573   // Build and validate certificate chain.
574   CERT_CHAIN_PARA chain_para;
575   memset(&chain_para, 0, sizeof(chain_para));
576   chain_para.cbSize = sizeof(chain_para);
577   // ExtendedKeyUsage.
578   // We still need to request szOID_SERVER_GATED_CRYPTO and szOID_SGC_NETSCAPE
579   // today because some certificate chains need them.  IE also requests these
580   // two usages.
581   static const LPCSTR usage[] = {
582     szOID_PKIX_KP_SERVER_AUTH,
583     szOID_SERVER_GATED_CRYPTO,
584     szOID_SGC_NETSCAPE
585   };
586   chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
587   chain_para.RequestedUsage.Usage.cUsageIdentifier = arraysize(usage);
588   chain_para.RequestedUsage.Usage.rgpszUsageIdentifier =
589       const_cast<LPSTR*>(usage);
590
591   // Get the certificatePolicies extension of the certificate.
592   scoped_ptr<CERT_POLICIES_INFO, base::FreeDeleter> policies_info;
593   LPSTR ev_policy_oid = NULL;
594   if (flags & CertVerifier::VERIFY_EV_CERT) {
595     GetCertPoliciesInfo(cert_handle, &policies_info);
596     if (policies_info.get()) {
597       EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
598       for (DWORD i = 0; i < policies_info->cPolicyInfo; ++i) {
599         LPSTR policy_oid = policies_info->rgPolicyInfo[i].pszPolicyIdentifier;
600         if (metadata->IsEVPolicyOID(policy_oid)) {
601           ev_policy_oid = policy_oid;
602           chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_AND;
603           chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 1;
604           chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier =
605               &ev_policy_oid;
606           break;
607         }
608       }
609     }
610   }
611
612   // We can set CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS to get more chains.
613   DWORD chain_flags = CERT_CHAIN_CACHE_END_CERT |
614                       CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
615   bool rev_checking_enabled =
616       (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED);
617
618   if (rev_checking_enabled) {
619     verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
620   } else {
621     chain_flags |= CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
622   }
623
624   // For non-test scenarios, use the default HCERTCHAINENGINE, NULL, which
625   // corresponds to HCCE_CURRENT_USER and is is initialized as needed by
626   // crypt32. However, when testing, it is necessary to create a new
627   // HCERTCHAINENGINE and use that instead. This is because each
628   // HCERTCHAINENGINE maintains a cache of information about certificates
629   // encountered, and each test run may modify the trust status of a
630   // certificate.
631   ScopedHCERTCHAINENGINE chain_engine(NULL);
632   if (TestRootCerts::HasInstance())
633     chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
634
635   ScopedPCCERT_CONTEXT cert_list(cert->CreateOSCertChainForCert());
636   PCCERT_CHAIN_CONTEXT chain_context;
637   // IE passes a non-NULL pTime argument that specifies the current system
638   // time.  IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
639   // chain_flags argument.
640   if (!CertGetCertificateChain(
641            chain_engine,
642            cert_list.get(),
643            NULL,  // current system time
644            cert_list->hCertStore,
645            &chain_para,
646            chain_flags,
647            NULL,  // reserved
648            &chain_context)) {
649     verify_result->cert_status |= CERT_STATUS_INVALID;
650     return MapSecurityError(GetLastError());
651   }
652
653   CRLSetResult crl_set_result = kCRLSetUnknown;
654   if (crl_set)
655     crl_set_result = CheckRevocationWithCRLSet(chain_context, crl_set);
656
657   if (crl_set_result == kCRLSetRevoked) {
658     verify_result->cert_status |= CERT_STATUS_REVOKED;
659   } else if (crl_set_result == kCRLSetUnknown &&
660              (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY) &&
661              !rev_checking_enabled &&
662              ev_policy_oid != NULL) {
663     // We don't have fresh information about this chain from the CRLSet and
664     // it's probably an EV certificate. Retry with online revocation checking.
665     rev_checking_enabled = true;
666     chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
667     verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
668
669     CertFreeCertificateChain(chain_context);
670     if (!CertGetCertificateChain(
671              chain_engine,
672              cert_list.get(),
673              NULL,  // current system time
674              cert_list->hCertStore,
675              &chain_para,
676              chain_flags,
677              NULL,  // reserved
678              &chain_context)) {
679       verify_result->cert_status |= CERT_STATUS_INVALID;
680       return MapSecurityError(GetLastError());
681     }
682   }
683
684   if (chain_context->TrustStatus.dwErrorStatus &
685       CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
686     ev_policy_oid = NULL;
687     chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
688     chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL;
689     CertFreeCertificateChain(chain_context);
690     if (!CertGetCertificateChain(
691              chain_engine,
692              cert_list.get(),
693              NULL,  // current system time
694              cert_list->hCertStore,
695              &chain_para,
696              chain_flags,
697              NULL,  // reserved
698              &chain_context)) {
699       verify_result->cert_status |= CERT_STATUS_INVALID;
700       return MapSecurityError(GetLastError());
701     }
702   }
703
704   CertVerifyResult temp_verify_result = *verify_result;
705   GetCertChainInfo(chain_context, verify_result);
706   if (!verify_result->is_issued_by_known_root &&
707       (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS)) {
708     *verify_result = temp_verify_result;
709
710     rev_checking_enabled = true;
711     verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
712     chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
713
714     CertFreeCertificateChain(chain_context);
715     if (!CertGetCertificateChain(
716              chain_engine,
717              cert_list.get(),
718              NULL,  // current system time
719              cert_list->hCertStore,
720              &chain_para,
721              chain_flags,
722              NULL,  // reserved
723              &chain_context)) {
724       verify_result->cert_status |= CERT_STATUS_INVALID;
725       return MapSecurityError(GetLastError());
726     }
727     GetCertChainInfo(chain_context, verify_result);
728
729     if (chain_context->TrustStatus.dwErrorStatus &
730         CERT_TRUST_IS_OFFLINE_REVOCATION) {
731       verify_result->cert_status |= CERT_STATUS_REVOKED;
732     }
733   }
734
735   ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context);
736
737   verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
738       chain_context->TrustStatus.dwErrorStatus);
739
740   // Flag certificates that have a Subject common name with a NULL character.
741   if (CertSubjectCommonNameHasNull(cert_handle))
742     verify_result->cert_status |= CERT_STATUS_INVALID;
743
744   std::wstring wstr_hostname = base::ASCIIToWide(hostname);
745
746   SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para;
747   memset(&extra_policy_para, 0, sizeof(extra_policy_para));
748   extra_policy_para.cbSize = sizeof(extra_policy_para);
749   extra_policy_para.dwAuthType = AUTHTYPE_SERVER;
750   // Certificate name validation happens separately, later, using an internal
751   // routine that has better support for RFC 6125 name matching.
752   extra_policy_para.fdwChecks =
753       0x00001000;  // SECURITY_FLAG_IGNORE_CERT_CN_INVALID
754   extra_policy_para.pwszServerName =
755       const_cast<wchar_t*>(wstr_hostname.c_str());
756
757   CERT_CHAIN_POLICY_PARA policy_para;
758   memset(&policy_para, 0, sizeof(policy_para));
759   policy_para.cbSize = sizeof(policy_para);
760   policy_para.dwFlags = 0;
761   policy_para.pvExtraPolicyPara = &extra_policy_para;
762
763   CERT_CHAIN_POLICY_STATUS policy_status;
764   memset(&policy_status, 0, sizeof(policy_status));
765   policy_status.cbSize = sizeof(policy_status);
766
767   if (!CertVerifyCertificateChainPolicy(
768            CERT_CHAIN_POLICY_SSL,
769            chain_context,
770            &policy_para,
771            &policy_status)) {
772     return MapSecurityError(GetLastError());
773   }
774
775   if (policy_status.dwError) {
776     verify_result->cert_status |= MapNetErrorToCertStatus(
777         MapSecurityError(policy_status.dwError));
778   }
779
780   // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be
781   // compatible with WinHTTP, which doesn't report this error (bug 3004).
782   verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM;
783
784   // Perform hostname verification independent of
785   // CertVerifyCertificateChainPolicy.
786   if (!cert->VerifyNameMatch(hostname,
787                              &verify_result->common_name_fallback_used)) {
788     verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
789   }
790
791   if (!rev_checking_enabled) {
792     // If we didn't do online revocation checking then Windows will report
793     // CERT_UNABLE_TO_CHECK_REVOCATION unless it had cached OCSP or CRL
794     // information for every certificate. We only want to put up revoked
795     // statuses from the offline checks so we squash this error.
796     verify_result->cert_status &= ~CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
797   }
798
799   AppendPublicKeyHashes(chain_context, &verify_result->public_key_hashes);
800   verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(chain_context);
801
802   if (IsCertStatusError(verify_result->cert_status))
803     return MapCertStatusToNetError(verify_result->cert_status);
804
805   if (ev_policy_oid &&
806       CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) {
807     verify_result->cert_status |= CERT_STATUS_IS_EV;
808   }
809   return OK;
810 }
811
812 }  // namespace net