1// Copyright (c) 2011 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 <cert.h>
6#include <pk11pub.h>
7
8#include <algorithm>
9
10#include "base/file_path.h"
11#include "base/file_util.h"
12#include "base/lazy_instance.h"
13#include "base/memory/scoped_temp_dir.h"
14#include "base/path_service.h"
15#include "base/string_util.h"
16#include "base/utf_string_conversions.h"
17#include "crypto/nss_util.h"
18#include "crypto/nss_util_internal.h"
19#include "crypto/scoped_nss_types.h"
20#include "net/base/cert_database.h"
21#include "net/base/cert_status_flags.h"
22#include "net/base/cert_verify_result.h"
23#include "net/base/crypto_module.h"
24#include "net/base/net_errors.h"
25#include "net/base/x509_certificate.h"
26#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
27#include "net/third_party/mozilla_security_manager/nsNSSCertTrust.h"
28#include "testing/gtest/include/gtest/gtest.h"
29
30namespace psm = mozilla_security_manager;
31
32namespace net {
33
34namespace {
35
36// Returns a FilePath object representing the src/net/data/ssl/certificates
37// directory in the source tree.
38FilePath GetTestCertsDirectory() {
39  FilePath certs_dir;
40  PathService::Get(base::DIR_SOURCE_ROOT, &certs_dir);
41  certs_dir = certs_dir.AppendASCII("net");
42  certs_dir = certs_dir.AppendASCII("data");
43  certs_dir = certs_dir.AppendASCII("ssl");
44  certs_dir = certs_dir.AppendASCII("certificates");
45  return certs_dir;
46}
47
48CertificateList ListCertsInSlot(PK11SlotInfo* slot) {
49  CertificateList result;
50  CERTCertList* cert_list = PK11_ListCertsInSlot(slot);
51  for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
52       !CERT_LIST_END(node, cert_list);
53       node = CERT_LIST_NEXT(node)) {
54    result.push_back(
55        X509Certificate::CreateFromHandle(
56            node->cert,
57            X509Certificate::SOURCE_LONE_CERT_IMPORT,
58            X509Certificate::OSCertHandles()));
59  }
60  CERT_DestroyCertList(cert_list);
61
62  // Sort the result so that test comparisons can be deterministic.
63  std::sort(result.begin(), result.end(), X509Certificate::LessThan());
64  return result;
65}
66
67bool CleanupSlotContents(PK11SlotInfo* slot) {
68  CertDatabase cert_db;
69  bool ok = true;
70  CertificateList certs = ListCertsInSlot(slot);
71  for (size_t i = 0; i < certs.size(); ++i) {
72    if (!cert_db.DeleteCertAndKey(certs[i]))
73      ok = false;
74  }
75  return ok;
76}
77
78std::string ReadTestFile(const std::string& name) {
79  std::string result;
80  FilePath cert_path = GetTestCertsDirectory().AppendASCII(name);
81  EXPECT_TRUE(file_util::ReadFileToString(cert_path, &result));
82  return result;
83}
84
85bool ReadCertIntoList(const std::string& name, CertificateList* certs) {
86  std::string cert_data = ReadTestFile(name);
87  if (cert_data.empty())
88    return false;
89
90  X509Certificate* cert = X509Certificate::CreateFromBytes(
91      cert_data.data(), cert_data.size());
92  if (!cert)
93    return false;
94
95  certs->push_back(cert);
96  return true;
97}
98
99}  // namespace
100
101// TODO(mattm): when https://bugzilla.mozilla.org/show_bug.cgi?id=588269 is
102// fixed, switch back to using a separate userdb for each test.
103// (When doing so, remember to add some standalone tests of DeleteCert since it
104// won't be tested by TearDown anymore.)
105class CertDatabaseNSSTest : public testing::Test {
106 public:
107  virtual void SetUp() {
108    if (!temp_db_initialized_) {
109      ASSERT_TRUE(temp_db_dir_.Get().CreateUniqueTempDir());
110      ASSERT_TRUE(
111          crypto::OpenTestNSSDB(temp_db_dir_.Get().path(),
112                                "CertDatabaseNSSTest db"));
113      temp_db_initialized_ = true;
114    }
115    slot_ = cert_db_.GetPublicModule();
116
117    // Test db should be empty at start of test.
118    EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
119  }
120  virtual void TearDown() {
121    // Don't try to cleanup if the setup failed.
122    ASSERT_TRUE(slot_->os_module_handle());
123
124    EXPECT_TRUE(CleanupSlotContents(slot_->os_module_handle()));
125    EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
126  }
127
128 protected:
129  scoped_refptr<CryptoModule> slot_;
130  CertDatabase cert_db_;
131
132 private:
133  static base::LazyInstance<ScopedTempDir> temp_db_dir_;
134  static bool temp_db_initialized_;
135};
136
137// static
138base::LazyInstance<ScopedTempDir> CertDatabaseNSSTest::temp_db_dir_(
139    base::LINKER_INITIALIZED);
140bool CertDatabaseNSSTest::temp_db_initialized_ = false;
141
142TEST_F(CertDatabaseNSSTest, ListCerts) {
143  // This test isn't terribly useful, though it will at least let valgrind test
144  // for leaks.
145  CertificateList certs;
146  cert_db_.ListCerts(&certs);
147  // The test DB is empty, but let's assume there will always be something in
148  // the other slots.
149  EXPECT_LT(0U, certs.size());
150}
151
152TEST_F(CertDatabaseNSSTest, ImportFromPKCS12WrongPassword) {
153  std::string pkcs12_data = ReadTestFile("client.p12");
154
155  EXPECT_EQ(ERR_PKCS12_IMPORT_BAD_PASSWORD,
156            cert_db_.ImportFromPKCS12(slot_,
157                                      pkcs12_data,
158                                      ASCIIToUTF16("")));
159
160  // Test db should still be empty.
161  EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
162}
163
164TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AndExportAgain) {
165  std::string pkcs12_data = ReadTestFile("client.p12");
166
167  EXPECT_EQ(OK, cert_db_.ImportFromPKCS12(slot_,
168                                          pkcs12_data,
169                                          ASCIIToUTF16("12345")));
170
171  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
172  ASSERT_EQ(1U, cert_list.size());
173  scoped_refptr<X509Certificate> cert(cert_list[0]);
174
175  EXPECT_EQ("testusercert",
176            cert->subject().common_name);
177
178  // TODO(mattm): move export test to seperate test case?
179  std::string exported_data;
180  EXPECT_EQ(1, cert_db_.ExportToPKCS12(cert_list, ASCIIToUTF16("exportpw"),
181                                       &exported_data));
182  ASSERT_LT(0U, exported_data.size());
183  // TODO(mattm): further verification of exported data?
184}
185
186TEST_F(CertDatabaseNSSTest, ImportCACert_SSLTrust) {
187  std::string cert_data = ReadTestFile("root_ca_cert.crt");
188
189  CertificateList certs =
190      X509Certificate::CreateCertificateListFromBytes(
191          cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
192  ASSERT_EQ(1U, certs.size());
193  EXPECT_FALSE(certs[0]->os_cert_handle()->isperm);
194
195  // Import it.
196  CertDatabase::ImportCertFailureList failed;
197  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_SSL,
198                                     &failed));
199
200  EXPECT_EQ(0U, failed.size());
201
202  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
203  ASSERT_EQ(1U, cert_list.size());
204  scoped_refptr<X509Certificate> cert(cert_list[0]);
205  EXPECT_EQ("Test CA", cert->subject().common_name);
206
207  EXPECT_EQ(CertDatabase::TRUSTED_SSL,
208            cert_db_.GetCertTrust(cert.get(), CA_CERT));
209
210  psm::nsNSSCertTrust trust(cert->os_cert_handle()->trust);
211  EXPECT_TRUE(trust.HasTrustedCA(PR_TRUE, PR_FALSE, PR_FALSE));
212  EXPECT_FALSE(trust.HasTrustedCA(PR_FALSE, PR_TRUE, PR_FALSE));
213  EXPECT_FALSE(trust.HasTrustedCA(PR_FALSE, PR_FALSE, PR_TRUE));
214  EXPECT_FALSE(trust.HasTrustedCA(PR_TRUE, PR_TRUE, PR_TRUE));
215  EXPECT_TRUE(trust.HasCA(PR_TRUE, PR_TRUE, PR_TRUE));
216}
217
218TEST_F(CertDatabaseNSSTest, ImportCACert_EmailTrust) {
219  std::string cert_data = ReadTestFile("root_ca_cert.crt");
220
221  CertificateList certs =
222      X509Certificate::CreateCertificateListFromBytes(
223          cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
224  ASSERT_EQ(1U, certs.size());
225  EXPECT_FALSE(certs[0]->os_cert_handle()->isperm);
226
227  // Import it.
228  CertDatabase::ImportCertFailureList failed;
229  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_EMAIL,
230                                     &failed));
231
232  EXPECT_EQ(0U, failed.size());
233
234  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
235  ASSERT_EQ(1U, cert_list.size());
236  scoped_refptr<X509Certificate> cert(cert_list[0]);
237  EXPECT_EQ("Test CA", cert->subject().common_name);
238
239  EXPECT_EQ(CertDatabase::TRUSTED_EMAIL,
240            cert_db_.GetCertTrust(cert.get(), CA_CERT));
241
242  psm::nsNSSCertTrust trust(cert->os_cert_handle()->trust);
243  EXPECT_FALSE(trust.HasTrustedCA(PR_TRUE, PR_FALSE, PR_FALSE));
244  EXPECT_TRUE(trust.HasTrustedCA(PR_FALSE, PR_TRUE, PR_FALSE));
245  EXPECT_FALSE(trust.HasTrustedCA(PR_FALSE, PR_FALSE, PR_TRUE));
246  EXPECT_TRUE(trust.HasCA(PR_TRUE, PR_TRUE, PR_TRUE));
247}
248
249TEST_F(CertDatabaseNSSTest, ImportCACert_ObjSignTrust) {
250  std::string cert_data = ReadTestFile("root_ca_cert.crt");
251
252  CertificateList certs =
253      X509Certificate::CreateCertificateListFromBytes(
254          cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
255  ASSERT_EQ(1U, certs.size());
256  EXPECT_FALSE(certs[0]->os_cert_handle()->isperm);
257
258  // Import it.
259  CertDatabase::ImportCertFailureList failed;
260  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_OBJ_SIGN,
261                                     &failed));
262
263  EXPECT_EQ(0U, failed.size());
264
265  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
266  ASSERT_EQ(1U, cert_list.size());
267  scoped_refptr<X509Certificate> cert(cert_list[0]);
268  EXPECT_EQ("Test CA", cert->subject().common_name);
269
270  EXPECT_EQ(CertDatabase::TRUSTED_OBJ_SIGN,
271            cert_db_.GetCertTrust(cert.get(), CA_CERT));
272
273  psm::nsNSSCertTrust trust(cert->os_cert_handle()->trust);
274  EXPECT_FALSE(trust.HasTrustedCA(PR_TRUE, PR_FALSE, PR_FALSE));
275  EXPECT_FALSE(trust.HasTrustedCA(PR_FALSE, PR_TRUE, PR_FALSE));
276  EXPECT_TRUE(trust.HasTrustedCA(PR_FALSE, PR_FALSE, PR_TRUE));
277  EXPECT_TRUE(trust.HasCA(PR_TRUE, PR_TRUE, PR_TRUE));
278}
279
280TEST_F(CertDatabaseNSSTest, ImportCA_NotCACert) {
281  std::string cert_data = ReadTestFile("google.single.pem");
282
283  CertificateList certs =
284      X509Certificate::CreateCertificateListFromBytes(
285          cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
286  ASSERT_EQ(1U, certs.size());
287  EXPECT_FALSE(certs[0]->os_cert_handle()->isperm);
288
289  // Import it.
290  CertDatabase::ImportCertFailureList failed;
291  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::TRUSTED_SSL,
292                                     &failed));
293  ASSERT_EQ(1U, failed.size());
294  // Note: this compares pointers directly.  It's okay in this case because
295  // ImportCACerts returns the same pointers that were passed in.  In the
296  // general case IsSameOSCert should be used.
297  EXPECT_EQ(certs[0], failed[0].certificate);
298  EXPECT_EQ(ERR_IMPORT_CA_CERT_NOT_CA, failed[0].net_error);
299
300  EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
301}
302
303TEST_F(CertDatabaseNSSTest, ImportCACertHierarchy) {
304  CertificateList certs;
305  ASSERT_TRUE(ReadCertIntoList("dod_root_ca_2_cert.der", &certs));
306  ASSERT_TRUE(ReadCertIntoList("dod_ca_17_cert.der", &certs));
307  ASSERT_TRUE(ReadCertIntoList("www_us_army_mil_cert.der", &certs));
308
309  // Import it.
310  CertDatabase::ImportCertFailureList failed;
311  // Have to specify email trust for the cert verification of the child cert to
312  // work (see
313  // http://mxr.mozilla.org/mozilla/source/security/nss/lib/certhigh/certvfy.c#752
314  // "XXX This choice of trustType seems arbitrary.")
315  EXPECT_TRUE(cert_db_.ImportCACerts(
316      certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
317      &failed));
318
319  ASSERT_EQ(1U, failed.size());
320  EXPECT_EQ("www.us.army.mil", failed[0].certificate->subject().common_name);
321  EXPECT_EQ(ERR_IMPORT_CA_CERT_NOT_CA, failed[0].net_error);
322
323  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
324  ASSERT_EQ(2U, cert_list.size());
325  EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
326  EXPECT_EQ("DOD CA-17", cert_list[1]->subject().common_name);
327}
328
329TEST_F(CertDatabaseNSSTest, ImportCACertHierarchyDupeRoot) {
330  CertificateList certs;
331  ASSERT_TRUE(ReadCertIntoList("dod_root_ca_2_cert.der", &certs));
332
333  // First import just the root.
334  CertDatabase::ImportCertFailureList failed;
335  EXPECT_TRUE(cert_db_.ImportCACerts(
336      certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
337      &failed));
338
339  EXPECT_EQ(0U, failed.size());
340  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
341  ASSERT_EQ(1U, cert_list.size());
342  EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
343
344  ASSERT_TRUE(ReadCertIntoList("dod_ca_17_cert.der", &certs));
345  ASSERT_TRUE(ReadCertIntoList("www_us_army_mil_cert.der", &certs));
346
347  // Now import with the other certs in the list too.  Even though the root is
348  // already present, we should still import the rest.
349  failed.clear();
350  EXPECT_TRUE(cert_db_.ImportCACerts(
351      certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
352      &failed));
353
354  ASSERT_EQ(2U, failed.size());
355  EXPECT_EQ("DoD Root CA 2", failed[0].certificate->subject().common_name);
356  EXPECT_EQ(ERR_IMPORT_CERT_ALREADY_EXISTS, failed[0].net_error);
357  EXPECT_EQ("www.us.army.mil", failed[1].certificate->subject().common_name);
358  EXPECT_EQ(ERR_IMPORT_CA_CERT_NOT_CA, failed[1].net_error);
359
360  cert_list = ListCertsInSlot(slot_->os_module_handle());
361  ASSERT_EQ(2U, cert_list.size());
362  EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
363  EXPECT_EQ("DOD CA-17", cert_list[1]->subject().common_name);
364}
365
366TEST_F(CertDatabaseNSSTest, ImportCACertHierarchyUntrusted) {
367  CertificateList certs;
368  ASSERT_TRUE(ReadCertIntoList("dod_root_ca_2_cert.der", &certs));
369  ASSERT_TRUE(ReadCertIntoList("dod_ca_17_cert.der", &certs));
370
371  // Import it.
372  CertDatabase::ImportCertFailureList failed;
373  EXPECT_TRUE(cert_db_.ImportCACerts(certs, CertDatabase::UNTRUSTED, &failed));
374
375  ASSERT_EQ(1U, failed.size());
376  EXPECT_EQ("DOD CA-17", failed[0].certificate->subject().common_name);
377  // TODO(mattm): should check for net error equivalent of
378  // SEC_ERROR_UNTRUSTED_ISSUER
379  EXPECT_EQ(ERR_FAILED, failed[0].net_error);
380
381  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
382  ASSERT_EQ(1U, cert_list.size());
383  EXPECT_EQ("DoD Root CA 2", cert_list[0]->subject().common_name);
384}
385
386TEST_F(CertDatabaseNSSTest, ImportCACertHierarchyTree) {
387  CertificateList certs;
388  ASSERT_TRUE(ReadCertIntoList("dod_root_ca_2_cert.der", &certs));
389  ASSERT_TRUE(ReadCertIntoList("dod_ca_13_cert.der", &certs));
390  ASSERT_TRUE(ReadCertIntoList("dod_ca_17_cert.der", &certs));
391
392  // Import it.
393  CertDatabase::ImportCertFailureList failed;
394  EXPECT_TRUE(cert_db_.ImportCACerts(
395      certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL,
396      &failed));
397
398  EXPECT_EQ(0U, failed.size());
399
400  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
401  ASSERT_EQ(3U, cert_list.size());
402  EXPECT_EQ("DOD CA-13", cert_list[0]->subject().common_name);
403  EXPECT_EQ("DoD Root CA 2", cert_list[1]->subject().common_name);
404  EXPECT_EQ("DOD CA-17", cert_list[2]->subject().common_name);
405}
406
407TEST_F(CertDatabaseNSSTest, ImportCACertNotHierarchy) {
408  std::string cert_data = ReadTestFile("root_ca_cert.crt");
409  CertificateList certs =
410      X509Certificate::CreateCertificateListFromBytes(
411          cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
412  ASSERT_EQ(1U, certs.size());
413  ASSERT_TRUE(ReadCertIntoList("dod_ca_13_cert.der", &certs));
414  ASSERT_TRUE(ReadCertIntoList("dod_ca_17_cert.der", &certs));
415
416  // Import it.
417  CertDatabase::ImportCertFailureList failed;
418  EXPECT_TRUE(cert_db_.ImportCACerts(
419      certs, CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL |
420      CertDatabase::TRUSTED_OBJ_SIGN, &failed));
421
422  ASSERT_EQ(2U, failed.size());
423  // TODO(mattm): should check for net error equivalent of
424  // SEC_ERROR_UNKNOWN_ISSUER
425  EXPECT_EQ("DOD CA-13", failed[0].certificate->subject().common_name);
426  EXPECT_EQ(ERR_FAILED, failed[0].net_error);
427  EXPECT_EQ("DOD CA-17", failed[1].certificate->subject().common_name);
428  EXPECT_EQ(ERR_FAILED, failed[1].net_error);
429
430  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
431  ASSERT_EQ(1U, cert_list.size());
432  EXPECT_EQ("Test CA", cert_list[0]->subject().common_name);
433}
434
435TEST_F(CertDatabaseNSSTest, ImportServerCert) {
436  // Need to import intermediate cert for the verify of google cert, otherwise
437  // it will try to fetch it automatically with cert_pi_useAIACertFetch, which
438  // will cause OCSPCreateSession on the main thread, which is not allowed.
439  std::string cert_data = ReadTestFile("google.chain.pem");
440  CertificateList certs =
441      X509Certificate::CreateCertificateListFromBytes(
442          cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
443  ASSERT_EQ(2U, certs.size());
444
445  CertDatabase::ImportCertFailureList failed;
446  EXPECT_TRUE(cert_db_.ImportServerCert(certs, &failed));
447
448  EXPECT_EQ(0U, failed.size());
449
450  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
451  ASSERT_EQ(2U, cert_list.size());
452  scoped_refptr<X509Certificate> goog_cert(cert_list[0]);
453  scoped_refptr<X509Certificate> thawte_cert(cert_list[1]);
454  EXPECT_EQ("www.google.com", goog_cert->subject().common_name);
455  EXPECT_EQ("Thawte SGC CA", thawte_cert->subject().common_name);
456
457  EXPECT_EQ(CertDatabase::UNTRUSTED,
458            cert_db_.GetCertTrust(goog_cert.get(), SERVER_CERT));
459  psm::nsNSSCertTrust goog_trust(goog_cert->os_cert_handle()->trust);
460  EXPECT_TRUE(goog_trust.HasPeer(PR_TRUE, PR_TRUE, PR_TRUE));
461
462  int flags = 0;
463  CertVerifyResult verify_result;
464  int error = goog_cert->Verify("www.google.com", flags, &verify_result);
465  EXPECT_EQ(OK, error);
466  EXPECT_EQ(0, verify_result.cert_status);
467}
468
469TEST_F(CertDatabaseNSSTest, ImportServerCert_SelfSigned) {
470  CertificateList certs;
471  ASSERT_TRUE(ReadCertIntoList("punycodetest.der", &certs));
472
473  CertDatabase::ImportCertFailureList failed;
474  EXPECT_TRUE(cert_db_.ImportServerCert(certs, &failed));
475
476  EXPECT_EQ(0U, failed.size());
477
478  CertificateList cert_list = ListCertsInSlot(slot_->os_module_handle());
479  ASSERT_EQ(1U, cert_list.size());
480  scoped_refptr<X509Certificate> puny_cert(cert_list[0]);
481
482  EXPECT_EQ(CertDatabase::UNTRUSTED,
483            cert_db_.GetCertTrust(puny_cert.get(), SERVER_CERT));
484  psm::nsNSSCertTrust puny_trust(puny_cert->os_cert_handle()->trust);
485  EXPECT_TRUE(puny_trust.HasPeer(PR_TRUE, PR_TRUE, PR_TRUE));
486
487  int flags = 0;
488  CertVerifyResult verify_result;
489  int error = puny_cert->Verify("xn--wgv71a119e.com", flags, &verify_result);
490  EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error);
491  EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
492
493  // TODO(mattm): this should be SERVER_CERT, not CA_CERT, but that does not
494  // work due to NSS bug: https://bugzilla.mozilla.org/show_bug.cgi?id=531160
495  EXPECT_TRUE(cert_db_.SetCertTrust(
496      puny_cert.get(), CA_CERT,
497      CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL));
498
499  verify_result.Reset();
500  error = puny_cert->Verify("xn--wgv71a119e.com", flags, &verify_result);
501  EXPECT_EQ(OK, error);
502  EXPECT_EQ(0, verify_result.cert_status);
503}
504
505}  // namespace net
506