Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/ct_policy_enforcer.h" | 5 #include "net/cert/ct_policy_enforcer.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| 11 #include "base/version.h" | 11 #include "base/version.h" |
| 12 #include "crypto/rsa_private_key.h" | |
| 12 #include "crypto/sha2.h" | 13 #include "crypto/sha2.h" |
| 13 #include "net/base/test_data_directory.h" | 14 #include "net/base/test_data_directory.h" |
| 14 #include "net/cert/ct_ev_whitelist.h" | 15 #include "net/cert/ct_ev_whitelist.h" |
| 15 #include "net/cert/ct_policy_status.h" | 16 #include "net/cert/ct_policy_status.h" |
| 16 #include "net/cert/ct_verify_result.h" | 17 #include "net/cert/ct_verify_result.h" |
| 17 #include "net/cert/x509_certificate.h" | 18 #include "net/cert/x509_certificate.h" |
| 19 #include "net/cert/x509_util.h" | |
| 18 #include "net/test/cert_test_util.h" | 20 #include "net/test/cert_test_util.h" |
| 19 #include "net/test/ct_test_util.h" | 21 #include "net/test/ct_test_util.h" |
| 20 #include "testing/gmock/include/gmock/gmock.h" | 22 #include "testing/gmock/include/gmock/gmock.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 24 |
| 23 namespace net { | 25 namespace net { |
| 24 | 26 |
| 25 namespace { | 27 namespace { |
| 26 | 28 |
| 27 class DummyEVCertsWhitelist : public ct::EVCertsWhitelist { | 29 class DummyEVCertsWhitelist : public ct::EVCertsWhitelist { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 void FillListWithSCTsOfOrigin( | 122 void FillListWithSCTsOfOrigin( |
| 121 ct::SignedCertificateTimestamp::Origin desired_origin, | 123 ct::SignedCertificateTimestamp::Origin desired_origin, |
| 122 size_t num_scts, | 124 size_t num_scts, |
| 123 ct::SCTList* verified_scts) { | 125 ct::SCTList* verified_scts) { |
| 124 std::vector<std::string> desired_log_ids; | 126 std::vector<std::string> desired_log_ids; |
| 125 desired_log_ids.push_back(google_log_id_); | 127 desired_log_ids.push_back(google_log_id_); |
| 126 FillListWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, true, | 128 FillListWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, true, |
| 127 verified_scts); | 129 verified_scts); |
| 128 } | 130 } |
| 129 | 131 |
| 130 void CheckCertificateCompliesWithExactNumberOfEmbeddedSCTs( | |
| 131 const base::Time& start, | |
| 132 const base::Time& end, | |
| 133 size_t required_scts) { | |
| 134 scoped_refptr<X509Certificate> cert( | |
| 135 new X509Certificate("subject", "issuer", start, end)); | |
| 136 for (size_t i = 0; i < required_scts - 1; ++i) { | |
| 137 ct::SCTList scts; | |
| 138 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, i, | |
| 139 std::vector<std::string>(), false, &scts); | |
| 140 EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS, | |
| 141 policy_enforcer_->DoesConformToCertPolicy(cert.get(), scts, | |
| 142 BoundNetLog())) | |
| 143 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 144 << " scts=" << scts.size() << " i=" << i; | |
| 145 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS, | |
| 146 policy_enforcer_->DoesConformToCTEVPolicy(cert.get(), nullptr, | |
| 147 scts, BoundNetLog())) | |
| 148 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 149 << " scts=" << scts.size() << " i=" << i; | |
| 150 } | |
| 151 ct::SCTList scts; | |
| 152 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, | |
| 153 required_scts, std::vector<std::string>(), false, | |
| 154 &scts); | |
| 155 EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS, | |
| 156 policy_enforcer_->DoesConformToCertPolicy(cert.get(), scts, | |
| 157 BoundNetLog())) | |
| 158 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 159 << " scts=" << scts.size(); | |
| 160 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS, | |
| 161 policy_enforcer_->DoesConformToCTEVPolicy(cert.get(), nullptr, | |
| 162 scts, BoundNetLog())) | |
| 163 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 164 << " scts=" << scts.size(); | |
| 165 } | |
| 166 | |
| 167 protected: | 132 protected: |
| 168 std::unique_ptr<CTPolicyEnforcer> policy_enforcer_; | 133 std::unique_ptr<CTPolicyEnforcer> policy_enforcer_; |
| 169 scoped_refptr<X509Certificate> chain_; | 134 scoped_refptr<X509Certificate> chain_; |
| 170 std::string google_log_id_; | 135 std::string google_log_id_; |
| 171 std::string non_google_log_id_; | 136 std::string non_google_log_id_; |
| 172 }; | 137 }; |
| 173 | 138 |
| 174 TEST_F(CTPolicyEnforcerTest, | 139 TEST_F(CTPolicyEnforcerTest, |
| 175 DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle) { | 140 DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle) { |
| 176 ct::SCTList scts; | 141 ct::SCTList scts; |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. | 428 // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. |
| 464 // However, there are only 4 SCTs are from distinct logs. | 429 // However, there are only 4 SCTs are from distinct logs. |
| 465 EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS, | 430 EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS, |
| 466 policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts, | 431 policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts, |
| 467 BoundNetLog())); | 432 BoundNetLog())); |
| 468 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS, | 433 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS, |
| 469 policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr, | 434 policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr, |
| 470 scts, BoundNetLog())); | 435 scts, BoundNetLog())); |
| 471 } | 436 } |
| 472 | 437 |
| 473 // TODO(estark): fix this test so that it can check if | |
| 474 // |no_valid_dates_cert| is on the whitelist without | |
| 475 // crashing. https://crbug.com/582740 | |
| 476 TEST_F(CTPolicyEnforcerTest, DISABLED_DoesNotConformToPolicyInvalidDates) { | |
| 477 scoped_refptr<X509Certificate> no_valid_dates_cert(new X509Certificate( | |
| 478 "subject", "issuer", base::Time(), base::Time::Now())); | |
| 479 ct::SCTList scts; | |
| 480 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5, | |
| 481 &scts); | |
| 482 ASSERT_TRUE(no_valid_dates_cert); | |
| 483 EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS, | |
| 484 policy_enforcer_->DoesConformToCertPolicy(no_valid_dates_cert.get(), | |
| 485 scts, BoundNetLog())); | |
| 486 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS, | |
| 487 policy_enforcer_->DoesConformToCTEVPolicy( | |
| 488 no_valid_dates_cert.get(), nullptr, scts, BoundNetLog())); | |
| 489 // ... but should be OK if whitelisted. | |
| 490 scoped_refptr<ct::EVCertsWhitelist> whitelist( | |
| 491 new DummyEVCertsWhitelist(true, true)); | |
| 492 EXPECT_EQ( | |
| 493 ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST, | |
| 494 policy_enforcer_->DoesConformToCTEVPolicy( | |
| 495 no_valid_dates_cert.get(), whitelist.get(), scts, BoundNetLog())); | |
| 496 } | |
| 497 | |
| 498 TEST_F(CTPolicyEnforcerTest, | 438 TEST_F(CTPolicyEnforcerTest, |
| 499 ConformsToPolicyExactNumberOfSCTsForValidityPeriod) { | 439 ConformsToPolicyExactNumberOfSCTsForValidityPeriod) { |
| 440 std::unique_ptr<crypto::RSAPrivateKey> private_key( | |
| 441 crypto::RSAPrivateKey::Create(1024)); | |
| 442 ASSERT_TRUE(private_key); | |
| 443 | |
| 500 // Test multiple validity periods | 444 // Test multiple validity periods |
| 501 const struct TestData { | 445 const struct TestData { |
| 502 base::Time validity_start; | 446 base::Time validity_start; |
| 503 base::Time validity_end; | 447 base::Time validity_end; |
| 504 size_t scts_required; | 448 size_t scts_required; |
| 505 } kTestData[] = {{// Cert valid for 14 months, needs 2 SCTs. | 449 } kTestData[] = {{// Cert valid for 14 months, needs 2 SCTs. |
| 506 base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}), | 450 base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}), |
| 507 base::Time::FromUTCExploded({2016, 6, 0, 6, 11, 25, 0, 0}), | 451 base::Time::FromUTCExploded({2016, 6, 0, 6, 11, 25, 0, 0}), |
| 508 2}, | 452 2}, |
| 509 {// Cert valid for exactly 15 months, needs 3 SCTs. | 453 {// Cert valid for exactly 15 months, needs 3 SCTs. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 526 base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}), | 470 base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}), |
| 527 base::Time::FromUTCExploded({2018, 6, 0, 25, 11, 25, 0, 0}), | 471 base::Time::FromUTCExploded({2018, 6, 0, 25, 11, 25, 0, 0}), |
| 528 4}, | 472 4}, |
| 529 {// Cert valid for over 39 months, needs 5 SCTs. | 473 {// Cert valid for over 39 months, needs 5 SCTs. |
| 530 base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}), | 474 base::Time::FromUTCExploded({2015, 3, 0, 25, 11, 25, 0, 0}), |
| 531 base::Time::FromUTCExploded({2018, 6, 0, 27, 11, 25, 0, 0}), | 475 base::Time::FromUTCExploded({2018, 6, 0, 27, 11, 25, 0, 0}), |
| 532 5}}; | 476 5}}; |
| 533 | 477 |
| 534 for (size_t i = 0; i < arraysize(kTestData); ++i) { | 478 for (size_t i = 0; i < arraysize(kTestData); ++i) { |
| 535 SCOPED_TRACE(i); | 479 SCOPED_TRACE(i); |
| 536 CheckCertificateCompliesWithExactNumberOfEmbeddedSCTs( | 480 const base::Time& start = kTestData[i].validity_start; |
|
eroman
2016/06/22 16:51:08
optional: could instead alias kTestData[i]
| |
| 537 kTestData[i].validity_start, kTestData[i].validity_end, | 481 const base::Time& end = kTestData[i].validity_end; |
| 538 kTestData[i].scts_required); | 482 size_t required_scts = kTestData[i].scts_required; |
| 483 | |
| 484 // Create a self-signed certificate with exactly the validity period. | |
| 485 std::string cert_data; | |
| 486 ASSERT_TRUE(x509_util::CreateSelfSignedCert( | |
| 487 private_key.get(), x509_util::DIGEST_SHA256, "CN=test", | |
| 488 i * 10 + required_scts, start, end, &cert_data)); | |
| 489 scoped_refptr<X509Certificate> cert( | |
| 490 X509Certificate::CreateFromBytes(cert_data.data(), cert_data.size())); | |
| 491 ASSERT_TRUE(cert); | |
| 492 | |
| 493 for (size_t i = 0; i < required_scts - 1; ++i) { | |
| 494 ct::SCTList scts; | |
| 495 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, i, | |
| 496 std::vector<std::string>(), false, &scts); | |
| 497 EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS, | |
| 498 policy_enforcer_->DoesConformToCertPolicy(cert.get(), scts, | |
| 499 BoundNetLog())) | |
| 500 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 501 << " scts=" << scts.size() << " i=" << i; | |
| 502 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS, | |
| 503 policy_enforcer_->DoesConformToCTEVPolicy(cert.get(), nullptr, | |
| 504 scts, BoundNetLog())) | |
| 505 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 506 << " scts=" << scts.size() << " i=" << i; | |
| 507 } | |
| 508 ct::SCTList scts; | |
| 509 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, | |
| 510 required_scts, std::vector<std::string>(), false, | |
| 511 &scts); | |
| 512 EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS, | |
| 513 policy_enforcer_->DoesConformToCertPolicy(cert.get(), scts, | |
| 514 BoundNetLog())) | |
| 515 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 516 << " scts=" << scts.size(); | |
| 517 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS, | |
| 518 policy_enforcer_->DoesConformToCTEVPolicy(cert.get(), nullptr, | |
| 519 scts, BoundNetLog())) | |
| 520 << " for: " << (end - start).InDays() << " and " << required_scts | |
| 521 << " scts=" << scts.size(); | |
| 539 } | 522 } |
| 540 } | 523 } |
| 541 | 524 |
| 542 TEST_F(CTPolicyEnforcerTest, ConformsToPolicyByEVWhitelistPresence) { | 525 TEST_F(CTPolicyEnforcerTest, ConformsToPolicyByEVWhitelistPresence) { |
| 543 scoped_refptr<ct::EVCertsWhitelist> whitelist( | 526 scoped_refptr<ct::EVCertsWhitelist> whitelist( |
| 544 new DummyEVCertsWhitelist(true, true)); | 527 new DummyEVCertsWhitelist(true, true)); |
| 545 | 528 |
| 546 ct::SCTList scts; | 529 ct::SCTList scts; |
| 547 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 2, | 530 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 2, |
| 548 &scts); | 531 &scts); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 571 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 2, | 554 FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 2, |
| 572 &scts); | 555 &scts); |
| 573 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS, | 556 EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS, |
| 574 policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr, | 557 policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr, |
| 575 scts, BoundNetLog())); | 558 scts, BoundNetLog())); |
| 576 } | 559 } |
| 577 | 560 |
| 578 } // namespace | 561 } // namespace |
| 579 | 562 |
| 580 } // namespace net | 563 } // namespace net |
| OLD | NEW |