Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: net/base/x509_certificate_unittest.cc

Issue 9812035: Introduce CertVerifierProc to handle system cert validation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Lint Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/file_path.h" 5 #include "base/file_path.h"
6 #include "base/file_util.h" 6 #include "base/memory/scoped_ptr.h"
7 #include "base/path_service.h"
8 #include "base/pickle.h" 7 #include "base/pickle.h"
9 #include "base/sha1.h" 8 #include "base/sha1.h"
10 #include "base/string_number_conversions.h" 9 #include "base/string_number_conversions.h"
11 #include "base/string_split.h" 10 #include "base/string_split.h"
12 #include "crypto/rsa_private_key.h" 11 #include "crypto/rsa_private_key.h"
13 #include "net/base/asn1_util.h" 12 #include "net/base/asn1_util.h"
14 #include "net/base/cert_status_flags.h"
15 #include "net/base/cert_test_util.h" 13 #include "net/base/cert_test_util.h"
16 #include "net/base/cert_verify_result.h"
17 #include "net/base/crl_set.h"
18 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
19 #include "net/base/test_certificate_data.h" 15 #include "net/base/test_certificate_data.h"
20 #include "net/base/test_root_certs.h"
21 #include "net/base/x509_certificate.h" 16 #include "net/base/x509_certificate.h"
22 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
23 18
24 #if defined(USE_NSS) 19 #if defined(USE_NSS)
25 #include <cert.h> 20 #include <cert.h>
26 #endif 21 #endif
27 22
28 #if defined(OS_WIN)
29 #include "base/win/windows_version.h"
30 #elif defined(OS_MACOSX)
31 #include "base/mac/mac_util.h"
32 #endif
33
34 using base::HexEncode; 23 using base::HexEncode;
35 using base::Time; 24 using base::Time;
36 25
37 namespace net { 26 namespace net {
38 27
39 // Certificates for test data. They're obtained with: 28 // Certificates for test data. They're obtained with:
40 // 29 //
41 // $ openssl s_client -connect [host]:443 -showcerts > /tmp/host.pem < /dev/null 30 // $ openssl s_client -connect [host]:443 -showcerts > /tmp/host.pem < /dev/null
42 // $ openssl x509 -inform PEM -outform DER < /tmp/host.pem > /tmp/host.der 31 // $ openssl x509 -inform PEM -outform DER < /tmp/host.pem > /tmp/host.der
43 // 32 //
(...skipping 16 matching lines...) Expand all
60 0xa1, 0x4a, 0x94, 0x46, 0x22, 0x8e, 0x70, 0x66, 0x2b, 0x94, 0xf9, 0xf8, 49 0xa1, 0x4a, 0x94, 0x46, 0x22, 0x8e, 0x70, 0x66, 0x2b, 0x94, 0xf9, 0xf8,
61 0x57, 0x83, 0x2d, 0xa2, 0xff, 0xbc, 0x84, 0xc2 50 0x57, 0x83, 0x2d, 0xa2, 0xff, 0xbc, 0x84, 0xc2
62 }; 51 };
63 52
64 // thawte.com's cert (it's EV-licious!). 53 // thawte.com's cert (it's EV-licious!).
65 unsigned char thawte_fingerprint[] = { 54 unsigned char thawte_fingerprint[] = {
66 0x85, 0x04, 0x2d, 0xfd, 0x2b, 0x0e, 0xc6, 0xc8, 0xaf, 0x2d, 0x77, 0xd6, 55 0x85, 0x04, 0x2d, 0xfd, 0x2b, 0x0e, 0xc6, 0xc8, 0xaf, 0x2d, 0x77, 0xd6,
67 0xa1, 0x3a, 0x64, 0x04, 0x27, 0x90, 0x97, 0x37 56 0xa1, 0x3a, 0x64, 0x04, 0x27, 0x90, 0x97, 0x37
68 }; 57 };
69 58
70 // A certificate for www.paypal.com with a NULL byte in the common name.
71 // From http://www.gossamer-threads.com/lists/fulldisc/full-disclosure/70363
72 unsigned char paypal_null_fingerprint[] = {
73 0x4c, 0x88, 0x9e, 0x28, 0xd7, 0x7a, 0x44, 0x1e, 0x13, 0xf2, 0x6a, 0xba,
74 0x1f, 0xe8, 0x1b, 0xd6, 0xab, 0x7b, 0xe8, 0xd7
75 };
76
77 // A certificate for https://www.unosoft.hu/, whose AIA extension contains 59 // A certificate for https://www.unosoft.hu/, whose AIA extension contains
78 // an LDAP URL without a host name. 60 // an LDAP URL without a host name.
79 unsigned char unosoft_hu_fingerprint[] = { 61 unsigned char unosoft_hu_fingerprint[] = {
80 0x32, 0xff, 0xe3, 0xbe, 0x2c, 0x3b, 0xc7, 0xca, 0xbf, 0x2d, 0x64, 0xbd, 62 0x32, 0xff, 0xe3, 0xbe, 0x2c, 0x3b, 0xc7, 0xca, 0xbf, 0x2d, 0x64, 0xbd,
81 0x25, 0x66, 0xf2, 0xec, 0x8b, 0x0f, 0xbf, 0xd8 63 0x25, 0x66, 0xf2, 0xec, 0x8b, 0x0f, 0xbf, 0xd8
82 }; 64 };
83 65
84 // The fingerprint of the Google certificate used in the parsing tests, 66 // The fingerprint of the Google certificate used in the parsing tests,
85 // which is newer than the one included in the x509_certificate_data.h 67 // which is newer than the one included in the x509_certificate_data.h
86 unsigned char google_parse_fingerprint[] = { 68 unsigned char google_parse_fingerprint[] = {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 EXPECT_EQ("webkit.org", dns_names[1]); 252 EXPECT_EQ("webkit.org", dns_names[1]);
271 253
272 // Test that the wildcard cert matches properly. 254 // Test that the wildcard cert matches properly.
273 EXPECT_TRUE(webkit_cert->VerifyNameMatch("www.webkit.org")); 255 EXPECT_TRUE(webkit_cert->VerifyNameMatch("www.webkit.org"));
274 EXPECT_TRUE(webkit_cert->VerifyNameMatch("foo.webkit.org")); 256 EXPECT_TRUE(webkit_cert->VerifyNameMatch("foo.webkit.org"));
275 EXPECT_TRUE(webkit_cert->VerifyNameMatch("webkit.org")); 257 EXPECT_TRUE(webkit_cert->VerifyNameMatch("webkit.org"));
276 EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.webkit.com")); 258 EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.webkit.com"));
277 EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.foo.webkit.com")); 259 EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.foo.webkit.com"));
278 } 260 }
279 261
280 TEST(X509CertificateTest, WithoutRevocationChecking) {
281 // Check that verification without revocation checking works.
282 CertificateList certs = CreateCertificateListFromFile(
283 GetTestCertsDirectory(),
284 "googlenew.chain.pem",
285 X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
286
287 X509Certificate::OSCertHandles intermediates;
288 intermediates.push_back(certs[1]->os_cert_handle());
289
290 scoped_refptr<X509Certificate> google_full_chain =
291 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
292 intermediates);
293
294 CertVerifyResult verify_result;
295 EXPECT_EQ(OK, google_full_chain->Verify("www.google.com", 0 /* flags */, NULL,
296 &verify_result));
297 }
298
299 TEST(X509CertificateTest, ThawteCertParsing) { 262 TEST(X509CertificateTest, ThawteCertParsing) {
300 scoped_refptr<X509Certificate> thawte_cert(X509Certificate::CreateFromBytes( 263 scoped_refptr<X509Certificate> thawte_cert(X509Certificate::CreateFromBytes(
301 reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der))); 264 reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)));
302 265
303 ASSERT_NE(static_cast<X509Certificate*>(NULL), thawte_cert); 266 ASSERT_NE(static_cast<X509Certificate*>(NULL), thawte_cert);
304 267
305 const CertPrincipal& subject = thawte_cert->subject(); 268 const CertPrincipal& subject = thawte_cert->subject();
306 EXPECT_EQ("www.thawte.com", subject.common_name); 269 EXPECT_EQ("www.thawte.com", subject.common_name);
307 EXPECT_EQ("Mountain View", subject.locality_name); 270 EXPECT_EQ("Mountain View", subject.locality_name);
308 EXPECT_EQ("California", subject.state_or_province_name); 271 EXPECT_EQ("California", subject.state_or_province_name);
(...skipping 27 matching lines...) Expand all
336 const SHA1Fingerprint& fingerprint = thawte_cert->fingerprint(); 299 const SHA1Fingerprint& fingerprint = thawte_cert->fingerprint();
337 for (size_t i = 0; i < 20; ++i) 300 for (size_t i = 0; i < 20; ++i)
338 EXPECT_EQ(thawte_fingerprint[i], fingerprint.data[i]); 301 EXPECT_EQ(thawte_fingerprint[i], fingerprint.data[i]);
339 302
340 std::vector<std::string> dns_names; 303 std::vector<std::string> dns_names;
341 thawte_cert->GetDNSNames(&dns_names); 304 thawte_cert->GetDNSNames(&dns_names);
342 ASSERT_EQ(1U, dns_names.size()); 305 ASSERT_EQ(1U, dns_names.size());
343 EXPECT_EQ("www.thawte.com", dns_names[0]); 306 EXPECT_EQ("www.thawte.com", dns_names[0]);
344 } 307 }
345 308
346 #if defined(OS_ANDROID) || defined(USE_OPENSSL)
347 // TODO(jnd): http://crbug.com/117478 - EV verification is not yet supported.
348 #define MAYBE_EVVerification DISABLED_EVVerification
349 #else
350 #define MAYBE_EVVerification EVVerification
351 #endif
352 TEST(X509CertificateTest, MAYBE_EVVerification) {
353 // This certificate will expire Jun 21, 2013.
354 CertificateList certs = CreateCertificateListFromFile(
355 GetTestCertsDirectory(),
356 "comodo.chain.pem",
357 X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
358 ASSERT_EQ(3U, certs.size());
359
360 X509Certificate::OSCertHandles intermediates;
361 intermediates.push_back(certs[1]->os_cert_handle());
362 intermediates.push_back(certs[2]->os_cert_handle());
363
364 scoped_refptr<X509Certificate> comodo_chain =
365 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
366 intermediates);
367
368 scoped_refptr<CRLSet> crl_set(CRLSet::EmptyCRLSetForTesting());
369 CertVerifyResult verify_result;
370 int flags = X509Certificate::VERIFY_EV_CERT;
371 int error = comodo_chain->Verify(
372 "comodo.com", flags, crl_set.get(), &verify_result);
373 EXPECT_EQ(OK, error);
374 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
375 }
376
377 // Test that all desired AttributeAndValue pairs can be extracted when only 309 // Test that all desired AttributeAndValue pairs can be extracted when only
378 // a single RelativeDistinguishedName is present. "Normally" there is only 310 // a single RelativeDistinguishedName is present. "Normally" there is only
379 // one AVA per RDN, but some CAs place all AVAs within a single RDN. 311 // one AVA per RDN, but some CAs place all AVAs within a single RDN.
380 // This is a regression test for http://crbug.com/101009 312 // This is a regression test for http://crbug.com/101009
381 TEST(X509CertificateTest, MultivalueRDN) { 313 TEST(X509CertificateTest, MultivalueRDN) {
382 FilePath certs_dir = GetTestCertsDirectory(); 314 FilePath certs_dir = GetTestCertsDirectory();
383 315
384 scoped_refptr<X509Certificate> multivalue_rdn_cert = 316 scoped_refptr<X509Certificate> multivalue_rdn_cert =
385 ImportCertFromFile(certs_dir, "multivalue_rdn.pem"); 317 ImportCertFromFile(certs_dir, "multivalue_rdn.pem");
386 ASSERT_NE(static_cast<X509Certificate*>(NULL), multivalue_rdn_cert); 318 ASSERT_NE(static_cast<X509Certificate*>(NULL), multivalue_rdn_cert);
(...skipping 30 matching lines...) Expand all
417 ASSERT_EQ(1U, subject.street_addresses.size()); 349 ASSERT_EQ(1U, subject.street_addresses.size());
418 EXPECT_EQ("1600 Amphitheatre Parkway", subject.street_addresses[0]); 350 EXPECT_EQ("1600 Amphitheatre Parkway", subject.street_addresses[0]);
419 ASSERT_EQ(1U, subject.organization_names.size()); 351 ASSERT_EQ(1U, subject.organization_names.size());
420 EXPECT_EQ("Chromium = \"net_unittests\"", subject.organization_names[0]); 352 EXPECT_EQ("Chromium = \"net_unittests\"", subject.organization_names[0]);
421 ASSERT_EQ(2U, subject.organization_unit_names.size()); 353 ASSERT_EQ(2U, subject.organization_unit_names.size());
422 EXPECT_EQ("net_unittests", subject.organization_unit_names[0]); 354 EXPECT_EQ("net_unittests", subject.organization_unit_names[0]);
423 EXPECT_EQ("Chromium", subject.organization_unit_names[1]); 355 EXPECT_EQ("Chromium", subject.organization_unit_names[1]);
424 EXPECT_EQ(0U, subject.domain_components.size()); 356 EXPECT_EQ(0U, subject.domain_components.size());
425 } 357 }
426 358
427 TEST(X509CertificateTest, PaypalNullCertParsing) {
428 scoped_refptr<X509Certificate> paypal_null_cert(
429 X509Certificate::CreateFromBytes(
430 reinterpret_cast<const char*>(paypal_null_der),
431 sizeof(paypal_null_der)));
432
433 ASSERT_NE(static_cast<X509Certificate*>(NULL), paypal_null_cert);
434
435 const SHA1Fingerprint& fingerprint =
436 paypal_null_cert->fingerprint();
437 for (size_t i = 0; i < 20; ++i)
438 EXPECT_EQ(paypal_null_fingerprint[i], fingerprint.data[i]);
439
440 int flags = 0;
441 CertVerifyResult verify_result;
442 int error = paypal_null_cert->Verify("www.paypal.com", flags, NULL,
443 &verify_result);
444 #if defined(USE_OPENSSL) || defined(OS_MACOSX) || defined(OS_WIN)
445 // TOOD(bulach): investigate why macosx and win aren't returning
446 // ERR_CERT_INVALID or ERR_CERT_COMMON_NAME_INVALID.
447 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error);
448 #else
449 EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error);
450 #endif
451 // Either the system crypto library should correctly report a certificate
452 // name mismatch, or our certificate blacklist should cause us to report an
453 // invalid certificate.
454 #if !defined(OS_MACOSX) && !defined(USE_OPENSSL)
455 EXPECT_TRUE(verify_result.cert_status &
456 (CERT_STATUS_COMMON_NAME_INVALID | CERT_STATUS_INVALID));
457 #endif
458 }
459
460 TEST(X509CertificateTest, SerialNumbers) { 359 TEST(X509CertificateTest, SerialNumbers) {
461 scoped_refptr<X509Certificate> google_cert( 360 scoped_refptr<X509Certificate> google_cert(
462 X509Certificate::CreateFromBytes( 361 X509Certificate::CreateFromBytes(
463 reinterpret_cast<const char*>(google_der), sizeof(google_der))); 362 reinterpret_cast<const char*>(google_der), sizeof(google_der)));
464 363
465 static const uint8 google_serial[16] = { 364 static const uint8 google_serial[16] = {
466 0x01,0x2a,0x39,0x76,0x0d,0x3f,0x4f,0xc9, 365 0x01,0x2a,0x39,0x76,0x0d,0x3f,0x4f,0xc9,
467 0x0b,0xe7,0xbd,0x2b,0xcf,0x95,0x2e,0x7a, 366 0x0b,0xe7,0xbd,0x2b,0xcf,0x95,0x2e,0x7a,
468 }; 367 };
469 368
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 431 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09
533 }; 432 };
534 EXPECT_TRUE(memcmp(cert_chain1->ca_fingerprint().data, 433 EXPECT_TRUE(memcmp(cert_chain1->ca_fingerprint().data,
535 cert_chain1_ca_fingerprint, 20) == 0); 434 cert_chain1_ca_fingerprint, 20) == 0);
536 EXPECT_TRUE(memcmp(cert_chain2->ca_fingerprint().data, 435 EXPECT_TRUE(memcmp(cert_chain2->ca_fingerprint().data,
537 cert_chain2_ca_fingerprint, 20) == 0); 436 cert_chain2_ca_fingerprint, 20) == 0);
538 EXPECT_TRUE(memcmp(cert_chain3->ca_fingerprint().data, 437 EXPECT_TRUE(memcmp(cert_chain3->ca_fingerprint().data,
539 cert_chain3_ca_fingerprint, 20) == 0); 438 cert_chain3_ca_fingerprint, 20) == 0);
540 } 439 }
541 440
542 // A regression test for http://crbug.com/31497.
543 // This certificate will expire on 2012-04-08. The test will still
544 // pass if error == ERR_CERT_DATE_INVALID. TODO(wtc): generate test
545 // certificates for this unit test. http://crbug.com/111742
546 TEST(X509CertificateTest, IntermediateCARequireExplicitPolicy) {
547 FilePath certs_dir = GetTestCertsDirectory();
548
549 scoped_refptr<X509Certificate> server_cert =
550 ImportCertFromFile(certs_dir, "www_us_army_mil_cert.der");
551 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
552
553 // The intermediate CA certificate's policyConstraints extension has a
554 // requireExplicitPolicy field with SkipCerts=0.
555 scoped_refptr<X509Certificate> intermediate_cert =
556 ImportCertFromFile(certs_dir, "dod_ca_17_cert.der");
557 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
558
559 scoped_refptr<X509Certificate> root_cert =
560 ImportCertFromFile(certs_dir, "dod_root_ca_2_cert.der");
561 ScopedTestRoot scoped_root(root_cert);
562
563 X509Certificate::OSCertHandles intermediates;
564 intermediates.push_back(intermediate_cert->os_cert_handle());
565 scoped_refptr<X509Certificate> cert_chain =
566 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
567 intermediates);
568
569 int flags = 0;
570 CertVerifyResult verify_result;
571 int error = cert_chain->Verify("www.us.army.mil", flags, NULL,
572 &verify_result);
573 if (error == OK) {
574 EXPECT_EQ(0U, verify_result.cert_status);
575 } else {
576 EXPECT_EQ(ERR_CERT_DATE_INVALID, error);
577 EXPECT_EQ(CERT_STATUS_DATE_INVALID, verify_result.cert_status);
578 }
579 }
580
581 // Test for bug 58437.
582 // This certificate will expire on 2011-12-21. The test will still
583 // pass if error == ERR_CERT_DATE_INVALID.
584 // This test is DISABLED because it appears that we cannot do
585 // certificate revocation checking when running all of the net unit tests.
586 // This test passes when run individually, but when run with all of the net
587 // unit tests, the call to PKIXVerifyCert returns the NSS error -8180, which is
588 // SEC_ERROR_REVOKED_CERTIFICATE. This indicates a lack of revocation
589 // status, i.e. that the revocation check is failing for some reason.
590 TEST(X509CertificateTest, DISABLED_GlobalSignR3EVTest) {
591 FilePath certs_dir = GetTestCertsDirectory();
592
593 scoped_refptr<X509Certificate> server_cert =
594 ImportCertFromFile(certs_dir, "2029_globalsign_com_cert.pem");
595 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
596
597 scoped_refptr<X509Certificate> intermediate_cert =
598 ImportCertFromFile(certs_dir, "globalsign_ev_sha256_ca_cert.pem");
599 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
600
601 X509Certificate::OSCertHandles intermediates;
602 intermediates.push_back(intermediate_cert->os_cert_handle());
603 scoped_refptr<X509Certificate> cert_chain =
604 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
605 intermediates);
606
607 CertVerifyResult verify_result;
608 int flags = X509Certificate::VERIFY_REV_CHECKING_ENABLED |
609 X509Certificate::VERIFY_EV_CERT;
610 int error = cert_chain->Verify("2029.globalsign.com", flags, NULL,
611 &verify_result);
612 if (error == OK)
613 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
614 else
615 EXPECT_EQ(ERR_CERT_DATE_INVALID, error);
616 }
617
618 // Currently, only RSA and DSA keys are checked for weakness, and our example
619 // weak size is 768. These could change in the future.
620 //
621 // Note that this means there may be false negatives: keys for other
622 // algorithms and which are weak will pass this test.
623 static bool IsWeakKeyType(const std::string& key_type) {
624 size_t pos = key_type.find("-");
625 std::string size = key_type.substr(0, pos);
626 std::string type = key_type.substr(pos + 1);
627
628 if (type == "rsa" || type == "dsa")
629 return size == "768";
630
631 return false;
632 }
633
634 TEST(X509CertificateTest, RejectWeakKeys) {
635 FilePath certs_dir = GetTestCertsDirectory();
636 typedef std::vector<std::string> Strings;
637 Strings key_types;
638
639 // generate-weak-test-chains.sh currently has:
640 // key_types="768-rsa 1024-rsa 2048-rsa prime256v1-ecdsa"
641 // We must use the same key types here. The filenames generated look like:
642 // 2048-rsa-ee-by-768-rsa-intermediate.pem
643 key_types.push_back("768-rsa");
644 key_types.push_back("1024-rsa");
645 key_types.push_back("2048-rsa");
646
647 bool use_ecdsa = true;
648 #if defined(OS_WIN)
649 use_ecdsa = base::win::GetVersion() > base::win::VERSION_XP;
650 #elif defined(OS_MACOSX)
651 use_ecdsa = base::mac::IsOSSnowLeopardOrLater();
652 #endif
653
654 if (use_ecdsa)
655 key_types.push_back("prime256v1-ecdsa");
656
657 // Add the root that signed the intermediates for this test.
658 scoped_refptr<X509Certificate> root_cert =
659 ImportCertFromFile(certs_dir, "2048-rsa-root.pem");
660 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert);
661 ScopedTestRoot scoped_root(root_cert);
662
663 // Now test each chain.
664 for (Strings::const_iterator ee_type = key_types.begin();
665 ee_type != key_types.end(); ++ee_type) {
666 for (Strings::const_iterator signer_type = key_types.begin();
667 signer_type != key_types.end(); ++signer_type) {
668 std::string basename = *ee_type + "-ee-by-" + *signer_type +
669 "-intermediate.pem";
670 SCOPED_TRACE(basename);
671 scoped_refptr<X509Certificate> ee_cert =
672 ImportCertFromFile(certs_dir, basename);
673 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert);
674
675 basename = *signer_type + "-intermediate.pem";
676 scoped_refptr<X509Certificate> intermediate =
677 ImportCertFromFile(certs_dir, basename);
678 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate);
679
680 X509Certificate::OSCertHandles intermediates;
681 intermediates.push_back(intermediate->os_cert_handle());
682 scoped_refptr<X509Certificate> cert_chain =
683 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(),
684 intermediates);
685
686 CertVerifyResult verify_result;
687 int error = cert_chain->Verify("127.0.0.1", 0, NULL, &verify_result);
688
689 if (IsWeakKeyType(*ee_type) || IsWeakKeyType(*signer_type)) {
690 EXPECT_NE(OK, error);
691 EXPECT_EQ(CERT_STATUS_WEAK_KEY,
692 verify_result.cert_status & CERT_STATUS_WEAK_KEY);
693 } else {
694 EXPECT_EQ(OK, error);
695 EXPECT_EQ(0U, verify_result.cert_status & CERT_STATUS_WEAK_KEY);
696 }
697 }
698 }
699 }
700
701 // Test for bug 108514.
702 // The certificate will expire on 2012-07-20. The test will still
703 // pass if error == ERR_CERT_DATE_INVALID. TODO(rsleevi): generate test
704 // certificates for this unit test. http://crbug.com/111730
705 TEST(X509CertificateTest, ExtraneousMD5RootCert) {
706 FilePath certs_dir = GetTestCertsDirectory();
707
708 scoped_refptr<X509Certificate> server_cert =
709 ImportCertFromFile(certs_dir, "images_etrade_wallst_com.pem");
710 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
711
712 scoped_refptr<X509Certificate> intermediate_cert =
713 ImportCertFromFile(certs_dir, "globalsign_orgv1_ca.pem");
714 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
715
716 scoped_refptr<X509Certificate> md5_root_cert =
717 ImportCertFromFile(certs_dir, "globalsign_root_ca_md5.pem");
718 ASSERT_NE(static_cast<X509Certificate*>(NULL), md5_root_cert);
719
720 X509Certificate::OSCertHandles intermediates;
721 intermediates.push_back(intermediate_cert->os_cert_handle());
722 intermediates.push_back(md5_root_cert->os_cert_handle());
723 scoped_refptr<X509Certificate> cert_chain =
724 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
725 intermediates);
726
727 CertVerifyResult verify_result;
728 int flags = 0;
729 int error = cert_chain->Verify("images.etrade.wallst.com", flags, NULL,
730 &verify_result);
731 if (error != OK)
732 EXPECT_EQ(ERR_CERT_DATE_INVALID, error);
733
734 EXPECT_FALSE(verify_result.has_md5);
735 EXPECT_FALSE(verify_result.has_md5_ca);
736 }
737
738 // Test for bug 94673.
739 TEST(X509CertificateTest, GoogleDigiNotarTest) {
740 FilePath certs_dir = GetTestCertsDirectory();
741
742 scoped_refptr<X509Certificate> server_cert =
743 ImportCertFromFile(certs_dir, "google_diginotar.pem");
744 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
745
746 scoped_refptr<X509Certificate> intermediate_cert =
747 ImportCertFromFile(certs_dir, "diginotar_public_ca_2025.pem");
748 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
749
750 X509Certificate::OSCertHandles intermediates;
751 intermediates.push_back(intermediate_cert->os_cert_handle());
752 scoped_refptr<X509Certificate> cert_chain =
753 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
754 intermediates);
755
756 CertVerifyResult verify_result;
757 int flags = X509Certificate::VERIFY_REV_CHECKING_ENABLED;
758 int error = cert_chain->Verify("mail.google.com", flags, NULL,
759 &verify_result);
760 EXPECT_NE(OK, error);
761
762 // Now turn off revocation checking. Certificate verification should still
763 // fail.
764 flags = 0;
765 error = cert_chain->Verify("mail.google.com", flags, NULL, &verify_result);
766 EXPECT_NE(OK, error);
767 }
768
769 TEST(X509CertificateTest, DigiNotarCerts) { 441 TEST(X509CertificateTest, DigiNotarCerts) {
770 static const char* const kDigiNotarFilenames[] = { 442 static const char* const kDigiNotarFilenames[] = {
771 "diginotar_root_ca.pem", 443 "diginotar_root_ca.pem",
772 "diginotar_cyber_ca.pem", 444 "diginotar_cyber_ca.pem",
773 "diginotar_services_1024_ca.pem", 445 "diginotar_services_1024_ca.pem",
774 "diginotar_pkioverheid.pem", 446 "diginotar_pkioverheid.pem",
775 "diginotar_pkioverheid_g2.pem", 447 "diginotar_pkioverheid_g2.pem",
776 NULL, 448 NULL,
777 }; 449 };
778 450
(...skipping 15 matching lines...) Expand all
794 SHA1Fingerprint fingerprint; 466 SHA1Fingerprint fingerprint;
795 ASSERT_EQ(sizeof(fingerprint.data), spki_sha1.size()); 467 ASSERT_EQ(sizeof(fingerprint.data), spki_sha1.size());
796 memcpy(fingerprint.data, spki_sha1.data(), spki_sha1.size()); 468 memcpy(fingerprint.data, spki_sha1.data(), spki_sha1.size());
797 public_keys.push_back(fingerprint); 469 public_keys.push_back(fingerprint);
798 470
799 EXPECT_TRUE(X509Certificate::IsPublicKeyBlacklisted(public_keys)) << 471 EXPECT_TRUE(X509Certificate::IsPublicKeyBlacklisted(public_keys)) <<
800 "Public key not blocked for " << kDigiNotarFilenames[i]; 472 "Public key not blocked for " << kDigiNotarFilenames[i];
801 } 473 }
802 } 474 }
803 475
804 // Bug 111893: This test needs a new certificate.
805 TEST(X509CertificateTest, DISABLED_TestKnownRoot) {
806 FilePath certs_dir = GetTestCertsDirectory();
807 scoped_refptr<X509Certificate> cert =
808 ImportCertFromFile(certs_dir, "nist.der");
809 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert);
810
811 // This intermediate is only needed for old Linux machines. Modern NSS
812 // includes it as a root already.
813 scoped_refptr<X509Certificate> intermediate_cert =
814 ImportCertFromFile(certs_dir, "nist_intermediate.der");
815 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
816
817 X509Certificate::OSCertHandles intermediates;
818 intermediates.push_back(intermediate_cert->os_cert_handle());
819 scoped_refptr<X509Certificate> cert_chain =
820 X509Certificate::CreateFromHandle(cert->os_cert_handle(),
821 intermediates);
822
823 int flags = 0;
824 CertVerifyResult verify_result;
825 // This is going to blow up in Feb 2012. Sorry! Disable and file a bug
826 // against agl. Also see PublicKeyHashes in this file.
827 int error = cert_chain->Verify("www.nist.gov", flags, NULL, &verify_result);
828 EXPECT_EQ(OK, error);
829 EXPECT_EQ(0U, verify_result.cert_status);
830 EXPECT_TRUE(verify_result.is_issued_by_known_root);
831 }
832
833 // This is the SHA1 hash of the SubjectPublicKeyInfo of nist.der.
834 static const char nistSPKIHash[] =
835 "\x15\x60\xde\x65\x4e\x03\x9f\xd0\x08\x82"
836 "\xa9\x6a\xc4\x65\x8e\x6f\x92\x06\x84\x35";
837
838 TEST(X509CertificateTest, ExtractSPKIFromDERCert) { 476 TEST(X509CertificateTest, ExtractSPKIFromDERCert) {
839 FilePath certs_dir = GetTestCertsDirectory(); 477 FilePath certs_dir = GetTestCertsDirectory();
840 scoped_refptr<X509Certificate> cert = 478 scoped_refptr<X509Certificate> cert =
841 ImportCertFromFile(certs_dir, "nist.der"); 479 ImportCertFromFile(certs_dir, "nist.der");
842 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert); 480 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert);
843 481
844 std::string derBytes; 482 std::string derBytes;
845 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(), 483 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(),
846 &derBytes)); 484 &derBytes));
847 485
(...skipping 20 matching lines...) Expand all
868 std::vector<base::StringPiece> crl_urls; 506 std::vector<base::StringPiece> crl_urls;
869 EXPECT_TRUE(asn1::ExtractCRLURLsFromDERCert(derBytes, &crl_urls)); 507 EXPECT_TRUE(asn1::ExtractCRLURLsFromDERCert(derBytes, &crl_urls));
870 508
871 EXPECT_EQ(1u, crl_urls.size()); 509 EXPECT_EQ(1u, crl_urls.size());
872 if (crl_urls.size() > 0) { 510 if (crl_urls.size() > 0) {
873 EXPECT_EQ("http://SVRSecure-G3-crl.verisign.com/SVRSecureG3.crl", 511 EXPECT_EQ("http://SVRSecure-G3-crl.verisign.com/SVRSecureG3.crl",
874 crl_urls[0].as_string()); 512 crl_urls[0].as_string());
875 } 513 }
876 } 514 }
877 515
878 // Bug 111893: This test needs a new certificate.
879 TEST(X509CertificateTest, DISABLED_PublicKeyHashes) {
880 FilePath certs_dir = GetTestCertsDirectory();
881 // This is going to blow up in Feb 2012. Sorry! Disable and file a bug
882 // against agl. Also see TestKnownRoot in this file.
883 scoped_refptr<X509Certificate> cert =
884 ImportCertFromFile(certs_dir, "nist.der");
885 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert);
886
887 // This intermediate is only needed for old Linux machines. Modern NSS
888 // includes it as a root already.
889 scoped_refptr<X509Certificate> intermediate_cert =
890 ImportCertFromFile(certs_dir, "nist_intermediate.der");
891 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
892
893 ScopedTestRoot scoped_intermediate(intermediate_cert);
894
895 X509Certificate::OSCertHandles intermediates;
896 intermediates.push_back(intermediate_cert->os_cert_handle());
897 scoped_refptr<X509Certificate> cert_chain =
898 X509Certificate::CreateFromHandle(cert->os_cert_handle(),
899 intermediates);
900
901 int flags = 0;
902 CertVerifyResult verify_result;
903
904 int error = cert_chain->Verify("www.nist.gov", flags, NULL, &verify_result);
905 EXPECT_EQ(OK, error);
906 EXPECT_EQ(0U, verify_result.cert_status);
907 ASSERT_LE(2u, verify_result.public_key_hashes.size());
908 EXPECT_EQ(HexEncode(nistSPKIHash, base::kSHA1Length),
909 HexEncode(verify_result.public_key_hashes[0].data, base::kSHA1Length));
910 EXPECT_EQ("83244223D6CBF0A26FC7DE27CEBCA4BDA32612AD",
911 HexEncode(verify_result.public_key_hashes[1].data, base::kSHA1Length));
912 }
913
914 // A regression test for http://crbug.com/70293.
915 // The Key Usage extension in this RSA SSL server certificate does not have
916 // the keyEncipherment bit.
917 TEST(X509CertificateTest, InvalidKeyUsage) {
918 FilePath certs_dir = GetTestCertsDirectory();
919
920 scoped_refptr<X509Certificate> server_cert =
921 ImportCertFromFile(certs_dir, "invalid_key_usage_cert.der");
922 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
923
924 int flags = 0;
925 CertVerifyResult verify_result;
926 int error = server_cert->Verify("jira.aquameta.com", flags, NULL,
927 &verify_result);
928 #if defined(USE_OPENSSL)
929 // This certificate has two errors: "invalid key usage" and "untrusted CA".
930 // However, OpenSSL returns only one (the latter), and we can't detect
931 // the other errors.
932 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error);
933 #else
934 EXPECT_EQ(ERR_CERT_INVALID, error);
935 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID);
936 #endif
937 // TODO(wtc): fix http://crbug.com/75520 to get all the certificate errors
938 // from NSS.
939 #if !defined(USE_NSS)
940 // The certificate is issued by an unknown CA.
941 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
942 #endif
943 }
944
945 // Tests X509CertificateCache via X509Certificate::CreateFromHandle. We 516 // Tests X509CertificateCache via X509Certificate::CreateFromHandle. We
946 // call X509Certificate::CreateFromHandle several times and observe whether 517 // call X509Certificate::CreateFromHandle several times and observe whether
947 // it returns a cached or new OSCertHandle. 518 // it returns a cached or new OSCertHandle.
948 TEST(X509CertificateTest, Cache) { 519 TEST(X509CertificateTest, Cache) {
949 X509Certificate::OSCertHandle google_cert_handle; 520 X509Certificate::OSCertHandle google_cert_handle;
950 X509Certificate::OSCertHandle thawte_cert_handle; 521 X509Certificate::OSCertHandle thawte_cert_handle;
951 522
952 // Add a single certificate to the certificate cache. 523 // Add a single certificate to the certificate cache.
953 google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( 524 google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
954 reinterpret_cast<const char*>(google_der), sizeof(google_der)); 525 reinterpret_cast<const char*>(google_der), sizeof(google_der));
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 ASSERT_EQ(2u, cert2_intermediates.size()); 668 ASSERT_EQ(2u, cert2_intermediates.size());
1098 EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2_intermediates[0], 669 EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2_intermediates[0],
1099 webkit_cert->os_cert_handle())); 670 webkit_cert->os_cert_handle()));
1100 EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2_intermediates[1], 671 EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2_intermediates[1],
1101 thawte_cert->os_cert_handle())); 672 thawte_cert->os_cert_handle()));
1102 673
1103 // Cleanup 674 // Cleanup
1104 X509Certificate::FreeOSCertHandle(google_handle); 675 X509Certificate::FreeOSCertHandle(google_handle);
1105 } 676 }
1106 677
1107 // Basic test for returning the chain in CertVerifyResult. Note that the
1108 // returned chain may just be a reflection of the originally supplied chain;
1109 // that is, if any errors occur, the default chain returned is an exact copy
1110 // of the certificate to be verified. The remaining VerifyReturn* tests are
1111 // used to ensure that the actual, verified chain is being returned by
1112 // Verify().
1113 TEST(X509CertificateTest, VerifyReturnChainBasic) {
1114 FilePath certs_dir = GetTestCertsDirectory();
1115 CertificateList certs = CreateCertificateListFromFile(
1116 certs_dir, "x509_verify_results.chain.pem",
1117 X509Certificate::FORMAT_AUTO);
1118 ASSERT_EQ(3U, certs.size());
1119
1120 X509Certificate::OSCertHandles intermediates;
1121 intermediates.push_back(certs[1]->os_cert_handle());
1122 intermediates.push_back(certs[2]->os_cert_handle());
1123
1124 ScopedTestRoot scoped_root(certs[2]);
1125
1126 scoped_refptr<X509Certificate> google_full_chain =
1127 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
1128 intermediates);
1129 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain);
1130 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size());
1131
1132 CertVerifyResult verify_result;
1133 EXPECT_EQ(static_cast<X509Certificate*>(NULL), verify_result.verified_cert);
1134 int error = google_full_chain->Verify("127.0.0.1", 0, NULL, &verify_result);
1135 EXPECT_EQ(OK, error);
1136 ASSERT_NE(static_cast<X509Certificate*>(NULL), verify_result.verified_cert);
1137
1138 EXPECT_NE(google_full_chain, verify_result.verified_cert);
1139 EXPECT_TRUE(X509Certificate::IsSameOSCert(
1140 google_full_chain->os_cert_handle(),
1141 verify_result.verified_cert->os_cert_handle()));
1142 const X509Certificate::OSCertHandles& return_intermediates =
1143 verify_result.verified_cert->GetIntermediateCertificates();
1144 ASSERT_EQ(2U, return_intermediates.size());
1145 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0],
1146 certs[1]->os_cert_handle()));
1147 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1],
1148 certs[2]->os_cert_handle()));
1149 }
1150
1151 // Test that the certificate returned in CertVerifyResult is able to reorder
1152 // certificates that are not ordered from end-entity to root. While this is
1153 // a protocol violation if sent during a TLS handshake, if multiple sources
1154 // of intermediate certificates are combined, it's possible that order may
1155 // not be maintained.
1156 TEST(X509CertificateTest, VerifyReturnChainProperlyOrdered) {
1157 FilePath certs_dir = GetTestCertsDirectory();
1158 CertificateList certs = CreateCertificateListFromFile(
1159 certs_dir, "x509_verify_results.chain.pem",
1160 X509Certificate::FORMAT_AUTO);
1161 ASSERT_EQ(3U, certs.size());
1162
1163 // Construct the chain out of order.
1164 X509Certificate::OSCertHandles intermediates;
1165 intermediates.push_back(certs[2]->os_cert_handle());
1166 intermediates.push_back(certs[1]->os_cert_handle());
1167
1168 ScopedTestRoot scoped_root(certs[2]);
1169
1170 scoped_refptr<X509Certificate> google_full_chain =
1171 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
1172 intermediates);
1173 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain);
1174 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size());
1175
1176 CertVerifyResult verify_result;
1177 EXPECT_EQ(static_cast<X509Certificate*>(NULL), verify_result.verified_cert);
1178 int error = google_full_chain->Verify("127.0.0.1", 0, NULL, &verify_result);
1179 EXPECT_EQ(OK, error);
1180 ASSERT_NE(static_cast<X509Certificate*>(NULL), verify_result.verified_cert);
1181
1182 EXPECT_NE(google_full_chain, verify_result.verified_cert);
1183 EXPECT_TRUE(X509Certificate::IsSameOSCert(
1184 google_full_chain->os_cert_handle(),
1185 verify_result.verified_cert->os_cert_handle()));
1186 const X509Certificate::OSCertHandles& return_intermediates =
1187 verify_result.verified_cert->GetIntermediateCertificates();
1188 ASSERT_EQ(2U, return_intermediates.size());
1189 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0],
1190 certs[1]->os_cert_handle()));
1191 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1],
1192 certs[2]->os_cert_handle()));
1193 }
1194
1195 // Test that Verify() filters out certificates which are not related to
1196 // or part of the certificate chain being verified.
1197 TEST(X509CertificateTest, VerifyReturnChainFiltersUnrelatedCerts) {
1198 FilePath certs_dir = GetTestCertsDirectory();
1199 CertificateList certs = CreateCertificateListFromFile(
1200 certs_dir, "x509_verify_results.chain.pem",
1201 X509Certificate::FORMAT_AUTO);
1202 ASSERT_EQ(3U, certs.size());
1203 ScopedTestRoot scoped_root(certs[2]);
1204
1205 scoped_refptr<X509Certificate> unrelated_dod_certificate =
1206 ImportCertFromFile(certs_dir, "dod_ca_17_cert.der");
1207 scoped_refptr<X509Certificate> unrelated_dod_certificate2 =
1208 ImportCertFromFile(certs_dir, "dod_root_ca_2_cert.der");
1209 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_dod_certificate);
1210 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_dod_certificate2);
1211
1212 // Interject unrelated certificates into the list of intermediates.
1213 X509Certificate::OSCertHandles intermediates;
1214 intermediates.push_back(unrelated_dod_certificate->os_cert_handle());
1215 intermediates.push_back(certs[1]->os_cert_handle());
1216 intermediates.push_back(unrelated_dod_certificate2->os_cert_handle());
1217 intermediates.push_back(certs[2]->os_cert_handle());
1218
1219 scoped_refptr<X509Certificate> google_full_chain =
1220 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
1221 intermediates);
1222 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain);
1223 ASSERT_EQ(4U, google_full_chain->GetIntermediateCertificates().size());
1224
1225 CertVerifyResult verify_result;
1226 EXPECT_EQ(static_cast<X509Certificate*>(NULL), verify_result.verified_cert);
1227 int error = google_full_chain->Verify("127.0.0.1", 0, NULL, &verify_result);
1228 EXPECT_EQ(OK, error);
1229 ASSERT_NE(static_cast<X509Certificate*>(NULL), verify_result.verified_cert);
1230
1231 EXPECT_NE(google_full_chain, verify_result.verified_cert);
1232 EXPECT_TRUE(X509Certificate::IsSameOSCert(
1233 google_full_chain->os_cert_handle(),
1234 verify_result.verified_cert->os_cert_handle()));
1235 const X509Certificate::OSCertHandles& return_intermediates =
1236 verify_result.verified_cert->GetIntermediateCertificates();
1237 ASSERT_EQ(2U, return_intermediates.size());
1238 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0],
1239 certs[1]->os_cert_handle()));
1240 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1],
1241 certs[2]->os_cert_handle()));
1242 }
1243
1244 #if defined(OS_MACOSX) 678 #if defined(OS_MACOSX)
1245 TEST(X509CertificateTest, IsIssuedBy) { 679 TEST(X509CertificateTest, IsIssuedBy) {
1246 FilePath certs_dir = GetTestCertsDirectory(); 680 FilePath certs_dir = GetTestCertsDirectory();
1247 681
1248 // Test a client certificate from MIT. 682 // Test a client certificate from MIT.
1249 scoped_refptr<X509Certificate> mit_davidben_cert( 683 scoped_refptr<X509Certificate> mit_davidben_cert(
1250 ImportCertFromFile(certs_dir, "mit.davidben.der")); 684 ImportCertFromFile(certs_dir, "mit.davidben.der"));
1251 ASSERT_NE(static_cast<X509Certificate*>(NULL), mit_davidben_cert); 685 ASSERT_NE(static_cast<X509Certificate*>(NULL), mit_davidben_cert);
1252 686
1253 CertPrincipal mit_issuer; 687 CertPrincipal mit_issuer;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 X509Certificate::CreateSelfSigned( 839 X509Certificate::CreateSelfSigned(
1406 private_key.get(), "CN=subject", 0, base::TimeDelta::FromDays(1)); 840 private_key.get(), "CN=subject", 0, base::TimeDelta::FromDays(1));
1407 841
1408 std::string der_cert; 842 std::string der_cert;
1409 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(), 843 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(),
1410 &der_cert)); 844 &der_cert));
1411 EXPECT_FALSE(der_cert.empty()); 845 EXPECT_FALSE(der_cert.empty());
1412 } 846 }
1413 #endif 847 #endif
1414 848
1415 #if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
1416 static const uint8 kCRLSetThawteSPKIBlocked[] = {
1417 0x8e, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
1418 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
1419 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
1420 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22,
1421 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
1422 0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
1423 0x30, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
1424 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x36, 0x58, 0x36, 0x4d, 0x78, 0x52, 0x37,
1425 0x58, 0x70, 0x4d, 0x51, 0x4b, 0x78, 0x49, 0x41, 0x39, 0x50, 0x6a, 0x36, 0x37,
1426 0x36, 0x38, 0x76, 0x74, 0x55, 0x6b, 0x6b, 0x7a, 0x48, 0x79, 0x7a, 0x41, 0x6f,
1427 0x6d, 0x6f, 0x4f, 0x68, 0x4b, 0x55, 0x6e, 0x7a, 0x73, 0x55, 0x3d, 0x22, 0x5d,
1428 0x7d,
1429 };
1430
1431 static const uint8 kCRLSetThawteSerialBlocked[] = {
1432 0x60, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
1433 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
1434 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
1435 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22,
1436 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
1437 0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
1438 0x31, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
1439 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0xb1, 0x12, 0x41, 0x42, 0xa5, 0xa1,
1440 0xa5, 0xa2, 0x88, 0x19, 0xc7, 0x35, 0x34, 0x0e, 0xff, 0x8c, 0x9e, 0x2f, 0x81,
1441 0x68, 0xfe, 0xe3, 0xba, 0x18, 0x7f, 0x25, 0x3b, 0xc1, 0xa3, 0x92, 0xd7, 0xe2,
1442 // Note that this is actually blocking two serial numbers because on XP and
1443 // Vista, CryptoAPI finds a different Thawte certificate.
1444 0x02, 0x00, 0x00, 0x00,
1445 0x04, 0x30, 0x00, 0x00, 0x02,
1446 0x04, 0x30, 0x00, 0x00, 0x06,
1447 };
1448
1449 static const uint8 kCRLSetGoogleSerialBlocked[] = {
1450 0x60, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
1451 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
1452 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
1453 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22,
1454 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
1455 0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
1456 0x31, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
1457 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0xe9, 0x7e, 0x8c, 0xc5, 0x1e, 0xd7,
1458 0xa4, 0xc4, 0x0a, 0xc4, 0x80, 0x3d, 0x3e, 0x3e, 0xbb, 0xeb, 0xcb, 0xed, 0x52,
1459 0x49, 0x33, 0x1f, 0x2c, 0xc0, 0xa2, 0x6a, 0x0e, 0x84, 0xa5, 0x27, 0xce, 0xc5,
1460 0x01, 0x00, 0x00, 0x00, 0x10, 0x4f, 0x9d, 0x96, 0xd9, 0x66, 0xb0, 0x99, 0x2b,
1461 0x54, 0xc2, 0x95, 0x7c, 0xb4, 0x15, 0x7d, 0x4d,
1462 };
1463
1464 // Test that CRLSets are effective in making a certificate appear to be
1465 // revoked.
1466 TEST(X509CertificateTest, CRLSet) {
1467 CertificateList certs = CreateCertificateListFromFile(
1468 GetTestCertsDirectory(),
1469 "googlenew.chain.pem",
1470 X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
1471
1472 X509Certificate::OSCertHandles intermediates;
1473 intermediates.push_back(certs[1]->os_cert_handle());
1474
1475 scoped_refptr<X509Certificate> google_full_chain =
1476 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
1477 intermediates);
1478
1479 CertVerifyResult verify_result;
1480 int error = google_full_chain->Verify(
1481 "www.google.com", 0, NULL, &verify_result);
1482 EXPECT_EQ(OK, error);
1483
1484 // First test blocking by SPKI.
1485 base::StringPiece crl_set_bytes(
1486 reinterpret_cast<const char*>(kCRLSetThawteSPKIBlocked),
1487 sizeof(kCRLSetThawteSPKIBlocked));
1488 scoped_refptr<CRLSet> crl_set;
1489 ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
1490
1491 error = google_full_chain->Verify(
1492 "www.google.com", 0, crl_set.get(), &verify_result);
1493 EXPECT_EQ(ERR_CERT_REVOKED, error);
1494
1495 // Second, test revocation by serial number of a cert directly under the
1496 // root.
1497 crl_set_bytes = base::StringPiece(
1498 reinterpret_cast<const char*>(kCRLSetThawteSerialBlocked),
1499 sizeof(kCRLSetThawteSerialBlocked));
1500 ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
1501
1502 error = google_full_chain->Verify(
1503 "www.google.com", 0, crl_set.get(), &verify_result);
1504 EXPECT_EQ(ERR_CERT_REVOKED, error);
1505
1506 // Lastly, test revocation by serial number of a certificate not under the
1507 // root.
1508 crl_set_bytes = base::StringPiece(
1509 reinterpret_cast<const char*>(kCRLSetGoogleSerialBlocked),
1510 sizeof(kCRLSetGoogleSerialBlocked));
1511 ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
1512
1513 error = google_full_chain->Verify(
1514 "www.google.com", 0, crl_set.get(), &verify_result);
1515 EXPECT_EQ(ERR_CERT_REVOKED, error);
1516 }
1517 #endif
1518
1519 class X509CertificateParseTest 849 class X509CertificateParseTest
1520 : public testing::TestWithParam<CertificateFormatTestData> { 850 : public testing::TestWithParam<CertificateFormatTestData> {
1521 public: 851 public:
1522 virtual ~X509CertificateParseTest() {} 852 virtual ~X509CertificateParseTest() {}
1523 virtual void SetUp() { 853 virtual void SetUp() {
1524 test_data_ = GetParam(); 854 test_data_ = GetParam();
1525 } 855 }
1526 virtual void TearDown() {} 856 virtual void TearDown() {}
1527 857
1528 protected: 858 protected:
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
1769 } 1099 }
1770 } 1100 }
1771 1101
1772 EXPECT_EQ(test_data.expected, X509Certificate::VerifyHostname( 1102 EXPECT_EQ(test_data.expected, X509Certificate::VerifyHostname(
1773 test_data.hostname, common_name, dns_names, ip_addressses)); 1103 test_data.hostname, common_name, dns_names, ip_addressses));
1774 } 1104 }
1775 1105
1776 INSTANTIATE_TEST_CASE_P(, X509CertificateNameVerifyTest, 1106 INSTANTIATE_TEST_CASE_P(, X509CertificateNameVerifyTest,
1777 testing::ValuesIn(kNameVerifyTestData)); 1107 testing::ValuesIn(kNameVerifyTestData));
1778 1108
1779 struct WeakDigestTestData {
1780 const char* root_cert_filename;
1781 const char* intermediate_cert_filename;
1782 const char* ee_cert_filename;
1783 bool expected_has_md5;
1784 bool expected_has_md4;
1785 bool expected_has_md2;
1786 bool expected_has_md5_ca;
1787 bool expected_has_md2_ca;
1788 };
1789
1790 // GTest 'magic' pretty-printer, so that if/when a test fails, it knows how
1791 // to output the parameter that was passed. Without this, it will simply
1792 // attempt to print out the first twenty bytes of the object, which depending
1793 // on platform and alignment, may result in an invalid read.
1794 void PrintTo(const WeakDigestTestData& data, std::ostream* os) {
1795 *os << "root: "
1796 << (data.root_cert_filename ? data.root_cert_filename : "none")
1797 << "; intermediate: " << data.intermediate_cert_filename
1798 << "; end-entity: " << data.ee_cert_filename;
1799 }
1800
1801 class X509CertificateWeakDigestTest
1802 : public testing::TestWithParam<WeakDigestTestData> {
1803 public:
1804 X509CertificateWeakDigestTest() {}
1805 virtual ~X509CertificateWeakDigestTest() {}
1806 };
1807
1808 TEST_P(X509CertificateWeakDigestTest, Verify) {
1809 WeakDigestTestData data = GetParam();
1810 FilePath certs_dir = GetTestCertsDirectory();
1811
1812 ScopedTestRoot test_root;
1813 if (data.root_cert_filename) {
1814 scoped_refptr<X509Certificate> root_cert =
1815 ImportCertFromFile(certs_dir, data.root_cert_filename);
1816 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert);
1817 test_root.Reset(root_cert);
1818 }
1819
1820 scoped_refptr<X509Certificate> intermediate_cert =
1821 ImportCertFromFile(certs_dir, data.intermediate_cert_filename);
1822 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert);
1823 scoped_refptr<X509Certificate> ee_cert =
1824 ImportCertFromFile(certs_dir, data.ee_cert_filename);
1825 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert);
1826
1827 X509Certificate::OSCertHandles intermediates;
1828 intermediates.push_back(intermediate_cert->os_cert_handle());
1829
1830 scoped_refptr<X509Certificate> ee_chain =
1831 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(),
1832 intermediates);
1833 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_chain);
1834
1835 int flags = 0;
1836 CertVerifyResult verify_result;
1837 int rv = ee_chain->Verify("127.0.0.1", flags, NULL, &verify_result);
1838 EXPECT_EQ(data.expected_has_md5, verify_result.has_md5);
1839 EXPECT_EQ(data.expected_has_md4, verify_result.has_md4);
1840 EXPECT_EQ(data.expected_has_md2, verify_result.has_md2);
1841 EXPECT_EQ(data.expected_has_md5_ca, verify_result.has_md5_ca);
1842 EXPECT_EQ(data.expected_has_md2_ca, verify_result.has_md2_ca);
1843
1844 // Ensure that MD4 and MD2 are tagged as invalid.
1845 if (data.expected_has_md4 || data.expected_has_md2) {
1846 EXPECT_EQ(CERT_STATUS_INVALID,
1847 verify_result.cert_status & CERT_STATUS_INVALID);
1848 }
1849
1850 // Ensure that MD5 is flagged as weak.
1851 if (data.expected_has_md5) {
1852 EXPECT_EQ(
1853 CERT_STATUS_WEAK_SIGNATURE_ALGORITHM,
1854 verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
1855 }
1856
1857 // If a root cert is present, then check that the chain was rejected if any
1858 // weak algorithms are present. This is only checked when a root cert is
1859 // present because the error reported for incomplete chains with weak
1860 // algorithms depends on which implementation was used to validate (NSS,
1861 // OpenSSL, CryptoAPI, Security.framework) and upon which weak algorithm
1862 // present (MD2, MD4, MD5).
1863 if (data.root_cert_filename) {
1864 if (data.expected_has_md4 || data.expected_has_md2) {
1865 EXPECT_EQ(ERR_CERT_INVALID, rv);
1866 } else if (data.expected_has_md5) {
1867 EXPECT_EQ(ERR_CERT_WEAK_SIGNATURE_ALGORITHM, rv);
1868 } else {
1869 EXPECT_EQ(OK, rv);
1870 }
1871 }
1872 }
1873
1874 // Unlike TEST/TEST_F, which are macros that expand to further macros,
1875 // INSTANTIATE_TEST_CASE_P is a macro that expands directly to code that
1876 // stringizes the arguments. As a result, macros passed as parameters (such as
1877 // prefix or test_case_name) will not be expanded by the preprocessor. To work
1878 // around this, indirect the macro for INSTANTIATE_TEST_CASE_P, so that the
1879 // pre-processor will expand macros such as MAYBE_test_name before
1880 // instantiating the test.
1881 #define WRAPPED_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
1882 INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator)
1883
1884 // The signature algorithm of the root CA should not matter.
1885 const WeakDigestTestData kVerifyRootCATestData[] = {
1886 { "weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem",
1887 "weak_digest_sha1_ee.pem", false, false, false, false, false },
1888 #if !defined(OS_MACOSX) // MD4 is not supported.
1889 { "weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem",
1890 "weak_digest_sha1_ee.pem", false, false, false, false, false },
1891 #endif
1892 { "weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem",
1893 "weak_digest_sha1_ee.pem", false, false, false, false, false },
1894 };
1895 INSTANTIATE_TEST_CASE_P(VerifyRoot, X509CertificateWeakDigestTest,
1896 testing::ValuesIn(kVerifyRootCATestData));
1897
1898 // The signature algorithm of intermediates should be properly detected.
1899 const WeakDigestTestData kVerifyIntermediateCATestData[] = {
1900 { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem",
1901 "weak_digest_sha1_ee.pem", true, false, false, true, false },
1902 #if !defined(USE_NSS) && !defined(OS_MACOSX) // MD4 is not supported.
1903 { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
1904 "weak_digest_sha1_ee.pem", false, true, false, false, false },
1905 #endif
1906 #if !defined(USE_NSS) // MD2 is disabled by default.
1907 { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
1908 "weak_digest_sha1_ee.pem", false, false, true, false, true },
1909 #endif
1910 };
1911 INSTANTIATE_TEST_CASE_P(VerifyIntermediate, X509CertificateWeakDigestTest,
1912 testing::ValuesIn(kVerifyIntermediateCATestData));
1913
1914 // The signature algorithm of end-entity should be properly detected.
1915 const WeakDigestTestData kVerifyEndEntityTestData[] = {
1916 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
1917 "weak_digest_md5_ee.pem", true, false, false, false, false },
1918 #if !defined(USE_NSS) && !defined(OS_MACOSX) // MD4 is not supported.
1919 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
1920 "weak_digest_md4_ee.pem", false, true, false, false, false },
1921 #endif
1922 #if !defined(USE_NSS) // MD2 is disabled by default.
1923 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
1924 "weak_digest_md2_ee.pem", false, false, true, false, false },
1925 #endif
1926 };
1927 // Disabled on NSS - NSS caches chains/signatures in such a way that cannot
1928 // be cleared until NSS is cleanly shutdown, which is not presently supported
1929 // in Chromium.
1930 #if defined(USE_NSS)
1931 #define MAYBE_VerifyEndEntity DISABLED_VerifyEndEntity
1932 #else
1933 #define MAYBE_VerifyEndEntity VerifyEndEntity
1934 #endif
1935 WRAPPED_INSTANTIATE_TEST_CASE_P(MAYBE_VerifyEndEntity,
1936 X509CertificateWeakDigestTest,
1937 testing::ValuesIn(kVerifyEndEntityTestData));
1938
1939 // Incomplete chains should still report the status of the intermediate.
1940 const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = {
1941 { NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem",
1942 true, false, false, true, false },
1943 #if !defined(OS_MACOSX) // MD4 is not supported.
1944 { NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem",
1945 false, true, false, false, false },
1946 #endif
1947 { NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem",
1948 false, false, true, false, true },
1949 };
1950 // Disabled on NSS - libpkix does not return constructed chains on error,
1951 // preventing us from detecting/inspecting the verified chain.
1952 #if defined(USE_NSS)
1953 #define MAYBE_VerifyIncompleteIntermediate \
1954 DISABLED_VerifyIncompleteIntermediate
1955 #else
1956 #define MAYBE_VerifyIncompleteIntermediate VerifyIncompleteIntermediate
1957 #endif
1958 WRAPPED_INSTANTIATE_TEST_CASE_P(
1959 MAYBE_VerifyIncompleteIntermediate,
1960 X509CertificateWeakDigestTest,
1961 testing::ValuesIn(kVerifyIncompleteIntermediateTestData));
1962
1963 // Incomplete chains should still report the status of the end-entity.
1964 const WeakDigestTestData kVerifyIncompleteEETestData[] = {
1965 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem",
1966 true, false, false, false, false },
1967 #if !defined(OS_MACOSX) // MD4 is not supported.
1968 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem",
1969 false, true, false, false, false },
1970 #endif
1971 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md2_ee.pem",
1972 false, false, true, false, false },
1973 };
1974 // Disabled on NSS - libpkix does not return constructed chains on error,
1975 // preventing us from detecting/inspecting the verified chain.
1976 #if defined(USE_NSS)
1977 #define MAYBE_VerifyIncompleteEndEntity DISABLED_VerifyIncompleteEndEntity
1978 #else
1979 #define MAYBE_VerifyIncompleteEndEntity VerifyIncompleteEndEntity
1980 #endif
1981 WRAPPED_INSTANTIATE_TEST_CASE_P(
1982 MAYBE_VerifyIncompleteEndEntity,
1983 X509CertificateWeakDigestTest,
1984 testing::ValuesIn(kVerifyIncompleteEETestData));
1985
1986 // Differing algorithms between the intermediate and the EE should still be
1987 // reported.
1988 const WeakDigestTestData kVerifyMixedTestData[] = {
1989 { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem",
1990 "weak_digest_md2_ee.pem", true, false, true, true, false },
1991 { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
1992 "weak_digest_md5_ee.pem", true, false, true, false, true },
1993 #if !defined(OS_MACOSX) // MD4 is not supported.
1994 { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
1995 "weak_digest_md2_ee.pem", false, true, true, false, false },
1996 #endif
1997 };
1998 // NSS does not support MD4 and does not enable MD2 by default, making all
1999 // permutations invalid.
2000 #if defined(USE_NSS)
2001 #define MAYBE_VerifyMixed DISABLED_VerifyMixed
2002 #else
2003 #define MAYBE_VerifyMixed VerifyMixed
2004 #endif
2005 WRAPPED_INSTANTIATE_TEST_CASE_P(
2006 MAYBE_VerifyMixed,
2007 X509CertificateWeakDigestTest,
2008 testing::ValuesIn(kVerifyMixedTestData));
2009
2010 } // namespace net 1109 } // namespace net
OLDNEW
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698