summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/cert/ct_policy_enforcer.cc86
-rw-r--r--net/cert/ct_policy_enforcer.h28
-rw-r--r--net/cert/ct_policy_enforcer_unittest.cc79
-rw-r--r--net/cert/ct_policy_status.h39
-rw-r--r--net/cert/ct_verify_result.cc6
-rw-r--r--net/cert/ct_verify_result.h15
-rw-r--r--net/net.gypi1
-rw-r--r--net/quic/crypto/proof_verifier_chromium.cc18
-rw-r--r--net/quic/crypto/proof_verifier_chromium_test.cc24
-rw-r--r--net/quic/quic_chromium_client_session.cc2
-rw-r--r--net/socket/ssl_client_socket_nss.cc22
-rw-r--r--net/socket/ssl_client_socket_nss.h2
-rw-r--r--net/socket/ssl_client_socket_openssl.cc22
-rw-r--r--net/socket/ssl_client_socket_openssl.h5
-rw-r--r--net/socket/ssl_client_socket_unittest.cc15
-rw-r--r--net/ssl/ssl_info.cc14
-rw-r--r--net/ssl/ssl_info.h32
17 files changed, 280 insertions, 130 deletions
diff --git a/net/cert/ct_policy_enforcer.cc b/net/cert/ct_policy_enforcer.cc
index 32181d4..aa8838b 100644
--- a/net/cert/ct_policy_enforcer.cc
+++ b/net/cert/ct_policy_enforcer.cc
@@ -19,6 +19,7 @@
#include "base/version.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_known_logs.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/x509_certificate.h"
@@ -78,11 +79,10 @@ void RoundedDownMonthDifference(const base::Time& start,
}
bool HasRequiredNumberOfSCTs(const X509Certificate& cert,
- const ct::CTVerifyResult& ct_result) {
- size_t num_valid_scts = ct_result.verified_scts.size();
+ const ct::SCTList& verified_scts) {
+ size_t num_valid_scts = verified_scts.size();
size_t num_embedded_scts = base::checked_cast<size_t>(
- std::count_if(ct_result.verified_scts.begin(),
- ct_result.verified_scts.end(), IsEmbeddedSCT));
+ std::count_if(verified_scts.begin(), verified_scts.end(), IsEmbeddedSCT));
size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts;
// If at least two valid SCTs were delivered by means other than embedding
@@ -166,8 +166,8 @@ enum EVWhitelistStatus {
EV_WHITELIST_MAX,
};
-void LogCTComplianceStatusToUMA(CTComplianceStatus status,
- const ct::EVCertsWhitelist* ev_whitelist) {
+void LogCTEVComplianceStatusToUMA(CTComplianceStatus status,
+ const ct::EVCertsWhitelist* ev_whitelist) {
UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status,
CT_COMPLIANCE_MAX);
if (status == CT_NOT_COMPLIANT) {
@@ -185,18 +185,11 @@ void LogCTComplianceStatusToUMA(CTComplianceStatus status,
}
struct ComplianceDetails {
- ComplianceDetails()
- : ct_presence_required(false),
- build_timely(false),
- status(CT_NOT_COMPLIANT) {}
-
- // Whether enforcement of the policy was required or not.
- bool ct_presence_required;
- // Whether the build is not older than 10 weeks. The value is meaningful only
- // if |ct_presence_required| is true.
+ ComplianceDetails() : build_timely(false), status(CT_NOT_COMPLIANT) {}
+
+ // Whether the build is not older than 10 weeks.
bool build_timely;
- // Compliance status - meaningful only if |ct_presence_required| and
- // |build_timely| are true.
+ // Compliance status - meaningful only if |build_timely| is true.
CTComplianceStatus status;
// EV whitelist version.
base::Version whitelist_version;
@@ -208,17 +201,14 @@ scoped_ptr<base::Value> NetLogComplianceCheckResultCallback(
NetLogCaptureMode capture_mode) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode));
- dict->SetBoolean("policy_enforcement_required",
- details->ct_presence_required);
- if (details->ct_presence_required) {
- dict->SetBoolean("build_timely", details->build_timely);
- if (details->build_timely) {
- dict->SetString("ct_compliance_status",
- ComplianceStatusToString(details->status));
- if (details->whitelist_version.IsValid())
- dict->SetString("ev_whitelist_version",
- details->whitelist_version.GetString());
- }
+ dict->SetBoolean("policy_enforcement_required", true);
+ dict->SetBoolean("build_timely", details->build_timely);
+ if (details->build_timely) {
+ dict->SetString("ct_compliance_status",
+ ComplianceStatusToString(details->status));
+ if (details->whitelist_version.IsValid())
+ dict->SetString("ev_whitelist_version",
+ details->whitelist_version.GetString());
}
return std::move(dict);
}
@@ -259,10 +249,8 @@ bool IsCertificateInWhitelist(const X509Certificate& cert,
void CheckCTEVPolicyCompliance(X509Certificate* cert,
const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
+ const ct::SCTList& verified_scts,
ComplianceDetails* result) {
- result->ct_presence_required = true;
-
if (!IsBuildTimely())
return;
result->build_timely = true;
@@ -275,14 +263,13 @@ void CheckCTEVPolicyCompliance(X509Certificate* cert,
return;
}
- if (!HasRequiredNumberOfSCTs(*cert, ct_result)) {
+ if (!HasRequiredNumberOfSCTs(*cert, verified_scts)) {
result->status = CT_NOT_COMPLIANT;
return;
}
- if (AllSCTsPastDistinctSCTRequirementEnforcementDate(
- ct_result.verified_scts) &&
- !HasEnoughDiverseSCTs(ct_result.verified_scts)) {
+ if (AllSCTsPastDistinctSCTRequirementEnforcementDate(verified_scts) &&
+ !HasEnoughDiverseSCTs(verified_scts)) {
result->status = CT_NOT_ENOUGH_DIVERSE_SCTS;
return;
}
@@ -292,14 +279,14 @@ void CheckCTEVPolicyCompliance(X509Certificate* cert,
} // namespace
-bool CTPolicyEnforcer::DoesConformToCTEVPolicy(
+ct::EVPolicyCompliance CTPolicyEnforcer::DoesConformToCTEVPolicy(
X509Certificate* cert,
const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
+ const ct::SCTList& verified_scts,
const BoundNetLog& net_log) {
ComplianceDetails details;
- CheckCTEVPolicyCompliance(cert, ev_whitelist, ct_result, &details);
+ CheckCTEVPolicyCompliance(cert, ev_whitelist, verified_scts, &details);
NetLog::ParametersCallback net_log_callback =
base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert),
@@ -308,18 +295,25 @@ bool CTPolicyEnforcer::DoesConformToCTEVPolicy(
net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED,
net_log_callback);
- if (!details.ct_presence_required)
- return true;
-
if (!details.build_timely)
- return false;
+ return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY;
- LogCTComplianceStatusToUMA(details.status, ev_whitelist);
+ LogCTEVComplianceStatusToUMA(details.status, ev_whitelist);
- if (details.status == CT_IN_WHITELIST || details.status == CT_ENOUGH_SCTS)
- return true;
+ switch (details.status) {
+ case CT_NOT_COMPLIANT:
+ return ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS;
+ case CT_IN_WHITELIST:
+ return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST;
+ case CT_ENOUGH_SCTS:
+ return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS;
+ case CT_NOT_ENOUGH_DIVERSE_SCTS:
+ return ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS;
+ case CT_COMPLIANCE_MAX:
+ return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
+ }
- return false;
+ return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
}
} // namespace net
diff --git a/net/cert/ct_policy_enforcer.h b/net/cert/ct_policy_enforcer.h
index 8c29da5e..a2db8f0 100644
--- a/net/cert/ct_policy_enforcer.h
+++ b/net/cert/ct_policy_enforcer.h
@@ -1,25 +1,30 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
#ifndef NET_CERT_CT_POLICY_ENFORCER_H
#define NET_CERT_CT_POLICY_ENFORCER_H
#include <stddef.h>
+#include <vector>
#include "net/base/net_export.h"
+#include "net/cert/signed_certificate_timestamp.h"
#include "net/log/net_log.h"
namespace net {
namespace ct {
-struct CTVerifyResult;
class EVCertsWhitelist;
+enum class EVPolicyCompliance;
} // namespace ct
class X509Certificate;
+using SCTList = std::vector<scoped_refptr<ct::SignedCertificateTimestamp>>;
+
// Class for checking that a given certificate conforms to security-related
// policies.
class NET_EXPORT CTPolicyEnforcer {
@@ -27,16 +32,17 @@ class NET_EXPORT CTPolicyEnforcer {
CTPolicyEnforcer() {}
virtual ~CTPolicyEnforcer() {}
- // Returns true if the collection of SCTs for the given certificate
- // conforms with the CT/EV policy. Conformance details are logged to
- // |net_log|.
- // |cert| is the certificate for which the SCTs apply.
- // |ct_result| must contain the result of verifying any SCTs associated with
- // |cert| prior to invoking this method.
- virtual bool DoesConformToCTEVPolicy(X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
- const BoundNetLog& net_log);
+ // Returns the CT/EV policy compliance status for a given certificate
+ // and collection of SCTs.
+ // |cert| is the certificate for which to check compliance, and
+ // |verified_scts| contains any/all SCTs associated with |cert| that
+ // have been verified (well-formed, issued by known logs, and applying to
+ // |cert|).
+ virtual ct::EVPolicyCompliance DoesConformToCTEVPolicy(
+ X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const SCTList& verified_scts,
+ const BoundNetLog& net_log);
};
} // namespace net
diff --git a/net/cert/ct_policy_enforcer_unittest.cc b/net/cert/ct_policy_enforcer_unittest.cc
index 4355252..c6c61b3 100644
--- a/net/cert/ct_policy_enforcer_unittest.cc
+++ b/net/cert/ct_policy_enforcer_unittest.cc
@@ -12,6 +12,7 @@
#include "crypto/sha2.h"
#include "net/base/test_data_directory.h"
#include "net/cert/ct_ev_whitelist.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/test/cert_test_util.h"
@@ -65,6 +66,8 @@ class CTPolicyEnforcerTest : public ::testing::Test {
non_google_log_id_.assign(crypto::kSHA256Length, 'A');
}
+ // TODO(eranm): Remove the use of CTVerifyResult in this file and just
+ // use lists of verified SCTs. https://crbug.com/587921
void FillResultWithSCTsOfOrigin(
ct::SignedCertificateTimestamp::Origin desired_origin,
size_t num_scts,
@@ -123,15 +126,17 @@ class CTPolicyEnforcerTest : public ::testing::Test {
for (size_t i = 0; i < required_scts - 1; ++i) {
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED,
1, std::vector<std::string>(), false, &result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- cert.get(), nullptr, result, BoundNetLog()))
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ cert.get(), nullptr, result.verified_scts, BoundNetLog()))
<< " for: " << (end - start).InDays() << " and " << required_scts
<< " scts=" << result.verified_scts.size() << " i=" << i;
}
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
std::vector<std::string>(), false, &result);
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- cert.get(), nullptr, result, BoundNetLog()))
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ cert.get(), nullptr, result.verified_scts, BoundNetLog()))
<< " for: " << (end - start).InDays() << " and " << required_scts
<< " scts=" << result.verified_scts.size();
}
@@ -148,8 +153,9 @@ TEST_F(CTPolicyEnforcerTest,
ct::CTVerifyResult result;
FillResultWithRepeatedLogID(google_log_id_, 2, true, &result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), nullptr, result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), nullptr, result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest,
@@ -157,16 +163,18 @@ TEST_F(CTPolicyEnforcerTest,
ct::CTVerifyResult result;
FillResultWithRepeatedLogID(non_google_log_id_, 2, true, &result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), nullptr, result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), nullptr, result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyIfSCTBeforeEnforcementDate) {
ct::CTVerifyResult result;
FillResultWithRepeatedLogID(non_google_log_id_, 2, false, &result);
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
- result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), nullptr, result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithNonEmbeddedSCTs) {
@@ -174,8 +182,9 @@ TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithNonEmbeddedSCTs) {
FillResultWithSCTsOfOrigin(
ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, &result);
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
- result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), nullptr, result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithEmbeddedSCTs) {
@@ -184,8 +193,9 @@ TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithEmbeddedSCTs) {
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5,
&result);
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
- result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), nullptr, result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTEVPolicyNotEnoughSCTs) {
@@ -198,14 +208,18 @@ TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTEVPolicyNotEnoughSCTs) {
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
&result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), non_including_whitelist.get(), result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), non_including_whitelist.get(),
+ result.verified_scts, BoundNetLog()));
// ... but should be OK if whitelisted.
scoped_refptr<ct::EVCertsWhitelist> whitelist(
new DummyEVCertsWhitelist(true, true));
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ EXPECT_EQ(
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), whitelist.get(), result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, DoesNotConformToPolicyInvalidDates) {
@@ -214,13 +228,17 @@ TEST_F(CTPolicyEnforcerTest, DoesNotConformToPolicyInvalidDates) {
ct::CTVerifyResult result;
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5,
&result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- no_valid_dates_cert.get(), nullptr, result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ no_valid_dates_cert.get(), nullptr, result.verified_scts,
+ BoundNetLog()));
// ... but should be OK if whitelisted.
scoped_refptr<ct::EVCertsWhitelist> whitelist(
new DummyEVCertsWhitelist(true, true));
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ EXPECT_EQ(
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), whitelist.get(), result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest,
@@ -274,8 +292,10 @@ TEST_F(CTPolicyEnforcerTest, ConformsToPolicyByEVWhitelistPresence) {
ct::CTVerifyResult result;
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
&result);
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ EXPECT_EQ(
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), whitelist.get(), result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, IgnoresInvalidEVWhitelist) {
@@ -285,16 +305,19 @@ TEST_F(CTPolicyEnforcerTest, IgnoresInvalidEVWhitelist) {
ct::CTVerifyResult result;
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
&result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ EXPECT_EQ(
+ ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), whitelist.get(), result.verified_scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, IgnoresNullEVWhitelist) {
ct::CTVerifyResult result;
FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
&result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), nullptr, result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), nullptr, result.verified_scts, BoundNetLog()));
}
} // namespace
diff --git a/net/cert/ct_policy_status.h b/net/cert/ct_policy_status.h
new file mode 100644
index 0000000..e234cb7
--- /dev/null
+++ b/net/cert/ct_policy_status.h
@@ -0,0 +1,39 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_CERT_CT_POLICY_STATUS_H
+#define NET_CERT_CT_POLICY_STATUS_H
+
+namespace net {
+
+namespace ct {
+
+// Information about a connection's compliance with the CT EV
+// certificate policy.
+enum class EVPolicyCompliance {
+ // The certificate was not EV, so the EV policy doesn't apply.
+ EV_POLICY_DOES_NOT_APPLY,
+ // The connection complied with the EV certificate policy by being
+ // included on the EV whitelist.
+ EV_POLICY_COMPLIES_VIA_WHITELIST,
+ // The connection complied with the EV certificate policy by
+ // including SCTs that satisfy the policy.
+ EV_POLICY_COMPLIES_VIA_SCTS,
+ // The connection did not have enough SCTs to retain its EV
+ // status.
+ EV_POLICY_NOT_ENOUGH_SCTS,
+ // The connection did not have diverse enough SCTs to retain its
+ // EV status.
+ EV_POLICY_NOT_DIVERSE_SCTS,
+ // The connection cannot be considered compliant because the build
+ // isn't timely and therefore log information might be out of date
+ // (for example a log might no longer be considered trustworthy).
+ EV_POLICY_BUILD_NOT_TIMELY,
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_POLICY_STATUS_H
diff --git a/net/cert/ct_verify_result.cc b/net/cert/ct_verify_result.cc
index c62a18a..5e89b8f 100644
--- a/net/cert/ct_verify_result.cc
+++ b/net/cert/ct_verify_result.cc
@@ -4,11 +4,15 @@
#include "net/cert/ct_verify_result.h"
+#include "net/cert/ct_policy_status.h"
+
namespace net {
namespace ct {
-CTVerifyResult::CTVerifyResult() {}
+CTVerifyResult::CTVerifyResult()
+ : ct_policies_applied(false),
+ ev_policy_compliance(ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY) {}
CTVerifyResult::~CTVerifyResult() {}
diff --git a/net/cert/ct_verify_result.h b/net/cert/ct_verify_result.h
index aa90164..e434fb8 100644
--- a/net/cert/ct_verify_result.h
+++ b/net/cert/ct_verify_result.h
@@ -7,17 +7,20 @@
#include <vector>
+#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/signed_certificate_timestamp.h"
namespace net {
namespace ct {
+enum class EVPolicyCompliance;
+
typedef std::vector<scoped_refptr<SignedCertificateTimestamp> > SCTList;
-// Holds Signed Certificate Timestamps, depending on their verification results.
-// More information could be tracked here about SCTs, but for the current UI
-// this categorization is enough.
+// Holds Signed Certificate Timestamps, depending on their verification
+// results, and information about CT policies that were applied on the
+// connection.
struct NET_EXPORT CTVerifyResult {
CTVerifyResult();
~CTVerifyResult();
@@ -28,6 +31,12 @@ struct NET_EXPORT CTVerifyResult {
SCTList invalid_scts;
// SCTs from unknown logs and as such are unverifiable.
SCTList unknown_logs_scts;
+
+ // True if any CT policies were applied on this connection.
+ bool ct_policies_applied;
+ // The result of evaluating whether the connection complies with the
+ // EV CT policy.
+ EVPolicyCompliance ev_policy_compliance;
};
} // namespace ct
diff --git a/net/net.gypi b/net/net.gypi
index c95a6cb..15f12c5 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -88,6 +88,7 @@
'cert/ct_known_logs_static.h',
'cert/ct_policy_enforcer.cc',
'cert/ct_policy_enforcer.h',
+ 'cert/ct_policy_status.h',
'cert/ct_verifier.h',
'cert/ct_verify_result.cc',
'cert/ct_verify_result.h',
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index e9191a7..9e3b2ec 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -23,6 +23,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
@@ -284,12 +285,25 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
const CertVerifyResult& cert_verify_result =
verify_details_->cert_verify_result;
const CertStatus cert_status = cert_verify_result.cert_status;
+ verify_details_->ct_verify_result.ct_policies_applied =
+ (result == OK && policy_enforcer_ != nullptr);
+ verify_details_->ct_verify_result.ev_policy_compliance =
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
if (result == OK && policy_enforcer_ &&
(cert_verify_result.cert_status & CERT_STATUS_IS_EV)) {
- if (!policy_enforcer_->DoesConformToCTEVPolicy(
+ ct::EVPolicyCompliance ev_policy_compliance =
+ policy_enforcer_->DoesConformToCTEVPolicy(
cert_verify_result.verified_cert.get(),
SSLConfigService::GetEVCertsWhitelist().get(),
- verify_details_->ct_verify_result, net_log_)) {
+ verify_details_->ct_verify_result.verified_scts, net_log_);
+ verify_details_->ct_verify_result.ev_policy_compliance =
+ ev_policy_compliance;
+ if (ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
verify_details_->cert_verify_result.cert_status |=
CERT_STATUS_CT_COMPLIANCE_FAILED;
verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
diff --git a/net/quic/crypto/proof_verifier_chromium_test.cc b/net/quic/crypto/proof_verifier_chromium_test.cc
index ddd4c94..19ccdef 100644
--- a/net/quic/crypto/proof_verifier_chromium_test.cc
+++ b/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -12,6 +12,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_log_verifier.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_serialization.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/mock_cert_verifier.h"
@@ -56,13 +57,14 @@ class FailsTestCTPolicyEnforcer : public CTPolicyEnforcer {
FailsTestCTPolicyEnforcer() {}
~FailsTestCTPolicyEnforcer() override {}
- bool DoesConformToCTEVPolicy(X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
- const BoundNetLog& net_log) override {
+ ct::EVPolicyCompliance DoesConformToCTEVPolicy(
+ X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::SCTList& verified_scts,
+ const BoundNetLog& net_log) override {
ADD_FAILURE() << "CTPolicyEnforcer::DoesConformToCTEVPolicy() should "
<< "not be called";
- return false;
+ return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
}
};
@@ -73,11 +75,13 @@ class MockCTPolicyEnforcer : public CTPolicyEnforcer {
MockCTPolicyEnforcer(bool is_ev) : is_ev_(is_ev) {}
~MockCTPolicyEnforcer() override {}
- bool DoesConformToCTEVPolicy(X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
- const BoundNetLog& net_log) override {
- return is_ev_;
+ ct::EVPolicyCompliance DoesConformToCTEVPolicy(
+ X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::SCTList& verified_scts,
+ const BoundNetLog& net_log) override {
+ return is_ev_ ? ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS
+ : ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS;
}
private:
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index d68f3bb..cb4f5ae 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -510,7 +510,7 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL;
ssl_info->pinning_failure_log = pinning_failure_log_;
- ssl_info->UpdateSignedCertificateTimestamps(*ct_verify_result_);
+ ssl_info->UpdateCertificateTransparencyInfo(*ct_verify_result_);
return true;
}
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 5619247..9526c1c 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -95,6 +95,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/scoped_nss_types.h"
@@ -2410,7 +2411,7 @@ bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->cert = server_cert_verify_result_.verified_cert;
ssl_info->unverified_cert = core_->state().server_cert;
- AddSCTInfoToSSLInfo(ssl_info);
+ AddCTInfoToSSLInfo(ssl_info);
ssl_info->connection_status =
core_->state().ssl_connection_status;
@@ -3126,13 +3127,24 @@ void SSLClientSocketNSS::VerifyCT() {
// TODO(ekasper): wipe stapled_ocsp_response and sct_list_from_tls_extension
// from the state after verification is complete, to conserve memory.
+ ct_verify_result_.ct_policies_applied = (policy_enforcer_ != nullptr);
+ ct_verify_result_.ev_policy_compliance =
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
if (policy_enforcer_ &&
(server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV)) {
scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
SSLConfigService::GetEVCertsWhitelist();
- if (!policy_enforcer_->DoesConformToCTEVPolicy(
+ ct::EVPolicyCompliance ev_policy_compliance =
+ policy_enforcer_->DoesConformToCTEVPolicy(
server_cert_verify_result_.verified_cert.get(), ev_whitelist.get(),
- ct_verify_result_, net_log_)) {
+ ct_verify_result_.verified_scts, net_log_);
+ ct_verify_result_.ev_policy_compliance = ev_policy_compliance;
+ if (ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
// TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
VLOG(1) << "EV certificate for "
<< server_cert_verify_result_.verified_cert->subject()
@@ -3158,8 +3170,8 @@ bool SSLClientSocketNSS::CalledOnValidThread() const {
return valid_thread_id_ == base::PlatformThread::CurrentId();
}
-void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
- ssl_info->UpdateSignedCertificateTimestamps(ct_verify_result_);
+void SSLClientSocketNSS::AddCTInfoToSSLInfo(SSLInfo* ssl_info) const {
+ ssl_info->UpdateCertificateTransparencyInfo(ct_verify_result_);
}
// static
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
index d8a1549..0df9d4f 100644
--- a/net/socket/ssl_client_socket_nss.h
+++ b/net/socket/ssl_client_socket_nss.h
@@ -146,7 +146,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
// vetor representing a particular verification state, this method associates
// each of the SCTs with the corresponding SCTVerifyStatus as it adds it to
// the |ssl_info|.signed_certificate_timestamps list.
- void AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const;
+ void AddCTInfoToSSLInfo(SSLInfo* ssl_info) const;
// Move last protocol to first place: SSLConfig::next_protos has protocols in
// decreasing order of preference with NPN fallback protocol at the end, but
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 4b09828..b92c4a8 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -39,6 +39,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/x509_certificate_net_log_param.h"
#include "net/cert/x509_util_openssl.h"
@@ -867,7 +868,7 @@ bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->token_binding_key_param = tb_negotiated_param_;
ssl_info->pinning_failure_log = pinning_failure_log_;
- AddSCTInfoToSSLInfo(ssl_info);
+ AddCTInfoToSSLInfo(ssl_info);
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
CHECK(cipher);
@@ -1479,13 +1480,24 @@ void SSLClientSocketOpenSSL::VerifyCT() {
server_cert_verify_result_.verified_cert.get(), ocsp_response, sct_list,
&ct_verify_result_, net_log_);
+ ct_verify_result_.ct_policies_applied = (policy_enforcer_ != nullptr);
+ ct_verify_result_.ev_policy_compliance =
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
if (policy_enforcer_ &&
(server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV)) {
scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
SSLConfigService::GetEVCertsWhitelist();
- if (!policy_enforcer_->DoesConformToCTEVPolicy(
+ ct::EVPolicyCompliance ev_policy_compliance =
+ policy_enforcer_->DoesConformToCTEVPolicy(
server_cert_verify_result_.verified_cert.get(), ev_whitelist.get(),
- ct_verify_result_, net_log_)) {
+ ct_verify_result_.verified_scts, net_log_);
+ ct_verify_result_.ev_policy_compliance = ev_policy_compliance;
+ if (ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
// TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
VLOG(1) << "EV certificate for "
<< server_cert_verify_result_.verified_cert->subject()
@@ -2147,8 +2159,8 @@ int SSLClientSocketOpenSSL::NewSessionCallback(SSL_SESSION* session) {
return 1;
}
-void SSLClientSocketOpenSSL::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
- ssl_info->UpdateSignedCertificateTimestamps(ct_verify_result_);
+void SSLClientSocketOpenSSL::AddCTInfoToSSLInfo(SSLInfo* ssl_info) const {
+ ssl_info->UpdateCertificateTransparencyInfo(ct_verify_result_);
}
std::string SSLClientSocketOpenSSL::GetSessionCacheKey() const {
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h
index 6e464d7..70d195a 100644
--- a/net/socket/ssl_client_socket_openssl.h
+++ b/net/socket/ssl_client_socket_openssl.h
@@ -197,12 +197,13 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
// Called from the SSL layer whenever a new session is established.
int NewSessionCallback(SSL_SESSION* session);
- // Adds the SignedCertificateTimestamps from ct_verify_result_ to |ssl_info|.
+ // Adds the Certificate Transparency info from ct_verify_result_ to
+ // |ssl_info|.
// SCTs are held in three separate vectors in ct_verify_result, each
// vetor representing a particular verification state, this method associates
// each of the SCTs with the corresponding SCTVerifyStatus as it adds it to
// the |ssl_info|.signed_certificate_timestamps list.
- void AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const;
+ void AddCTInfoToSSLInfo(SSLInfo* ssl_info) const;
// Returns a unique key string for the SSL session cache for
// this socket.
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index d225390..d54f003 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -22,6 +22,7 @@
#include "net/base/test_data_directory.h"
#include "net/cert/asn1_util.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/test_root_certs.h"
@@ -699,10 +700,10 @@ class MockCTVerifier : public CTVerifier {
class MockCTPolicyEnforcer : public CTPolicyEnforcer {
public:
MOCK_METHOD4(DoesConformToCTEVPolicy,
- bool(X509Certificate* cert,
- const ct::EVCertsWhitelist*,
- const ct::CTVerifyResult&,
- const BoundNetLog&));
+ ct::EVPolicyCompliance(X509Certificate* cert,
+ const ct::EVCertsWhitelist*,
+ const ct::SCTList&,
+ const BoundNetLog&));
};
class SSLClientSocketTest : public PlatformTest {
@@ -2349,7 +2350,8 @@ TEST_F(SSLClientSocketTest, EVCertStatusMaintainedForCompliantCert) {
MockCTPolicyEnforcer policy_enforcer;
SetCTPolicyEnforcer(&policy_enforcer);
EXPECT_CALL(policy_enforcer, DoesConformToCTEVPolicy(_, _, _, _))
- .WillRepeatedly(Return(true));
+ .WillRepeatedly(
+ Return(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS));
int rv;
ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
@@ -2381,7 +2383,8 @@ TEST_F(SSLClientSocketTest, EVCertStatusRemovedForNonCompliantCert) {
MockCTPolicyEnforcer policy_enforcer;
SetCTPolicyEnforcer(&policy_enforcer);
EXPECT_CALL(policy_enforcer, DoesConformToCTEVPolicy(_, _, _, _))
- .WillRepeatedly(Return(false));
+ .WillRepeatedly(
+ Return(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS));
int rv;
ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
diff --git a/net/ssl/ssl_info.cc b/net/ssl/ssl_info.cc
index 545bf7e..aca1f43 100644
--- a/net/ssl/ssl_info.cc
+++ b/net/ssl/ssl_info.cc
@@ -6,6 +6,7 @@
#include "base/pickle.h"
#include "net/cert/cert_status_flags.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/x509_certificate.h"
@@ -36,8 +37,10 @@ SSLInfo& SSLInfo::operator=(const SSLInfo& info) {
token_binding_key_param = info.token_binding_key_param;
handshake_type = info.handshake_type;
public_key_hashes = info.public_key_hashes;
- signed_certificate_timestamps = info.signed_certificate_timestamps;
pinning_failure_log = info.pinning_failure_log;
+ signed_certificate_timestamps = info.signed_certificate_timestamps;
+ ct_compliance_details_available = info.ct_compliance_details_available;
+ ct_ev_policy_compliance = info.ct_ev_policy_compliance;
return *this;
}
@@ -56,15 +59,17 @@ void SSLInfo::Reset() {
token_binding_key_param = TB_PARAM_ECDSAP256;
handshake_type = HANDSHAKE_UNKNOWN;
public_key_hashes.clear();
- signed_certificate_timestamps.clear();
pinning_failure_log.clear();
+ signed_certificate_timestamps.clear();
+ ct_compliance_details_available = false;
+ ct_ev_policy_compliance = ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
}
void SSLInfo::SetCertError(int error) {
cert_status |= MapNetErrorToCertStatus(error);
}
-void SSLInfo::UpdateSignedCertificateTimestamps(
+void SSLInfo::UpdateCertificateTransparencyInfo(
const ct::CTVerifyResult& ct_verify_result) {
for (const auto& sct : ct_verify_result.verified_scts) {
signed_certificate_timestamps.push_back(
@@ -78,6 +83,9 @@ void SSLInfo::UpdateSignedCertificateTimestamps(
signed_certificate_timestamps.push_back(
SignedCertificateTimestampAndStatus(sct, ct::SCT_STATUS_LOG_UNKNOWN));
}
+
+ ct_compliance_details_available = ct_verify_result.ct_policies_applied;
+ ct_ev_policy_compliance = ct_verify_result.ev_policy_compliance;
}
} // namespace net
diff --git a/net/ssl/ssl_info.h b/net/ssl/ssl_info.h
index 40dec28..3935369 100644
--- a/net/ssl/ssl_info.h
+++ b/net/ssl/ssl_info.h
@@ -18,6 +18,12 @@
namespace net {
+namespace ct {
+
+enum class EVPolicyCompliance;
+
+} // namespace ct
+
class X509Certificate;
// SSL connection info.
@@ -44,12 +50,14 @@ class NET_EXPORT SSLInfo {
// Adds the specified |error| to the cert status.
void SetCertError(int error);
- // Adds the SignedCertificateTimestamps from ct_verify_result to
- // |signed_certificate_timestamps|. SCTs are held in three separate vectors
- // in ct_verify_result, each vetor representing a particular verification
- // state, this method associates each of the SCTs with the corresponding
- // SCTVerifyStatus as it adds it to the |signed_certificate_timestamps| list.
- void UpdateSignedCertificateTimestamps(
+ // Adds the SignedCertificateTimestamps and policy compliance details
+ // from ct_verify_result to |signed_certificate_timestamps| and
+ // |ct_policy_compliance_details|. SCTs are held in three separate
+ // vectors in ct_verify_result, each vetor representing a particular
+ // verification state, this method associates each of the SCTs with
+ // the corresponding SCTVerifyStatus as it adds it to the
+ // |signed_certificate_timestamps| list.
+ void UpdateCertificateTransparencyInfo(
const ct::CTVerifyResult& ct_verify_result);
// The SSL certificate.
@@ -115,6 +123,18 @@ class NET_EXPORT SSLInfo {
// List of SignedCertificateTimestamps and their corresponding validation
// status.
SignedCertificateTimestampAndStatusList signed_certificate_timestamps;
+
+ // True if Certificate Transparency policies were applied on this
+ // connection and results are available. If true, the field below
+ // (|ev_policy_compliance|) will contain information about whether
+ // the connection complied with the policy and why the connection
+ // was considered non-compliant, if applicable.
+ bool ct_compliance_details_available;
+
+ // Whether the connection complied with the CT EV policy, and if not,
+ // why not. Only meaningful if |ct_compliance_details_available| is
+ // true.
+ ct::EVPolicyCompliance ct_ev_policy_compliance;
};
} // namespace net