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 17 matching lines...) Expand all Loading... |
28 #include "net/test/gtest_util.h" | 28 #include "net/test/gtest_util.h" |
29 #include "net/test/test_certificate_data.h" | 29 #include "net/test/test_certificate_data.h" |
30 #include "net/test/test_data_directory.h" | 30 #include "net/test/test_data_directory.h" |
31 #include "testing/gmock/include/gmock/gmock.h" | 31 #include "testing/gmock/include/gmock/gmock.h" |
32 #include "testing/gtest/include/gtest/gtest.h" | 32 #include "testing/gtest/include/gtest/gtest.h" |
33 | 33 |
34 #if defined(OS_ANDROID) | 34 #if defined(OS_ANDROID) |
35 #include "base/android/build_info.h" | 35 #include "base/android/build_info.h" |
36 #endif | 36 #endif |
37 | 37 |
| 38 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 39 #include "net/cert/test_keychain_search_list_mac.h" |
| 40 #endif |
| 41 |
38 using net::test::IsError; | 42 using net::test::IsError; |
39 using net::test::IsOk; | 43 using net::test::IsOk; |
40 | 44 |
41 using base::HexEncode; | 45 using base::HexEncode; |
42 | 46 |
43 namespace net { | 47 namespace net { |
44 | 48 |
45 namespace { | 49 namespace { |
46 | 50 |
47 // Mock CertVerifyProc that sets the CertVerifyResult to a given value for | 51 // Mock CertVerifyProc that sets the CertVerifyResult to a given value for |
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1333 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) | 1337 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) |
1334 << "Expected: " << testcase.expected_intermediate->subject().common_name | 1338 << "Expected: " << testcase.expected_intermediate->subject().common_name |
1335 << " issued by " << testcase.expected_intermediate->issuer().common_name | 1339 << " issued by " << testcase.expected_intermediate->issuer().common_name |
1336 << "; Got: " << intermediate->subject().common_name << " issued by " | 1340 << "; Got: " << intermediate->subject().common_name << " issued by " |
1337 << intermediate->issuer().common_name; | 1341 << intermediate->issuer().common_name; |
1338 } | 1342 } |
1339 } | 1343 } |
1340 | 1344 |
1341 #endif | 1345 #endif |
1342 | 1346 |
| 1347 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 1348 // Test that a CRLSet blocking one of the intermediates supplied by the server |
| 1349 // can be worked around by the chopping workaround for path building. (Once the |
| 1350 // supplied chain is chopped back to just the target, a better path can be |
| 1351 // found out-of-band. Normally that would be by AIA fetching, for the purposes |
| 1352 // of this test the better path is supplied by a test keychain.) |
| 1353 // |
| 1354 // In this test, there are two possible paths to validate a leaf (A): |
| 1355 // 1. A(B) -> B(C) -> C(E) -> E(E) |
| 1356 // 2. A(B) -> B(F) -> F(E) -> E(E) |
| 1357 // |
| 1358 // A(B) -> B(C) -> C(E) is supplied to the verifier. |
| 1359 // B(F) and F(E) are supplied in a test keychain. |
| 1360 // C is blocked by a CRLset. |
| 1361 // |
| 1362 // The verifier should rollback until it just tries A(B) alone, at which point |
| 1363 // it will pull B(F) & F(E) from the keychain and succeed. |
| 1364 TEST_F(CertVerifyProcTest, MacCRLIntermediate) { |
| 1365 const char* const kPath2Files[] = { |
| 1366 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-E.pem", |
| 1367 "multi-root-E-by-E.pem"}; |
| 1368 CertificateList path_2_certs; |
| 1369 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath2Files, &path_2_certs)); |
| 1370 |
| 1371 const char* const kPath3Files[] = { |
| 1372 "multi-root-A-by-B.pem", "multi-root-B-by-F.pem", "multi-root-F-by-E.pem", |
| 1373 "multi-root-E-by-E.pem"}; |
| 1374 |
| 1375 CertificateList path_3_certs; |
| 1376 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath3Files, &path_3_certs)); |
| 1377 |
| 1378 // Add E as trust anchor. |
| 1379 ScopedTestRoot test_root_E(path_3_certs[3].get()); // E-by-E |
| 1380 |
| 1381 X509Certificate::OSCertHandles intermediates; |
| 1382 intermediates.push_back(path_2_certs[1]->os_cert_handle()); // B-by-C |
| 1383 intermediates.push_back(path_2_certs[2]->os_cert_handle()); // C-by-E |
| 1384 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( |
| 1385 path_3_certs[0]->os_cert_handle(), intermediates); |
| 1386 ASSERT_TRUE(cert); |
| 1387 |
| 1388 std::unique_ptr<TestKeychainSearchList> test_keychain_search_list( |
| 1389 TestKeychainSearchList::Create()); |
| 1390 ASSERT_TRUE(test_keychain_search_list); |
| 1391 |
| 1392 base::FilePath keychain_path( |
| 1393 GetTestCertsDirectory().AppendASCII("multi-root-BFE.keychain")); |
| 1394 // SecKeychainOpen does not fail if the file doesn't exist, so assert it here |
| 1395 // for easier debugging. |
| 1396 ASSERT_TRUE(base::PathExists(keychain_path)); |
| 1397 SecKeychainRef keychain; |
| 1398 OSStatus status = |
| 1399 SecKeychainOpen(keychain_path.MaybeAsASCII().c_str(), &keychain); |
| 1400 ASSERT_EQ(errSecSuccess, status); |
| 1401 ASSERT_TRUE(keychain); |
| 1402 base::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); |
| 1403 test_keychain_search_list->AddKeychain(keychain); |
| 1404 |
| 1405 scoped_refptr<CRLSet> crl_set; |
| 1406 std::string crl_set_bytes; |
| 1407 // CRL which blocks C by SPKI. |
| 1408 EXPECT_TRUE(base::ReadFileToString( |
| 1409 GetTestCertsDirectory().AppendASCII("multi-root-crlset-C.raw"), |
| 1410 &crl_set_bytes)); |
| 1411 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); |
| 1412 |
| 1413 int flags = 0; |
| 1414 CertVerifyResult verify_result; |
| 1415 int error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), |
| 1416 empty_cert_list_, &verify_result); |
| 1417 |
| 1418 ASSERT_EQ(OK, error); |
| 1419 ASSERT_EQ(0U, verify_result.cert_status); |
| 1420 ASSERT_TRUE(verify_result.verified_cert.get()); |
| 1421 |
| 1422 const X509Certificate::OSCertHandles& verified_intermediates = |
| 1423 verify_result.verified_cert->GetIntermediateCertificates(); |
| 1424 ASSERT_EQ(3U, verified_intermediates.size()); |
| 1425 |
| 1426 scoped_refptr<X509Certificate> intermediate = |
| 1427 X509Certificate::CreateFromHandle(verified_intermediates[1], |
| 1428 X509Certificate::OSCertHandles()); |
| 1429 ASSERT_TRUE(intermediate); |
| 1430 |
| 1431 scoped_refptr<X509Certificate> expected_intermediate = path_3_certs[2]; |
| 1432 EXPECT_TRUE(expected_intermediate->Equals(intermediate.get())) |
| 1433 << "Expected: " << expected_intermediate->subject().common_name |
| 1434 << " issued by " << expected_intermediate->issuer().common_name |
| 1435 << "; Got: " << intermediate->subject().common_name << " issued by " |
| 1436 << intermediate->issuer().common_name; |
| 1437 } |
| 1438 |
| 1439 // Test that if a keychain is present which trusts a less-desirable root (ex, |
| 1440 // one using SHA1), that the keychain reordering hack will cause the better |
| 1441 // root in the System Roots to be used instead. |
| 1442 TEST_F(CertVerifyProcTest, MacKeychainReordering) { |
| 1443 // Note: target cert expires Apr 2 23:59:59 2018 GMT |
| 1444 scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile( |
| 1445 GetTestCertsDirectory(), "tripadvisor-verisign-chain.pem", |
| 1446 X509Certificate::FORMAT_AUTO); |
| 1447 ASSERT_TRUE(cert); |
| 1448 |
| 1449 // Create a test keychain search list that will Always Trust the SHA1 |
| 1450 // cross-signed VeriSign Class 3 Public Primary Certification Authority - G5 |
| 1451 std::unique_ptr<TestKeychainSearchList> test_keychain_search_list( |
| 1452 TestKeychainSearchList::Create()); |
| 1453 ASSERT_TRUE(test_keychain_search_list); |
| 1454 |
| 1455 base::FilePath keychain_path(GetTestCertsDirectory().AppendASCII( |
| 1456 "verisign_class3_g5_crosssigned-trusted.keychain")); |
| 1457 // SecKeychainOpen does not fail if the file doesn't exist, so assert it here |
| 1458 // for easier debugging. |
| 1459 ASSERT_TRUE(base::PathExists(keychain_path)); |
| 1460 SecKeychainRef keychain; |
| 1461 OSStatus status = |
| 1462 SecKeychainOpen(keychain_path.MaybeAsASCII().c_str(), &keychain); |
| 1463 ASSERT_EQ(errSecSuccess, status); |
| 1464 ASSERT_TRUE(keychain); |
| 1465 base::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); |
| 1466 test_keychain_search_list->AddKeychain(keychain); |
| 1467 |
| 1468 int flags = 0; |
| 1469 CertVerifyResult verify_result; |
| 1470 int error = Verify(cert.get(), "www.tripadvisor.com", flags, |
| 1471 nullptr /* crl_set */, empty_cert_list_, &verify_result); |
| 1472 |
| 1473 ASSERT_EQ(OK, error); |
| 1474 EXPECT_EQ(0U, verify_result.cert_status); |
| 1475 EXPECT_FALSE(verify_result.has_sha1); |
| 1476 ASSERT_TRUE(verify_result.verified_cert.get()); |
| 1477 |
| 1478 const X509Certificate::OSCertHandles& verified_intermediates = |
| 1479 verify_result.verified_cert->GetIntermediateCertificates(); |
| 1480 ASSERT_EQ(2U, verified_intermediates.size()); |
| 1481 } |
| 1482 |
| 1483 // Test that the system root certificate keychain is in the expected location |
| 1484 // and can be opened. Other tests would fail if this was not true, but this |
| 1485 // test makes the reason for the failure obvious. |
| 1486 TEST_F(CertVerifyProcTest, MacSystemRootCertificateKeychainLocation) { |
| 1487 const char* root_keychain_path = |
| 1488 "/System/Library/Keychains/SystemRootCertificates.keychain"; |
| 1489 ASSERT_TRUE(base::PathExists(base::FilePath(root_keychain_path))); |
| 1490 |
| 1491 SecKeychainRef keychain; |
| 1492 OSStatus status = SecKeychainOpen(root_keychain_path, &keychain); |
| 1493 ASSERT_EQ(errSecSuccess, status); |
| 1494 CFRelease(keychain); |
| 1495 } |
| 1496 #endif |
| 1497 |
1343 enum ExpectedAlgorithms { | 1498 enum ExpectedAlgorithms { |
1344 EXPECT_MD2 = 1 << 0, | 1499 EXPECT_MD2 = 1 << 0, |
1345 EXPECT_MD4 = 1 << 1, | 1500 EXPECT_MD4 = 1 << 1, |
1346 EXPECT_MD5 = 1 << 2, | 1501 EXPECT_MD5 = 1 << 2, |
1347 EXPECT_SHA1 = 1 << 3, | 1502 EXPECT_SHA1 = 1 << 3, |
1348 EXPECT_SHA1_LEAF = 1 << 4, | 1503 EXPECT_SHA1_LEAF = 1 << 4, |
1349 }; | 1504 }; |
1350 | 1505 |
1351 struct WeakDigestTestData { | 1506 struct WeakDigestTestData { |
1352 const char* root_cert_filename; | 1507 const char* root_cert_filename; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1683 int flags = 0; | 1838 int flags = 0; |
1684 CertVerifyResult verify_result; | 1839 CertVerifyResult verify_result; |
1685 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | 1840 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, |
1686 &verify_result); | 1841 &verify_result); |
1687 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | 1842 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); |
1688 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); | 1843 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); |
1689 } | 1844 } |
1690 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 1845 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
1691 | 1846 |
1692 } // namespace net | 1847 } // namespace net |
OLD | NEW |