15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h"
92385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/strings/stringprintf.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/net_util.h"
13d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_status_flags.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verifier.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_result.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/crl_set.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h"
19d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "url/url_canon.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_NSS) || defined(OS_IOS)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc_nss.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc_openssl.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_ANDROID)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc_android.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc_mac.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc_win.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Implement certificate verification.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Constants used to build histogram names
412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char kLeafCert[] = "Leaf";
422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char kIntermediateCert[] = "Intermediate";
432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char kRootCert[] = "Root";
442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Matches the order of X509Certificate::PublicKeyType
452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char* const kCertTypeStrings[] = {
462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "Unknown",
472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "RSA",
482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "DSA",
492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "ECDSA",
502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "DH",
512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    "ECDH"
522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch};
532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Histogram buckets for RSA/DSA/DH key sizes.
542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst int kRsaDsaKeySizes[] = {512, 768, 1024, 1536, 2048, 3072, 4096, 8192,
552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               16384};
562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Histogram buckets for ECDSA/ECDH key sizes. The list is based upon the FIPS
572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// 186-4 approved curves.
582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst int kEccKeySizes[] = {163, 192, 224, 233, 256, 283, 384, 409, 521, 571};
592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char* CertTypeToString(int cert_type) {
612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (cert_type < 0 ||
622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      static_cast<size_t>(cert_type) >= arraysize(kCertTypeStrings)) {
632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return "Unsupported";
642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return kCertTypeStrings[cert_type];
662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid RecordPublicKeyHistogram(const char* chain_position,
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              bool baseline_keysize_applies,
702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                              size_t size_bits,
712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                              X509Certificate::PublicKeyType cert_type) {
722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string histogram_name =
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::StringPrintf("CertificateType2.%s.%s.%s",
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                         baseline_keysize_applies ? "BR" : "NonBR",
752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                         chain_position,
762385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                         CertTypeToString(cert_type));
772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Do not use UMA_HISTOGRAM_... macros here, as it caches the Histogram
782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // instance and thus only works if |histogram_name| is constant.
792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::HistogramBase* counter = NULL;
802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Histogram buckets are contingent upon the underlying algorithm being used.
822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (cert_type == X509Certificate::kPublicKeyTypeECDH ||
832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      cert_type == X509Certificate::kPublicKeyTypeECDSA) {
842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // Typical key sizes match SECP/FIPS 186-3 recommendations for prime and
852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // binary curves - which range from 163 bits to 571 bits.
862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    counter = base::CustomHistogram::FactoryGet(
872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        histogram_name,
882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        base::CustomHistogram::ArrayToCustomRanges(kEccKeySizes,
892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                                   arraysize(kEccKeySizes)),
902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        base::HistogramBase::kUmaTargetedHistogramFlag);
912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  } else {
922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // Key sizes < 1024 bits should cause errors, while key sizes > 16K are not
932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // uniformly supported by the underlying cryptographic libraries.
942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    counter = base::CustomHistogram::FactoryGet(
952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        histogram_name,
962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        base::CustomHistogram::ArrayToCustomRanges(kRsaDsaKeySizes,
972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                                   arraysize(kRsaDsaKeySizes)),
982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        base::HistogramBase::kUmaTargetedHistogramFlag);
992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
1002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  counter->Add(size_bits);
1012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
1022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |type| is |kPublicKeyTypeRSA| or |kPublicKeyTypeDSA|, and
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if |size_bits| is < 1024. Note that this means there may be false
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// negatives: keys for other algorithms and which are weak will pass this
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// test.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWeakKey(X509Certificate::PublicKeyType type, size_t size_bits) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case X509Certificate::kPublicKeyTypeRSA:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case X509Certificate::kPublicKeyTypeDSA:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return size_bits < 1024;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Returns true if |cert| contains a known-weak key. Additionally, histograms
1182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// the observed keys for future tightening of the definition of what
1192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// constitutes a weak key.
1202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert,
1212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                       bool should_histogram) {
1222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // The effective date of the CA/Browser Forum's Baseline Requirements -
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // 2012-07-01 00:00:00 UTC.
1242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const base::Time kBaselineEffectiveDate =
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Time::FromInternalValue(GG_INT64_C(12985574400000000));
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The effective date of the key size requirements from Appendix A, v1.1.5
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // 2014-01-01 00:00:00 UTC.
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const base::Time kBaselineKeysizeEffectiveDate =
1292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base::Time::FromInternalValue(GG_INT64_C(13033008000000000));
1302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  size_t size_bits = 0;
1322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  X509Certificate::PublicKeyType type = X509Certificate::kPublicKeyTypeUnknown;
1332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  bool weak_key = false;
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool baseline_keysize_applies =
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      cert->valid_start() >= kBaselineEffectiveDate &&
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      cert->valid_expiry() >= kBaselineKeysizeEffectiveDate;
1372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  X509Certificate::GetPublicKeyInfo(cert->os_cert_handle(), &size_bits, &type);
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (should_histogram) {
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    RecordPublicKeyHistogram(kLeafCert, baseline_keysize_applies, size_bits,
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             type);
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (IsWeakKey(type, size_bits))
1442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    weak_key = true;
1452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const X509Certificate::OSCertHandles& intermediates =
1472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      cert->GetIntermediateCertificates();
1482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (size_t i = 0; i < intermediates.size(); ++i) {
1492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    X509Certificate::GetPublicKeyInfo(intermediates[i], &size_bits, &type);
1502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (should_histogram) {
1512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      RecordPublicKeyHistogram(
1522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          (i < intermediates.size() - 1) ? kIntermediateCert : kRootCert,
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          baseline_keysize_applies,
1542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          size_bits,
1552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          type);
1562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    }
1572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (!weak_key && IsWeakKey(type, size_bits))
1582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      weak_key = true;
1592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
1602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return weak_key;
1622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
1632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertVerifyProc* CertVerifyProc::CreateDefault() {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_NSS) || defined(OS_IOS)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new CertVerifyProcNSS();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new CertVerifyProcOpenSSL();
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_ANDROID)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new CertVerifyProcAndroid();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new CertVerifyProcMac();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new CertVerifyProcWin();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertVerifyProc::CertVerifyProc() {}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertVerifyProc::~CertVerifyProc() {}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CertVerifyProc::Verify(X509Certificate* cert,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const std::string& hostname,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int flags,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           CRLSet* crl_set,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const CertificateList& additional_trust_anchors,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           CertVerifyResult* verify_result) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verify_result->Reset();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verify_result->verified_cert = cert;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsBlacklisted(cert)) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verify_result->cert_status |= CERT_STATUS_REVOKED;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CERT_REVOKED;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We do online revocation checking for EV certificates that aren't covered
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // by a fresh CRLSet.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // disable revocation checking.
205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (flags & CertVerifier::VERIFY_EV_CERT)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv = VerifyInternal(cert, hostname, flags, crl_set,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          additional_trust_anchors, verify_result);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallback",
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        verify_result->common_name_fallback_used);
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!verify_result->is_issued_by_known_root) {
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallbackPrivateCA",
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          verify_result->common_name_fallback_used);
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This check is done after VerifyInternal so that VerifyInternal can fill
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the list of public key hashes.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verify_result->cert_status |= CERT_STATUS_REVOKED;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = MapCertStatusToNetError(verify_result->cert_status);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  std::vector<std::string> dns_names, ip_addrs;
226d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  cert->GetSubjectAltName(&dns_names, &ip_addrs);
227d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (HasNameConstraintsViolation(verify_result->public_key_hashes,
228d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                  cert->subject().common_name,
229d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                  dns_names,
230d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                  ip_addrs)) {
231d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    verify_result->cert_status |= CERT_STATUS_NAME_CONSTRAINT_VIOLATION;
232d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    rv = MapCertStatusToNetError(verify_result->cert_status);
233d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  }
234d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for weak keys in the entire verified chain.
2362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  bool weak_key = ExaminePublicKeys(verify_result->verified_cert,
2372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                    verify_result->is_issued_by_known_root);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (weak_key) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verify_result->cert_status |= CERT_STATUS_WEAK_KEY;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Avoid replacing a more serious error, such as an OS/library failure,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // by ensuring that if verification failed, it failed with a certificate
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // error.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == OK || IsCertificateError(rv))
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = MapCertStatusToNetError(verify_result->cert_status);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Treat certificates signed using broken signature algorithms as invalid.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (verify_result->has_md2 || verify_result->has_md4) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verify_result->cert_status |= CERT_STATUS_INVALID;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = MapCertStatusToNetError(verify_result->cert_status);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flag certificates using weak signature algorithms.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (verify_result->has_md5) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Avoid replacing a more serious error, such as an OS/library failure,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // by ensuring that if verification failed, it failed with a certificate
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // error.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == OK || IsCertificateError(rv))
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = MapCertStatusToNetError(verify_result->cert_status);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if !defined(OS_ANDROID)
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Flag certificates from publicly-trusted CAs that are issued to intranet
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // hosts. While the CA/Browser Forum Baseline Requirements (v1.1) permit
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // these to be issued until 1 November 2015, they represent a real risk for
268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the deployment of gTLDs and are being phased out ahead of the hard
269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // deadline.
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  //
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // TODO(ppi): is_issued_by_known_root is incorrect on Android. Once this is
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // fixed, re-enable this check for Android. crbug.com/116838
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (verify_result->is_issued_by_known_root && IsHostnameNonUnique(hostname)) {
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    verify_result->cert_status |= CERT_STATUS_NON_UNIQUE_NAME;
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CertVerifyProc::IsBlacklisted(X509Certificate* cert) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned kComodoSerialBytes = 16;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const uint8 kComodoSerials[][kComodoSerialBytes] = {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a real certificate. For testing only.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x07,0x7a,0x59,0xbc,0xd5,0x34,0x59,0x60,0x1c,0xa6,0x90,0x72,0x67,0xa6,0xdd,0x1c},
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The next nine certificates all expire on Fri Mar 14 23:59:59 2014.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Some serial numbers actually have a leading 0x00 byte required to
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // encode a positive integer in DER if the most significant bit is 0.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We omit the leading 0x00 bytes to make all serial numbers 16 bytes.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=mail.google.com
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: mail.google.com, www.mail.google.com
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x04,0x7e,0xcb,0xe9,0xfc,0xa5,0x5f,0x7b,0xd0,0x9e,0xae,0x36,0xe1,0x0c,0xae,0x1e},
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=global trustee
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: global trustee
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note: not a CA certificate.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xd8,0xf3,0x5f,0x4e,0xb7,0x87,0x2b,0x2d,0xab,0x06,0x92,0xe3,0x15,0x38,0x2f,0xb0},
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=login.live.com
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: login.live.com, www.login.live.com
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xb0,0xb7,0x13,0x3e,0xd0,0x96,0xf9,0xb5,0x6f,0xae,0x91,0xc8,0x74,0xbd,0x3a,0xc0},
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=addons.mozilla.org
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: addons.mozilla.org, www.addons.mozilla.org
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x92,0x39,0xd5,0x34,0x8f,0x40,0xd1,0x69,0x5a,0x74,0x54,0x70,0xe1,0xf2,0x3f,0x43},
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=login.skype.com
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: login.skype.com, www.login.skype.com
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xe9,0x02,0x8b,0x95,0x78,0xe4,0x15,0xdc,0x1a,0x71,0x0a,0x2b,0x88,0x15,0x44,0x47},
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=login.yahoo.com
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: login.yahoo.com, www.login.yahoo.com
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xd7,0x55,0x8f,0xda,0xf5,0xf1,0x10,0x5b,0xb2,0x13,0x28,0x2b,0x70,0x77,0x29,0xa3},
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=www.google.com
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: www.google.com, google.com
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xf5,0xc8,0x6a,0xf3,0x61,0x62,0xf1,0x3a,0x64,0xf5,0x4f,0x6d,0xc9,0x58,0x7c,0x06},
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=login.yahoo.com
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: login.yahoo.com
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x39,0x2a,0x43,0x4f,0x0e,0x07,0xdf,0x1f,0x8a,0xa3,0x05,0xde,0x34,0xe0,0xc2,0x29},
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=login.yahoo.com
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subjectAltName dNSName: login.yahoo.com
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x3e,0x75,0xce,0xd4,0x6b,0x69,0x30,0x21,0x21,0x88,0x30,0xae,0x86,0xa8,0x2a,0x71},
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& serial_number = cert->serial_number();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!serial_number.empty() && (serial_number[0] & 0x80) != 0) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is a negative serial number, which isn't technically allowed but
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which probably happens. In order to avoid confusing a negative serial
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // number with a positive one once the leading zeros have been removed, we
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // disregard it.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece serial(serial_number);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove leading zeros.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (serial.size() > 1 && serial[0] == 0)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    serial.remove_prefix(1);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (serial.size() == kComodoSerialBytes) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned i = 0; i < arraysize(kComodoSerials); i++) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (memcmp(kComodoSerials[i], serial.data(), kComodoSerialBytes) == 0) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_ENUMERATION("Net.SSLCertBlacklisted", i,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  arraysize(kComodoSerials) + 1);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: This implementation assumes and enforces that the hashes are SHA1.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CertVerifyProc::IsPublicKeyBlacklisted(
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HashValueVector& public_key_hashes) {
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  static const unsigned kNumHashes = 11;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const uint8 kHashes[kNumHashes][base::kSHA1Length] = {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=DigiNotar Root CA
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=Entrust.net x2 and self-signed
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x41, 0x0f, 0x36, 0x36, 0x32, 0x58, 0xf3, 0x0b, 0x34, 0x7d,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0x12, 0xce, 0x48, 0x63, 0xe4, 0x33, 0x43, 0x78, 0x06, 0xa8},
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=DigiNotar Cyber CA
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=GTE CyberTrust Global Root
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xc4, 0xf9, 0x66, 0x37, 0x16, 0xcd, 0x5e, 0x71, 0xd6, 0x95,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0x0b, 0x5f, 0x33, 0xce, 0x04, 0x1c, 0x95, 0xb4, 0x35, 0xd1},
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=DigiNotar Services 1024 CA
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=Entrust.net
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xe2, 0x3b, 0x8d, 0x10, 0x5f, 0x87, 0x71, 0x0a, 0x68, 0xd9,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0x24, 0x80, 0x50, 0xeb, 0xef, 0xc6, 0x27, 0xbe, 0x4c, 0xa6},
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=Staat der Nederlanden Organisatie CA - G2
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x7b, 0x2e, 0x16, 0xbc, 0x39, 0xbc, 0xd7, 0x2b, 0x45, 0x6e,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0x9f, 0x05, 0x5d, 0x1d, 0xe6, 0x15, 0xb7, 0x49, 0x45, 0xdb},
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: CN=DigiNotar PKIoverheid CA Overheid en Bedrijven
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=Staat der Nederlanden Overheid CA
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xe8, 0xf9, 0x12, 0x00, 0xc6, 0x5c, 0xee, 0x16, 0xe0, 0x39,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0xb9, 0xf8, 0x83, 0x84, 0x16, 0x61, 0x63, 0x5f, 0x81, 0xc5},
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: O=Digicert Sdn. Bhd.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=GTE CyberTrust Global Root
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Expires: Jul 17 15:16:54 2012 GMT
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0x01, 0x29, 0xbc, 0xd5, 0xb4, 0x48, 0xae, 0x8d, 0x24, 0x96,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0xd1, 0xc3, 0xe1, 0x97, 0x23, 0x91, 0x90, 0x88, 0xe1, 0x52},
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Subject: O=Digicert Sdn. Bhd.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=Entrust.net Certification Authority (2048)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Expires: Jul 16 17:53:37 2015 GMT
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xd3, 0x3c, 0x5b, 0x41, 0xe4, 0x5c, 0xc4, 0xb3, 0xbe, 0x9a,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0xd6, 0x95, 0x2c, 0x4e, 0xcc, 0x25, 0x28, 0x03, 0x29, 0x81},
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Issuer: CN=Trustwave Organization Issuing CA, Level 2
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Covers two certificates, the latter of which expires Apr 15 21:09:30
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 2021 GMT.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xe1, 0x2d, 0x89, 0xf5, 0x6d, 0x22, 0x76, 0xf8, 0x30, 0xe6,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0xce, 0xaf, 0xa6, 0x6c, 0x72, 0x5c, 0x0b, 0x41, 0xa9, 0x32},
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cyberoam CA certificate. Private key leaked, but this certificate would
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // only have been installed by Cyberoam customers. The certificate expires
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in 2036, but we can probably remove in a couple of years (2014).
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {0xd9, 0xf5, 0xc6, 0xce, 0x57, 0xff, 0xaa, 0x39, 0xcc, 0x7e,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0xd1, 0x72, 0xbd, 0x53, 0xe0, 0xd3, 0x07, 0x83, 0x4b, 0xd1},
396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Win32/Sirefef.gen!C generates fake certificates with this public key.
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {0xa4, 0xf5, 0x6e, 0x9e, 0x1d, 0x9a, 0x3b, 0x7b, 0x1a, 0xc3,
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     0x31, 0xcf, 0x64, 0xfc, 0x76, 0x2c, 0xd0, 0x51, 0xfb, 0xa4},
399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // ANSSI certificate under which a MITM proxy was mistakenly operated.
400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Expires: Jul 18 10:05:28 2014 GMT
401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    {0x3e, 0xcf, 0x4b, 0xbb, 0xe4, 0x60, 0x96, 0xd5, 0x14, 0xbb,
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     0x53, 0x9b, 0xb9, 0x13, 0xd7, 0x7a, 0xa4, 0xef, 0x31, 0xbf},
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < kNumHashes; i++) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (HashValueVector::const_iterator j = public_key_hashes.begin();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         j != public_key_hashes.end(); ++j) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j->tag == HASH_VALUE_SHA1 &&
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          memcmp(j->data(), kHashes[i], base::kSHA1Length) == 0) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
418d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)static const size_t kMaxTLDLength = 4;
419d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
420d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// CheckNameConstraints verifies that every name in |dns_names| is in one of
421d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// the domains specified by |tlds|. The |tlds| array is terminated by an empty
422d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// string.
423d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)static bool CheckNameConstraints(const std::vector<std::string>& dns_names,
424d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                 const char tlds[][kMaxTLDLength]) {
425d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  for (std::vector<std::string>::const_iterator i = dns_names.begin();
426d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)       i != dns_names.end(); ++i) {
427d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    bool ok = false;
428d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    url_canon::CanonHostInfo host_info;
429d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const std::string dns_name = CanonicalizeHost(*i, &host_info);
430d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (host_info.IsIPAddress())
431d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      continue;
432d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
433d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const size_t registry_len = registry_controlled_domains::GetRegistryLength(
434d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        dns_name,
435d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
436d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
437d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // If the name is not in a known TLD, ignore it. This permits internal
438d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // names.
439d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (registry_len == 0)
440d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      continue;
441d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
442d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    for (size_t j = 0; tlds[j][0]; ++j) {
443d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      const size_t tld_length = strlen(tlds[j]);
444d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      // The DNS name must have "." + tlds[j] as a suffix.
445d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      if (i->size() <= (1 /* period before TLD */ + tld_length))
446d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        continue;
447d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
448d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      const char* suffix = &dns_name[i->size() - tld_length - 1];
449d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      if (suffix[0] != '.')
450d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        continue;
451d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      if (memcmp(&suffix[1], tlds[j], tld_length) != 0)
452d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        continue;
453d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      ok = true;
454d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      break;
455d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    }
456d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
457d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (!ok)
458d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      return false;
459d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  }
460d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
461d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return true;
462d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
463d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
464d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// PublicKeyTLDLimitation contains a SHA1, SPKI hash and a pointer to an array
465d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// of fixed-length strings that contain the TLDs that the SPKI is allowed to
466d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// issue for.
467d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)struct PublicKeyTLDLimitation {
468d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  uint8 public_key[base::kSHA1Length];
469d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  const char (*tlds)[kMaxTLDLength];
470d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)};
471d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
472d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// static
473d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool CertVerifyProc::HasNameConstraintsViolation(
474d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const HashValueVector& public_key_hashes,
475d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const std::string& common_name,
476d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const std::vector<std::string>& dns_names,
477d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const std::vector<std::string>& ip_addrs) {
478d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  static const char kTLDsANSSI[][kMaxTLDLength] = {
479d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "fr",  // France
480d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "gp",  // Guadeloupe
481d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "gf",  // Guyane
482d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "mq",  // Martinique
483d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "re",  // Réunion
484d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "yt",  // Mayotte
485d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "pm",  // Saint-Pierre et Miquelon
486d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "bl",  // Saint Barthélemy
487d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "mf",  // Saint Martin
488d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "wf",  // Wallis et Futuna
489d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "pf",  // Polynésie française
490d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "nc",  // Nouvelle Calédonie
491d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "tf",  // Terres australes et antarctiques françaises
492d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "",
493d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  };
494d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
495d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  static const char kTLDsTest[][kMaxTLDLength] = {
496d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "com",
497d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    "",
498d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  };
499d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
500d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  static const PublicKeyTLDLimitation kLimits[] = {
501d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI,
502d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr
503d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    {
504d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      {0x79, 0x23, 0xd5, 0x8d, 0x0f, 0xe0, 0x3c, 0xe6, 0xab, 0xad,
505d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)       0xae, 0x27, 0x1a, 0x6d, 0x94, 0xf4, 0x14, 0xd1, 0xa8, 0x73},
506d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      kTLDsANSSI,
507d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    },
508d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // Not a real certificate - just for testing. This is the SPKI hash of
509d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // the keys used in net/data/ssl/certificates/name_constraint_*.crt.
510d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    {
511d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      {0x15, 0x45, 0xd7, 0x3b, 0x58, 0x6b, 0x47, 0xcf, 0xc1, 0x44,
512d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)       0xa2, 0xc9, 0xaa, 0xab, 0x98, 0x3d, 0x21, 0xcc, 0x42, 0xde},
513d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      kTLDsTest,
514d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    },
515d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  };
516d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
517d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  for (unsigned i = 0; i < arraysize(kLimits); ++i) {
518d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    for (HashValueVector::const_iterator j = public_key_hashes.begin();
519d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)         j != public_key_hashes.end(); ++j) {
520d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      if (j->tag == HASH_VALUE_SHA1 &&
521d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          memcmp(j->data(), kLimits[i].public_key, base::kSHA1Length) == 0) {
522d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        if (dns_names.empty() && ip_addrs.empty()) {
523d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          std::vector<std::string> dns_names;
524d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          dns_names.push_back(common_name);
525d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          if (!CheckNameConstraints(dns_names, kLimits[i].tlds))
526d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)            return true;
527d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        } else {
528d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          if (!CheckNameConstraints(dns_names, kLimits[i].tlds))
529d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)            return true;
530d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        }
531d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      }
532d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    }
533d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  }
534d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
535d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return false;
536d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
537d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
539