Index: net/cert/cert_policy_enforcer.cc |
diff --git a/net/cert/cert_policy_enforcer.cc b/net/cert/cert_policy_enforcer.cc |
deleted file mode 100644 |
index 8e4ba8d8b2eb38e8fb1d998b2753a580352b4f1c..0000000000000000000000000000000000000000 |
--- a/net/cert/cert_policy_enforcer.cc |
+++ /dev/null |
@@ -1,329 +0,0 @@ |
-// 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. |
- |
-#include "net/cert/cert_policy_enforcer.h" |
- |
-#include <algorithm> |
-#include <utility> |
- |
-#include "base/bind.h" |
-#include "base/build_time.h" |
-#include "base/callback_helpers.h" |
-#include "base/metrics/field_trial.h" |
-#include "base/metrics/histogram_macros.h" |
-#include "base/numerics/safe_conversions.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/time/time.h" |
-#include "base/values.h" |
-#include "base/version.h" |
-#include "net/cert/ct_ev_whitelist.h" |
-#include "net/cert/ct_known_logs.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" |
-#include "net/log/net_log.h" |
- |
-namespace net { |
- |
-namespace { |
- |
-bool IsEmbeddedSCT(const scoped_refptr<ct::SignedCertificateTimestamp>& sct) { |
- return sct->origin == ct::SignedCertificateTimestamp::SCT_EMBEDDED; |
-} |
- |
-// Returns true if the current build is recent enough to ensure that |
-// built-in security information (e.g. CT Logs) is fresh enough. |
-// TODO(eranm): Move to base or net/base |
-bool IsBuildTimely() { |
-#if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD) |
- return true; |
-#else |
- const base::Time build_time = base::GetBuildTime(); |
- // We consider built-in information to be timely for 10 weeks. |
- return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
-#endif |
-} |
- |
-bool IsGoogleIssuedSCT( |
- const scoped_refptr<ct::SignedCertificateTimestamp>& sct) { |
- return ct::IsLogOperatedByGoogle(sct->log_id); |
-} |
- |
-// Returns a rounded-down months difference of |start| and |end|, |
-// together with an indication of whether the last month was |
-// a full month, because the range starts specified in the policy |
-// are not consistent in terms of including the range start value. |
-void RoundedDownMonthDifference(const base::Time& start, |
- const base::Time& end, |
- size_t* rounded_months_difference, |
- bool* has_partial_month) { |
- DCHECK(rounded_months_difference); |
- DCHECK(has_partial_month); |
- base::Time::Exploded exploded_start; |
- base::Time::Exploded exploded_expiry; |
- start.UTCExplode(&exploded_start); |
- end.UTCExplode(&exploded_expiry); |
- if (end < start) { |
- *rounded_months_difference = 0; |
- *has_partial_month = false; |
- } |
- |
- *has_partial_month = true; |
- uint32_t month_diff = (exploded_expiry.year - exploded_start.year) * 12 + |
- (exploded_expiry.month - exploded_start.month); |
- if (exploded_expiry.day_of_month < exploded_start.day_of_month) |
- --month_diff; |
- else if (exploded_expiry.day_of_month == exploded_start.day_of_month) |
- *has_partial_month = false; |
- |
- *rounded_months_difference = month_diff; |
-} |
- |
-bool HasRequiredNumberOfSCTs(const X509Certificate& cert, |
- const ct::CTVerifyResult& ct_result) { |
- size_t num_valid_scts = ct_result.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)); |
- |
- 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; |
- } |
- |
- size_t lifetime; |
- bool has_partial_month; |
- RoundedDownMonthDifference(cert.valid_start(), cert.valid_expiry(), &lifetime, |
- &has_partial_month); |
- |
- // 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 (lifetime > 39 || (lifetime == 39 && has_partial_month)) { |
- num_required_embedded_scts = 5; |
- } else if (lifetime > 27 || (lifetime == 27 && has_partial_month)) { |
- num_required_embedded_scts = 4; |
- } else if (lifetime >= 15) { |
- num_required_embedded_scts = 3; |
- } else { |
- num_required_embedded_scts = 2; |
- } |
- |
- return num_embedded_scts >= num_required_embedded_scts; |
-} |
- |
-// Returns true if |verified_scts| contains SCTs from at least one log that is |
-// operated by Google and at least one log that is not operated by Google. This |
-// is required for SCTs after July 1st, 2015, as documented at |
-// http://dev.chromium.org/Home/chromium-security/root-ca-policy/EVCTPlanMay2015edition.pdf |
-bool HasEnoughDiverseSCTs(const ct::SCTList& verified_scts) { |
- size_t num_google_issued_scts = base::checked_cast<size_t>(std::count_if( |
- verified_scts.begin(), verified_scts.end(), IsGoogleIssuedSCT)); |
- return (num_google_issued_scts > 0) && |
- (verified_scts.size() != num_google_issued_scts); |
-} |
- |
-enum CTComplianceStatus { |
- CT_NOT_COMPLIANT = 0, |
- CT_IN_WHITELIST = 1, |
- CT_ENOUGH_SCTS = 2, |
- CT_NOT_ENOUGH_DIVERSE_SCTS = 3, |
- 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_NOT_ENOUGH_DIVERSE_SCTS: |
- return "NOT_ENOUGH_DIVERSE_SCTS"; |
- break; |
- case CT_COMPLIANCE_MAX: |
- break; |
- } |
- |
- return "unknown"; |
-} |
- |
-enum EVWhitelistStatus { |
- EV_WHITELIST_NOT_PRESENT = 0, |
- EV_WHITELIST_INVALID = 1, |
- EV_WHITELIST_VALID = 2, |
- EV_WHITELIST_MAX, |
-}; |
- |
-void LogCTComplianceStatusToUMA(CTComplianceStatus status, |
- const ct::EVCertsWhitelist* ev_whitelist) { |
- UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status, |
- CT_COMPLIANCE_MAX); |
- if (status == CT_NOT_COMPLIANT) { |
- EVWhitelistStatus ev_whitelist_status = EV_WHITELIST_NOT_PRESENT; |
- if (ev_whitelist != NULL) { |
- if (ev_whitelist->IsValid()) |
- ev_whitelist_status = EV_WHITELIST_VALID; |
- else |
- ev_whitelist_status = EV_WHITELIST_INVALID; |
- } |
- |
- UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVWhitelistValidityForNonCompliantCert", |
- ev_whitelist_status, EV_WHITELIST_MAX); |
- } |
-} |
- |
-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; |
-}; |
- |
-scoped_ptr<base::Value> NetLogComplianceCheckResultCallback( |
- X509Certificate* cert, |
- ComplianceDetails* details, |
- 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()); |
- } |
- } |
- return std::move(dict); |
-} |
- |
-// Returns true if all SCTs in |verified_scts| were issued on, or after, the |
-// date specified in kDiverseSCTRequirementStartDate |
-bool AllSCTsPastDistinctSCTRequirementEnforcementDate( |
- const ct::SCTList& verified_scts) { |
- // The date when diverse SCTs requirement is effective from. |
- // 2015-07-01 00:00:00 UTC. |
- base::Time kDiverseSCTRequirementStartDate = |
- base::Time::FromInternalValue(13080182400000000); |
- |
- for (const auto& it : verified_scts) { |
- if (it->timestamp < kDiverseSCTRequirementStartDate) |
- return false; |
- } |
- |
- return true; |
-} |
- |
-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())); |
- |
- 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; |
-} |
- |
-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_NOT_COMPLIANT; |
- return; |
- } |
- |
- if (AllSCTsPastDistinctSCTRequirementEnforcementDate( |
- ct_result.verified_scts) && |
- !HasEnoughDiverseSCTs(ct_result.verified_scts)) { |
- result->status = CT_NOT_ENOUGH_DIVERSE_SCTS; |
- return; |
- } |
- |
- result->status = CT_ENOUGH_SCTS; |
-} |
- |
-} // namespace |
- |
-bool CertPolicyEnforcer::DoesConformToCTEVPolicy( |
- X509Certificate* cert, |
- const ct::EVCertsWhitelist* ev_whitelist, |
- const ct::CTVerifyResult& ct_result, |
- const BoundNetLog& net_log) { |
- ComplianceDetails details; |
- |
- 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 (!details.build_timely) |
- return false; |
- |
- LogCTComplianceStatusToUMA(details.status, ev_whitelist); |
- |
- if (details.status == CT_IN_WHITELIST || details.status == CT_ENOUGH_SCTS) |
- return true; |
- |
- return false; |
-} |
- |
-} // namespace net |