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
30 namespace psm = mozilla_security_manager;
31
32 namespace net {
33
34 namespace {
35
36 // Returns a FilePath object representing the src/net/data/ssl/certificates
37 // directory in the source tree.
GetTestCertsDirectory()38 FilePath 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
ListCertsInSlot(PK11SlotInfo * slot)48 CertificateList 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
CleanupSlotContents(PK11SlotInfo * slot)67 bool 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
ReadTestFile(const std::string & name)78 std::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
ReadCertIntoList(const std::string & name,CertificateList * certs)85 bool 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.)
105 class CertDatabaseNSSTest : public testing::Test {
106 public:
SetUp()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 }
TearDown()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
138 base::LazyInstance<ScopedTempDir> CertDatabaseNSSTest::temp_db_dir_(
139 base::LINKER_INITIALIZED);
140 bool CertDatabaseNSSTest::temp_db_initialized_ = false;
141
TEST_F(CertDatabaseNSSTest,ListCerts)142 TEST_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
TEST_F(CertDatabaseNSSTest,ImportFromPKCS12WrongPassword)152 TEST_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
TEST_F(CertDatabaseNSSTest,ImportFromPKCS12AndExportAgain)164 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACert_SSLTrust)186 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACert_EmailTrust)218 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACert_ObjSignTrust)249 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCA_NotCACert)280 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACertHierarchy)303 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACertHierarchyDupeRoot)329 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACertHierarchyUntrusted)366 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACertHierarchyTree)386 TEST_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
TEST_F(CertDatabaseNSSTest,ImportCACertNotHierarchy)407 TEST_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
TEST_F(CertDatabaseNSSTest,ImportServerCert)435 TEST_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
TEST_F(CertDatabaseNSSTest,ImportServerCert_SelfSigned)469 TEST_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