Commit 9091cacb authored by Chris Thompson's avatar Chris Thompson Committed by Commit Bot

[SCT Auditing] Only audit SCTs for certs issued from known roots

This is an initial solution for crbug.com/1129197 -- the full solution
is implemented in crrev.com/c/2422435 but requires changes to allow
mocking CT results in order to land.

This prevents logging private certificates, and adds a test explicitly
exercising this case. It also makes the browser tests a bit more robust
by tracking the last report seen by the test server and adding a step to
flush a new report through for negative tests.

Bug: 1129197
Change-Id: I7e1d4010b2666db7f98194aa1e3ba80df1e0a493
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2453777Reviewed-by: default avatarEmily Stark <estark@chromium.org>
Reviewed-by: default avatarDavid Schinazi <dschinazi@chromium.org>
Reviewed-by: default avatarNick Harper <nharper@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Kinuko Yasuda <kinuko@chromium.org>
Auto-Submit: Chris Thompson <cthomp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815086}
parent e835ae29
......@@ -1078,6 +1078,44 @@ TEST_P(SignedExchangeHandlerTest, SCTAuditingReportEnqueued) {
EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
}
// Test that SignedExchangeHandler does not enqueue SCT auditing reports if the
// certificate is not issued by a known root. Mirrors the
// `SCTAuditingReportEnqueued` test above, except that `is_issued_by_known_root`
// is set to false.
TEST_P(SignedExchangeHandlerTest, SCTAuditingReportNonPublicCertsNotReported) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
GetTestFileContents("test.example.org.public.pem.cbor"));
net::CertVerifyResult cert_result = CreateCertVerifyResult();
cert_result.is_issued_by_known_root = false;
SetupMockCertVerifier("prime256v1-sha256.public.pem", cert_result);
// The mock CT policy enforcer will return CT_POLICY_COMPLIES_VIA_SCTS, as
// configured in SetUp().
// Add SCTAuditingDelegate mock results.
EXPECT_CALL(*mock_sct_auditing_delegate_, IsSCTAuditingEnabled())
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_sct_auditing_delegate_, MaybeEnqueueReport(_, _, _))
.Times(0);
SetSourceStreamContents("test.example.org_test.sxg");
CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
std::string payload;
int rv = ReadPayloadStream(&payload);
std::string expected_payload = GetTestFileContents("test.html");
EXPECT_EQ(expected_payload, payload);
EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
}
INSTANTIATE_TEST_SUITE_P(SignedExchangeHandlerTests,
SignedExchangeHandlerTest,
::testing::Values(net::MockSourceStream::SYNC,
......
......@@ -477,7 +477,8 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
}
if (sct_auditing_delegate_ &&
sct_auditing_delegate_->IsSCTAuditingEnabled()) {
sct_auditing_delegate_->IsSCTAuditingEnabled() &&
cert_verify_result.is_issued_by_known_root) {
sct_auditing_delegate_->MaybeEnqueueReport(
HostPortPair(hostname_, port_),
cert_verify_result.verified_cert.get(), cert_verify_result.scts);
......
......@@ -1206,5 +1206,41 @@ TEST_F(ProofVerifierChromiumTest, SCTAuditingReportCollected) {
ASSERT_EQ(quic::QUIC_SUCCESS, status);
}
// Tests that the SCTAuditingDelegate is not called when a cert isn't issued
// from a known root. Mirrors `SCTAuditingReportCollected` test above, but with
// `is_issued_by_known_root` set to false. Note that QUIC fails for certs that
// aren't issued from known roots.
TEST_F(ProofVerifierChromiumTest, SCTAuditingNonPublicCertsNotReported) {
MockCertVerifier cert_verifier;
dummy_result_.is_issued_by_known_root = false;
cert_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
MockSCTAuditingDelegate sct_auditing_delegate;
EXPECT_CALL(sct_auditing_delegate, IsSCTAuditingEnabled())
.WillRepeatedly(Return(true));
HostPortPair host_port_pair(kTestHostname, kTestPort);
EXPECT_CALL(sct_auditing_delegate, MaybeEnqueueReport(host_port_pair, _, _))
.Times(0);
ProofVerifierChromium proof_verifier(
&cert_verifier, &ct_policy_enforcer_, &transport_security_state_,
ct_verifier_.get(), &sct_auditing_delegate, {}, NetworkIsolationKey());
auto callback = std::make_unique<DummyProofVerifierCallback>();
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
callback = std::make_unique<DummyProofVerifierCallback>();
status = proof_verifier.VerifyCertChain(
kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
}
} // namespace test
} // namespace net
......@@ -1607,7 +1607,8 @@ int SSLClientSocketImpl::VerifyCT() {
}
if (context_->sct_auditing_delegate() &&
context_->sct_auditing_delegate()->IsSCTAuditingEnabled()) {
context_->sct_auditing_delegate()->IsSCTAuditingEnabled() &&
server_cert_verify_result_.is_issued_by_known_root) {
context_->sct_auditing_delegate()->MaybeEnqueueReport(
host_and_port_, server_cert_verify_result_.verified_cert.get(),
server_cert_verify_result_.scts);
......
......@@ -2403,7 +2403,8 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id,
net::NetworkIsolationKey::Todo());
if (url_request_context_->sct_auditing_delegate() &&
url_request_context_->sct_auditing_delegate()->IsSCTAuditingEnabled()) {
url_request_context_->sct_auditing_delegate()->IsSCTAuditingEnabled() &&
pending_cert_verify->result->is_issued_by_known_root) {
url_request_context_->sct_auditing_delegate()->MaybeEnqueueReport(
net::HostPortPair::FromURL(pending_cert_verify->url), verified_cert,
pending_cert_verify->result->scts);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment