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 15 matching lines...) Expand all Loading... | |
26 #include "net/cert/test_root_certs.h" | 26 #include "net/cert/test_root_certs.h" |
27 #include "net/cert/x509_certificate.h" | 27 #include "net/cert/x509_certificate.h" |
28 #include "net/test/cert_test_util.h" | 28 #include "net/test/cert_test_util.h" |
29 #include "net/test/test_certificate_data.h" | 29 #include "net/test/test_certificate_data.h" |
30 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
31 | 31 |
32 #if defined(OS_ANDROID) | 32 #if defined(OS_ANDROID) |
33 #include "base/android/build_info.h" | 33 #include "base/android/build_info.h" |
34 #endif | 34 #endif |
35 | 35 |
36 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
37 #include "net/cert/test_keychain_search_list_mac.h" | |
38 #endif | |
39 | |
36 using base::HexEncode; | 40 using base::HexEncode; |
37 | 41 |
38 namespace net { | 42 namespace net { |
39 | 43 |
40 namespace { | 44 namespace { |
41 | 45 |
42 // A certificate for www.paypal.com with a NULL byte in the common name. | 46 // A certificate for www.paypal.com with a NULL byte in the common name. |
43 // From http://www.gossamer-threads.com/lists/fulldisc/full-disclosure/70363 | 47 // From http://www.gossamer-threads.com/lists/fulldisc/full-disclosure/70363 |
44 unsigned char paypal_null_fingerprint[] = { | 48 unsigned char paypal_null_fingerprint[] = { |
45 0x4c, 0x88, 0x9e, 0x28, 0xd7, 0x7a, 0x44, 0x1e, 0x13, 0xf2, 0x6a, 0xba, | 49 0x4c, 0x88, 0x9e, 0x28, 0xd7, 0x7a, 0x44, 0x1e, 0x13, 0xf2, 0x6a, 0xba, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 bool SupportsAdditionalTrustAnchors() { | 142 bool SupportsAdditionalTrustAnchors() { |
139 return verify_proc_->SupportsAdditionalTrustAnchors(); | 143 return verify_proc_->SupportsAdditionalTrustAnchors(); |
140 } | 144 } |
141 | 145 |
142 // Returns true if the underlying CertVerifyProc supports integrating CRLSets | 146 // Returns true if the underlying CertVerifyProc supports integrating CRLSets |
143 // into path building logic, such as allowing the selection of alternatively | 147 // into path building logic, such as allowing the selection of alternatively |
144 // valid paths when one or more are revoked. As the goal is to integrate this | 148 // valid paths when one or more are revoked. As the goal is to integrate this |
145 // into all platforms, this is a temporary, test-only flag to centralize the | 149 // into all platforms, this is a temporary, test-only flag to centralize the |
146 // conditionals in tests. | 150 // conditionals in tests. |
147 bool SupportsCRLSetsInPathBuilding() { | 151 bool SupportsCRLSetsInPathBuilding() { |
148 #if defined(OS_WIN) || defined(USE_NSS_CERTS) | 152 #if defined(OS_WIN) || defined(USE_NSS_CERTS) |
Ryan Sleevi
2016/06/30 01:49:16
Can this be set for OS_MACOSX now? If not, should
mattm
2016/06/30 03:20:52
It still fails, since adding CRLSet checking to th
| |
149 return true; | 153 return true; |
150 #else | 154 #else |
151 return false; | 155 return false; |
152 #endif | 156 #endif |
153 } | 157 } |
154 | 158 |
155 int Verify(X509Certificate* cert, | 159 int Verify(X509Certificate* cert, |
156 const std::string& hostname, | 160 const std::string& hostname, |
157 int flags, | 161 int flags, |
158 CRLSet* crl_set, | 162 CRLSet* crl_set, |
(...skipping 1174 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 #endif | |
1483 | |
1343 enum ExpectedAlgorithms { | 1484 enum ExpectedAlgorithms { |
1344 EXPECT_MD2 = 1 << 0, | 1485 EXPECT_MD2 = 1 << 0, |
1345 EXPECT_MD4 = 1 << 1, | 1486 EXPECT_MD4 = 1 << 1, |
1346 EXPECT_MD5 = 1 << 2, | 1487 EXPECT_MD5 = 1 << 2, |
1347 EXPECT_SHA1 = 1 << 3, | 1488 EXPECT_SHA1 = 1 << 3, |
1348 EXPECT_SHA1_LEAF = 1 << 4, | 1489 EXPECT_SHA1_LEAF = 1 << 4, |
1349 }; | 1490 }; |
1350 | 1491 |
1351 struct WeakDigestTestData { | 1492 struct WeakDigestTestData { |
1352 const char* root_cert_filename; | 1493 const char* root_cert_filename; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1683 int flags = 0; | 1824 int flags = 0; |
1684 CertVerifyResult verify_result; | 1825 CertVerifyResult verify_result; |
1685 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | 1826 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, |
1686 &verify_result); | 1827 &verify_result); |
1687 EXPECT_EQ(ERR_CERT_INVALID, error); | 1828 EXPECT_EQ(ERR_CERT_INVALID, error); |
1688 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); | 1829 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); |
1689 } | 1830 } |
1690 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 1831 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
1691 | 1832 |
1692 } // namespace net | 1833 } // namespace net |
OLD | NEW |