| OLD | NEW |
| 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 "net/cert/cert_verify_proc.h" | 5 #include "net/cert/cert_verify_proc.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #include "net/test/test_data_directory.h" | 32 #include "net/test/test_data_directory.h" |
| 33 #include "testing/gmock/include/gmock/gmock.h" | 33 #include "testing/gmock/include/gmock/gmock.h" |
| 34 #include "testing/gtest/include/gtest/gtest.h" | 34 #include "testing/gtest/include/gtest/gtest.h" |
| 35 | 35 |
| 36 #if defined(OS_ANDROID) | 36 #if defined(OS_ANDROID) |
| 37 #include "base/android/build_info.h" | 37 #include "base/android/build_info.h" |
| 38 #endif | 38 #endif |
| 39 | 39 |
| 40 #if defined(OS_MACOSX) && !defined(OS_IOS) | 40 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 41 #include "base/mac/mac_util.h" | 41 #include "base/mac/mac_util.h" |
| 42 #include "net/cert/test_keychain_search_list_mac.h" | |
| 43 #endif | 42 #endif |
| 44 | 43 |
| 45 #if defined(OS_WIN) | 44 #if defined(OS_WIN) |
| 46 #include "base/win/windows_version.h" | 45 #include "base/win/windows_version.h" |
| 47 #endif | 46 #endif |
| 48 | 47 |
| 49 using net::test::IsError; | 48 using net::test::IsError; |
| 50 using net::test::IsOk; | 49 using net::test::IsOk; |
| 51 | 50 |
| 52 using base::HexEncode; | 51 using base::HexEncode; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 } | 134 } |
| 136 | 135 |
| 137 // Whether the test is running within the iphone simulator. | 136 // Whether the test is running within the iphone simulator. |
| 138 const bool kTargetIsIphoneSimulator = | 137 const bool kTargetIsIphoneSimulator = |
| 139 #if TARGET_IPHONE_SIMULATOR | 138 #if TARGET_IPHONE_SIMULATOR |
| 140 true; | 139 true; |
| 141 #else | 140 #else |
| 142 false; | 141 false; |
| 143 #endif | 142 #endif |
| 144 | 143 |
| 145 // Template helper to load a series of certificate files into a CertificateList. | |
| 146 // Like CertTestUtil's CreateCertificateListFromFile, except it can load a | |
| 147 // series of individual certificates (to make the tests clearer). | |
| 148 template <size_t N> | |
| 149 void LoadCertificateFiles(const char* const (&cert_files)[N], | |
| 150 CertificateList* certs) { | |
| 151 certs->clear(); | |
| 152 for (size_t i = 0; i < N; ++i) { | |
| 153 SCOPED_TRACE(cert_files[i]); | |
| 154 scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile( | |
| 155 GetTestCertsDirectory(), cert_files[i], X509Certificate::FORMAT_AUTO); | |
| 156 ASSERT_TRUE(cert); | |
| 157 certs->push_back(cert); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 // Returns a textual description of the CertVerifyProc implementation | 144 // Returns a textual description of the CertVerifyProc implementation |
| 162 // that is being tested, used to give better names to parameterized | 145 // that is being tested, used to give better names to parameterized |
| 163 // tests. | 146 // tests. |
| 164 std::string VerifyProcTypeToName( | 147 std::string VerifyProcTypeToName( |
| 165 const testing::TestParamInfo<CertVerifyProcType>& params) { | 148 const testing::TestParamInfo<CertVerifyProcType>& params) { |
| 166 switch (params.param) { | 149 switch (params.param) { |
| 167 case CERT_VERIFY_PROC_NSS: | 150 case CERT_VERIFY_PROC_NSS: |
| 168 return "CertVerifyProcNSS"; | 151 return "CertVerifyProcNSS"; |
| 169 case CERT_VERIFY_PROC_OPENSSL: | 152 case CERT_VERIFY_PROC_OPENSSL: |
| 170 return "CertVerifyProcOpenSSL"; | 153 return "CertVerifyProcOpenSSL"; |
| (...skipping 1208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 ASSERT_TRUE(intermediate); | 1362 ASSERT_TRUE(intermediate); |
| 1380 | 1363 |
| 1381 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) | 1364 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) |
| 1382 << "Expected: " << testcase.expected_intermediate->subject().common_name | 1365 << "Expected: " << testcase.expected_intermediate->subject().common_name |
| 1383 << " issued by " << testcase.expected_intermediate->issuer().common_name | 1366 << " issued by " << testcase.expected_intermediate->issuer().common_name |
| 1384 << "; Got: " << intermediate->subject().common_name << " issued by " | 1367 << "; Got: " << intermediate->subject().common_name << " issued by " |
| 1385 << intermediate->issuer().common_name; | 1368 << intermediate->issuer().common_name; |
| 1386 } | 1369 } |
| 1387 } | 1370 } |
| 1388 | 1371 |
| 1389 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 1390 // Test that a CRLSet blocking one of the intermediates supplied by the server | |
| 1391 // can be worked around by the chopping workaround for path building. (Once the | |
| 1392 // supplied chain is chopped back to just the target, a better path can be | |
| 1393 // found out-of-band. Normally that would be by AIA fetching, for the purposes | |
| 1394 // of this test the better path is supplied by a test keychain.) | |
| 1395 // | |
| 1396 // In this test, there are two possible paths to validate a leaf (A): | |
| 1397 // 1. A(B) -> B(C) -> C(E) -> E(E) | |
| 1398 // 2. A(B) -> B(F) -> F(E) -> E(E) | |
| 1399 // | |
| 1400 // A(B) -> B(C) -> C(E) is supplied to the verifier. | |
| 1401 // B(F) and F(E) are supplied in a test keychain. | |
| 1402 // C is blocked by a CRLset. | |
| 1403 // | |
| 1404 // The verifier should rollback until it just tries A(B) alone, at which point | |
| 1405 // it will pull B(F) & F(E) from the keychain and succeed. | |
| 1406 TEST(CertVerifyProcMacTest, MacCRLIntermediate) { | |
| 1407 if (base::mac::IsAtLeastOS10_12()) { | |
| 1408 // TODO(crbug.com/671889): Investigate SecTrustSetKeychains issue on Sierra. | |
| 1409 LOG(INFO) << "Skipping test, SecTrustSetKeychains does not work on 10.12"; | |
| 1410 return; | |
| 1411 } | |
| 1412 const char* const kPath2Files[] = { | |
| 1413 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-E.pem", | |
| 1414 "multi-root-E-by-E.pem"}; | |
| 1415 CertificateList path_2_certs; | |
| 1416 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath2Files, &path_2_certs)); | |
| 1417 | |
| 1418 const char* const kPath3Files[] = { | |
| 1419 "multi-root-A-by-B.pem", "multi-root-B-by-F.pem", "multi-root-F-by-E.pem", | |
| 1420 "multi-root-E-by-E.pem"}; | |
| 1421 | |
| 1422 CertificateList path_3_certs; | |
| 1423 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath3Files, &path_3_certs)); | |
| 1424 | |
| 1425 // Add E as trust anchor. | |
| 1426 ScopedTestRoot test_root_E(path_3_certs[3].get()); // E-by-E | |
| 1427 | |
| 1428 X509Certificate::OSCertHandles intermediates; | |
| 1429 intermediates.push_back(path_2_certs[1]->os_cert_handle()); // B-by-C | |
| 1430 intermediates.push_back(path_2_certs[2]->os_cert_handle()); // C-by-E | |
| 1431 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
| 1432 path_3_certs[0]->os_cert_handle(), intermediates); | |
| 1433 ASSERT_TRUE(cert); | |
| 1434 | |
| 1435 std::unique_ptr<TestKeychainSearchList> test_keychain_search_list( | |
| 1436 TestKeychainSearchList::Create()); | |
| 1437 ASSERT_TRUE(test_keychain_search_list); | |
| 1438 | |
| 1439 base::FilePath keychain_path( | |
| 1440 GetTestCertsDirectory().AppendASCII("multi-root-BFE.keychain")); | |
| 1441 // SecKeychainOpen does not fail if the file doesn't exist, so assert it here | |
| 1442 // for easier debugging. | |
| 1443 ASSERT_TRUE(base::PathExists(keychain_path)); | |
| 1444 SecKeychainRef keychain; | |
| 1445 OSStatus status = | |
| 1446 SecKeychainOpen(keychain_path.MaybeAsASCII().c_str(), &keychain); | |
| 1447 ASSERT_EQ(errSecSuccess, status); | |
| 1448 ASSERT_TRUE(keychain); | |
| 1449 base::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); | |
| 1450 test_keychain_search_list->AddKeychain(keychain); | |
| 1451 | |
| 1452 scoped_refptr<CRLSet> crl_set; | |
| 1453 std::string crl_set_bytes; | |
| 1454 // CRL which blocks C by SPKI. | |
| 1455 EXPECT_TRUE(base::ReadFileToString( | |
| 1456 GetTestCertsDirectory().AppendASCII("multi-root-crlset-C.raw"), | |
| 1457 &crl_set_bytes)); | |
| 1458 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1459 | |
| 1460 int flags = 0; | |
| 1461 CertVerifyResult verify_result; | |
| 1462 | |
| 1463 scoped_refptr<CertVerifyProc> verify_proc = CertVerifyProc::CreateDefault(); | |
| 1464 int error = | |
| 1465 verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1466 crl_set.get(), CertificateList(), &verify_result); | |
| 1467 | |
| 1468 ASSERT_EQ(OK, error); | |
| 1469 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1470 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1471 | |
| 1472 const X509Certificate::OSCertHandles& verified_intermediates = | |
| 1473 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1474 ASSERT_EQ(3U, verified_intermediates.size()); | |
| 1475 | |
| 1476 scoped_refptr<X509Certificate> intermediate = | |
| 1477 X509Certificate::CreateFromHandle(verified_intermediates[1], | |
| 1478 X509Certificate::OSCertHandles()); | |
| 1479 ASSERT_TRUE(intermediate); | |
| 1480 | |
| 1481 scoped_refptr<X509Certificate> expected_intermediate = path_3_certs[2]; | |
| 1482 EXPECT_TRUE(expected_intermediate->Equals(intermediate.get())) | |
| 1483 << "Expected: " << expected_intermediate->subject().common_name | |
| 1484 << " issued by " << expected_intermediate->issuer().common_name | |
| 1485 << "; Got: " << intermediate->subject().common_name << " issued by " | |
| 1486 << intermediate->issuer().common_name; | |
| 1487 } | |
| 1488 | |
| 1489 // Test that if a keychain is present which trusts a less-desirable root (ex, | |
| 1490 // one using SHA1), that the keychain reordering hack will cause the better | |
| 1491 // root in the System Roots to be used instead. | |
| 1492 TEST(CertVerifyProcMacTest, MacKeychainReordering) { | |
| 1493 // Note: target cert expires Apr 2 23:59:59 2018 GMT | |
| 1494 scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile( | |
| 1495 GetTestCertsDirectory(), "tripadvisor-verisign-chain.pem", | |
| 1496 X509Certificate::FORMAT_AUTO); | |
| 1497 ASSERT_TRUE(cert); | |
| 1498 | |
| 1499 // Create a test keychain search list that will Always Trust the SHA1 | |
| 1500 // cross-signed VeriSign Class 3 Public Primary Certification Authority - G5 | |
| 1501 std::unique_ptr<TestKeychainSearchList> test_keychain_search_list( | |
| 1502 TestKeychainSearchList::Create()); | |
| 1503 ASSERT_TRUE(test_keychain_search_list); | |
| 1504 | |
| 1505 base::FilePath keychain_path(GetTestCertsDirectory().AppendASCII( | |
| 1506 "verisign_class3_g5_crosssigned-trusted.keychain")); | |
| 1507 // SecKeychainOpen does not fail if the file doesn't exist, so assert it here | |
| 1508 // for easier debugging. | |
| 1509 ASSERT_TRUE(base::PathExists(keychain_path)); | |
| 1510 SecKeychainRef keychain; | |
| 1511 OSStatus status = | |
| 1512 SecKeychainOpen(keychain_path.MaybeAsASCII().c_str(), &keychain); | |
| 1513 ASSERT_EQ(errSecSuccess, status); | |
| 1514 ASSERT_TRUE(keychain); | |
| 1515 base::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); | |
| 1516 test_keychain_search_list->AddKeychain(keychain); | |
| 1517 | |
| 1518 int flags = 0; | |
| 1519 CertVerifyResult verify_result; | |
| 1520 scoped_refptr<CertVerifyProc> verify_proc = CertVerifyProc::CreateDefault(); | |
| 1521 int error = verify_proc->Verify(cert.get(), "www.tripadvisor.com", | |
| 1522 std::string(), flags, nullptr /* crl_set */, | |
| 1523 CertificateList(), &verify_result); | |
| 1524 | |
| 1525 ASSERT_EQ(OK, error); | |
| 1526 EXPECT_EQ(0U, verify_result.cert_status); | |
| 1527 EXPECT_FALSE(verify_result.has_sha1); | |
| 1528 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1529 | |
| 1530 const X509Certificate::OSCertHandles& verified_intermediates = | |
| 1531 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1532 ASSERT_EQ(2U, verified_intermediates.size()); | |
| 1533 } | |
| 1534 | |
| 1535 // Test that the system root certificate keychain is in the expected location | |
| 1536 // and can be opened. Other tests would fail if this was not true, but this | |
| 1537 // test makes the reason for the failure obvious. | |
| 1538 TEST(CertVerifyProcMacTest, MacSystemRootCertificateKeychainLocation) { | |
| 1539 const char* root_keychain_path = | |
| 1540 "/System/Library/Keychains/SystemRootCertificates.keychain"; | |
| 1541 ASSERT_TRUE(base::PathExists(base::FilePath(root_keychain_path))); | |
| 1542 | |
| 1543 SecKeychainRef keychain; | |
| 1544 OSStatus status = SecKeychainOpen(root_keychain_path, &keychain); | |
| 1545 ASSERT_EQ(errSecSuccess, status); | |
| 1546 CFRelease(keychain); | |
| 1547 } | |
| 1548 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | |
| 1549 | |
| 1550 // TODO(crbug.com/649017): This is not parameterized by the CertVerifyProc | 1372 // TODO(crbug.com/649017): This is not parameterized by the CertVerifyProc |
| 1551 // because the CertVerifyProc::Verify() does this unconditionally based on the | 1373 // because the CertVerifyProc::Verify() does this unconditionally based on the |
| 1552 // platform. | 1374 // platform. |
| 1553 bool AreSHA1IntermediatesAllowed() { | 1375 bool AreSHA1IntermediatesAllowed() { |
| 1554 #if defined(OS_WIN) | 1376 #if defined(OS_WIN) |
| 1555 // TODO(rsleevi): Remove this once https://crbug.com/588789 is resolved | 1377 // TODO(rsleevi): Remove this once https://crbug.com/588789 is resolved |
| 1556 // for Windows 7/2008 users. | 1378 // for Windows 7/2008 users. |
| 1557 // Note: This must be kept in sync with cert_verify_proc.cc | 1379 // Note: This must be kept in sync with cert_verify_proc.cc |
| 1558 return base::win::GetVersion() < base::win::VERSION_WIN8; | 1380 return base::win::GetVersion() < base::win::VERSION_WIN8; |
| 1559 #else | 1381 #else |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1989 // Should not match the dNSName SAN | 1811 // Should not match the dNSName SAN |
| 1990 TEST_P(CertVerifyProcNameTest, DoesntMatchDnsSanTrailingDot) { | 1812 TEST_P(CertVerifyProcNameTest, DoesntMatchDnsSanTrailingDot) { |
| 1991 VerifyCertName(".test.example", false); | 1813 VerifyCertName(".test.example", false); |
| 1992 } | 1814 } |
| 1993 | 1815 |
| 1994 INSTANTIATE_TEST_CASE_P(VerifyName, | 1816 INSTANTIATE_TEST_CASE_P(VerifyName, |
| 1995 CertVerifyProcNameTest, | 1817 CertVerifyProcNameTest, |
| 1996 testing::ValuesIn(kAllCertVerifiers), | 1818 testing::ValuesIn(kAllCertVerifiers), |
| 1997 VerifyProcTypeToName); | 1819 VerifyProcTypeToName); |
| 1998 | 1820 |
| 1999 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 2000 // Test that CertVerifyProcMac reacts appropriately when Apple's certificate | |
| 2001 // verifier rejects a certificate with a fatal error. This is a regression | |
| 2002 // test for https://crbug.com/472291. | |
| 2003 // (Since 10.12, this causes a recoverable error instead of a fatal one.) | |
| 2004 // TODO(mattm): Try to find a different way to cause a fatal error that works | |
| 2005 // on 10.12. | |
| 2006 TEST(CertVerifyProcMacTest, LargeKey) { | |
| 2007 // Load root_ca_cert.pem into the test root store. | |
| 2008 ScopedTestRoot test_root( | |
| 2009 ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem").get()); | |
| 2010 | |
| 2011 scoped_refptr<X509Certificate> cert( | |
| 2012 ImportCertFromFile(GetTestCertsDirectory(), "large_key.pem")); | |
| 2013 | |
| 2014 // Apple's verifier rejects this certificate as invalid because the | |
| 2015 // RSA key is too large. If a future version of OS X changes this, | |
| 2016 // large_key.pem may need to be regenerated with a larger key. | |
| 2017 int flags = 0; | |
| 2018 CertVerifyResult verify_result; | |
| 2019 scoped_refptr<CertVerifyProc> verify_proc = CertVerifyProc::CreateDefault(); | |
| 2020 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 2021 NULL, CertificateList(), &verify_result); | |
| 2022 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | |
| 2023 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); | |
| 2024 } | |
| 2025 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | |
| 2026 | |
| 2027 // Tests that CertVerifyProc records a histogram correctly when a | 1821 // Tests that CertVerifyProc records a histogram correctly when a |
| 2028 // certificate chaining to a private root contains the TLS feature | 1822 // certificate chaining to a private root contains the TLS feature |
| 2029 // extension and does not have a stapled OCSP response. | 1823 // extension and does not have a stapled OCSP response. |
| 2030 TEST(CertVerifyProcTest, HasTLSFeatureExtensionUMA) { | 1824 TEST(CertVerifyProcTest, HasTLSFeatureExtensionUMA) { |
| 2031 base::HistogramTester histograms; | 1825 base::HistogramTester histograms; |
| 2032 scoped_refptr<X509Certificate> cert( | 1826 scoped_refptr<X509Certificate> cert( |
| 2033 ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); | 1827 ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); |
| 2034 ASSERT_TRUE(cert); | 1828 ASSERT_TRUE(cert); |
| 2035 CertVerifyResult result; | 1829 CertVerifyResult result; |
| 2036 result.is_issued_by_known_root = false; | 1830 result.is_issued_by_known_root = false; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 int flags = 0; | 1913 int flags = 0; |
| 2120 CertVerifyResult verify_result; | 1914 CertVerifyResult verify_result; |
| 2121 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | 1915 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, |
| 2122 NULL, CertificateList(), &verify_result); | 1916 NULL, CertificateList(), &verify_result); |
| 2123 EXPECT_EQ(OK, error); | 1917 EXPECT_EQ(OK, error); |
| 2124 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); | 1918 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); |
| 2125 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); | 1919 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); |
| 2126 } | 1920 } |
| 2127 | 1921 |
| 2128 } // namespace net | 1922 } // namespace net |
| OLD | NEW |