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

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

Issue 1557133002: Perform CRLSet evaluation during Path Building on Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review feedback Created 4 years, 10 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
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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 bool SupportsDetectingKnownRoots() { 100 bool SupportsDetectingKnownRoots() {
101 #if defined(OS_ANDROID) 101 #if defined(OS_ANDROID)
102 // Before API level 17, Android does not expose the APIs necessary to get at 102 // Before API level 17, Android does not expose the APIs necessary to get at
103 // the verified certificate chain and detect known roots. 103 // the verified certificate chain and detect known roots.
104 if (base::android::BuildInfo::GetInstance()->sdk_int() < 17) 104 if (base::android::BuildInfo::GetInstance()->sdk_int() < 17)
105 return false; 105 return false;
106 #endif 106 #endif
107 return true; 107 return true;
108 } 108 }
109 109
110 // Template helper to load a series of certificate files into a CertificateList.
111 // Like CertTestUtil's CreateCertificateListFromFile, except it can load a
112 // series of individual certificates (to make the tests clearer).
113 template <size_t N>
114 void LoadCertificateFiles(const char* const(&cert_files)[N],
115 CertificateList* certs) {
116 certs->clear();
117 for (size_t i = 0; i < N; ++i) {
davidben 2016/01/28 20:52:32 Optional: This could also be a for each loop if yo
Ryan Sleevi 2016/02/05 21:26:03 ? Were you thinking Go? std::for_each is awful I
davidben 2016/02/05 21:32:45 for each loops are hardly a Go innovation...
118 SCOPED_TRACE(cert_files[i]);
119 scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile(
120 GetTestCertsDirectory(), cert_files[i], X509Certificate::FORMAT_AUTO);
121 ASSERT_TRUE(cert);
122 certs->push_back(cert);
123 }
124 }
125
110 } // namespace 126 } // namespace
111 127
112 class CertVerifyProcTest : public testing::Test { 128 class CertVerifyProcTest : public testing::Test {
113 public: 129 public:
114 CertVerifyProcTest() 130 CertVerifyProcTest()
115 : verify_proc_(CertVerifyProc::CreateDefault()) { 131 : verify_proc_(CertVerifyProc::CreateDefault()) {
116 } 132 }
117 ~CertVerifyProcTest() override {} 133 ~CertVerifyProcTest() override {}
118 134
119 protected: 135 protected:
(...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); 1369 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set));
1354 1370
1355 error = Verify(leaf.get(), 1371 error = Verify(leaf.get(),
1356 "test.example.com", 1372 "test.example.com",
1357 flags, 1373 flags,
1358 crl_set.get(), 1374 crl_set.get(),
1359 empty_cert_list_, 1375 empty_cert_list_,
1360 &verify_result); 1376 &verify_result);
1361 EXPECT_EQ(ERR_CERT_REVOKED, error); 1377 EXPECT_EQ(ERR_CERT_REVOKED, error);
1362 } 1378 }
1379
1380 // Tests that revocation by CRLSet functions properly with the certificate
1381 // immediately before the trust anchor is revoked by that trust anchor, but
1382 // another version to a different trust anchor exists.
1383 //
1384 // The two possible paths are:
1385 // 1. A(B) -> B(C) -> C(D) -> D(D)
1386 // 2. A(B) -> B(C) -> C(E) -> E(E)
1387 //
1388 // In this test, C(E) is revoked by CRLSet. It is configured to be the more
1389 // preferable version compared to C(D), once revoked, it should be ignored.
1390 TEST_F(CertVerifyProcTest, CRLSetRevokedIntermediateSameName) {
1391 const char* const kCertificatesToLoad[] = {
1392 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-D.pem",
1393 "multi-root-D-by-D.pem", "multi-root-C-by-E.pem", "multi-root-E-by-E.pem",
1394 };
1395 CertificateList certs;
1396 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kCertificatesToLoad, &certs));
1397
1398 // Add D and E as trust anchors
1399 ScopedTestRoot test_root_D(certs[3].get()); // D-by-D
1400 ScopedTestRoot test_root_F(certs[5].get()); // E-by-E
1401
1402 // Create a chain that sends A(B), B(C), C(E), C(D). The reason that
1403 // both C(E) and C(D) are sent are to ensure both certificates are available
1404 // for path building. The test
1405 // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts ensures this is
1406 // safe to do.
1407 X509Certificate::OSCertHandles intermediates;
1408 intermediates.push_back(certs[1]->os_cert_handle()); // B-by-C
1409 intermediates.push_back(certs[4]->os_cert_handle()); // C-by-E
1410 intermediates.push_back(certs[2]->os_cert_handle()); // C-by-D
1411 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
1412 certs[0]->os_cert_handle(), intermediates);
1413 ASSERT_TRUE(cert);
1414
1415 // Sanity check: Ensure that, without any revocation status, the to-be-revoked
1416 // path is preferred.
1417 int flags = 0;
1418 CertVerifyResult verify_result;
1419 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
davidben 2016/01/28 20:52:32 Nit: nullptr
1420 &verify_result);
1421 ASSERT_EQ(OK, error);
1422 ASSERT_EQ(0U, verify_result.cert_status);
1423 ASSERT_TRUE(verify_result.verified_cert.get());
1424
1425 // The expected path is A(B) -> B(C) -> C(E) -> E(E).
1426 const X509Certificate::OSCertHandles& verified_intermediates =
1427 verify_result.verified_cert->GetIntermediateCertificates();
1428 ASSERT_EQ(3U, verified_intermediates.size());
1429 scoped_refptr<X509Certificate> verified_root =
1430 X509Certificate::CreateFromHandle(verified_intermediates[2],
1431 X509Certificate::OSCertHandles());
1432 ASSERT_TRUE(verified_root.get());
1433 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1434
1435 // Load a CRLSet that blocks C-by-E.
1436 scoped_refptr<CRLSet> crl_set;
1437 std::string crl_set_bytes;
1438 EXPECT_TRUE(base::ReadFileToString(
1439 GetTestCertsDirectory().AppendASCII("multi-root-crlset-C-by-E.raw"),
1440 &crl_set_bytes));
1441 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set));
1442
1443 // Verify with the CRLSet. Because C-by-E is revoked, the expected path is
1444 // A(B) -> B(C) -> C(D) -> D(D).
1445 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(),
1446 empty_cert_list_, &verify_result);
1447 ASSERT_EQ(OK, error);
1448 ASSERT_EQ(0U, verify_result.cert_status);
1449 ASSERT_TRUE(verify_result.verified_cert.get());
1450
1451 const X509Certificate::OSCertHandles& new_verified_intermediates =
1452 verify_result.verified_cert->GetIntermediateCertificates();
1453 ASSERT_EQ(3U, new_verified_intermediates.size());
1454 verified_root = X509Certificate::CreateFromHandle(
1455 new_verified_intermediates[2], X509Certificate::OSCertHandles());
1456 ASSERT_TRUE(verified_root.get());
1457 EXPECT_EQ("D Root CA", verified_root->subject().common_name);
1458
1459 // Reverify without the CRLSet, to ensure that CRLSets do not persist between
1460 // separate calls. As in the first verification, the expected path is
1461 // A(B) -> B(C) -> C(E) -> E(E).
1462 error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
1463 &verify_result);
1464 ASSERT_EQ(OK, error);
1465 ASSERT_EQ(0U, verify_result.cert_status);
1466 ASSERT_TRUE(verify_result.verified_cert.get());
1467
1468 const X509Certificate::OSCertHandles& final_verified_intermediates =
1469 verify_result.verified_cert->GetIntermediateCertificates();
1470 ASSERT_EQ(3U, final_verified_intermediates.size());
1471 verified_root = X509Certificate::CreateFromHandle(
1472 final_verified_intermediates[2], X509Certificate::OSCertHandles());
1473 ASSERT_TRUE(verified_root.get());
1474 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1475 }
1476
1477 // Tests that revocation by CRLSet functions properly when an intermediate is
1478 // revoked by SPKI. In this case, path building should ignore all certificates
1479 // with that SPKI, and search for alternatively keyed versions.
1480 //
1481 // The two possible paths are:
1482 // 1. A(B) -> B(C) -> C(D) -> D(D)
1483 // 2. A(B) -> B(F) -> F(E) -> E(E)
1484 //
1485 // The path building algorithm needs to explore B(C) once it discovers that
1486 // F(E) is revoked, and that there are no valid paths with B(F).
1487 TEST_F(CertVerifyProcTest, CRLSetRevokedIntermediateCrossIntermediates) {
1488 const char* const kCertificatesToLoad[] = {
1489 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-D.pem",
1490 "multi-root-D-by-D.pem", "multi-root-B-by-F.pem", "multi-root-F-by-E.pem",
1491 "multi-root-E-by-E.pem",
1492 };
1493 CertificateList certs;
1494 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kCertificatesToLoad, &certs));
1495
1496 // Add D and E as trust anchors
1497 ScopedTestRoot test_root_D(certs[3].get()); // D-by-D
1498 ScopedTestRoot test_root_F(certs[6].get()); // E-by-E
1499
1500 // Create a chain that sends A(B), B(F), F(E), B(C), C(D). The reason that
1501 // both B(C) and C(D) are sent are to ensure both certificates are available
1502 // for path building. The test
1503 // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts ensures this is
1504 // safe to do.
1505 X509Certificate::OSCertHandles intermediates;
1506 intermediates.push_back(certs[4]->os_cert_handle()); // B-by-F
1507 intermediates.push_back(certs[5]->os_cert_handle()); // F-by-E
1508 intermediates.push_back(certs[1]->os_cert_handle()); // B-by-C
1509 intermediates.push_back(certs[2]->os_cert_handle()); // C-by-D
1510 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
1511 certs[0]->os_cert_handle(), intermediates);
1512 ASSERT_TRUE(cert);
1513
1514 // Sanity check: Ensure that, without any revocation status, the to-be-revoked
1515 // path is preferred.
1516 int flags = 0;
1517 CertVerifyResult verify_result;
1518 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
1519 &verify_result);
1520 ASSERT_EQ(OK, error);
1521 ASSERT_EQ(0U, verify_result.cert_status);
1522 ASSERT_TRUE(verify_result.verified_cert.get());
1523
1524 // The expected path is A(B) -> B(F) -> F(E) -> E(E).
1525 const X509Certificate::OSCertHandles& verified_intermediates =
1526 verify_result.verified_cert->GetIntermediateCertificates();
1527 ASSERT_EQ(3U, verified_intermediates.size());
1528 scoped_refptr<X509Certificate> verified_root =
1529 X509Certificate::CreateFromHandle(verified_intermediates[2],
1530 X509Certificate::OSCertHandles());
1531 ASSERT_TRUE(verified_root.get());
1532 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1533
1534 // Load a CRLSet that blocks F.
1535 scoped_refptr<CRLSet> crl_set;
1536 std::string crl_set_bytes;
1537 EXPECT_TRUE(base::ReadFileToString(
1538 GetTestCertsDirectory().AppendASCII("multi-root-crlset-F.raw"),
1539 &crl_set_bytes));
1540 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set));
1541
1542 // Verify with the CRLSet. Because F is revoked, the expected path is
1543 // A(B) -> B(C) -> C(D) -> D(D).
1544 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(),
1545 empty_cert_list_, &verify_result);
1546 ASSERT_EQ(OK, error);
1547 ASSERT_EQ(0U, verify_result.cert_status);
1548 ASSERT_TRUE(verify_result.verified_cert.get());
1549
1550 const X509Certificate::OSCertHandles& new_verified_intermediates =
1551 verify_result.verified_cert->GetIntermediateCertificates();
1552 ASSERT_EQ(3U, new_verified_intermediates.size());
1553 verified_root = X509Certificate::CreateFromHandle(
1554 new_verified_intermediates[2], X509Certificate::OSCertHandles());
1555 ASSERT_TRUE(verified_root.get());
1556 EXPECT_EQ("D Root CA", verified_root->subject().common_name);
davidben 2016/01/28 20:52:32 Could the existence of C(E) being used in a previo
Ryan Sleevi 2016/02/05 21:26:03 I'm not sure I understand your question. Line 1532
davidben 2016/02/05 21:32:45 *C*(E), not F(E). This tests revokes F(E) and does
Ryan Sleevi 2016/02/05 21:39:26 That's hard to answer, I think, in that you're ask
davidben 2016/02/05 21:46:48 I'm just asking if they do that right now. I agree
Ryan Sleevi 2016/02/05 21:52:11 Right, but I'm not sure that ambiguity is a proble
1557
1558 // Reverify without the CRLSet, to ensure that CRLSets do not persist between
1559 // separate calls. As in the first verification, the expected path is
1560 // A(B) -> B(F) -> F(E) -> E(E).
1561 error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
1562 &verify_result);
1563 ASSERT_EQ(OK, error);
1564 ASSERT_EQ(0U, verify_result.cert_status);
1565 ASSERT_TRUE(verify_result.verified_cert.get());
1566
1567 const X509Certificate::OSCertHandles& final_verified_intermediates =
1568 verify_result.verified_cert->GetIntermediateCertificates();
1569 ASSERT_EQ(3U, final_verified_intermediates.size());
1570 verified_root = X509Certificate::CreateFromHandle(
1571 final_verified_intermediates[2], X509Certificate::OSCertHandles());
1572 ASSERT_TRUE(verified_root.get());
1573 EXPECT_EQ("E Root CA", verified_root->subject().common_name);
1574 }
1575
1363 #endif 1576 #endif
1364 1577
1365 enum ExpectedAlgorithms { 1578 enum ExpectedAlgorithms {
1366 EXPECT_MD2 = 1 << 0, 1579 EXPECT_MD2 = 1 << 0,
1367 EXPECT_MD4 = 1 << 1, 1580 EXPECT_MD4 = 1 << 1,
1368 EXPECT_MD5 = 1 << 2, 1581 EXPECT_MD5 = 1 << 2,
1369 EXPECT_SHA1 = 1 << 3, 1582 EXPECT_SHA1 = 1 << 3,
1370 EXPECT_SHA1_LEAF = 1 << 4, 1583 EXPECT_SHA1_LEAF = 1 << 4,
1371 }; 1584 };
1372 1585
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 int flags = 0; 1918 int flags = 0;
1706 CertVerifyResult verify_result; 1919 CertVerifyResult verify_result;
1707 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, 1920 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_,
1708 &verify_result); 1921 &verify_result);
1709 EXPECT_EQ(ERR_CERT_INVALID, error); 1922 EXPECT_EQ(ERR_CERT_INVALID, error);
1710 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); 1923 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status);
1711 } 1924 }
1712 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 1925 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
1713 1926
1714 } // namespace net 1927 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/cert/cert_verify_proc_win.cc » ('j') | net/data/ssl/scripts/generate-multi-root-test-chains.sh » ('J')

Powered by Google App Engine
This is Rietveld 408576698