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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/ct_policy_enforcer.h" 5 #include "net/cert/ct_policy_enforcer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 12 matching lines...) Expand all
23 #include "net/cert/ct_verify_result.h" 23 #include "net/cert/ct_verify_result.h"
24 #include "net/cert/signed_certificate_timestamp.h" 24 #include "net/cert/signed_certificate_timestamp.h"
25 #include "net/cert/x509_certificate.h" 25 #include "net/cert/x509_certificate.h"
26 #include "net/cert/x509_certificate_net_log_param.h" 26 #include "net/cert/x509_certificate_net_log_param.h"
27 #include "net/log/net_log.h" 27 #include "net/log/net_log.h"
28 28
29 namespace net { 29 namespace net {
30 30
31 namespace { 31 namespace {
32 32
33 bool IsEmbeddedSCT(const scoped_refptr<ct::SignedCertificateTimestamp>& sct) {
34 return sct->origin == ct::SignedCertificateTimestamp::SCT_EMBEDDED;
35 }
36
37 // Returns true if the current build is recent enough to ensure that 33 // Returns true if the current build is recent enough to ensure that
38 // built-in security information (e.g. CT Logs) is fresh enough. 34 // built-in security information (e.g. CT Logs) is fresh enough.
39 // TODO(eranm): Move to base or net/base 35 // TODO(eranm): Move to base or net/base
40 bool IsBuildTimely() { 36 bool IsBuildTimely() {
41 const base::Time build_time = base::GetBuildTime(); 37 const base::Time build_time = base::GetBuildTime();
42 // We consider built-in information to be timely for 10 weeks. 38 // We consider built-in information to be timely for 10 weeks.
43 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 39 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
44 } 40 }
45 41
46 bool IsGoogleIssuedSCT( 42 bool IsGoogleIssuedSCT(
(...skipping 24 matching lines...) Expand all
71 uint32_t month_diff = (exploded_expiry.year - exploded_start.year) * 12 + 67 uint32_t month_diff = (exploded_expiry.year - exploded_start.year) * 12 +
72 (exploded_expiry.month - exploded_start.month); 68 (exploded_expiry.month - exploded_start.month);
73 if (exploded_expiry.day_of_month < exploded_start.day_of_month) 69 if (exploded_expiry.day_of_month < exploded_start.day_of_month)
74 --month_diff; 70 --month_diff;
75 else if (exploded_expiry.day_of_month == exploded_start.day_of_month) 71 else if (exploded_expiry.day_of_month == exploded_start.day_of_month)
76 *has_partial_month = false; 72 *has_partial_month = false;
77 73
78 *rounded_months_difference = month_diff; 74 *rounded_months_difference = month_diff;
79 } 75 }
80 76
77 bool CheckSCTPolicy(const X509Certificate& cert,
78 const ct::SCTList& verified_scts) {
79 const base::Time now = base::Time::Now();
80 const base::Time earliest_sct = base::Time::Max();
81
82 // Scan for the earliest SCT; this is used to determine whether or not to
83 // enforce log diversity requirements, as well as to determine when to
84 // compare log disqualification. It is OK to ignore the source of the SCT
85 // here, because it is presumed that an OCSP/TLS-delivered SCT cannot
86 // predate those delivered in the certificate, unless the CA submitted the
87 // precert to additional logs that didn't appear in the certificate. If
88 // the CA did, that is acceptable proof that the certificate was issued
89 // at that time.
90 for (const auto& sct : verified_scts) {
91 base::Time unused;
92 // Only allow still-valid logs to contribute to determining the issuance
93 // date.
94 if (IsLogDisqualified(sct->log_id, &unused))
95 continue;
96 if (it->timestamp < earliest_sct)
97 earliest_timestamp = it->timestamp;
98 }
99
100 enum {
101 HAS_GOOGLE_SCT = (1 << 0),
102 HAS_NON_GOOGLE_SCT = (1 << 1),
103 HAS_DIVERSE_SCTS = (HAS_GOOGLE_SCT & HAS_NON_GOOGLE_SCT),
104 };
105
106 struct SCTPolicyStatus {
107 int diversity = 0;
108 size_t qualifying_scts = 0;
109 };
110
111 SCTPolicyStatus ocsp_status;
112 SCTPolicyStatus tls_status;
113 SCTPolicyStatus embedded_status;
114 bool has_one_valid_embedded = false;
115
116 for (const auto& sct : verified_scts) {
117 base::Time disqualification_date;
118 bool is_disqualified =
119 IsLogDisqualified(sct->log_id, &disqualification_date);
120
121 // For OCSP and TLS-delivered SCTs, only SCTs that are valid at the time
122 // of check are accepted.
123 if (sct->origin != SignedCertificateTimestamp::SCT_EMBEDDED &&
124 is_disqualified)
125 continue;
126 // TODO(rsleevi): To be truly consistent, we wouldn't count disqualified
127 // SCTs towards the diversity requirement for precerts, requiring one
128 // (valid) Google and one (valid) non-Google. If that was the case, this
129 // would be rewritten as:
130 // if (is_disqualified &&
131 // (sct->origin != SignedCertificateTimestamp::SCT_EMBEDDED ||
132 // earliest_sct >= disqualification_date ||
133 // sct->timestamp >= disqualification_date)) {
134 // continue;
135 // }
136 SCTPolicyStatus* policy_status = nullptr;
137
138 switch (sct->origin) {
139 case SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION:
140 tls_status.qualifying_scts++;
141 policy_status = &tls_status;
142 break;
143 case SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE:
144 ocsp_status.qualifying_scts++;
145 policy_status = &ocsp_status;
146 break;
147 case SignedCertificateTimestamp::SCT_EMBEDDED:
148 if (is_disqualified && earliest_sct < disqualification_date &&
149 sct->timestamp < disqualification_date)
150 embedded_status.qualifying_scts++;
151 policy_status = &embedded_status;
152 break;
153 default:
154 NOTREACHED();
155 break;
156 }
157 if (policy_status->diversity != HAS_DIVERSE_SCTS) {
158 policy_status->diversity &= IsLogOperatedByGoogle(sct->log_id)
159 ? HAS_GOOGLE_SCT
160 : HAS_NON_GOOGLE_SCT;
161 }
162 }
163 if (tls_status.qualifying_scts >= 2 &&
164 tls_status.diversity == HAS_DIVERSE_SCTS ||
165 ocsp_status.qualifying_scts >= 2 &&
166 ocsp_status.diversity == HAS_DIVERSE_SCTS)
167 return true;
168
169 size_t num_expected_scts = 0;
170 if (embedded_status.qualifying_scts >= num_expected_scts &&
171 embedded_status.diversity == HAS_DIVERSE_SCTS) {
172 return true;
173 }
174
175 return false;
176 }
177
81 bool HasRequiredNumberOfSCTs(const X509Certificate& cert, 178 bool HasRequiredNumberOfSCTs(const X509Certificate& cert,
82 const ct::SCTList& verified_scts) { 179 const ct::SCTList& verified_scts) {
180 const base::Time now = base::Time::Now();
181
83 size_t num_valid_scts = verified_scts.size(); 182 size_t num_valid_scts = verified_scts.size();
84 size_t num_embedded_scts = base::checked_cast<size_t>( 183 size_t num_embedded_scts = base::checked_cast<size_t>(std::count_if(
85 std::count_if(verified_scts.begin(), verified_scts.end(), IsEmbeddedSCT)); 184 verified_scts.begin(), verified_scts.end(), IsQualifyingEmbeddedSCT));
86 185
87 size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts; 186 size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts;
88 // If at least two valid SCTs were delivered by means other than embedding 187 // If at least two valid SCTs were delivered by means other than embedding
89 // (i.e. in a TLS extension or OCSP), then the certificate conforms to bullet 188 // (i.e. in a TLS extension or OCSP), then the certificate conforms to bullet
90 // number 3 of the "Qualifying Certificate" section of the CT/EV policy. 189 // number 3 of the "Qualifying Certificate" section of the CT/EV policy.
91 if (num_non_embedded_scts >= 2) 190 if (num_non_embedded_scts >= 2)
92 return true; 191 return true;
93 192
94 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() || 193 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() ||
95 cert.valid_start().is_max() || cert.valid_expiry().is_max()) { 194 cert.valid_start().is_max() || cert.valid_expiry().is_max()) {
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 471
373 if (!details.build_timely) 472 if (!details.build_timely)
374 return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; 473 return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY;
375 474
376 LogEVPolicyComplianceToUMA(details.status, ev_whitelist); 475 LogEVPolicyComplianceToUMA(details.status, ev_whitelist);
377 476
378 return details.status; 477 return details.status;
379 } 478 }
380 479
381 } // namespace net 480 } // namespace net
OLDNEW
« 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