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

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: rsleevi nits 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
« no previous file with comments | « net/cert/ct_policy_enforcer.h ('k') | net/cert/ct_policy_enforcer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "base/build_time.h" 11 #include "base/build_time.h"
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/metrics/field_trial.h" 13 #include "base/metrics/field_trial.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/numerics/safe_conversions.h" 15 #include "base/numerics/safe_conversions.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "base/values.h" 18 #include "base/values.h"
19 #include "base/version.h" 19 #include "base/version.h"
20 #include "net/cert/ct_ev_whitelist.h" 20 #include "net/cert/ct_ev_whitelist.h"
21 #include "net/cert/ct_known_logs.h" 21 #include "net/cert/ct_known_logs.h"
22 #include "net/cert/ct_policy_status.h"
22 #include "net/cert/ct_verify_result.h" 23 #include "net/cert/ct_verify_result.h"
23 #include "net/cert/signed_certificate_timestamp.h" 24 #include "net/cert/signed_certificate_timestamp.h"
24 #include "net/cert/x509_certificate.h" 25 #include "net/cert/x509_certificate.h"
25 #include "net/cert/x509_certificate_net_log_param.h" 26 #include "net/cert/x509_certificate_net_log_param.h"
26 #include "net/log/net_log.h" 27 #include "net/log/net_log.h"
27 28
28 namespace net { 29 namespace net {
29 30
30 namespace { 31 namespace {
31 32
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 (exploded_expiry.month - exploded_start.month); 76 (exploded_expiry.month - exploded_start.month);
76 if (exploded_expiry.day_of_month < exploded_start.day_of_month) 77 if (exploded_expiry.day_of_month < exploded_start.day_of_month)
77 --month_diff; 78 --month_diff;
78 else if (exploded_expiry.day_of_month == exploded_start.day_of_month) 79 else if (exploded_expiry.day_of_month == exploded_start.day_of_month)
79 *has_partial_month = false; 80 *has_partial_month = false;
80 81
81 *rounded_months_difference = month_diff; 82 *rounded_months_difference = month_diff;
82 } 83 }
83 84
84 bool HasRequiredNumberOfSCTs(const X509Certificate& cert, 85 bool HasRequiredNumberOfSCTs(const X509Certificate& cert,
85 const ct::CTVerifyResult& ct_result) { 86 const ct::SCTList& verified_scts) {
86 size_t num_valid_scts = ct_result.verified_scts.size(); 87 size_t num_valid_scts = verified_scts.size();
87 size_t num_embedded_scts = base::checked_cast<size_t>( 88 size_t num_embedded_scts = base::checked_cast<size_t>(
88 std::count_if(ct_result.verified_scts.begin(), 89 std::count_if(verified_scts.begin(), verified_scts.end(), IsEmbeddedSCT));
89 ct_result.verified_scts.end(), IsEmbeddedSCT));
90 90
91 size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts; 91 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 92 // 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 93 // (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. 94 // number 3 of the "Qualifying Certificate" section of the CT/EV policy.
95 if (num_non_embedded_scts >= 2) 95 if (num_non_embedded_scts >= 2)
96 return true; 96 return true;
97 97
98 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() || 98 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() ||
99 cert.valid_start().is_max() || cert.valid_expiry().is_max()) { 99 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"; 163 return "unknown";
164 } 164 }
165 165
166 enum EVWhitelistStatus { 166 enum EVWhitelistStatus {
167 EV_WHITELIST_NOT_PRESENT = 0, 167 EV_WHITELIST_NOT_PRESENT = 0,
168 EV_WHITELIST_INVALID = 1, 168 EV_WHITELIST_INVALID = 1,
169 EV_WHITELIST_VALID = 2, 169 EV_WHITELIST_VALID = 2,
170 EV_WHITELIST_MAX, 170 EV_WHITELIST_MAX,
171 }; 171 };
172 172
173 void LogCTComplianceStatusToUMA(CTComplianceStatus status, 173 void LogCTEVComplianceStatusToUMA(CTComplianceStatus status,
174 const ct::EVCertsWhitelist* ev_whitelist) { 174 const ct::EVCertsWhitelist* ev_whitelist) {
175 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status, 175 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status,
176 CT_COMPLIANCE_MAX); 176 CT_COMPLIANCE_MAX);
177 if (status == CT_NOT_COMPLIANT) { 177 if (status == CT_NOT_COMPLIANT) {
178 EVWhitelistStatus ev_whitelist_status = EV_WHITELIST_NOT_PRESENT; 178 EVWhitelistStatus ev_whitelist_status = EV_WHITELIST_NOT_PRESENT;
179 if (ev_whitelist != NULL) { 179 if (ev_whitelist != NULL) {
180 if (ev_whitelist->IsValid()) 180 if (ev_whitelist->IsValid())
181 ev_whitelist_status = EV_WHITELIST_VALID; 181 ev_whitelist_status = EV_WHITELIST_VALID;
182 else 182 else
183 ev_whitelist_status = EV_WHITELIST_INVALID; 183 ev_whitelist_status = EV_WHITELIST_INVALID;
184 } 184 }
185 185
186 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVWhitelistValidityForNonCompliantCert", 186 UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVWhitelistValidityForNonCompliantCert",
187 ev_whitelist_status, EV_WHITELIST_MAX); 187 ev_whitelist_status, EV_WHITELIST_MAX);
188 } 188 }
189 } 189 }
190 190
191 struct ComplianceDetails { 191 struct ComplianceDetails {
192 ComplianceDetails() 192 ComplianceDetails() : build_timely(false), status(CT_NOT_COMPLIANT) {}
193 : ct_presence_required(false),
194 build_timely(false),
195 status(CT_NOT_COMPLIANT) {}
196 193
197 // Whether enforcement of the policy was required or not. 194 // 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; 195 bool build_timely;
202 // Compliance status - meaningful only if |ct_presence_required| and 196 // Compliance status - meaningful only if |build_timely| is true.
203 // |build_timely| are true.
204 CTComplianceStatus status; 197 CTComplianceStatus status;
205 // EV whitelist version. 198 // EV whitelist version.
206 base::Version whitelist_version; 199 base::Version whitelist_version;
207 }; 200 };
208 201
209 scoped_ptr<base::Value> NetLogComplianceCheckResultCallback( 202 scoped_ptr<base::Value> NetLogComplianceCheckResultCallback(
210 X509Certificate* cert, 203 X509Certificate* cert,
211 ComplianceDetails* details, 204 ComplianceDetails* details,
212 NetLogCaptureMode capture_mode) { 205 NetLogCaptureMode capture_mode) {
213 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 206 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
214 dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode)); 207 dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode));
215 dict->SetBoolean("policy_enforcement_required", 208 dict->SetBoolean("policy_enforcement_required", true);
216 details->ct_presence_required); 209 dict->SetBoolean("build_timely", details->build_timely);
217 if (details->ct_presence_required) { 210 if (details->build_timely) {
218 dict->SetBoolean("build_timely", details->build_timely); 211 dict->SetString("ct_compliance_status",
219 if (details->build_timely) { 212 ComplianceStatusToString(details->status));
220 dict->SetString("ct_compliance_status", 213 if (details->whitelist_version.IsValid())
221 ComplianceStatusToString(details->status)); 214 dict->SetString("ev_whitelist_version",
222 if (details->whitelist_version.IsValid()) 215 details->whitelist_version.GetString());
223 dict->SetString("ev_whitelist_version",
224 details->whitelist_version.GetString());
225 }
226 } 216 }
227 return std::move(dict); 217 return std::move(dict);
228 } 218 }
229 219
230 // Returns true if all SCTs in |verified_scts| were issued on, or after, the 220 // Returns true if all SCTs in |verified_scts| were issued on, or after, the
231 // date specified in kDiverseSCTRequirementStartDate 221 // date specified in kDiverseSCTRequirementStartDate
232 bool AllSCTsPastDistinctSCTRequirementEnforcementDate( 222 bool AllSCTsPastDistinctSCTRequirementEnforcementDate(
233 const ct::SCTList& verified_scts) { 223 const ct::SCTList& verified_scts) {
234 // The date when diverse SCTs requirement is effective from. 224 // The date when diverse SCTs requirement is effective from.
235 // 2015-07-01 00:00:00 UTC. 225 // 2015-07-01 00:00:00 UTC.
(...skipping 20 matching lines...) Expand all
256 cert_in_ev_whitelist = ev_whitelist->ContainsCertificateHash(truncated_fp); 246 cert_in_ev_whitelist = ev_whitelist->ContainsCertificateHash(truncated_fp);
257 247
258 UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist", 248 UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist",
259 cert_in_ev_whitelist); 249 cert_in_ev_whitelist);
260 } 250 }
261 return cert_in_ev_whitelist; 251 return cert_in_ev_whitelist;
262 } 252 }
263 253
264 void CheckCTEVPolicyCompliance(X509Certificate* cert, 254 void CheckCTEVPolicyCompliance(X509Certificate* cert,
265 const ct::EVCertsWhitelist* ev_whitelist, 255 const ct::EVCertsWhitelist* ev_whitelist,
266 const ct::CTVerifyResult& ct_result, 256 const ct::SCTList& verified_scts,
267 ComplianceDetails* result) { 257 ComplianceDetails* result) {
268 result->ct_presence_required = true;
269
270 if (!IsBuildTimely()) 258 if (!IsBuildTimely())
271 return; 259 return;
272 result->build_timely = true; 260 result->build_timely = true;
273 261
274 if (ev_whitelist && ev_whitelist->IsValid()) 262 if (ev_whitelist && ev_whitelist->IsValid())
275 result->whitelist_version = ev_whitelist->Version(); 263 result->whitelist_version = ev_whitelist->Version();
276 264
277 if (IsCertificateInWhitelist(*cert, ev_whitelist)) { 265 if (IsCertificateInWhitelist(*cert, ev_whitelist)) {
278 result->status = CT_IN_WHITELIST; 266 result->status = CT_IN_WHITELIST;
279 return; 267 return;
280 } 268 }
281 269
282 if (!HasRequiredNumberOfSCTs(*cert, ct_result)) { 270 if (!HasRequiredNumberOfSCTs(*cert, verified_scts)) {
283 result->status = CT_NOT_COMPLIANT; 271 result->status = CT_NOT_COMPLIANT;
284 return; 272 return;
285 } 273 }
286 274
287 if (AllSCTsPastDistinctSCTRequirementEnforcementDate( 275 if (AllSCTsPastDistinctSCTRequirementEnforcementDate(verified_scts) &&
288 ct_result.verified_scts) && 276 !HasEnoughDiverseSCTs(verified_scts)) {
289 !HasEnoughDiverseSCTs(ct_result.verified_scts)) {
290 result->status = CT_NOT_ENOUGH_DIVERSE_SCTS; 277 result->status = CT_NOT_ENOUGH_DIVERSE_SCTS;
291 return; 278 return;
292 } 279 }
293 280
294 result->status = CT_ENOUGH_SCTS; 281 result->status = CT_ENOUGH_SCTS;
295 } 282 }
296 283
297 } // namespace 284 } // namespace
298 285
299 bool CTPolicyEnforcer::DoesConformToCTEVPolicy( 286 ct::EVPolicyCompliance CTPolicyEnforcer::DoesConformToCTEVPolicy(
300 X509Certificate* cert, 287 X509Certificate* cert,
301 const ct::EVCertsWhitelist* ev_whitelist, 288 const ct::EVCertsWhitelist* ev_whitelist,
302 const ct::CTVerifyResult& ct_result, 289 const ct::SCTList& verified_scts,
303 const BoundNetLog& net_log) { 290 const BoundNetLog& net_log) {
304 ComplianceDetails details; 291 ComplianceDetails details;
305 292
306 CheckCTEVPolicyCompliance(cert, ev_whitelist, ct_result, &details); 293 CheckCTEVPolicyCompliance(cert, ev_whitelist, verified_scts, &details);
307 294
308 NetLog::ParametersCallback net_log_callback = 295 NetLog::ParametersCallback net_log_callback =
309 base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert), 296 base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert),
310 base::Unretained(&details)); 297 base::Unretained(&details));
311 298
312 net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED, 299 net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED,
313 net_log_callback); 300 net_log_callback);
314 301
315 if (!details.ct_presence_required) 302 if (!details.build_timely)
316 return true; 303 return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY;
317 304
318 if (!details.build_timely) 305 LogCTEVComplianceStatusToUMA(details.status, ev_whitelist);
319 return false;
320 306
321 LogCTComplianceStatusToUMA(details.status, ev_whitelist); 307 switch (details.status) {
308 case CT_NOT_COMPLIANT:
309 return ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS;
310 case CT_IN_WHITELIST:
311 return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST;
312 case CT_ENOUGH_SCTS:
313 return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS;
314 case CT_NOT_ENOUGH_DIVERSE_SCTS:
315 return ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS;
316 case CT_COMPLIANCE_MAX:
317 return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
318 }
322 319
323 if (details.status == CT_IN_WHITELIST || details.status == CT_ENOUGH_SCTS) 320 return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
324 return true;
325
326 return false;
327 } 321 }
328 322
329 } // namespace net 323 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/ct_policy_enforcer.h ('k') | net/cert/ct_policy_enforcer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698