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

Side by Side Diff: net/cert/ct_policy_enforcer.cc

Issue 1652603002: Add information to SSLInfo about CT EV policy compliance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: expand a comment Created 4 years, 10 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 (exploded_expiry.month - exploded_start.month); 75 (exploded_expiry.month - exploded_start.month);
76 if (exploded_expiry.day_of_month < exploded_start.day_of_month) 76 if (exploded_expiry.day_of_month < exploded_start.day_of_month)
77 --month_diff; 77 --month_diff;
78 else if (exploded_expiry.day_of_month == exploded_start.day_of_month) 78 else if (exploded_expiry.day_of_month == exploded_start.day_of_month)
79 *has_partial_month = false; 79 *has_partial_month = false;
80 80
81 *rounded_months_difference = month_diff; 81 *rounded_months_difference = month_diff;
82 } 82 }
83 83
84 bool HasRequiredNumberOfSCTs(const X509Certificate& cert, 84 bool HasRequiredNumberOfSCTs(const X509Certificate& cert,
85 const ct::CTVerifyResult& ct_result) { 85 const ct::SCTList& verified_scts) {
86 size_t num_valid_scts = ct_result.verified_scts.size(); 86 size_t num_valid_scts = verified_scts.size();
87 size_t num_embedded_scts = base::checked_cast<size_t>( 87 size_t num_embedded_scts = base::checked_cast<size_t>(
88 std::count_if(ct_result.verified_scts.begin(), 88 std::count_if(verified_scts.begin(), verified_scts.end(), IsEmbeddedSCT));
89 ct_result.verified_scts.end(), IsEmbeddedSCT));
90 89
91 size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts; 90 size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts;
92 // If at least two valid SCTs were delivered by means other than embedding 91 // If at least two valid SCTs were delivered by means other than embedding
93 // (i.e. in a TLS extension or OCSP), then the certificate conforms to bullet 92 // (i.e. in a TLS extension or OCSP), then the certificate conforms to bullet
94 // number 3 of the "Qualifying Certificate" section of the CT/EV policy. 93 // number 3 of the "Qualifying Certificate" section of the CT/EV policy.
95 if (num_non_embedded_scts >= 2) 94 if (num_non_embedded_scts >= 2)
96 return true; 95 return true;
97 96
98 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() || 97 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() ||
99 cert.valid_start().is_max() || cert.valid_expiry().is_max()) { 98 cert.valid_start().is_max() || cert.valid_expiry().is_max()) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 return "unknown"; 162 return "unknown";
164 } 163 }
165 164
166 enum EVWhitelistStatus { 165 enum EVWhitelistStatus {
167 EV_WHITELIST_NOT_PRESENT = 0, 166 EV_WHITELIST_NOT_PRESENT = 0,
168 EV_WHITELIST_INVALID = 1, 167 EV_WHITELIST_INVALID = 1,
169 EV_WHITELIST_VALID = 2, 168 EV_WHITELIST_VALID = 2,
170 EV_WHITELIST_MAX, 169 EV_WHITELIST_MAX,
171 }; 170 };
172 171
173 void LogCTComplianceStatusToUMA(CTComplianceStatus status, 172 void LogCTEVComplianceStatusToUMA(CTComplianceStatus status,
174 const ct::EVCertsWhitelist* ev_whitelist) { 173 const ct::EVCertsWhitelist* ev_whitelist) {
175 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status, 174 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status,
176 CT_COMPLIANCE_MAX); 175 CT_COMPLIANCE_MAX);
177 if (status == CT_NOT_COMPLIANT) { 176 if (status == CT_NOT_COMPLIANT) {
178 EVWhitelistStatus ev_whitelist_status = EV_WHITELIST_NOT_PRESENT; 177 EVWhitelistStatus ev_whitelist_status = EV_WHITELIST_NOT_PRESENT;
179 if (ev_whitelist != NULL) { 178 if (ev_whitelist != NULL) {
180 if (ev_whitelist->IsValid()) 179 if (ev_whitelist->IsValid())
181 ev_whitelist_status = EV_WHITELIST_VALID; 180 ev_whitelist_status = EV_WHITELIST_VALID;
182 else 181 else
183 ev_whitelist_status = EV_WHITELIST_INVALID; 182 ev_whitelist_status = EV_WHITELIST_INVALID;
184 } 183 }
185 184
186 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVWhitelistValidityForNonCompliantCert", 185 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVWhitelistValidityForNonCompliantCert",
187 ev_whitelist_status, EV_WHITELIST_MAX); 186 ev_whitelist_status, EV_WHITELIST_MAX);
188 } 187 }
189 } 188 }
190 189
191 struct ComplianceDetails { 190 struct ComplianceDetails {
192 ComplianceDetails() 191 ComplianceDetails() : build_timely(false), status(CT_NOT_COMPLIANT) {}
193 : ct_presence_required(false),
194 build_timely(false),
195 status(CT_NOT_COMPLIANT) {}
196 192
197 // Whether enforcement of the policy was required or not. 193 // Whether the build is not older than 10 weeks.
198 bool ct_presence_required;
199 // Whether the build is not older than 10 weeks. The value is meaningful only
200 // if |ct_presence_required| is true.
201 bool build_timely; 194 bool build_timely;
202 // Compliance status - meaningful only if |ct_presence_required| and 195 // Compliance status - meaningful only if |build_timely| is true.
203 // |build_timely| are true.
204 CTComplianceStatus status; 196 CTComplianceStatus status;
205 // EV whitelist version. 197 // EV whitelist version.
206 base::Version whitelist_version; 198 base::Version whitelist_version;
207 }; 199 };
208 200
209 scoped_ptr<base::Value> NetLogComplianceCheckResultCallback( 201 scoped_ptr<base::Value> NetLogComplianceCheckResultCallback(
210 X509Certificate* cert, 202 X509Certificate* cert,
211 ComplianceDetails* details, 203 ComplianceDetails* details,
212 NetLogCaptureMode capture_mode) { 204 NetLogCaptureMode capture_mode) {
213 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 205 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
214 dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode)); 206 dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode));
215 dict->SetBoolean("policy_enforcement_required", 207 dict->SetBoolean("policy_enforcement_required", true);
216 details->ct_presence_required); 208 dict->SetBoolean("build_timely", details->build_timely);
217 if (details->ct_presence_required) { 209 if (details->build_timely) {
218 dict->SetBoolean("build_timely", details->build_timely); 210 dict->SetString("ct_compliance_status",
219 if (details->build_timely) { 211 ComplianceStatusToString(details->status));
220 dict->SetString("ct_compliance_status", 212 if (details->whitelist_version.IsValid())
221 ComplianceStatusToString(details->status)); 213 dict->SetString("ev_whitelist_version",
222 if (details->whitelist_version.IsValid()) 214 details->whitelist_version.GetString());
223 dict->SetString("ev_whitelist_version",
224 details->whitelist_version.GetString());
225 }
226 } 215 }
227 return std::move(dict); 216 return std::move(dict);
228 } 217 }
229 218
230 // Returns true if all SCTs in |verified_scts| were issued on, or after, the 219 // Returns true if all SCTs in |verified_scts| were issued on, or after, the
231 // date specified in kDiverseSCTRequirementStartDate 220 // date specified in kDiverseSCTRequirementStartDate
232 bool AllSCTsPastDistinctSCTRequirementEnforcementDate( 221 bool AllSCTsPastDistinctSCTRequirementEnforcementDate(
233 const ct::SCTList& verified_scts) { 222 const ct::SCTList& verified_scts) {
234 // The date when diverse SCTs requirement is effective from. 223 // The date when diverse SCTs requirement is effective from.
235 // 2015-07-01 00:00:00 UTC. 224 // 2015-07-01 00:00:00 UTC.
(...skipping 20 matching lines...) Expand all
256 cert_in_ev_whitelist = ev_whitelist->ContainsCertificateHash(truncated_fp); 245 cert_in_ev_whitelist = ev_whitelist->ContainsCertificateHash(truncated_fp);
257 246
258 UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist", 247 UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist",
259 cert_in_ev_whitelist); 248 cert_in_ev_whitelist);
260 } 249 }
261 return cert_in_ev_whitelist; 250 return cert_in_ev_whitelist;
262 } 251 }
263 252
264 void CheckCTEVPolicyCompliance(X509Certificate* cert, 253 void CheckCTEVPolicyCompliance(X509Certificate* cert,
265 const ct::EVCertsWhitelist* ev_whitelist, 254 const ct::EVCertsWhitelist* ev_whitelist,
266 const ct::CTVerifyResult& ct_result, 255 const ct::SCTList& verified_scts,
267 ComplianceDetails* result) { 256 ComplianceDetails* result) {
268 result->ct_presence_required = true;
269
270 if (!IsBuildTimely()) 257 if (!IsBuildTimely())
271 return; 258 return;
272 result->build_timely = true; 259 result->build_timely = true;
273 260
274 if (ev_whitelist && ev_whitelist->IsValid()) 261 if (ev_whitelist && ev_whitelist->IsValid())
275 result->whitelist_version = ev_whitelist->Version(); 262 result->whitelist_version = ev_whitelist->Version();
276 263
277 if (IsCertificateInWhitelist(*cert, ev_whitelist)) { 264 if (IsCertificateInWhitelist(*cert, ev_whitelist)) {
278 result->status = CT_IN_WHITELIST; 265 result->status = CT_IN_WHITELIST;
279 return; 266 return;
280 } 267 }
281 268
282 if (!HasRequiredNumberOfSCTs(*cert, ct_result)) { 269 if (!HasRequiredNumberOfSCTs(*cert, verified_scts)) {
283 result->status = CT_NOT_COMPLIANT; 270 result->status = CT_NOT_COMPLIANT;
284 return; 271 return;
285 } 272 }
286 273
287 if (AllSCTsPastDistinctSCTRequirementEnforcementDate( 274 if (AllSCTsPastDistinctSCTRequirementEnforcementDate(verified_scts) &&
288 ct_result.verified_scts) && 275 !HasEnoughDiverseSCTs(verified_scts)) {
289 !HasEnoughDiverseSCTs(ct_result.verified_scts)) {
290 result->status = CT_NOT_ENOUGH_DIVERSE_SCTS; 276 result->status = CT_NOT_ENOUGH_DIVERSE_SCTS;
291 return; 277 return;
292 } 278 }
293 279
294 result->status = CT_ENOUGH_SCTS; 280 result->status = CT_ENOUGH_SCTS;
295 } 281 }
296 282
297 } // namespace 283 } // namespace
298 284
299 bool CTPolicyEnforcer::DoesConformToCTEVPolicy( 285 CTPolicyEnforcer::EVPolicyCompliance CTPolicyEnforcer::DoesConformToCTEVPolicy(
300 X509Certificate* cert, 286 X509Certificate* cert,
301 const ct::EVCertsWhitelist* ev_whitelist, 287 const ct::EVCertsWhitelist* ev_whitelist,
302 const ct::CTVerifyResult& ct_result, 288 const ct::SCTList& verified_scts,
303 const BoundNetLog& net_log) { 289 const BoundNetLog& net_log) {
304 ComplianceDetails details; 290 ComplianceDetails details;
305 291
306 CheckCTEVPolicyCompliance(cert, ev_whitelist, ct_result, &details); 292 CheckCTEVPolicyCompliance(cert, ev_whitelist, verified_scts, &details);
307 293
308 NetLog::ParametersCallback net_log_callback = 294 NetLog::ParametersCallback net_log_callback =
309 base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert), 295 base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert),
310 base::Unretained(&details)); 296 base::Unretained(&details));
311 297
312 net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED, 298 net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED,
313 net_log_callback); 299 net_log_callback);
314 300
315 if (!details.ct_presence_required) 301 if (!details.build_timely)
316 return true; 302 return EV_POLICY_BUILD_NOT_TIMELY;
317 303
318 if (!details.build_timely) 304 LogCTEVComplianceStatusToUMA(details.status, ev_whitelist);
319 return false;
320 305
321 LogCTComplianceStatusToUMA(details.status, ev_whitelist); 306 switch (details.status) {
307 case CT_NOT_COMPLIANT:
308 return EV_POLICY_NOT_ENOUGH_SCTS;
309 case CT_IN_WHITELIST:
310 return EV_POLICY_COMPLIES_VIA_WHITELIST;
311 case CT_ENOUGH_SCTS:
312 return EV_POLICY_COMPLIES_VIA_SCTS;
313 case CT_NOT_ENOUGH_DIVERSE_SCTS:
314 return EV_POLICY_NOT_DIVERSE_SCTS;
315 case CT_COMPLIANCE_MAX:
316 return EV_POLICY_DOES_NOT_APPLY;
317 }
322 318
323 if (details.status == CT_IN_WHITELIST || details.status == CT_ENOUGH_SCTS) 319 return EV_POLICY_DOES_NOT_APPLY;
324 return true;
325
326 return false;
327 } 320 }
328 321
329 } // namespace net 322 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698