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

Side by Side Diff: net/cert/cert_verify_proc_unittest.cc

Issue 1762923002: Revert of Perform CRLSet evaluation during Path Building on NSS (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months 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
« no previous file with comments | « net/cert/cert_verify_proc_nss.cc ('k') | net/data/ssl/certificates/multi-root-crlset-C.raw » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 bool SupportsAdditionalTrustAnchors() { 136 bool SupportsAdditionalTrustAnchors() {
137 return verify_proc_->SupportsAdditionalTrustAnchors(); 137 return verify_proc_->SupportsAdditionalTrustAnchors();
138 } 138 }
139 139
140 // Returns true if the underlying CertVerifyProc supports integrating CRLSets 140 // Returns true if the underlying CertVerifyProc supports integrating CRLSets
141 // into path building logic, such as allowing the selection of alternatively 141 // into path building logic, such as allowing the selection of alternatively
142 // valid paths when one or more are revoked. As the goal is to integrate this 142 // valid paths when one or more are revoked. As the goal is to integrate this
143 // into all platforms, this is a temporary, test-only flag to centralize the 143 // into all platforms, this is a temporary, test-only flag to centralize the
144 // conditionals in tests. 144 // conditionals in tests.
145 bool SupportsCRLSetsInPathBuilding() { 145 bool SupportsCRLSetsInPathBuilding() {
146 #if defined(OS_WIN) || defined(USE_NSS_CERTS) 146 #if defined(OS_WIN)
147 return true; 147 return true;
148 #else 148 #else
149 return false; 149 return false;
150 #endif 150 #endif
151 } 151 }
152 152
153 int Verify(X509Certificate* cert, 153 int Verify(X509Certificate* cert,
154 const std::string& hostname, 154 const std::string& hostname,
155 int flags, 155 int flags,
156 CRLSet* crl_set, 156 CRLSet* crl_set,
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1395 1395
1396 error = Verify(leaf.get(), 1396 error = Verify(leaf.get(),
1397 "test.example.com", 1397 "test.example.com",
1398 flags, 1398 flags,
1399 crl_set.get(), 1399 crl_set.get(),
1400 empty_cert_list_, 1400 empty_cert_list_,
1401 &verify_result); 1401 &verify_result);
1402 EXPECT_EQ(ERR_CERT_REVOKED, error); 1402 EXPECT_EQ(ERR_CERT_REVOKED, error);
1403 } 1403 }
1404 1404
1405 // Tests that CRLSets participate in path building functions, and that as 1405 // Tests that revocation by CRLSet functions properly with the certificate
1406 // long as a valid path exists within the verification graph, verification 1406 // immediately before the trust anchor is revoked by that trust anchor, but
1407 // succeeds. 1407 // another version to a different trust anchor exists.
1408 // 1408 //
1409 // In this test, there are two roots (D and E), and three possible paths 1409 // The two possible paths are:
1410 // to validate a leaf (A):
1411 // 1. A(B) -> B(C) -> C(D) -> D(D) 1410 // 1. A(B) -> B(C) -> C(D) -> D(D)
1412 // 2. A(B) -> B(C) -> C(E) -> E(E) 1411 // 2. A(B) -> B(C) -> C(E) -> E(E)
1413 // 3. A(B) -> B(F) -> F(E) -> E(E) 1412 //
1414 // 1413 // In this test, C(E) is revoked by CRLSet. It is configured to be the more
1415 // Each permutation of revocation is tried: 1414 // preferable version compared to C(D), once revoked, it should be ignored.
1416 // 1. Revoking E by SPKI, so that only Path 1 is valid (as E is in Paths 2 & 3) 1415 TEST_F(CertVerifyProcTest, CRLSetRevokedIntermediateSameName) {
1417 // 2. Revoking C(D) and F(E) by serial, so that only Path 2 is valid.
1418 // 3. Revoking C by SPKI, so that only Path 3 is valid (as C is in Paths 1 & 2)
1419 TEST_F(CertVerifyProcTest, CRLSetDuringPathBuilding) {
1420 if (!SupportsCRLSetsInPathBuilding()) { 1416 if (!SupportsCRLSetsInPathBuilding()) {
1421 LOG(INFO) << "Skipping this test on this platform."; 1417 LOG(INFO) << "Skipping this test on this platform.";
1422 return; 1418 return;
1423 } 1419 }
1424 1420
1425 const char* const kPath1Files[] = { 1421 const char* const kCertificatesToLoad[] = {
1426 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-D.pem", 1422 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-D.pem",
1427 "multi-root-D-by-D.pem"}; 1423 "multi-root-D-by-D.pem", "multi-root-C-by-E.pem", "multi-root-E-by-E.pem",
1428 const char* const kPath2Files[] = { 1424 };
1429 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-E.pem", 1425 CertificateList certs;
1430 "multi-root-E-by-E.pem"}; 1426 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kCertificatesToLoad, &certs));
1431 const char* const kPath3Files[] = { 1427
1432 "multi-root-A-by-B.pem", "multi-root-B-by-F.pem", "multi-root-F-by-E.pem", 1428 // Add D and E as trust anchors
1433 "multi-root-E-by-E.pem"}; 1429 ScopedTestRoot test_root_D(certs[3].get()); // D-by-D
1434 1430 ScopedTestRoot test_root_F(certs[5].get()); // E-by-E
1435 CertificateList path_1_certs; 1431
1436 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath1Files, &path_1_certs)); 1432 // Create a chain that sends A(B), B(C), C(E), C(D). The reason that
1437 1433 // both C(E) and C(D) are sent are to ensure both certificates are available
1438 CertificateList path_2_certs; 1434 // for path building. The test
1439 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath2Files, &path_2_certs)); 1435 // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts ensures this is
1440 1436 // safe to do.
1441 CertificateList path_3_certs;
1442 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath3Files, &path_3_certs));
1443
1444 // Add D and E as trust anchors.
1445 ScopedTestRoot test_root_D(path_1_certs[3].get()); // D-by-D
1446 ScopedTestRoot test_root_E(path_2_certs[3].get()); // E-by-E
1447
1448 // Create a chain that contains all the certificate paths possible.
1449 // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts already
1450 // ensures that it's safe to send additional certificates as inputs, and
1451 // that they're ignored if not necessary.
1452 // This is to avoid relying on AIA or internal object caches when
1453 // interacting with the underlying library.
1454 X509Certificate::OSCertHandles intermediates; 1437 X509Certificate::OSCertHandles intermediates;
1455 intermediates.push_back(path_1_certs[1]->os_cert_handle()); // B-by-C 1438 intermediates.push_back(certs[1]->os_cert_handle()); // B-by-C
1456 intermediates.push_back(path_1_certs[2]->os_cert_handle()); // C-by-D 1439 intermediates.push_back(certs[4]->os_cert_handle()); // C-by-E
1457 intermediates.push_back(path_2_certs[2]->os_cert_handle()); // C-by-E 1440 intermediates.push_back(certs[2]->os_cert_handle()); // C-by-D
1458 intermediates.push_back(path_3_certs[1]->os_cert_handle()); // B-by-F
1459 intermediates.push_back(path_3_certs[2]->os_cert_handle()); // F-by-E
1460 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( 1441 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
1461 path_1_certs[0]->os_cert_handle(), intermediates); 1442 certs[0]->os_cert_handle(), intermediates);
1462 ASSERT_TRUE(cert); 1443 ASSERT_TRUE(cert);
1463 1444
1464 struct TestPermutations { 1445 // Sanity check: Ensure that, without any revocation status, the to-be-revoked
1465 const char* crlset; 1446 // path is preferred.
1466 bool expect_valid; 1447 int flags = 0;
1467 scoped_refptr<X509Certificate> expected_intermediate; 1448 CertVerifyResult verify_result;
1468 } kTests[] = { 1449 int error = Verify(cert.get(), "127.0.0.1", flags, nullptr, empty_cert_list_,
1469 {"multi-root-crlset-D-and-E.raw", false, nullptr}, 1450 &verify_result);
1470 {"multi-root-crlset-E.raw", true, path_1_certs[2].get()}, 1451 ASSERT_EQ(OK, error);
1471 {"multi-root-crlset-CD-and-FE.raw", true, path_2_certs[2].get()}, 1452 ASSERT_EQ(0U, verify_result.cert_status);
1472 {"multi-root-crlset-C.raw", true, path_3_certs[2].get()}, 1453 ASSERT_TRUE(verify_result.verified_cert.get());
1473 {"multi-root-crlset-unrelated.raw", true, nullptr}}; 1454
1474 1455 // The expected path is A(B) -> B(C) -> C(E) -> E(E).
1475 for (const auto& testcase : kTests) { 1456 const X509Certificate::OSCertHandles& verified_intermediates =
1476 SCOPED_TRACE(testcase.crlset); 1457 verify_result.verified_cert->GetIntermediateCertificates();
1477 scoped_refptr<CRLSet> crl_set; 1458 ASSERT_EQ(3U, verified_intermediates.size());
1478 std::string crl_set_bytes; 1459 scoped_refptr<X509Certificate> verified_root =
1479 EXPECT_TRUE(base::ReadFileToString( 1460 X509Certificate::CreateFromHandle(verified_intermediates[2],
1480 GetTestCertsDirectory().AppendASCII(testcase.crlset), &crl_set_bytes)); 1461 X509Certificate::OSCertHandles());
1481 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); 1462 ASSERT_TRUE(verified_root.get());
1482 1463 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1483 int flags = 0; 1464
1484 CertVerifyResult verify_result; 1465 // Load a CRLSet that blocks C-by-E.
1485 int error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), 1466 scoped_refptr<CRLSet> crl_set;
1486 empty_cert_list_, &verify_result); 1467 std::string crl_set_bytes;
1487 1468 EXPECT_TRUE(base::ReadFileToString(
1488 if (!testcase.expect_valid) { 1469 GetTestCertsDirectory().AppendASCII("multi-root-crlset-C-by-E.raw"),
1489 EXPECT_NE(OK, error); 1470 &crl_set_bytes));
1490 EXPECT_NE(0U, verify_result.cert_status); 1471 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set));
1491 continue; 1472
1492 } 1473 // Verify with the CRLSet. Because C-by-E is revoked, the expected path is
1493 1474 // A(B) -> B(C) -> C(D) -> D(D).
1494 ASSERT_EQ(OK, error); 1475 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(),
1495 ASSERT_EQ(0U, verify_result.cert_status); 1476 empty_cert_list_, &verify_result);
1496 ASSERT_TRUE(verify_result.verified_cert.get()); 1477 ASSERT_EQ(OK, error);
1497 1478 ASSERT_EQ(0U, verify_result.cert_status);
1498 if (!testcase.expected_intermediate) 1479 ASSERT_TRUE(verify_result.verified_cert.get());
1499 continue; 1480
1500 1481 const X509Certificate::OSCertHandles& new_verified_intermediates =
1501 const X509Certificate::OSCertHandles& verified_intermediates = 1482 verify_result.verified_cert->GetIntermediateCertificates();
1502 verify_result.verified_cert->GetIntermediateCertificates(); 1483 ASSERT_EQ(3U, new_verified_intermediates.size());
1503 ASSERT_EQ(3U, verified_intermediates.size()); 1484 verified_root = X509Certificate::CreateFromHandle(
1504 1485 new_verified_intermediates[2], X509Certificate::OSCertHandles());
1505 scoped_refptr<X509Certificate> intermediate = 1486 ASSERT_TRUE(verified_root.get());
1506 X509Certificate::CreateFromHandle(verified_intermediates[1], 1487 EXPECT_EQ("D Root CA", verified_root->subject().common_name);
1507 X509Certificate::OSCertHandles()); 1488
1508 ASSERT_TRUE(intermediate); 1489 // Reverify without the CRLSet, to ensure that CRLSets do not persist between
1509 1490 // separate calls. As in the first verification, the expected path is
1510 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) 1491 // A(B) -> B(C) -> C(E) -> E(E).
1511 << "Expected: " << testcase.expected_intermediate->subject().common_name 1492 error = Verify(cert.get(), "127.0.0.1", flags, nullptr, empty_cert_list_,
1512 << " issued by " << testcase.expected_intermediate->issuer().common_name 1493 &verify_result);
1513 << "; Got: " << intermediate->subject().common_name << " issued by " 1494 ASSERT_EQ(OK, error);
1514 << intermediate->issuer().common_name; 1495 ASSERT_EQ(0U, verify_result.cert_status);
1496 ASSERT_TRUE(verify_result.verified_cert.get());
1497
1498 const X509Certificate::OSCertHandles& final_verified_intermediates =
1499 verify_result.verified_cert->GetIntermediateCertificates();
1500 ASSERT_EQ(3U, final_verified_intermediates.size());
1501 verified_root = X509Certificate::CreateFromHandle(
1502 final_verified_intermediates[2], X509Certificate::OSCertHandles());
1503 ASSERT_TRUE(verified_root.get());
1504 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1505 }
1506
1507 // Tests that revocation by CRLSet functions properly when an intermediate is
1508 // revoked by SPKI. In this case, path building should ignore all certificates
1509 // with that SPKI, and search for alternatively keyed versions.
1510 //
1511 // The two possible paths are:
1512 // 1. A(B) -> B(C) -> C(D) -> D(D)
1513 // 2. A(B) -> B(F) -> F(E) -> E(E)
1514 //
1515 // The path building algorithm needs to explore B(C) once it discovers that
1516 // F(E) is revoked, and that there are no valid paths with B(F).
1517 TEST_F(CertVerifyProcTest, CRLSetRevokedIntermediateCrossIntermediates) {
1518 if (!SupportsCRLSetsInPathBuilding()) {
1519 LOG(INFO) << "Skipping this test on this platform.";
1520 return;
1515 } 1521 }
1522
1523 const char* const kCertificatesToLoad[] = {
1524 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-D.pem",
1525 "multi-root-D-by-D.pem", "multi-root-B-by-F.pem", "multi-root-F-by-E.pem",
1526 "multi-root-E-by-E.pem",
1527 };
1528 CertificateList certs;
1529 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kCertificatesToLoad, &certs));
1530
1531 // Add D and E as trust anchors
1532 ScopedTestRoot test_root_D(certs[3].get()); // D-by-D
1533 ScopedTestRoot test_root_F(certs[6].get()); // E-by-E
1534
1535 // Create a chain that sends A(B), B(F), F(E), B(C), C(D). The reason that
1536 // both B(C) and C(D) are sent are to ensure both certificates are available
1537 // for path building. The test
1538 // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts ensures this is
1539 // safe to do.
1540 X509Certificate::OSCertHandles intermediates;
1541 intermediates.push_back(certs[4]->os_cert_handle()); // B-by-F
1542 intermediates.push_back(certs[5]->os_cert_handle()); // F-by-E
1543 intermediates.push_back(certs[1]->os_cert_handle()); // B-by-C
1544 intermediates.push_back(certs[2]->os_cert_handle()); // C-by-D
1545 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
1546 certs[0]->os_cert_handle(), intermediates);
1547 ASSERT_TRUE(cert);
1548
1549 // Sanity check: Ensure that, without any revocation status, the to-be-revoked
1550 // path is preferred.
1551 int flags = 0;
1552 CertVerifyResult verify_result;
1553 int error = Verify(cert.get(), "127.0.0.1", flags, nullptr, empty_cert_list_,
1554 &verify_result);
1555 ASSERT_EQ(OK, error);
1556 ASSERT_EQ(0U, verify_result.cert_status);
1557 ASSERT_TRUE(verify_result.verified_cert.get());
1558
1559 // The expected path is A(B) -> B(F) -> F(E) -> E(E).
1560 const X509Certificate::OSCertHandles& verified_intermediates =
1561 verify_result.verified_cert->GetIntermediateCertificates();
1562 ASSERT_EQ(3U, verified_intermediates.size());
1563 scoped_refptr<X509Certificate> verified_root =
1564 X509Certificate::CreateFromHandle(verified_intermediates[2],
1565 X509Certificate::OSCertHandles());
1566 ASSERT_TRUE(verified_root.get());
1567 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1568
1569 // Load a CRLSet that blocks F.
1570 scoped_refptr<CRLSet> crl_set;
1571 std::string crl_set_bytes;
1572 EXPECT_TRUE(base::ReadFileToString(
1573 GetTestCertsDirectory().AppendASCII("multi-root-crlset-F.raw"),
1574 &crl_set_bytes));
1575 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set));
1576
1577 // Verify with the CRLSet. Because F is revoked, the expected path is
1578 // A(B) -> B(C) -> C(D) -> D(D).
1579 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(),
1580 empty_cert_list_, &verify_result);
1581 ASSERT_EQ(OK, error);
1582 ASSERT_EQ(0U, verify_result.cert_status);
1583 ASSERT_TRUE(verify_result.verified_cert.get());
1584
1585 const X509Certificate::OSCertHandles& new_verified_intermediates =
1586 verify_result.verified_cert->GetIntermediateCertificates();
1587 ASSERT_EQ(3U, new_verified_intermediates.size());
1588 verified_root = X509Certificate::CreateFromHandle(
1589 new_verified_intermediates[2], X509Certificate::OSCertHandles());
1590 ASSERT_TRUE(verified_root.get());
1591 EXPECT_EQ("D Root CA", verified_root->subject().common_name);
1592
1593 // Reverify without the CRLSet, to ensure that CRLSets do not persist between
1594 // separate calls. As in the first verification, the expected path is
1595 // A(B) -> B(F) -> F(E) -> E(E).
1596 error = Verify(cert.get(), "127.0.0.1", flags, nullptr, empty_cert_list_,
1597 &verify_result);
1598 ASSERT_EQ(OK, error);
1599 ASSERT_EQ(0U, verify_result.cert_status);
1600 ASSERT_TRUE(verify_result.verified_cert.get());
1601
1602 const X509Certificate::OSCertHandles& final_verified_intermediates =
1603 verify_result.verified_cert->GetIntermediateCertificates();
1604 ASSERT_EQ(3U, final_verified_intermediates.size());
1605 verified_root = X509Certificate::CreateFromHandle(
1606 final_verified_intermediates[2], X509Certificate::OSCertHandles());
1607 ASSERT_TRUE(verified_root.get());
1608 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1516 } 1609 }
1517 1610
1518 #endif 1611 #endif
1519 1612
1520 enum ExpectedAlgorithms { 1613 enum ExpectedAlgorithms {
1521 EXPECT_MD2 = 1 << 0, 1614 EXPECT_MD2 = 1 << 0,
1522 EXPECT_MD4 = 1 << 1, 1615 EXPECT_MD4 = 1 << 1,
1523 EXPECT_MD5 = 1 << 2, 1616 EXPECT_MD5 = 1 << 2,
1524 EXPECT_SHA1 = 1 << 3, 1617 EXPECT_SHA1 = 1 << 3,
1525 EXPECT_SHA1_LEAF = 1 << 4, 1618 EXPECT_SHA1_LEAF = 1 << 4,
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
1860 int flags = 0; 1953 int flags = 0;
1861 CertVerifyResult verify_result; 1954 CertVerifyResult verify_result;
1862 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, 1955 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
1863 &verify_result); 1956 &verify_result);
1864 EXPECT_EQ(ERR_CERT_INVALID, error); 1957 EXPECT_EQ(ERR_CERT_INVALID, error);
1865 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); 1958 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status);
1866 } 1959 }
1867 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 1960 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
1868 1961
1869 } // namespace net 1962 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/cert_verify_proc_nss.cc ('k') | net/data/ssl/certificates/multi-root-crlset-C.raw » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698