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

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

Issue 8568040: Refuse to accept certificate chains containing any RSA public key smaller (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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/file_util.h"
7 #include "base/path_service.h" 7 #include "base/path_service.h"
8 #include "base/pickle.h" 8 #include "base/pickle.h"
9 #include "base/sha1.h" 9 #include "base/sha1.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
11 #include "base/string_split.h" 11 #include "base/string_split.h"
12 #include "crypto/rsa_private_key.h" 12 #include "crypto/rsa_private_key.h"
13 #include "net/base/asn1_util.h" 13 #include "net/base/asn1_util.h"
14 #include "net/base/cert_status_flags.h" 14 #include "net/base/cert_status_flags.h"
15 #include "net/base/cert_test_util.h" 15 #include "net/base/cert_test_util.h"
16 #include "net/base/cert_verify_result.h" 16 #include "net/base/cert_verify_result.h"
17 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
18 #include "net/base/test_certificate_data.h" 18 #include "net/base/test_certificate_data.h"
19 #include "net/base/test_root_certs.h" 19 #include "net/base/test_root_certs.h"
20 #include "net/base/x509_certificate.h" 20 #include "net/base/x509_certificate.h"
21 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
22 22
23 #if defined(USE_NSS) 23 #if defined(USE_NSS)
24 #include <cert.h> 24 #include <cert.h>
25 #endif 25 #endif
26 26
27 #if defined(OS_WIN)
28 #include "base/win/windows_version.h"
29 #elif defined(OS_MACOSX)
30 #include "base/mac/mac_util.h"
31 #endif
32
27 // Unit tests aren't allowed to access external resources. Unfortunately, to 33 // Unit tests aren't allowed to access external resources. Unfortunately, to
28 // properly verify the EV-ness of a cert, we need to check for its revocation 34 // properly verify the EV-ness of a cert, we need to check for its revocation
29 // through online servers. If you're manually running unit tests, feel free to 35 // through online servers. If you're manually running unit tests, feel free to
30 // turn this on to test EV certs. But leave it turned off for the automated 36 // turn this on to test EV certs. But leave it turned off for the automated
31 // testing. 37 // testing.
32 #define ALLOW_EXTERNAL_ACCESS 0 38 #define ALLOW_EXTERNAL_ACCESS 0
33 39
34 #if ALLOW_EXTERNAL_ACCESS && defined(OS_WIN) 40 #if ALLOW_EXTERNAL_ACCESS && defined(OS_WIN)
35 #define TEST_EV 1 // Test CERT_STATUS_IS_EV 41 #define TEST_EV 1 // Test CERT_STATUS_IS_EV
36 #endif 42 #endif
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 int flags = X509Certificate::VERIFY_REV_CHECKING_ENABLED | 610 int flags = X509Certificate::VERIFY_REV_CHECKING_ENABLED |
605 X509Certificate::VERIFY_EV_CERT; 611 X509Certificate::VERIFY_EV_CERT;
606 int error = cert_chain->Verify("2029.globalsign.com", flags, NULL, 612 int error = cert_chain->Verify("2029.globalsign.com", flags, NULL,
607 &verify_result); 613 &verify_result);
608 if (error == OK) 614 if (error == OK)
609 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV); 615 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
610 else 616 else
611 EXPECT_EQ(ERR_CERT_DATE_INVALID, error); 617 EXPECT_EQ(ERR_CERT_DATE_INVALID, error);
612 } 618 }
613 619
620 // Currently, only RSA and DSA keys are checked for weakness, and our example
621 // weak size is 768. These could change in the future.
622 //
623 // Note that this means there may be false negatives: keys for other
624 // algorithms and which are weak will pass this test.
625 static bool IsWeakKeyType(const std::string& key_type) {
626 size_t pos = key_type.find("-");
627 std::string size = key_type.substr(0, pos);
628 std::string type = key_type.substr(pos + 1);
629
630 if (type == "rsa" || type == "dsa")
631 return size == "768";
632
633 return false;
634 }
635
636 TEST(X509CertificateTest, RejectWeakKeys) {
637 FilePath certs_dir = GetTestCertsDirectory();
638 typedef std::vector<std::string> Strings;
639 Strings key_types;
640
641 // generate-weak-test-chains.sh currently has:
642 // key_types="768-rsa 1024-rsa 2048-rsa prime256v1-ecdsa"
643 // We must use the same key types here. The filenames generated look like:
644 // 2048-rsa-ee-by-768-rsa-intermediate.pem
645 key_types.push_back("768-rsa");
646 key_types.push_back("1024-rsa");
647 key_types.push_back("2048-rsa");
648
649 bool use_ecdsa = true;
650 #if defined(OS_WIN)
651 use_ecdsa = base::win::GetVersion() > base::win::VERSION_XP;
652 #elif defined(OS_MACOSX)
653 use_ecdsa = base::mac::IsOSSnowLeopardOrLater();
654 #endif
655
656 if (use_ecdsa)
657 key_types.push_back("prime256v1-ecdsa");
658
659 // Add the root that signed the intermediates for this test.
660 scoped_refptr<X509Certificate> root_cert =
661 ImportCertFromFile(certs_dir, "2048-rsa-root.pem");
662 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert);
663 TestRootCerts::GetInstance()->Add(root_cert.get());
664
665 // Now test each chain.
666 for (Strings::const_iterator ee_type = key_types.begin();
667 ee_type != key_types.end(); ++ee_type) {
668 for (Strings::const_iterator signer_type = key_types.begin();
669 signer_type != key_types.end(); ++signer_type) {
670 std::string basename = *ee_type + "-ee-by-" + *signer_type +
671 "-intermediate.pem";
672 scoped_refptr<X509Certificate> ee_cert =
673 ImportCertFromFile(certs_dir, basename);
674 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert);
675
676 basename = *signer_type + "-intermediate.pem";
677 scoped_refptr<X509Certificate> intermediate =
678 ImportCertFromFile(certs_dir, basename);
679 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate);
680
681 X509Certificate::OSCertHandles intermediates;
682 intermediates.push_back(intermediate->os_cert_handle());
683 scoped_refptr<X509Certificate> cert_chain =
684 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(),
685 intermediates);
686
687 CertVerifyResult verify_result;
688 int error = cert_chain->Verify("127.0.0.1", 0, NULL, &verify_result);
689
690 if (IsWeakKeyType(*ee_type) || IsWeakKeyType(*signer_type)) {
691 EXPECT_NE(OK, error);
692 EXPECT_EQ(CERT_STATUS_WEAK_KEY,
693 verify_result.cert_status & CERT_STATUS_WEAK_KEY);
694 } else {
695 EXPECT_EQ(OK, error);
696 EXPECT_EQ(0U, verify_result.cert_status & CERT_STATUS_WEAK_KEY);
697 }
698 }
699 }
700
701 TestRootCerts::GetInstance()->Clear();
702 }
703
614 // Test for bug 94673. 704 // Test for bug 94673.
615 TEST(X509CertificateTest, GoogleDigiNotarTest) { 705 TEST(X509CertificateTest, GoogleDigiNotarTest) {
616 FilePath certs_dir = GetTestCertsDirectory(); 706 FilePath certs_dir = GetTestCertsDirectory();
617 707
618 scoped_refptr<X509Certificate> server_cert = 708 scoped_refptr<X509Certificate> server_cert =
619 ImportCertFromFile(certs_dir, "google_diginotar.pem"); 709 ImportCertFromFile(certs_dir, "google_diginotar.pem");
620 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); 710 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
621 711
622 scoped_refptr<X509Certificate> intermediate_cert = 712 scoped_refptr<X509Certificate> intermediate_cert =
623 ImportCertFromFile(certs_dir, "diginotar_public_ca_2025.pem"); 713 ImportCertFromFile(certs_dir, "diginotar_public_ca_2025.pem");
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(), 810 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(),
721 &derBytes)); 811 &derBytes));
722 812
723 base::StringPiece spkiBytes; 813 base::StringPiece spkiBytes;
724 EXPECT_TRUE(asn1::ExtractSPKIFromDERCert(derBytes, &spkiBytes)); 814 EXPECT_TRUE(asn1::ExtractSPKIFromDERCert(derBytes, &spkiBytes));
725 815
726 uint8 hash[base::kSHA1Length]; 816 uint8 hash[base::kSHA1Length];
727 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spkiBytes.data()), 817 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spkiBytes.data()),
728 spkiBytes.size(), hash); 818 spkiBytes.size(), hash);
729 819
730 EXPECT_TRUE(0 == memcmp(hash, nistSPKIHash, sizeof(hash))); 820 EXPECT_EQ(0, memcmp(hash, nistSPKIHash, sizeof(hash)));
731 } 821 }
732 822
733 TEST(X509CertificateTest, ExtractCRLURLsFromDERCert) { 823 TEST(X509CertificateTest, ExtractCRLURLsFromDERCert) {
734 FilePath certs_dir = GetTestCertsDirectory(); 824 FilePath certs_dir = GetTestCertsDirectory();
735 scoped_refptr<X509Certificate> cert = 825 scoped_refptr<X509Certificate> cert =
736 ImportCertFromFile(certs_dir, "nist.der"); 826 ImportCertFromFile(certs_dir, "nist.der");
737 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert); 827 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert);
738 828
739 std::string derBytes; 829 std::string derBytes;
740 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(), 830 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(),
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 { true, "f", "f" }, 1465 { true, "f", "f" },
1376 { false, "h", "i" }, 1466 { false, "h", "i" },
1377 { true, "bar.foo.com", "*.foo.com" }, 1467 { true, "bar.foo.com", "*.foo.com" },
1378 { true, "www.test.fr", "common.name", 1468 { true, "www.test.fr", "common.name",
1379 "*.test.com,*.test.co.uk,*.test.de,*.test.fr" }, 1469 "*.test.com,*.test.co.uk,*.test.de,*.test.fr" },
1380 { true, "wwW.tESt.fr", "common.name", 1470 { true, "wwW.tESt.fr", "common.name",
1381 ",*.*,*.test.de,*.test.FR,www" }, 1471 ",*.*,*.test.de,*.test.FR,www" },
1382 { false, "f.uk", ".uk" }, 1472 { false, "f.uk", ".uk" },
1383 { false, "w.bar.foo.com", "?.bar.foo.com" }, 1473 { false, "w.bar.foo.com", "?.bar.foo.com" },
1384 { false, "www.foo.com", "(www|ftp).foo.com" }, 1474 { false, "www.foo.com", "(www|ftp).foo.com" },
1385 { false, "www.foo.com", "www.foo.com#" }, // # = null char. 1475 { false, "www.foo.com", "www.foo.com#" }, // # = null char.
1386 { false, "www.foo.com", "", "www.foo.com#*.foo.com,#,#" }, 1476 { false, "www.foo.com", "", "www.foo.com#*.foo.com,#,#" },
1387 { false, "www.house.example", "ww.house.example" }, 1477 { false, "www.house.example", "ww.house.example" },
1388 { false, "test.org", "", "www.test.org,*.test.org,*.org" }, 1478 { false, "test.org", "", "www.test.org,*.test.org,*.org" },
1389 { false, "w.bar.foo.com", "w*.bar.foo.com" }, 1479 { false, "w.bar.foo.com", "w*.bar.foo.com" },
1390 { false, "www.bar.foo.com", "ww*ww.bar.foo.com" }, 1480 { false, "www.bar.foo.com", "ww*ww.bar.foo.com" },
1391 { false, "wwww.bar.foo.com", "ww*ww.bar.foo.com" }, 1481 { false, "wwww.bar.foo.com", "ww*ww.bar.foo.com" },
1392 { true, "wwww.bar.foo.com", "w*w.bar.foo.com" }, 1482 { true, "wwww.bar.foo.com", "w*w.bar.foo.com" },
1393 { false, "wwww.bar.foo.com", "w*w.bar.foo.c0m" }, 1483 { false, "wwww.bar.foo.com", "w*w.bar.foo.c0m" },
1394 { true, "WALLY.bar.foo.com", "wa*.bar.foo.com" }, 1484 { true, "WALLY.bar.foo.com", "wa*.bar.foo.com" },
1395 { true, "wally.bar.foo.com", "*Ly.bar.foo.com" }, 1485 { true, "wally.bar.foo.com", "*Ly.bar.foo.com" },
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 } 1603 }
1514 1604
1515 if (test_data.ip_addrs) { 1605 if (test_data.ip_addrs) {
1516 // Build up the certificate IP address list. 1606 // Build up the certificate IP address list.
1517 std::string ip_addrs_line(test_data.ip_addrs); 1607 std::string ip_addrs_line(test_data.ip_addrs);
1518 std::vector<std::string> ip_addressses_ascii; 1608 std::vector<std::string> ip_addressses_ascii;
1519 base::SplitString(ip_addrs_line, ',', &ip_addressses_ascii); 1609 base::SplitString(ip_addrs_line, ',', &ip_addressses_ascii);
1520 for (size_t i = 0; i < ip_addressses_ascii.size(); ++i) { 1610 for (size_t i = 0; i < ip_addressses_ascii.size(); ++i) {
1521 std::string& addr_ascii = ip_addressses_ascii[i]; 1611 std::string& addr_ascii = ip_addressses_ascii[i];
1522 ASSERT_NE(0U, addr_ascii.length()); 1612 ASSERT_NE(0U, addr_ascii.length());
1523 if (addr_ascii[0] == 'x') { // Hex encoded address 1613 if (addr_ascii[0] == 'x') { // Hex encoded address
1524 addr_ascii.erase(0, 1); 1614 addr_ascii.erase(0, 1);
1525 std::vector<uint8> bytes; 1615 std::vector<uint8> bytes;
1526 EXPECT_TRUE(base::HexStringToBytes(addr_ascii, &bytes)) 1616 EXPECT_TRUE(base::HexStringToBytes(addr_ascii, &bytes))
1527 << "Could not parse hex address " << addr_ascii << " i = " << i; 1617 << "Could not parse hex address " << addr_ascii << " i = " << i;
1528 ip_addressses.push_back(std::string(reinterpret_cast<char*>(&bytes[0]), 1618 ip_addressses.push_back(std::string(reinterpret_cast<char*>(&bytes[0]),
1529 bytes.size())); 1619 bytes.size()));
1530 ASSERT_EQ(16U, ip_addressses.back().size()) << i; 1620 ASSERT_EQ(16U, ip_addressses.back().size()) << i;
1531 } else { // Decimal groups 1621 } else { // Decimal groups
1532 std::vector<std::string> decimals_ascii; 1622 std::vector<std::string> decimals_ascii;
1533 base::SplitString(addr_ascii, '.', &decimals_ascii); 1623 base::SplitString(addr_ascii, '.', &decimals_ascii);
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
1780 #define MAYBE_VerifyMixed DISABLED_VerifyMixed 1870 #define MAYBE_VerifyMixed DISABLED_VerifyMixed
1781 #else 1871 #else
1782 #define MAYBE_VerifyMixed VerifyMixed 1872 #define MAYBE_VerifyMixed VerifyMixed
1783 #endif 1873 #endif
1784 WRAPPED_INSTANTIATE_TEST_CASE_P( 1874 WRAPPED_INSTANTIATE_TEST_CASE_P(
1785 MAYBE_VerifyMixed, 1875 MAYBE_VerifyMixed,
1786 X509CertificateWeakDigestTest, 1876 X509CertificateWeakDigestTest,
1787 testing::ValuesIn(kVerifyMixedTestData)); 1877 testing::ValuesIn(kVerifyMixedTestData));
1788 1878
1789 } // namespace net 1879 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698