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

Unified Diff: net/cert/ct_policy_enforcer.cc

Issue 1888463003: DO NOT REVIEW: CT policy enforcement WIP (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months 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
« net/cert/ct_known_logs_static.h ('K') | « net/cert/ct_known_logs_static.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/cert/ct_policy_enforcer.cc
diff --git a/net/cert/ct_policy_enforcer.cc b/net/cert/ct_policy_enforcer.cc
index e036087c5cab04ec9b16e33d1f25cf2f17118d50..841e97646ece7eb8b0635a0bea0ab3ff7e9b7743 100644
--- a/net/cert/ct_policy_enforcer.cc
+++ b/net/cert/ct_policy_enforcer.cc
@@ -30,10 +30,6 @@ 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
@@ -78,11 +74,114 @@ void RoundedDownMonthDifference(const base::Time& start,
*rounded_months_difference = month_diff;
}
+bool CheckSCTPolicy(const X509Certificate& cert,
+ const ct::SCTList& verified_scts) {
+ const base::Time now = base::Time::Now();
+ const base::Time earliest_sct = base::Time::Max();
+
+ // Scan for the earliest SCT; this is used to determine whether or not to
+ // enforce log diversity requirements, as well as to determine when to
+ // compare log disqualification. It is OK to ignore the source of the SCT
+ // here, because it is presumed that an OCSP/TLS-delivered SCT cannot
+ // predate those delivered in the certificate, unless the CA submitted the
+ // precert to additional logs that didn't appear in the certificate. If
+ // the CA did, that is acceptable proof that the certificate was issued
+ // at that time.
+ for (const auto& sct : verified_scts) {
+ base::Time unused;
+ // Only allow still-valid logs to contribute to determining the issuance
+ // date.
+ if (IsLogDisqualified(sct->log_id, &unused))
+ continue;
+ if (it->timestamp < earliest_sct)
+ earliest_timestamp = it->timestamp;
+ }
+
+ enum {
+ HAS_GOOGLE_SCT = (1 << 0),
+ HAS_NON_GOOGLE_SCT = (1 << 1),
+ HAS_DIVERSE_SCTS = (HAS_GOOGLE_SCT & HAS_NON_GOOGLE_SCT),
+ };
+
+ struct SCTPolicyStatus {
+ int diversity = 0;
+ size_t qualifying_scts = 0;
+ };
+
+ SCTPolicyStatus ocsp_status;
+ SCTPolicyStatus tls_status;
+ SCTPolicyStatus embedded_status;
+ bool has_one_valid_embedded = false;
+
+ for (const auto& sct : verified_scts) {
+ base::Time disqualification_date;
+ bool is_disqualified =
+ IsLogDisqualified(sct->log_id, &disqualification_date);
+
+ // For OCSP and TLS-delivered SCTs, only SCTs that are valid at the time
+ // of check are accepted.
+ if (sct->origin != SignedCertificateTimestamp::SCT_EMBEDDED &&
+ is_disqualified)
+ continue;
+ // TODO(rsleevi): To be truly consistent, we wouldn't count disqualified
+ // SCTs towards the diversity requirement for precerts, requiring one
+ // (valid) Google and one (valid) non-Google. If that was the case, this
+ // would be rewritten as:
+ // if (is_disqualified &&
+ // (sct->origin != SignedCertificateTimestamp::SCT_EMBEDDED ||
+ // earliest_sct >= disqualification_date ||
+ // sct->timestamp >= disqualification_date)) {
+ // continue;
+ // }
+ SCTPolicyStatus* policy_status = nullptr;
+
+ switch (sct->origin) {
+ case SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION:
+ tls_status.qualifying_scts++;
+ policy_status = &tls_status;
+ break;
+ case SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE:
+ ocsp_status.qualifying_scts++;
+ policy_status = &ocsp_status;
+ break;
+ case SignedCertificateTimestamp::SCT_EMBEDDED:
+ if (is_disqualified && earliest_sct < disqualification_date &&
+ sct->timestamp < disqualification_date)
+ embedded_status.qualifying_scts++;
+ policy_status = &embedded_status;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ if (policy_status->diversity != HAS_DIVERSE_SCTS) {
+ policy_status->diversity &= IsLogOperatedByGoogle(sct->log_id)
+ ? HAS_GOOGLE_SCT
+ : HAS_NON_GOOGLE_SCT;
+ }
+ }
+ if (tls_status.qualifying_scts >= 2 &&
+ tls_status.diversity == HAS_DIVERSE_SCTS ||
+ ocsp_status.qualifying_scts >= 2 &&
+ ocsp_status.diversity == HAS_DIVERSE_SCTS)
+ return true;
+
+ size_t num_expected_scts = 0;
+ if (embedded_status.qualifying_scts >= num_expected_scts &&
+ embedded_status.diversity == HAS_DIVERSE_SCTS) {
+ return true;
+ }
+
+ return false;
+}
+
bool HasRequiredNumberOfSCTs(const X509Certificate& cert,
const ct::SCTList& verified_scts) {
+ const base::Time now = base::Time::Now();
+
size_t num_valid_scts = verified_scts.size();
- size_t num_embedded_scts = base::checked_cast<size_t>(
- std::count_if(verified_scts.begin(), verified_scts.end(), IsEmbeddedSCT));
+ size_t num_embedded_scts = base::checked_cast<size_t>(std::count_if(
+ verified_scts.begin(), verified_scts.end(), IsQualifyingEmbeddedSCT));
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
« net/cert/ct_known_logs_static.h ('K') | « net/cert/ct_known_logs_static.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698