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

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: Addressing review comments 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
« no previous file with comments | « net/cert/cert_policy_enforcer.h ('k') | net/cert/cert_policy_enforcer_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..25e9325fd4309f954bb171c2c05d648897ad94c0 100644
--- a/net/cert/cert_policy_enforcer.cc
+++ b/net/cert/cert_policy_enforcer.cc
@@ -6,15 +6,21 @@
#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 "base/version.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 +59,48 @@ uint32_t ApproximateMonthDifference(const base::Time& start,
return month_diff;
}
+bool HasRequiredNumberOfSCTs(const 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);
+
+ 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,51 +108,73 @@ enum CTComplianceStatus {
CT_COMPLIANCE_MAX,
};
-void LogCTComplianceStatusToUMA(CTComplianceStatus status) {
- UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status,
- CT_COMPLIANCE_MAX);
-}
-
-} // namespace
+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;
+ }
-CertPolicyEnforcer::CertPolicyEnforcer(bool require_ct_for_ev)
- : require_ct_for_ev_(require_ct_for_ev) {
+ return "unknown";
}
-CertPolicyEnforcer::~CertPolicyEnforcer() {
+void LogCTComplianceStatusToUMA(CTComplianceStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status,
+ CT_COMPLIANCE_MAX);
}
-bool CertPolicyEnforcer::DoesConformToCTEVPolicy(
- X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result) {
- if (!require_ct_for_ev_)
- return true;
-
- if (!IsBuildTimely())
- return false;
-
- if (IsCertificateInWhitelist(cert, ev_whitelist)) {
- LogCTComplianceStatusToUMA(CT_IN_WHITELIST);
- return true;
- }
+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;
+};
- if (HasRequiredNumberOfSCTs(cert, ct_result)) {
- LogCTComplianceStatusToUMA(CT_ENOUGH_SCTS);
- return true;
+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());
+ }
}
-
- LogCTComplianceStatusToUMA(CT_NOT_COMPLIANT);
- return false;
+ return dict;
}
-bool CertPolicyEnforcer::IsCertificateInWhitelist(
- X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist) {
+bool IsCertificateInWhitelist(const 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()));
+ X509Certificate::CalculateFingerprint256(cert.os_cert_handle()));
std::string truncated_fp =
std::string(reinterpret_cast<const char*>(fingerprint.data), 8);
@@ -116,47 +186,70 @@ bool CertPolicyEnforcer::IsCertificateInWhitelist(
return cert_in_ev_whitelist;
}
-bool CertPolicyEnforcer::HasRequiredNumberOfSCTs(
+void CheckCTEVPolicyCompliance(X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::CTVerifyResult& ct_result,
+ ComplianceDetails* result) {
+ result->ct_presence_required = true;
+
+ if (!IsBuildTimely())
+ return;
+ result->build_timely = true;
+
+ if (ev_whitelist && ev_whitelist->IsValid())
+ result->whitelist_version = ev_whitelist->Version();
+
+ if (IsCertificateInWhitelist(*cert, ev_whitelist)) {
+ result->status = CT_IN_WHITELIST;
+ return;
+ }
+
+ if (HasRequiredNumberOfSCTs(*cert, ct_result)) {
+ result->status = CT_ENOUGH_SCTS;
+ return;
+ }
+
+ result->status = CT_NOT_COMPLIANT;
+}
+
+} // namespace
+
+CertPolicyEnforcer::CertPolicyEnforcer(bool require_ct_for_ev)
+ : require_ct_for_ev_(require_ct_for_ev) {
+}
+
+CertPolicyEnforcer::~CertPolicyEnforcer() {
+}
+
+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
« no previous file with comments | « net/cert/cert_policy_enforcer.h ('k') | net/cert/cert_policy_enforcer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698