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.h"
6
7#include "base/metrics/histogram.h"
8#include "base/sha1.h"
9#include "base/strings/stringprintf.h"
10#include "build/build_config.h"
11#include "net/base/net_errors.h"
12#include "net/base/net_util.h"
13#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14#include "net/cert/cert_status_flags.h"
15#include "net/cert/cert_verifier.h"
16#include "net/cert/cert_verify_result.h"
17#include "net/cert/crl_set.h"
18#include "net/cert/x509_certificate.h"
19#include "url/url_canon.h"
20
21#if defined(USE_NSS) || defined(OS_IOS)
22#include "net/cert/cert_verify_proc_nss.h"
23#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
24#include "net/cert/cert_verify_proc_openssl.h"
25#elif defined(OS_ANDROID)
26#include "net/cert/cert_verify_proc_android.h"
27#elif defined(OS_MACOSX)
28#include "net/cert/cert_verify_proc_mac.h"
29#elif defined(OS_WIN)
30#include "net/cert/cert_verify_proc_win.h"
31#else
32#error Implement certificate verification.
33#endif
34
35
36namespace net {
37
38namespace {
39
40// Constants used to build histogram names
41const char kLeafCert[] = "Leaf";
42const char kIntermediateCert[] = "Intermediate";
43const char kRootCert[] = "Root";
44// Matches the order of X509Certificate::PublicKeyType
45const char* const kCertTypeStrings[] = {
46    "Unknown",
47    "RSA",
48    "DSA",
49    "ECDSA",
50    "DH",
51    "ECDH"
52};
53// Histogram buckets for RSA/DSA/DH key sizes.
54const int kRsaDsaKeySizes[] = {512, 768, 1024, 1536, 2048, 3072, 4096, 8192,
55                               16384};
56// Histogram buckets for ECDSA/ECDH key sizes. The list is based upon the FIPS
57// 186-4 approved curves.
58const int kEccKeySizes[] = {163, 192, 224, 233, 256, 283, 384, 409, 521, 571};
59
60const char* CertTypeToString(int cert_type) {
61  if (cert_type < 0 ||
62      static_cast<size_t>(cert_type) >= arraysize(kCertTypeStrings)) {
63    return "Unsupported";
64  }
65  return kCertTypeStrings[cert_type];
66}
67
68void RecordPublicKeyHistogram(const char* chain_position,
69                              bool baseline_keysize_applies,
70                              size_t size_bits,
71                              X509Certificate::PublicKeyType cert_type) {
72  std::string histogram_name =
73      base::StringPrintf("CertificateType2.%s.%s.%s",
74                         baseline_keysize_applies ? "BR" : "NonBR",
75                         chain_position,
76                         CertTypeToString(cert_type));
77  // Do not use UMA_HISTOGRAM_... macros here, as it caches the Histogram
78  // instance and thus only works if |histogram_name| is constant.
79  base::HistogramBase* counter = NULL;
80
81  // Histogram buckets are contingent upon the underlying algorithm being used.
82  if (cert_type == X509Certificate::kPublicKeyTypeECDH ||
83      cert_type == X509Certificate::kPublicKeyTypeECDSA) {
84    // Typical key sizes match SECP/FIPS 186-3 recommendations for prime and
85    // binary curves - which range from 163 bits to 571 bits.
86    counter = base::CustomHistogram::FactoryGet(
87        histogram_name,
88        base::CustomHistogram::ArrayToCustomRanges(kEccKeySizes,
89                                                   arraysize(kEccKeySizes)),
90        base::HistogramBase::kUmaTargetedHistogramFlag);
91  } else {
92    // Key sizes < 1024 bits should cause errors, while key sizes > 16K are not
93    // uniformly supported by the underlying cryptographic libraries.
94    counter = base::CustomHistogram::FactoryGet(
95        histogram_name,
96        base::CustomHistogram::ArrayToCustomRanges(kRsaDsaKeySizes,
97                                                   arraysize(kRsaDsaKeySizes)),
98        base::HistogramBase::kUmaTargetedHistogramFlag);
99  }
100  counter->Add(size_bits);
101}
102
103// Returns true if |type| is |kPublicKeyTypeRSA| or |kPublicKeyTypeDSA|, and
104// if |size_bits| is < 1024. Note that this means there may be false
105// negatives: keys for other algorithms and which are weak will pass this
106// test.
107bool IsWeakKey(X509Certificate::PublicKeyType type, size_t size_bits) {
108  switch (type) {
109    case X509Certificate::kPublicKeyTypeRSA:
110    case X509Certificate::kPublicKeyTypeDSA:
111      return size_bits < 1024;
112    default:
113      return false;
114  }
115}
116
117// Returns true if |cert| contains a known-weak key. Additionally, histograms
118// the observed keys for future tightening of the definition of what
119// constitutes a weak key.
120bool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert,
121                       bool should_histogram) {
122  // The effective date of the CA/Browser Forum's Baseline Requirements -
123  // 2012-07-01 00:00:00 UTC.
124  const base::Time kBaselineEffectiveDate =
125      base::Time::FromInternalValue(GG_INT64_C(12985574400000000));
126  // The effective date of the key size requirements from Appendix A, v1.1.5
127  // 2014-01-01 00:00:00 UTC.
128  const base::Time kBaselineKeysizeEffectiveDate =
129      base::Time::FromInternalValue(GG_INT64_C(13033008000000000));
130
131  size_t size_bits = 0;
132  X509Certificate::PublicKeyType type = X509Certificate::kPublicKeyTypeUnknown;
133  bool weak_key = false;
134  bool baseline_keysize_applies =
135      cert->valid_start() >= kBaselineEffectiveDate &&
136      cert->valid_expiry() >= kBaselineKeysizeEffectiveDate;
137
138  X509Certificate::GetPublicKeyInfo(cert->os_cert_handle(), &size_bits, &type);
139  if (should_histogram) {
140    RecordPublicKeyHistogram(kLeafCert, baseline_keysize_applies, size_bits,
141                             type);
142  }
143  if (IsWeakKey(type, size_bits))
144    weak_key = true;
145
146  const X509Certificate::OSCertHandles& intermediates =
147      cert->GetIntermediateCertificates();
148  for (size_t i = 0; i < intermediates.size(); ++i) {
149    X509Certificate::GetPublicKeyInfo(intermediates[i], &size_bits, &type);
150    if (should_histogram) {
151      RecordPublicKeyHistogram(
152          (i < intermediates.size() - 1) ? kIntermediateCert : kRootCert,
153          baseline_keysize_applies,
154          size_bits,
155          type);
156    }
157    if (!weak_key && IsWeakKey(type, size_bits))
158      weak_key = true;
159  }
160
161  return weak_key;
162}
163
164}  // namespace
165
166// static
167CertVerifyProc* CertVerifyProc::CreateDefault() {
168#if defined(USE_NSS) || defined(OS_IOS)
169  return new CertVerifyProcNSS();
170#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
171  return new CertVerifyProcOpenSSL();
172#elif defined(OS_ANDROID)
173  return new CertVerifyProcAndroid();
174#elif defined(OS_MACOSX)
175  return new CertVerifyProcMac();
176#elif defined(OS_WIN)
177  return new CertVerifyProcWin();
178#else
179  return NULL;
180#endif
181}
182
183CertVerifyProc::CertVerifyProc() {}
184
185CertVerifyProc::~CertVerifyProc() {}
186
187int CertVerifyProc::Verify(X509Certificate* cert,
188                           const std::string& hostname,
189                           int flags,
190                           CRLSet* crl_set,
191                           const CertificateList& additional_trust_anchors,
192                           CertVerifyResult* verify_result) {
193  verify_result->Reset();
194  verify_result->verified_cert = cert;
195
196  if (IsBlacklisted(cert)) {
197    verify_result->cert_status |= CERT_STATUS_REVOKED;
198    return ERR_CERT_REVOKED;
199  }
200
201  // We do online revocation checking for EV certificates that aren't covered
202  // by a fresh CRLSet.
203  // TODO(rsleevi): http://crbug.com/142974 - Allow preferences to fully
204  // disable revocation checking.
205  if (flags & CertVerifier::VERIFY_EV_CERT)
206    flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY;
207
208  int rv = VerifyInternal(cert, hostname, flags, crl_set,
209                          additional_trust_anchors, verify_result);
210
211  UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallback",
212                        verify_result->common_name_fallback_used);
213  if (!verify_result->is_issued_by_known_root) {
214    UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallbackPrivateCA",
215                          verify_result->common_name_fallback_used);
216  }
217
218  // This check is done after VerifyInternal so that VerifyInternal can fill
219  // in the list of public key hashes.
220  if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) {
221    verify_result->cert_status |= CERT_STATUS_REVOKED;
222    rv = MapCertStatusToNetError(verify_result->cert_status);
223  }
224
225  std::vector<std::string> dns_names, ip_addrs;
226  cert->GetSubjectAltName(&dns_names, &ip_addrs);
227  if (HasNameConstraintsViolation(verify_result->public_key_hashes,
228                                  cert->subject().common_name,
229                                  dns_names,
230                                  ip_addrs)) {
231    verify_result->cert_status |= CERT_STATUS_NAME_CONSTRAINT_VIOLATION;
232    rv = MapCertStatusToNetError(verify_result->cert_status);
233  }
234
235  // Check for weak keys in the entire verified chain.
236  bool weak_key = ExaminePublicKeys(verify_result->verified_cert,
237                                    verify_result->is_issued_by_known_root);
238
239  if (weak_key) {
240    verify_result->cert_status |= CERT_STATUS_WEAK_KEY;
241    // Avoid replacing a more serious error, such as an OS/library failure,
242    // by ensuring that if verification failed, it failed with a certificate
243    // error.
244    if (rv == OK || IsCertificateError(rv))
245      rv = MapCertStatusToNetError(verify_result->cert_status);
246  }
247
248  // Treat certificates signed using broken signature algorithms as invalid.
249  if (verify_result->has_md2 || verify_result->has_md4) {
250    verify_result->cert_status |= CERT_STATUS_INVALID;
251    rv = MapCertStatusToNetError(verify_result->cert_status);
252  }
253
254  // Flag certificates using weak signature algorithms.
255  if (verify_result->has_md5) {
256    verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
257    // Avoid replacing a more serious error, such as an OS/library failure,
258    // by ensuring that if verification failed, it failed with a certificate
259    // error.
260    if (rv == OK || IsCertificateError(rv))
261      rv = MapCertStatusToNetError(verify_result->cert_status);
262  }
263
264#if !defined(OS_ANDROID)
265  // Flag certificates from publicly-trusted CAs that are issued to intranet
266  // hosts. While the CA/Browser Forum Baseline Requirements (v1.1) permit
267  // these to be issued until 1 November 2015, they represent a real risk for
268  // the deployment of gTLDs and are being phased out ahead of the hard
269  // deadline.
270  //
271  // TODO(ppi): is_issued_by_known_root is incorrect on Android. Once this is
272  // fixed, re-enable this check for Android. crbug.com/116838
273  if (verify_result->is_issued_by_known_root && IsHostnameNonUnique(hostname)) {
274    verify_result->cert_status |= CERT_STATUS_NON_UNIQUE_NAME;
275  }
276#endif
277
278  return rv;
279}
280
281// static
282bool CertVerifyProc::IsBlacklisted(X509Certificate* cert) {
283  static const unsigned kComodoSerialBytes = 16;
284  static const uint8 kComodoSerials[][kComodoSerialBytes] = {
285    // Not a real certificate. For testing only.
286    {0x07,0x7a,0x59,0xbc,0xd5,0x34,0x59,0x60,0x1c,0xa6,0x90,0x72,0x67,0xa6,0xdd,0x1c},
287
288    // The next nine certificates all expire on Fri Mar 14 23:59:59 2014.
289    // Some serial numbers actually have a leading 0x00 byte required to
290    // encode a positive integer in DER if the most significant bit is 0.
291    // We omit the leading 0x00 bytes to make all serial numbers 16 bytes.
292
293    // Subject: CN=mail.google.com
294    // subjectAltName dNSName: mail.google.com, www.mail.google.com
295    {0x04,0x7e,0xcb,0xe9,0xfc,0xa5,0x5f,0x7b,0xd0,0x9e,0xae,0x36,0xe1,0x0c,0xae,0x1e},
296    // Subject: CN=global trustee
297    // subjectAltName dNSName: global trustee
298    // Note: not a CA certificate.
299    {0xd8,0xf3,0x5f,0x4e,0xb7,0x87,0x2b,0x2d,0xab,0x06,0x92,0xe3,0x15,0x38,0x2f,0xb0},
300    // Subject: CN=login.live.com
301    // subjectAltName dNSName: login.live.com, www.login.live.com
302    {0xb0,0xb7,0x13,0x3e,0xd0,0x96,0xf9,0xb5,0x6f,0xae,0x91,0xc8,0x74,0xbd,0x3a,0xc0},
303    // Subject: CN=addons.mozilla.org
304    // subjectAltName dNSName: addons.mozilla.org, www.addons.mozilla.org
305    {0x92,0x39,0xd5,0x34,0x8f,0x40,0xd1,0x69,0x5a,0x74,0x54,0x70,0xe1,0xf2,0x3f,0x43},
306    // Subject: CN=login.skype.com
307    // subjectAltName dNSName: login.skype.com, www.login.skype.com
308    {0xe9,0x02,0x8b,0x95,0x78,0xe4,0x15,0xdc,0x1a,0x71,0x0a,0x2b,0x88,0x15,0x44,0x47},
309    // Subject: CN=login.yahoo.com
310    // subjectAltName dNSName: login.yahoo.com, www.login.yahoo.com
311    {0xd7,0x55,0x8f,0xda,0xf5,0xf1,0x10,0x5b,0xb2,0x13,0x28,0x2b,0x70,0x77,0x29,0xa3},
312    // Subject: CN=www.google.com
313    // subjectAltName dNSName: www.google.com, google.com
314    {0xf5,0xc8,0x6a,0xf3,0x61,0x62,0xf1,0x3a,0x64,0xf5,0x4f,0x6d,0xc9,0x58,0x7c,0x06},
315    // Subject: CN=login.yahoo.com
316    // subjectAltName dNSName: login.yahoo.com
317    {0x39,0x2a,0x43,0x4f,0x0e,0x07,0xdf,0x1f,0x8a,0xa3,0x05,0xde,0x34,0xe0,0xc2,0x29},
318    // Subject: CN=login.yahoo.com
319    // subjectAltName dNSName: login.yahoo.com
320    {0x3e,0x75,0xce,0xd4,0x6b,0x69,0x30,0x21,0x21,0x88,0x30,0xae,0x86,0xa8,0x2a,0x71},
321  };
322
323  const std::string& serial_number = cert->serial_number();
324  if (!serial_number.empty() && (serial_number[0] & 0x80) != 0) {
325    // This is a negative serial number, which isn't technically allowed but
326    // which probably happens. In order to avoid confusing a negative serial
327    // number with a positive one once the leading zeros have been removed, we
328    // disregard it.
329    return false;
330  }
331
332  base::StringPiece serial(serial_number);
333  // Remove leading zeros.
334  while (serial.size() > 1 && serial[0] == 0)
335    serial.remove_prefix(1);
336
337  if (serial.size() == kComodoSerialBytes) {
338    for (unsigned i = 0; i < arraysize(kComodoSerials); i++) {
339      if (memcmp(kComodoSerials[i], serial.data(), kComodoSerialBytes) == 0) {
340        UMA_HISTOGRAM_ENUMERATION("Net.SSLCertBlacklisted", i,
341                                  arraysize(kComodoSerials) + 1);
342        return true;
343      }
344    }
345  }
346
347  return false;
348}
349
350// static
351// NOTE: This implementation assumes and enforces that the hashes are SHA1.
352bool CertVerifyProc::IsPublicKeyBlacklisted(
353    const HashValueVector& public_key_hashes) {
354  static const unsigned kNumHashes = 11;
355  static const uint8 kHashes[kNumHashes][base::kSHA1Length] = {
356    // Subject: CN=DigiNotar Root CA
357    // Issuer: CN=Entrust.net x2 and self-signed
358    {0x41, 0x0f, 0x36, 0x36, 0x32, 0x58, 0xf3, 0x0b, 0x34, 0x7d,
359     0x12, 0xce, 0x48, 0x63, 0xe4, 0x33, 0x43, 0x78, 0x06, 0xa8},
360    // Subject: CN=DigiNotar Cyber CA
361    // Issuer: CN=GTE CyberTrust Global Root
362    {0xc4, 0xf9, 0x66, 0x37, 0x16, 0xcd, 0x5e, 0x71, 0xd6, 0x95,
363     0x0b, 0x5f, 0x33, 0xce, 0x04, 0x1c, 0x95, 0xb4, 0x35, 0xd1},
364    // Subject: CN=DigiNotar Services 1024 CA
365    // Issuer: CN=Entrust.net
366    {0xe2, 0x3b, 0x8d, 0x10, 0x5f, 0x87, 0x71, 0x0a, 0x68, 0xd9,
367     0x24, 0x80, 0x50, 0xeb, 0xef, 0xc6, 0x27, 0xbe, 0x4c, 0xa6},
368    // Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2
369    // Issuer: CN=Staat der Nederlanden Organisatie CA - G2
370    {0x7b, 0x2e, 0x16, 0xbc, 0x39, 0xbc, 0xd7, 0x2b, 0x45, 0x6e,
371     0x9f, 0x05, 0x5d, 0x1d, 0xe6, 0x15, 0xb7, 0x49, 0x45, 0xdb},
372    // Subject: CN=DigiNotar PKIoverheid CA Overheid en Bedrijven
373    // Issuer: CN=Staat der Nederlanden Overheid CA
374    {0xe8, 0xf9, 0x12, 0x00, 0xc6, 0x5c, 0xee, 0x16, 0xe0, 0x39,
375     0xb9, 0xf8, 0x83, 0x84, 0x16, 0x61, 0x63, 0x5f, 0x81, 0xc5},
376    // Subject: O=Digicert Sdn. Bhd.
377    // Issuer: CN=GTE CyberTrust Global Root
378    // Expires: Jul 17 15:16:54 2012 GMT
379    {0x01, 0x29, 0xbc, 0xd5, 0xb4, 0x48, 0xae, 0x8d, 0x24, 0x96,
380     0xd1, 0xc3, 0xe1, 0x97, 0x23, 0x91, 0x90, 0x88, 0xe1, 0x52},
381    // Subject: O=Digicert Sdn. Bhd.
382    // Issuer: CN=Entrust.net Certification Authority (2048)
383    // Expires: Jul 16 17:53:37 2015 GMT
384    {0xd3, 0x3c, 0x5b, 0x41, 0xe4, 0x5c, 0xc4, 0xb3, 0xbe, 0x9a,
385     0xd6, 0x95, 0x2c, 0x4e, 0xcc, 0x25, 0x28, 0x03, 0x29, 0x81},
386    // Issuer: CN=Trustwave Organization Issuing CA, Level 2
387    // Covers two certificates, the latter of which expires Apr 15 21:09:30
388    // 2021 GMT.
389    {0xe1, 0x2d, 0x89, 0xf5, 0x6d, 0x22, 0x76, 0xf8, 0x30, 0xe6,
390     0xce, 0xaf, 0xa6, 0x6c, 0x72, 0x5c, 0x0b, 0x41, 0xa9, 0x32},
391    // Cyberoam CA certificate. Private key leaked, but this certificate would
392    // only have been installed by Cyberoam customers. The certificate expires
393    // in 2036, but we can probably remove in a couple of years (2014).
394    {0xd9, 0xf5, 0xc6, 0xce, 0x57, 0xff, 0xaa, 0x39, 0xcc, 0x7e,
395     0xd1, 0x72, 0xbd, 0x53, 0xe0, 0xd3, 0x07, 0x83, 0x4b, 0xd1},
396    // Win32/Sirefef.gen!C generates fake certificates with this public key.
397    {0xa4, 0xf5, 0x6e, 0x9e, 0x1d, 0x9a, 0x3b, 0x7b, 0x1a, 0xc3,
398     0x31, 0xcf, 0x64, 0xfc, 0x76, 0x2c, 0xd0, 0x51, 0xfb, 0xa4},
399    // ANSSI certificate under which a MITM proxy was mistakenly operated.
400    // Expires: Jul 18 10:05:28 2014 GMT
401    {0x3e, 0xcf, 0x4b, 0xbb, 0xe4, 0x60, 0x96, 0xd5, 0x14, 0xbb,
402     0x53, 0x9b, 0xb9, 0x13, 0xd7, 0x7a, 0xa4, 0xef, 0x31, 0xbf},
403  };
404
405  for (unsigned i = 0; i < kNumHashes; i++) {
406    for (HashValueVector::const_iterator j = public_key_hashes.begin();
407         j != public_key_hashes.end(); ++j) {
408      if (j->tag == HASH_VALUE_SHA1 &&
409          memcmp(j->data(), kHashes[i], base::kSHA1Length) == 0) {
410        return true;
411      }
412    }
413  }
414
415  return false;
416}
417
418static const size_t kMaxTLDLength = 4;
419
420// CheckNameConstraints verifies that every name in |dns_names| is in one of
421// the domains specified by |tlds|. The |tlds| array is terminated by an empty
422// string.
423static bool CheckNameConstraints(const std::vector<std::string>& dns_names,
424                                 const char tlds[][kMaxTLDLength]) {
425  for (std::vector<std::string>::const_iterator i = dns_names.begin();
426       i != dns_names.end(); ++i) {
427    bool ok = false;
428    url_canon::CanonHostInfo host_info;
429    const std::string dns_name = CanonicalizeHost(*i, &host_info);
430    if (host_info.IsIPAddress())
431      continue;
432
433    const size_t registry_len = registry_controlled_domains::GetRegistryLength(
434        dns_name,
435        registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
436        registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
437    // If the name is not in a known TLD, ignore it. This permits internal
438    // names.
439    if (registry_len == 0)
440      continue;
441
442    for (size_t j = 0; tlds[j][0]; ++j) {
443      const size_t tld_length = strlen(tlds[j]);
444      // The DNS name must have "." + tlds[j] as a suffix.
445      if (i->size() <= (1 /* period before TLD */ + tld_length))
446        continue;
447
448      const char* suffix = &dns_name[i->size() - tld_length - 1];
449      if (suffix[0] != '.')
450        continue;
451      if (memcmp(&suffix[1], tlds[j], tld_length) != 0)
452        continue;
453      ok = true;
454      break;
455    }
456
457    if (!ok)
458      return false;
459  }
460
461  return true;
462}
463
464// PublicKeyTLDLimitation contains a SHA1, SPKI hash and a pointer to an array
465// of fixed-length strings that contain the TLDs that the SPKI is allowed to
466// issue for.
467struct PublicKeyTLDLimitation {
468  uint8 public_key[base::kSHA1Length];
469  const char (*tlds)[kMaxTLDLength];
470};
471
472// static
473bool CertVerifyProc::HasNameConstraintsViolation(
474    const HashValueVector& public_key_hashes,
475    const std::string& common_name,
476    const std::vector<std::string>& dns_names,
477    const std::vector<std::string>& ip_addrs) {
478  static const char kTLDsANSSI[][kMaxTLDLength] = {
479    "fr",  // France
480    "gp",  // Guadeloupe
481    "gf",  // Guyane
482    "mq",  // Martinique
483    "re",  // Réunion
484    "yt",  // Mayotte
485    "pm",  // Saint-Pierre et Miquelon
486    "bl",  // Saint Barthélemy
487    "mf",  // Saint Martin
488    "wf",  // Wallis et Futuna
489    "pf",  // Polynésie française
490    "nc",  // Nouvelle Calédonie
491    "tf",  // Terres australes et antarctiques françaises
492    "",
493  };
494
495  static const char kTLDsTest[][kMaxTLDLength] = {
496    "com",
497    "",
498  };
499
500  static const PublicKeyTLDLimitation kLimits[] = {
501    // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI,
502    // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr
503    {
504      {0x79, 0x23, 0xd5, 0x8d, 0x0f, 0xe0, 0x3c, 0xe6, 0xab, 0xad,
505       0xae, 0x27, 0x1a, 0x6d, 0x94, 0xf4, 0x14, 0xd1, 0xa8, 0x73},
506      kTLDsANSSI,
507    },
508    // Not a real certificate - just for testing. This is the SPKI hash of
509    // the keys used in net/data/ssl/certificates/name_constraint_*.crt.
510    {
511      {0x15, 0x45, 0xd7, 0x3b, 0x58, 0x6b, 0x47, 0xcf, 0xc1, 0x44,
512       0xa2, 0xc9, 0xaa, 0xab, 0x98, 0x3d, 0x21, 0xcc, 0x42, 0xde},
513      kTLDsTest,
514    },
515  };
516
517  for (unsigned i = 0; i < arraysize(kLimits); ++i) {
518    for (HashValueVector::const_iterator j = public_key_hashes.begin();
519         j != public_key_hashes.end(); ++j) {
520      if (j->tag == HASH_VALUE_SHA1 &&
521          memcmp(j->data(), kLimits[i].public_key, base::kSHA1Length) == 0) {
522        if (dns_names.empty() && ip_addrs.empty()) {
523          std::vector<std::string> dns_names;
524          dns_names.push_back(common_name);
525          if (!CheckNameConstraints(dns_names, kLimits[i].tlds))
526            return true;
527        } else {
528          if (!CheckNameConstraints(dns_names, kLimits[i].tlds))
529            return true;
530        }
531      }
532    }
533  }
534
535  return false;
536}
537
538}  // namespace net
539