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

Unified Diff: net/cert/cert_policy_enforcer.cc

Issue 782333002: Certificate Transparency: Adding finch and NetLog logging for EV certs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix typo in log_view_painter, update params description in netlog Created 6 years 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 side-by-side diff with in-line comments
Download patch
Index: net/cert/cert_policy_enforcer.cc
diff --git a/net/cert/cert_policy_enforcer.cc b/net/cert/cert_policy_enforcer.cc
index 0d05366a1162a746751c58ea98c71f22c6193a3c..9480283a212a52af724e3d025c30eda3213d4bff 100644
--- a/net/cert/cert_policy_enforcer.cc
+++ b/net/cert/cert_policy_enforcer.cc
@@ -6,15 +6,20 @@
#include <algorithm>
+#include "base/bind.h"
#include "base/build_time.h"
+#include "base/callback_helpers.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
+#include "net/base/net_log.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_certificate_net_log_param.h"
namespace net {
@@ -53,6 +58,48 @@ uint32_t ApproximateMonthDifference(const base::Time& start,
return month_diff;
}
+bool HasRequiredNumberOfSCTs(X509Certificate* cert,
mmenke 2014/12/16 16:40:12 optional nit: This should probably be const X509C
Eran Messeri 2014/12/17 16:19:31 Done, here and in IsCertificateInWhitelist
+ const ct::CTVerifyResult& ct_result) {
+ // TODO(eranm): Count the number of *independent* SCTs once the information
+ // about log operators is available, crbug.com/425174
+ size_t num_valid_scts = ct_result.verified_scts.size();
+ size_t num_embedded_scts =
+ std::count_if(ct_result.verified_scts.begin(),
+ ct_result.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
+ // (i.e. in a TLS extension or OCSP), then the certificate conforms to bullet
+ // number 3 of the "Qualifying Certificate" section of the CT/EV policy.
+ if (num_non_embedded_scts >= 2)
+ return true;
+
+ if (cert->valid_start().is_null() || cert->valid_expiry().is_null() ||
+ cert->valid_start().is_max() || cert->valid_expiry().is_max()) {
+ // Will not be able to calculate the certificate's validity period.
+ return false;
+ }
+
+ uint32_t expiry_in_months_approx =
+ ApproximateMonthDifference(cert->valid_start(), cert->valid_expiry());
+
+ // For embedded SCTs, if the certificate has the number of SCTs specified in
+ // table 1 of the "Qualifying Certificate" section of the CT/EV policy, then
+ // it qualifies.
+ size_t num_required_embedded_scts;
+ if (expiry_in_months_approx > 39) {
+ num_required_embedded_scts = 5;
+ } else if (expiry_in_months_approx > 27) {
+ num_required_embedded_scts = 4;
+ } else if (expiry_in_months_approx >= 15) {
+ num_required_embedded_scts = 3;
+ } else {
+ num_required_embedded_scts = 2;
+ }
+
+ return num_embedded_scts >= num_required_embedded_scts;
+}
+
enum CTComplianceStatus {
CT_NOT_COMPLIANT = 0,
CT_IN_WHITELIST = 1,
@@ -60,103 +107,148 @@ enum CTComplianceStatus {
CT_COMPLIANCE_MAX,
};
+const char* ComplianceStatusToString(CTComplianceStatus status) {
+ switch (status) {
+ case CT_NOT_COMPLIANT:
+ return "NOT_COMPLIANT";
+ break;
+ case CT_IN_WHITELIST:
+ return "WHITELISTED";
+ break;
+ case CT_ENOUGH_SCTS:
+ return "ENOUGH_SCTS";
+ break;
+ case CT_COMPLIANCE_MAX:
+ break;
+ }
+
+ return "unknown";
+}
+
void LogCTComplianceStatusToUMA(CTComplianceStatus status) {
UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status,
CT_COMPLIANCE_MAX);
}
-} // namespace
+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.
+ bool build_timely;
+ // Compliance status - meaningful only if |ct_presence_required| and
+ // |build_timely| are true.
+ CTComplianceStatus status;
+ // EV whitelist version.
+ base::Version whitelist_version;
+};
-CertPolicyEnforcer::CertPolicyEnforcer(bool require_ct_for_ev)
- : require_ct_for_ev_(require_ct_for_ev) {
+base::Value* NetLogComplianceCheckResultCallback(X509Certificate* cert,
+ ComplianceDetails* details,
+ NetLog::LogLevel log_level) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+ dict->Set("certificate", NetLogX509CertificateCallback(cert, log_level));
+ 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());
+ }
+ }
+ return dict;
}
-CertPolicyEnforcer::~CertPolicyEnforcer() {
+bool IsCertificateInWhitelist(X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist) {
+ bool cert_in_ev_whitelist = false;
+ if (ev_whitelist && ev_whitelist->IsValid()) {
+ const SHA256HashValue fingerprint(
+ X509Certificate::CalculateFingerprint256(cert->os_cert_handle()));
+
+ std::string truncated_fp =
+ std::string(reinterpret_cast<const char*>(fingerprint.data), 8);
+ cert_in_ev_whitelist = ev_whitelist->ContainsCertificateHash(truncated_fp);
+
+ UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist",
+ cert_in_ev_whitelist);
+ }
+ return cert_in_ev_whitelist;
}
-bool CertPolicyEnforcer::DoesConformToCTEVPolicy(
- X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result) {
- if (!require_ct_for_ev_)
- return true;
+void CheckCTEVPolicyCompliance(X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::CTVerifyResult& ct_result,
+ ComplianceDetails* result) {
+ result->ct_presence_required = true;
if (!IsBuildTimely())
- return false;
+ return;
+ result->build_timely = true;
+
+ if (ev_whitelist && ev_whitelist->IsValid())
+ result->whitelist_version = ev_whitelist->Version();
if (IsCertificateInWhitelist(cert, ev_whitelist)) {
- LogCTComplianceStatusToUMA(CT_IN_WHITELIST);
- return true;
+ result->status = CT_IN_WHITELIST;
+ return;
}
if (HasRequiredNumberOfSCTs(cert, ct_result)) {
- LogCTComplianceStatusToUMA(CT_ENOUGH_SCTS);
- return true;
+ result->status = CT_ENOUGH_SCTS;
+ return;
}
- LogCTComplianceStatusToUMA(CT_NOT_COMPLIANT);
- return false;
+ result->status = CT_NOT_COMPLIANT;
}
-bool CertPolicyEnforcer::IsCertificateInWhitelist(
- X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist) {
- bool cert_in_ev_whitelist = false;
- if (ev_whitelist && ev_whitelist->IsValid()) {
- const SHA256HashValue fingerprint(
- X509Certificate::CalculateFingerprint256(cert->os_cert_handle()));
+} // namespace
- std::string truncated_fp =
- std::string(reinterpret_cast<const char*>(fingerprint.data), 8);
- cert_in_ev_whitelist = ev_whitelist->ContainsCertificateHash(truncated_fp);
+CertPolicyEnforcer::CertPolicyEnforcer(bool require_ct_for_ev)
+ : require_ct_for_ev_(require_ct_for_ev) {
+}
- UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist",
- cert_in_ev_whitelist);
- }
- return cert_in_ev_whitelist;
+CertPolicyEnforcer::~CertPolicyEnforcer() {
}
-bool CertPolicyEnforcer::HasRequiredNumberOfSCTs(
+bool CertPolicyEnforcer::DoesConformToCTEVPolicy(
X509Certificate* cert,
- const ct::CTVerifyResult& ct_result) {
- // TODO(eranm): Count the number of *independent* SCTs once the information
- // about log operators is available, crbug.com/425174
- size_t num_valid_scts = ct_result.verified_scts.size();
- size_t num_embedded_scts =
- std::count_if(ct_result.verified_scts.begin(),
- ct_result.verified_scts.end(), IsEmbeddedSCT);
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::CTVerifyResult& ct_result,
+ const BoundNetLog& net_log) {
+ ComplianceDetails details;
- 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
- // (i.e. in a TLS extension or OCSP), then the certificate conforms to bullet
- // number 3 of the "Qualifying Certificate" section of the CT/EV policy.
- if (num_non_embedded_scts >= 2)
+ if (require_ct_for_ev_)
+ CheckCTEVPolicyCompliance(cert, ev_whitelist, ct_result, &details);
+
+ NetLog::ParametersCallback net_log_callback =
+ base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert),
+ base::Unretained(&details));
+
+ net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED,
+ net_log_callback);
+
+ if (!details.ct_presence_required)
return true;
- if (cert->valid_start().is_null() || cert->valid_expiry().is_null() ||
- cert->valid_start().is_max() || cert->valid_expiry().is_max()) {
- // Will not be able to calculate the certificate's validity period.
+ if (!details.build_timely)
return false;
- }
- uint32_t expiry_in_months_approx =
- ApproximateMonthDifference(cert->valid_start(), cert->valid_expiry());
+ LogCTComplianceStatusToUMA(details.status);
- // For embedded SCTs, if the certificate has the number of SCTs specified in
- // table 1 of the "Qualifying Certificate" section of the CT/EV policy, then
- // it qualifies.
- size_t num_required_embedded_scts;
- if (expiry_in_months_approx > 39) {
- num_required_embedded_scts = 5;
- } else if (expiry_in_months_approx > 27) {
- num_required_embedded_scts = 4;
- } else if (expiry_in_months_approx >= 15) {
- num_required_embedded_scts = 3;
- } else {
- num_required_embedded_scts = 2;
- }
+ if (details.status == CT_IN_WHITELIST || details.status == CT_ENOUGH_SCTS)
+ return true;
- return num_embedded_scts >= num_required_embedded_scts;
+ return false;
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698