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 | |
42 using net::test::IsError; | 38 using net::test::IsError; |
43 using net::test::IsOk; | 39 using net::test::IsOk; |
44 | 40 |
45 using base::HexEncode; | 41 using base::HexEncode; |
46 | 42 |
47 namespace net { | 43 namespace net { |
48 | 44 |
49 namespace { | 45 namespace { |
50 | 46 |
51 // Mock CertVerifyProc that sets the CertVerifyResult to a given value for | 47 // Mock CertVerifyProc that sets the CertVerifyResult to a given value for |
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) | 1333 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) |
1338 << "Expected: " << testcase.expected_intermediate->subject().common_name | 1334 << "Expected: " << testcase.expected_intermediate->subject().common_name |
1339 << " issued by " << testcase.expected_intermediate->issuer().common_name | 1335 << " issued by " << testcase.expected_intermediate->issuer().common_name |
1340 << "; Got: " << intermediate->subject().common_name << " issued by " | 1336 << "; Got: " << intermediate->subject().common_name << " issued by " |
1341 << intermediate->issuer().common_name; | 1337 << intermediate->issuer().common_name; |
1342 } | 1338 } |
1343 } | 1339 } |
1344 | 1340 |
1345 #endif | 1341 #endif |
1346 | 1342 |
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 | |
1498 enum ExpectedAlgorithms { | 1343 enum ExpectedAlgorithms { |
1499 EXPECT_MD2 = 1 << 0, | 1344 EXPECT_MD2 = 1 << 0, |
1500 EXPECT_MD4 = 1 << 1, | 1345 EXPECT_MD4 = 1 << 1, |
1501 EXPECT_MD5 = 1 << 2, | 1346 EXPECT_MD5 = 1 << 2, |
1502 EXPECT_SHA1 = 1 << 3, | 1347 EXPECT_SHA1 = 1 << 3, |
1503 EXPECT_SHA1_LEAF = 1 << 4, | 1348 EXPECT_SHA1_LEAF = 1 << 4, |
1504 }; | 1349 }; |
1505 | 1350 |
1506 struct WeakDigestTestData { | 1351 struct WeakDigestTestData { |
1507 const char* root_cert_filename; | 1352 const char* root_cert_filename; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 int flags = 0; | 1683 int flags = 0; |
1839 CertVerifyResult verify_result; | 1684 CertVerifyResult verify_result; |
1840 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | 1685 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, |
1841 &verify_result); | 1686 &verify_result); |
1842 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | 1687 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); |
1843 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); | 1688 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); |
1844 } | 1689 } |
1845 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 1690 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
1846 | 1691 |
1847 } // namespace net | 1692 } // namespace net |
OLD | NEW |