Chromium Code Reviews| 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 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1353 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | 1353 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); |
| 1354 | 1354 |
| 1355 error = Verify(leaf.get(), | 1355 error = Verify(leaf.get(), |
| 1356 "test.example.com", | 1356 "test.example.com", |
| 1357 flags, | 1357 flags, |
| 1358 crl_set.get(), | 1358 crl_set.get(), |
| 1359 empty_cert_list_, | 1359 empty_cert_list_, |
| 1360 &verify_result); | 1360 &verify_result); |
| 1361 EXPECT_EQ(ERR_CERT_REVOKED, error); | 1361 EXPECT_EQ(ERR_CERT_REVOKED, error); |
| 1362 } | 1362 } |
| 1363 | |
| 1364 // Test that when multiple paths exist for a certificate to be verified, and | |
| 1365 // one of them is revoked by a CRLSet, that the alternate and still valid | |
| 1366 // paths are considered. | |
| 1367 // This tests when the leaf (A) is issued by B, which is issued by C. Two | |
| 1368 // different versions of C exist, but both versions are signed by a trust | |
| 1369 // anchor (D and F, respectively). | |
| 1370 TEST_F(CertVerifyProcTest, CRLSetRevokedIntermediateSameName) { | |
| 1371 // Load the supplemental certificates for path building (B, C) into memory. | |
| 1372 CertificateList ca_cert_list = CreateCertificateListFromFile( | |
| 1373 GetTestCertsDirectory(), "multi-root-chain1.pem", | |
|
davidben
2016/01/21 02:37:39
Seeing as the tests themselves disassemble the pre
| |
| 1374 X509Certificate::FORMAT_AUTO); | |
| 1375 ASSERT_EQ(4U, ca_cert_list.size()); | |
| 1376 | |
| 1377 // Add the "D" test root. | |
| 1378 ScopedTestRoot test_root(ca_cert_list[3].get()); | |
| 1379 | |
| 1380 CertificateList cert_list = CreateCertificateListFromFile( | |
| 1381 GetTestCertsDirectory(), "multi-root-chain3.pem", | |
| 1382 X509Certificate::FORMAT_AUTO); | |
| 1383 ASSERT_EQ(4U, cert_list.size()); | |
| 1384 | |
| 1385 // Add the "F" test root. | |
| 1386 ScopedTestRoot second_test_root(cert_list[3].get()); | |
| 1387 | |
| 1388 // Create a certificate chain that sends | |
| 1389 // A -> B -> C3 -> C | |
| 1390 // This is way of ensuring that both versions of C are supplied as | |
| 1391 // supplemental certificates to be verified. The | |
| 1392 // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts test ensures that | |
| 1393 // these should not negatively impact chain building, as they would otherwise | |
| 1394 // be treated as 'ignorable' certificates. | |
| 1395 X509Certificate::OSCertHandles intermediates; | |
| 1396 intermediates.push_back(cert_list[1]->os_cert_handle()); | |
| 1397 intermediates.push_back(cert_list[2]->os_cert_handle()); | |
| 1398 intermediates.push_back(ca_cert_list[2]->os_cert_handle()); | |
| 1399 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
| 1400 cert_list[0]->os_cert_handle(), intermediates); | |
| 1401 ASSERT_TRUE(cert.get()); | |
| 1402 | |
| 1403 // Verify that, without any revocation, things verify successfully and | |
| 1404 // prefer the newer (to be revoked) certificate. | |
| 1405 int flags = 0; | |
| 1406 CertVerifyResult verify_result; | |
| 1407 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | |
| 1408 &verify_result); | |
| 1409 ASSERT_EQ(OK, error); | |
| 1410 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1411 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1412 | |
| 1413 // Ensure the first / newest chain provided is preferred - as this is the | |
| 1414 // chain that will subsequently be revoked. | |
| 1415 // The expected path is A -> B -> C3 -> F | |
| 1416 const X509Certificate::OSCertHandles& verified_intermediates = | |
| 1417 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1418 ASSERT_EQ(3U, verified_intermediates.size()); | |
| 1419 scoped_refptr<X509Certificate> verified_root = | |
| 1420 X509Certificate::CreateFromHandle(verified_intermediates[2], | |
| 1421 X509Certificate::OSCertHandles()); | |
| 1422 ASSERT_TRUE(verified_root.get()); | |
| 1423 EXPECT_EQ("F Root CA", verified_root->subject().common_name); | |
|
davidben
2016/01/21 02:37:39
It seems these tests could do with a few helper fu
Ryan Sleevi
2016/01/21 02:54:04
This is strongly discouraged by our internal testi
| |
| 1424 | |
| 1425 // Now test by blocking the C3-by-F intermediate, which should result | |
| 1426 // in a path of A -> B -> C -> D | |
| 1427 scoped_refptr<CRLSet> crl_set; | |
| 1428 std::string crl_set_bytes; | |
| 1429 EXPECT_TRUE(base::ReadFileToString( | |
| 1430 GetTestCertsDirectory().AppendASCII("multi-root-crlset-C3.raw"), | |
| 1431 &crl_set_bytes)); | |
| 1432 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1433 | |
| 1434 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), | |
| 1435 empty_cert_list_, &verify_result); | |
| 1436 ASSERT_EQ(OK, error); | |
| 1437 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1438 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1439 | |
| 1440 const X509Certificate::OSCertHandles& new_verified_intermediates = | |
| 1441 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1442 ASSERT_EQ(3U, new_verified_intermediates.size()); | |
| 1443 verified_root = X509Certificate::CreateFromHandle( | |
| 1444 new_verified_intermediates[2], X509Certificate::OSCertHandles()); | |
| 1445 ASSERT_TRUE(verified_root.get()); | |
| 1446 EXPECT_EQ("D Root CA", verified_root->subject().common_name); | |
| 1447 | |
| 1448 // Now reverify the cert without the CRLSet, to ensure that the CRLSet does | |
| 1449 // not persist in between independent calls. | |
| 1450 error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | |
| 1451 &verify_result); | |
| 1452 ASSERT_EQ(OK, error); | |
| 1453 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1454 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1455 | |
| 1456 // The expected path is A -> B -> C3 -> F | |
| 1457 const X509Certificate::OSCertHandles& final_verified_intermediates = | |
| 1458 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1459 ASSERT_EQ(3U, final_verified_intermediates.size()); | |
| 1460 verified_root = X509Certificate::CreateFromHandle( | |
| 1461 final_verified_intermediates[2], X509Certificate::OSCertHandles()); | |
| 1462 ASSERT_TRUE(verified_root.get()); | |
| 1463 EXPECT_EQ("F Root CA", verified_root->subject().common_name); | |
| 1464 } | |
| 1465 | |
| 1466 // Test that when multiple paths exist for a certificate to be verified, and | |
| 1467 // one of them is revoked by a CRLSet, that the alternate and still valid | |
| 1468 // paths are considered. | |
| 1469 // This tests when the leaf (A) is issued by B. Two versions of B | |
| 1470 // exist - one that goes to G and one that goes to C. Both G and C | |
| 1471 // are signed by trust anchors (F and D/E/F, respectively). This tests | |
| 1472 // the ability of path building to explore an edge where the immediate | |
| 1473 // certificate is not revoked, but the issuer is (in this case, G) - and thus | |
| 1474 // needs to backtrack to find the alternative path (B -> C -> D) | |
| 1475 TEST_F(CertVerifyProcTest, CRLSetRevokedIntermediateCrossIntermediates) { | |
| 1476 // Load the supplemental certificates for path building (B, C) into memory. | |
| 1477 CertificateList ca_cert_list = CreateCertificateListFromFile( | |
| 1478 GetTestCertsDirectory(), "multi-root-chain1.pem", | |
| 1479 X509Certificate::FORMAT_AUTO); | |
| 1480 ASSERT_EQ(4U, ca_cert_list.size()); | |
| 1481 | |
| 1482 // Add the "D" test root. | |
| 1483 ScopedTestRoot test_root(ca_cert_list[3].get()); | |
| 1484 | |
| 1485 CertificateList cert_list = CreateCertificateListFromFile( | |
| 1486 GetTestCertsDirectory(), "multi-root-chain4.pem", | |
| 1487 X509Certificate::FORMAT_AUTO); | |
| 1488 ASSERT_EQ(4U, cert_list.size()); | |
| 1489 | |
| 1490 // Add the "F" test root. | |
| 1491 ScopedTestRoot second_test_root(cert_list[3].get()); | |
| 1492 | |
| 1493 // Create a certificate chain that sends | |
| 1494 // A -> B2 -> G -> B -> C | |
| 1495 // This is way of ensuring that both B and C are supplied as supplemental | |
| 1496 // certificates to be verified. The | |
| 1497 // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts test ensures that | |
| 1498 // these should not negatively impact chain building, as they would otherwise | |
| 1499 // be treated as 'ignorable' certificates. | |
| 1500 X509Certificate::OSCertHandles intermediates; | |
| 1501 intermediates.push_back(cert_list[1]->os_cert_handle()); | |
| 1502 intermediates.push_back(cert_list[2]->os_cert_handle()); | |
| 1503 intermediates.push_back(ca_cert_list[1]->os_cert_handle()); | |
| 1504 intermediates.push_back(ca_cert_list[2]->os_cert_handle()); | |
| 1505 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
| 1506 cert_list[0]->os_cert_handle(), intermediates); | |
| 1507 ASSERT_TRUE(cert.get()); | |
| 1508 | |
| 1509 // Verify that, without any revocation, things verify successfully and | |
| 1510 // prefer the newer (to be revoked) certificate. | |
| 1511 int flags = 0; | |
| 1512 CertVerifyResult verify_result; | |
| 1513 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | |
| 1514 &verify_result); | |
| 1515 ASSERT_EQ(OK, error); | |
| 1516 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1517 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1518 | |
| 1519 // Ensure the first / newest chain provided is preferred - as this is the | |
| 1520 // chain that will subsequently be revoked. | |
| 1521 // The expected path is A -> B2 -> G -> F | |
| 1522 const X509Certificate::OSCertHandles& verified_intermediates = | |
| 1523 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1524 ASSERT_EQ(3U, verified_intermediates.size()); | |
| 1525 scoped_refptr<X509Certificate> verified_root = | |
| 1526 X509Certificate::CreateFromHandle(verified_intermediates[2], | |
| 1527 X509Certificate::OSCertHandles()); | |
| 1528 ASSERT_TRUE(verified_root.get()); | |
| 1529 EXPECT_EQ("F Root CA", verified_root->subject().common_name); | |
| 1530 scoped_refptr<X509Certificate> verified_intermediate = | |
| 1531 X509Certificate::CreateFromHandle(verified_intermediates[1], | |
| 1532 X509Certificate::OSCertHandles()); | |
| 1533 ASSERT_TRUE(verified_intermediate.get()); | |
| 1534 EXPECT_EQ("G CA", verified_intermediate->subject().common_name); | |
| 1535 | |
| 1536 // Now test by blocking the G-by-F intermediate, which should result | |
| 1537 // in a path of A -> B -> C -> D | |
| 1538 scoped_refptr<CRLSet> crl_set; | |
| 1539 std::string crl_set_bytes; | |
| 1540 EXPECT_TRUE(base::ReadFileToString( | |
| 1541 GetTestCertsDirectory().AppendASCII("multi-root-crlset-G.raw"), | |
| 1542 &crl_set_bytes)); | |
| 1543 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1544 | |
| 1545 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), | |
| 1546 empty_cert_list_, &verify_result); | |
| 1547 ASSERT_EQ(OK, error); | |
| 1548 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1549 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1550 | |
| 1551 const X509Certificate::OSCertHandles& new_verified_intermediates = | |
| 1552 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1553 ASSERT_EQ(3U, new_verified_intermediates.size()); | |
| 1554 verified_root = X509Certificate::CreateFromHandle( | |
| 1555 new_verified_intermediates[2], X509Certificate::OSCertHandles()); | |
| 1556 ASSERT_TRUE(verified_root.get()); | |
| 1557 EXPECT_EQ("D Root CA", verified_root->subject().common_name); | |
| 1558 | |
| 1559 // Now reverify the cert without the CRLSet, to ensure that the CRLSet does | |
| 1560 // not persist in between independent calls. | |
| 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("F Root CA", verified_root->subject().common_name); | |
| 1574 } | |
| 1575 | |
| 1576 // Test that when multiple paths exist for a certificate to be verified, and | |
| 1577 // one of them is revoked by a CRLSet, that the alternate and still valid | |
| 1578 // paths are considered. | |
| 1579 // This tests a variety of situations in which a CA has cyclicly certified | |
| 1580 // the certificates (e.g. Root J signed Root K, and Root K signed Root J). | |
| 1581 // When both of these roots are present in the trust store (J and K), but | |
| 1582 // one is revoked (K), paths should build and terminate in J. | |
| 1583 // This tests when the leaf (A) is issued by B. Two versions of B | |
| 1584 // exist - one that goes to G and one that goes to C. Both G and C | |
| 1585 // are signed by trust anchors (F and D/E/F, respectively). This tests | |
| 1586 // the ability of path building to explore an edge where the immediate | |
| 1587 // certificate is not revoked, but the issuer is (in this case, G) - and thus | |
| 1588 // needs to backtrack to find the alternative path (B -> C -> D) | |
| 1589 TEST_F(CertVerifyProcTest, CRLSetRevokedCyclicPathBuilding) { | |
| 1590 // Load the supplemental certificates for path building (B, C) into memory. | |
| 1591 CertificateList ca_cert_list = CreateCertificateListFromFile( | |
| 1592 GetTestCertsDirectory(), "multi-root-chain5.pem", | |
| 1593 X509Certificate::FORMAT_AUTO); | |
| 1594 ASSERT_EQ(3U, ca_cert_list.size()); | |
| 1595 | |
| 1596 struct TestData { | |
| 1597 // The name of the chain file to load. | |
| 1598 const char* const filename; | |
| 1599 // The expected length of the (parsed, validated) chain. | |
| 1600 const size_t chain_length; | |
| 1601 } kTestChains[] = { | |
| 1602 {"multi-root-chain6.pem", 4}, | |
| 1603 {"multi-root-chain7.pem", 5}, | |
| 1604 {"multi-root-chain8.pem", 6}, | |
| 1605 }; | |
| 1606 for (const auto& test_case : kTestChains) { | |
| 1607 SCOPED_TRACE(test_case.filename); | |
| 1608 | |
| 1609 CertificateList cert_list = CreateCertificateListFromFile( | |
| 1610 GetTestCertsDirectory(), test_case.filename, | |
| 1611 X509Certificate::FORMAT_AUTO); | |
| 1612 ASSERT_EQ(test_case.chain_length, cert_list.size()); | |
| 1613 | |
| 1614 // Add the "J" test root. | |
| 1615 ScopedTestRoot test_root(ca_cert_list[2].get()); | |
| 1616 | |
| 1617 // Add the chain root as a test root | |
| 1618 ScopedTestRoot second_test_root(cert_list.back().get()); | |
| 1619 | |
| 1620 // Create a certificate chain that sends everything but the last | |
| 1621 // certificate. | |
| 1622 cert_list.pop_back(); | |
| 1623 X509Certificate::OSCertHandles intermediates; | |
| 1624 for (size_t i = 1; i < cert_list.size(); ++i) { | |
| 1625 intermediates.push_back(cert_list[i]->os_cert_handle()); | |
| 1626 } | |
| 1627 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
| 1628 cert_list[0]->os_cert_handle(), intermediates); | |
| 1629 ASSERT_TRUE(cert.get()); | |
| 1630 | |
| 1631 // Verify that, without any revocation, the certificate verifies | |
| 1632 // successfully. | |
| 1633 int flags = 0; | |
| 1634 CertVerifyResult verify_result; | |
| 1635 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | |
| 1636 &verify_result); | |
| 1637 ASSERT_EQ(OK, error); | |
| 1638 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1639 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1640 | |
| 1641 // Now test by blocking K, which should result in a path of H -> I -> J | |
| 1642 scoped_refptr<CRLSet> crl_set; | |
| 1643 std::string crl_set_bytes; | |
| 1644 EXPECT_TRUE(base::ReadFileToString( | |
| 1645 GetTestCertsDirectory().AppendASCII("multi-root-crlset-K.raw"), | |
| 1646 &crl_set_bytes)); | |
| 1647 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1648 | |
| 1649 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), | |
| 1650 empty_cert_list_, &verify_result); | |
| 1651 ASSERT_EQ(OK, error); | |
| 1652 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1653 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1654 | |
| 1655 const X509Certificate::OSCertHandles& new_verified_intermediates = | |
| 1656 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1657 ASSERT_EQ(2U, new_verified_intermediates.size()); | |
| 1658 scoped_refptr<X509Certificate> verified_root = | |
| 1659 X509Certificate::CreateFromHandle(new_verified_intermediates[1], | |
| 1660 X509Certificate::OSCertHandles()); | |
| 1661 ASSERT_TRUE(verified_root.get()); | |
| 1662 EXPECT_EQ("J Root CA", verified_root->subject().common_name); | |
| 1663 } | |
| 1664 } | |
| 1665 | |
| 1363 #endif | 1666 #endif |
| 1364 | 1667 |
| 1365 enum ExpectedAlgorithms { | 1668 enum ExpectedAlgorithms { |
| 1366 EXPECT_MD2 = 1 << 0, | 1669 EXPECT_MD2 = 1 << 0, |
| 1367 EXPECT_MD4 = 1 << 1, | 1670 EXPECT_MD4 = 1 << 1, |
| 1368 EXPECT_MD5 = 1 << 2, | 1671 EXPECT_MD5 = 1 << 2, |
| 1369 EXPECT_SHA1 = 1 << 3, | 1672 EXPECT_SHA1 = 1 << 3, |
| 1370 EXPECT_SHA1_LEAF = 1 << 4, | 1673 EXPECT_SHA1_LEAF = 1 << 4, |
| 1371 }; | 1674 }; |
| 1372 | 1675 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1705 int flags = 0; | 2008 int flags = 0; |
| 1706 CertVerifyResult verify_result; | 2009 CertVerifyResult verify_result; |
| 1707 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, | 2010 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, |
| 1708 &verify_result); | 2011 &verify_result); |
| 1709 EXPECT_EQ(ERR_CERT_INVALID, error); | 2012 EXPECT_EQ(ERR_CERT_INVALID, error); |
| 1710 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); | 2013 EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); |
| 1711 } | 2014 } |
| 1712 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 2015 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 1713 | 2016 |
| 1714 } // namespace net | 2017 } // namespace net |
| OLD | NEW |