Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "net/cert/ct_verify_result.h" | 24 #include "net/cert/ct_verify_result.h" |
| 25 #include "net/cert/signed_certificate_timestamp.h" | 25 #include "net/cert/signed_certificate_timestamp.h" |
| 26 #include "net/cert/x509_certificate.h" | 26 #include "net/cert/x509_certificate.h" |
| 27 #include "net/cert/x509_certificate_net_log_param.h" | 27 #include "net/cert/x509_certificate_net_log_param.h" |
| 28 #include "net/log/net_log.h" | 28 #include "net/log/net_log.h" |
| 29 | 29 |
| 30 namespace net { | 30 namespace net { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 bool IsEmbeddedSCT(const scoped_refptr<ct::SignedCertificateTimestamp>& sct) { | |
| 35 return sct->origin == ct::SignedCertificateTimestamp::SCT_EMBEDDED; | |
| 36 } | |
| 37 | |
| 38 // Returns true if the current build is recent enough to ensure that | 34 // Returns true if the current build is recent enough to ensure that |
| 39 // built-in security information (e.g. CT Logs) is fresh enough. | 35 // built-in security information (e.g. CT Logs) is fresh enough. |
| 40 // TODO(eranm): Move to base or net/base | 36 // TODO(eranm): Move to base or net/base |
| 41 bool IsBuildTimely() { | 37 bool IsBuildTimely() { |
| 42 const base::Time build_time = base::GetBuildTime(); | 38 const base::Time build_time = base::GetBuildTime(); |
| 43 // We consider built-in information to be timely for 10 weeks. | 39 // We consider built-in information to be timely for 10 weeks. |
| 44 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 40 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
| 45 } | 41 } |
| 46 | 42 |
| 47 bool IsGoogleIssuedSCT( | |
| 48 const scoped_refptr<ct::SignedCertificateTimestamp>& sct) { | |
| 49 return ct::IsLogOperatedByGoogle(sct->log_id); | |
| 50 } | |
| 51 | |
| 52 // Returns a rounded-down months difference of |start| and |end|, | 43 // Returns a rounded-down months difference of |start| and |end|, |
| 53 // together with an indication of whether the last month was | 44 // together with an indication of whether the last month was |
| 54 // a full month, because the range starts specified in the policy | 45 // a full month, because the range starts specified in the policy |
| 55 // are not consistent in terms of including the range start value. | 46 // are not consistent in terms of including the range start value. |
| 56 void RoundedDownMonthDifference(const base::Time& start, | 47 void RoundedDownMonthDifference(const base::Time& start, |
| 57 const base::Time& end, | 48 const base::Time& end, |
| 58 size_t* rounded_months_difference, | 49 size_t* rounded_months_difference, |
| 59 bool* has_partial_month) { | 50 bool* has_partial_month) { |
| 60 DCHECK(rounded_months_difference); | 51 DCHECK(rounded_months_difference); |
| 61 DCHECK(has_partial_month); | 52 DCHECK(has_partial_month); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 72 uint32_t month_diff = (exploded_expiry.year - exploded_start.year) * 12 + | 63 uint32_t month_diff = (exploded_expiry.year - exploded_start.year) * 12 + |
| 73 (exploded_expiry.month - exploded_start.month); | 64 (exploded_expiry.month - exploded_start.month); |
| 74 if (exploded_expiry.day_of_month < exploded_start.day_of_month) | 65 if (exploded_expiry.day_of_month < exploded_start.day_of_month) |
| 75 --month_diff; | 66 --month_diff; |
| 76 else if (exploded_expiry.day_of_month == exploded_start.day_of_month) | 67 else if (exploded_expiry.day_of_month == exploded_start.day_of_month) |
| 77 *has_partial_month = false; | 68 *has_partial_month = false; |
| 78 | 69 |
| 79 *rounded_months_difference = month_diff; | 70 *rounded_months_difference = month_diff; |
| 80 } | 71 } |
| 81 | 72 |
| 82 bool HasRequiredNumberOfSCTs(const X509Certificate& cert, | |
| 83 const ct::SCTList& verified_scts) { | |
| 84 size_t num_valid_scts = verified_scts.size(); | |
| 85 size_t num_embedded_scts = base::checked_cast<size_t>( | |
| 86 std::count_if(verified_scts.begin(), verified_scts.end(), IsEmbeddedSCT)); | |
| 87 | |
| 88 size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts; | |
| 89 // If at least two valid SCTs were delivered by means other than embedding | |
| 90 // (i.e. in a TLS extension or OCSP), then the certificate conforms to bullet | |
| 91 // number 3 of the "Qualifying Certificate" section of the CT/EV policy. | |
| 92 if (num_non_embedded_scts >= 2) | |
| 93 return true; | |
| 94 | |
| 95 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() || | |
| 96 cert.valid_start().is_max() || cert.valid_expiry().is_max()) { | |
| 97 // Will not be able to calculate the certificate's validity period. | |
| 98 return false; | |
| 99 } | |
| 100 | |
| 101 size_t lifetime; | |
| 102 bool has_partial_month; | |
| 103 RoundedDownMonthDifference(cert.valid_start(), cert.valid_expiry(), &lifetime, | |
| 104 &has_partial_month); | |
| 105 | |
| 106 // For embedded SCTs, if the certificate has the number of SCTs specified in | |
| 107 // table 1 of the "Qualifying Certificate" section of the CT/EV policy, then | |
| 108 // it qualifies. | |
| 109 size_t num_required_embedded_scts; | |
| 110 if (lifetime > 39 || (lifetime == 39 && has_partial_month)) { | |
| 111 num_required_embedded_scts = 5; | |
| 112 } else if (lifetime > 27 || (lifetime == 27 && has_partial_month)) { | |
| 113 num_required_embedded_scts = 4; | |
| 114 } else if (lifetime >= 15) { | |
| 115 num_required_embedded_scts = 3; | |
| 116 } else { | |
| 117 num_required_embedded_scts = 2; | |
| 118 } | |
| 119 | |
| 120 return num_embedded_scts >= num_required_embedded_scts; | |
| 121 } | |
| 122 | |
| 123 // Returns true if |verified_scts| contains SCTs from at least one log that is | |
| 124 // operated by Google and at least one log that is not operated by Google. This | |
| 125 // is required for SCTs after July 1st, 2015, as documented at | |
| 126 // http://dev.chromium.org/Home/chromium-security/root-ca-policy/EVCTPlanMay2015 edition.pdf | |
| 127 bool HasEnoughDiverseSCTs(const ct::SCTList& verified_scts) { | |
| 128 size_t num_google_issued_scts = base::checked_cast<size_t>(std::count_if( | |
| 129 verified_scts.begin(), verified_scts.end(), IsGoogleIssuedSCT)); | |
| 130 return (num_google_issued_scts > 0) && | |
| 131 (verified_scts.size() != num_google_issued_scts); | |
| 132 } | |
| 133 | |
| 134 const char* EVPolicyComplianceToString(ct::EVPolicyCompliance status) { | 73 const char* EVPolicyComplianceToString(ct::EVPolicyCompliance status) { |
| 135 switch (status) { | 74 switch (status) { |
| 136 case ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY: | 75 case ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY: |
| 137 return "POLICY_DOES_NOT_APPLY"; | 76 return "POLICY_DOES_NOT_APPLY"; |
| 138 case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST: | 77 case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST: |
| 139 return "WHITELISTED"; | 78 return "WHITELISTED"; |
| 140 case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS: | 79 case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS: |
| 141 return "COMPLIES_VIA_SCTS"; | 80 return "COMPLIES_VIA_SCTS"; |
| 142 case ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS: | 81 case ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS: |
| 143 return "NOT_ENOUGH_SCTS"; | 82 return "NOT_ENOUGH_SCTS"; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 ct::CertPolicyCompliance compliance, | 170 ct::CertPolicyCompliance compliance, |
| 232 NetLogCaptureMode capture_mode) { | 171 NetLogCaptureMode capture_mode) { |
| 233 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 172 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 234 dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode)); | 173 dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode)); |
| 235 dict->SetBoolean("build_timely", build_timely); | 174 dict->SetBoolean("build_timely", build_timely); |
| 236 dict->SetString("ct_compliance_status", | 175 dict->SetString("ct_compliance_status", |
| 237 CertPolicyComplianceToString(compliance)); | 176 CertPolicyComplianceToString(compliance)); |
| 238 return std::move(dict); | 177 return std::move(dict); |
| 239 } | 178 } |
| 240 | 179 |
| 241 // Returns true if all SCTs in |verified_scts| were issued on, or after, the | |
| 242 // date specified in kDiverseSCTRequirementStartDate | |
| 243 bool AllSCTsPastDistinctSCTRequirementEnforcementDate( | |
| 244 const ct::SCTList& verified_scts) { | |
| 245 // The date when diverse SCTs requirement is effective from. | |
| 246 // 2015-07-01 00:00:00 UTC. | |
| 247 base::Time kDiverseSCTRequirementStartDate = | |
| 248 base::Time::FromInternalValue(13080182400000000); | |
| 249 | |
| 250 for (const auto& it : verified_scts) { | |
| 251 if (it->timestamp < kDiverseSCTRequirementStartDate) | |
| 252 return false; | |
| 253 } | |
| 254 | |
| 255 return true; | |
| 256 } | |
| 257 | |
| 258 bool IsCertificateInWhitelist(const X509Certificate& cert, | 180 bool IsCertificateInWhitelist(const X509Certificate& cert, |
| 259 const ct::EVCertsWhitelist* ev_whitelist) { | 181 const ct::EVCertsWhitelist* ev_whitelist) { |
| 260 bool cert_in_ev_whitelist = false; | 182 if (!ev_whitelist || !ev_whitelist->IsValid()) |
| 261 if (ev_whitelist && ev_whitelist->IsValid()) { | 183 return false; |
|
Ryan Sleevi
2016/05/02 23:41:23
This was just a style cleanup for better short-cir
| |
| 262 const SHA256HashValue fingerprint( | |
| 263 X509Certificate::CalculateFingerprint256(cert.os_cert_handle())); | |
| 264 | 184 |
| 265 std::string truncated_fp = | 185 const SHA256HashValue fingerprint( |
| 266 std::string(reinterpret_cast<const char*>(fingerprint.data), 8); | 186 X509Certificate::CalculateFingerprint256(cert.os_cert_handle())); |
| 267 cert_in_ev_whitelist = ev_whitelist->ContainsCertificateHash(truncated_fp); | |
| 268 | 187 |
| 269 UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist", | 188 std::string truncated_fp = |
| 270 cert_in_ev_whitelist); | 189 std::string(reinterpret_cast<const char*>(fingerprint.data), 8); |
| 271 } | 190 bool cert_in_ev_whitelist = |
| 191 ev_whitelist->ContainsCertificateHash(truncated_fp); | |
| 192 | |
| 193 UMA_HISTOGRAM_BOOLEAN("Net.SSL_EVCertificateInWhitelist", | |
| 194 cert_in_ev_whitelist); | |
| 272 return cert_in_ev_whitelist; | 195 return cert_in_ev_whitelist; |
| 273 } | 196 } |
| 274 | 197 |
| 275 ct::CertPolicyCompliance CheckCertPolicyCompliance( | 198 ct::CertPolicyCompliance CheckCertPolicyCompliance( |
| 276 X509Certificate* cert, | 199 const X509Certificate& cert, |
| 277 const ct::SCTList& verified_scts, | 200 const ct::SCTList& verified_scts) { |
| 278 const BoundNetLog& net_log) { | 201 base::Time issuance_date = base::Time::Max(); |
| 279 if (!HasRequiredNumberOfSCTs(*cert, verified_scts)) | 202 |
| 203 // Cert is outside the bounds of parsable; reject it. | |
| 204 if (cert.valid_start().is_null() || cert.valid_expiry().is_null() || | |
| 205 cert.valid_start().is_max() || cert.valid_expiry().is_max()) { | |
| 280 return ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; | 206 return ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; |
| 281 if (AllSCTsPastDistinctSCTRequirementEnforcementDate(verified_scts) && | 207 } |
|
Ryan Sleevi
2016/05/02 23:41:23
This is a functional change unspecified in policy,
Eran Messeri
2016/05/03 12:52:13
Nit: in that case issuance_date can be defined and
| |
| 282 !HasEnoughDiverseSCTs(verified_scts)) { | 208 |
| 209 // Scan for the earliest SCT. This is used to determine whether to enforce | |
| 210 // log diversity requirements, as well as whether to enforce whether or not | |
| 211 // a log was qualified or pending qualification at time of issuance (in the | |
| 212 // case of embedded SCTs). It's acceptable to ignore the origin of the SCT, | |
| 213 // because SCTs delivered via OCSP/TLS extension will cover the full | |
| 214 // certificate, which necessarily will exist only after the precertificate | |
| 215 // has been logged and the actual certificate issued. | |
| 216 // Note: Here, issuance date is defined as the earliest of all SCTs, rather | |
| 217 // than the latest of embedded SCTs, in order to give CAs the benefit of | |
| 218 // the doubt in the event a log is revoked in the midst of processing | |
| 219 // a precertificate and issuing the certificate. | |
| 220 for (const auto& sct : verified_scts) | |
| 221 issuance_date = std::min(sct->timestamp, issuance_date); | |
|
Ryan Sleevi
2016/05/02 23:41:23
This is intentionally pre-computed, because it wil
| |
| 222 | |
| 223 bool has_valid_google_sct = false; | |
| 224 bool has_valid_nongoogle_sct = false; | |
| 225 bool has_valid_embedded_sct = false; | |
| 226 bool has_valid_nonembedded_sct = false; | |
| 227 bool has_embedded_google_sct = false; | |
| 228 bool has_embedded_nongoogle_sct = false; | |
| 229 std::vector<base::StringPiece> embedded_log_ids; | |
| 230 for (const auto& sct : verified_scts) { | |
| 231 if (ct::IsLogOperatedByGoogle(sct->log_id)) { | |
| 232 has_valid_google_sct = true; | |
| 233 if (sct->origin == ct::SignedCertificateTimestamp::SCT_EMBEDDED) | |
| 234 has_embedded_google_sct = true; | |
| 235 } else { | |
| 236 has_valid_nongoogle_sct = true; | |
| 237 if (sct->origin == ct::SignedCertificateTimestamp::SCT_EMBEDDED) | |
| 238 has_embedded_nongoogle_sct = true; | |
| 239 } | |
| 240 if (sct->origin != ct::SignedCertificateTimestamp::SCT_EMBEDDED) { | |
| 241 has_valid_nonembedded_sct = true; | |
| 242 } else { | |
| 243 has_valid_embedded_sct = true; | |
| 244 embedded_log_ids.push_back(sct->log_id); | |
| 245 } | |
| 246 } | |
| 247 | |
| 248 // Option 1: | |
| 249 // An SCT presented via the TLS extension OR embedded within a stapled OCSP | |
| 250 // response is from a log qualified at time of check; | |
| 251 // AND there is at least one SCT from a Google Log that is qualified at | |
| 252 // time of check, presented via any method; | |
| 253 // AND there is at least one SCT from a non-Google Log that is qualified | |
| 254 // at the time of check, presented via any method. | |
| 255 // | |
| 256 // Note: Because SCTs embedded via TLS or OCSP can be updated on the fly, | |
| 257 // the issuance date is irrelevant, as any policy changes can be | |
| 258 // accomodated. | |
| 259 if (has_valid_nonembedded_sct && has_valid_google_sct && | |
| 260 has_valid_nongoogle_sct) { | |
| 261 return ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS; | |
| 262 } | |
| 263 // Note: If has_valid_nonembedded_sct was true, but Option 2 isn't met, | |
| 264 // then the result will be that there weren't diverse enough SCTs, as that | |
| 265 // the only other way for the conditional above to fail). Because Option 1 | |
| 266 // has the diversity requirement, it's implicitly a minimum number of SCTs | |
| 267 // (specifically, 2), but that's not explicitly specified in the policy. | |
| 268 | |
| 269 // Option 2: | |
| 270 // There is at least one embedded SCT from a log qualified at the time of | |
| 271 // check ... | |
| 272 if (!has_valid_embedded_sct) { | |
| 273 // Under Option 2, there weren't enough SCTs, and potentially under | |
| 274 // Option 1, there weren't diverse enough SCTs. Try to signal the error | |
| 275 // that is most easily fixed. | |
| 276 return has_valid_nonembedded_sct | |
| 277 ? ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS | |
| 278 : ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; | |
| 279 } | |
| 280 | |
| 281 // ... AND there is at least one embedded SCT from a Google Log once or | |
| 282 // currently qualified; | |
| 283 // AND there is at least one embedded SCT from a non-Google Log once or | |
| 284 // currently qualified; | |
| 285 // ... | |
| 286 // | |
| 287 // Note: This policy language is only enforced after the below issuance | |
| 288 // date, as that's when the diversity policy first came into effect for | |
| 289 // SCTs embedded in certificates. | |
| 290 // The date when diverse SCTs requirement is effective from. | |
| 291 // 2015-07-01 00:00:00 UTC. | |
| 292 const base::Time kDiverseSCTRequirementStartDate = | |
| 293 base::Time::FromInternalValue(13080182400000000); | |
| 294 if (issuance_date >= kDiverseSCTRequirementStartDate && | |
| 295 !(has_embedded_google_sct && has_embedded_nongoogle_sct)) { | |
| 296 // Note: This also covers the case for embedded SCTs, as it's only | |
|
estark
2016/05/03 18:15:03
This comment doesn't make sense to me. Is "embedde
Ryan Sleevi
2016/05/03 18:31:03
Yup, thanks.
| |
| 297 // possible to reach here if both sets are not diverse enough. | |
| 283 return ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS; | 298 return ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS; |
| 284 } | 299 } |
| 285 | 300 |
| 286 return ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS; | 301 size_t lifetime_in_months = 0; |
| 302 bool has_partial_month = false; | |
| 303 RoundedDownMonthDifference(cert.valid_start(), cert.valid_expiry(), | |
| 304 &lifetime_in_months, &has_partial_month); | |
| 305 | |
| 306 // ... AND the certificate embeds SCTs from AT LEAST the number of logs | |
| 307 // once or currently qualified shown in Table 1 of the CT Policy. | |
| 308 size_t num_required_embedded_scts = 5; | |
| 309 if (lifetime_in_months > 39 || | |
| 310 (lifetime_in_months == 39 && has_partial_month)) { | |
| 311 num_required_embedded_scts = 5; | |
| 312 } else if (lifetime_in_months > 27 || | |
| 313 (lifetime_in_months == 27 && has_partial_month)) { | |
| 314 num_required_embedded_scts = 4; | |
| 315 } else if (lifetime_in_months >= 15) { | |
| 316 num_required_embedded_scts = 3; | |
| 317 } else { | |
| 318 num_required_embedded_scts = 2; | |
| 319 } | |
| 320 | |
| 321 // Sort the embedded log IDs and remove duplicates, so that only a single | |
| 322 // SCT from each log is accepted. This is to handle the case where a given | |
| 323 // log returns different SCTs for the same precertificate (which is | |
| 324 // permitted, but advised against). | |
| 325 std::sort(embedded_log_ids.begin(), embedded_log_ids.end()); | |
| 326 size_t num_embedded_scts = std::distance( | |
| 327 embedded_log_ids.begin(), | |
|
Eran Messeri
2016/05/03 12:52:13
Question: Is the begin() iterator always valid aft
Ryan Sleevi
2016/05/03 18:31:03
Nope, that's a bug :)
Ryan Sleevi
2016/05/03 18:32:29
I guess I should clarify - for std::vector it's de
| |
| 328 std::unique(embedded_log_ids.begin(), embedded_log_ids.end())); | |
| 329 | |
| 330 if (num_embedded_scts >= num_required_embedded_scts) | |
| 331 return ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS; | |
| 332 | |
| 333 // Under Option 2, there weren't enough SCTs, and potentially under Option | |
| 334 // 1, there weren't diverse enough SCTs. Try to signal the error that is | |
| 335 // most easily fixed. | |
| 336 return has_valid_nonembedded_sct | |
| 337 ? ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS | |
| 338 : ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; | |
| 287 } | 339 } |
| 288 | 340 |
| 289 ct::EVPolicyCompliance CertPolicyComplianceToEVPolicyCompliance( | 341 ct::EVPolicyCompliance CertPolicyComplianceToEVPolicyCompliance( |
| 290 ct::CertPolicyCompliance cert_policy_compliance) { | 342 ct::CertPolicyCompliance cert_policy_compliance) { |
| 291 switch (cert_policy_compliance) { | 343 switch (cert_policy_compliance) { |
| 292 case ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS: | 344 case ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS: |
| 293 return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS; | 345 return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS; |
| 294 case ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS: | 346 case ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS: |
| 295 return ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS; | 347 return ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS; |
| 296 case ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS: | 348 case ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS: |
| 297 return ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS; | 349 return ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS; |
| 298 case ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY: | 350 case ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY: |
| 299 return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; | 351 return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; |
| 300 } | 352 } |
| 301 return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; | 353 return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; |
| 302 } | 354 } |
| 303 | 355 |
| 304 void CheckCTEVPolicyCompliance(X509Certificate* cert, | 356 void CheckCTEVPolicyCompliance(X509Certificate* cert, |
| 305 const ct::EVCertsWhitelist* ev_whitelist, | 357 const ct::EVCertsWhitelist* ev_whitelist, |
| 306 const ct::SCTList& verified_scts, | 358 const ct::SCTList& verified_scts, |
| 307 const BoundNetLog& net_log, | 359 const BoundNetLog& net_log, |
| 308 EVComplianceDetails* result) { | 360 EVComplianceDetails* result) { |
| 309 result->status = CertPolicyComplianceToEVPolicyCompliance( | 361 result->status = CertPolicyComplianceToEVPolicyCompliance( |
| 310 CheckCertPolicyCompliance(cert, verified_scts, net_log)); | 362 CheckCertPolicyCompliance(*cert, verified_scts)); |
| 311 if (ev_whitelist && ev_whitelist->IsValid()) | 363 if (ev_whitelist && ev_whitelist->IsValid()) |
| 312 result->whitelist_version = ev_whitelist->Version(); | 364 result->whitelist_version = ev_whitelist->Version(); |
| 313 | 365 |
| 314 if (result->status != ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS && | 366 if (result->status != ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS && |
| 315 IsCertificateInWhitelist(*cert, ev_whitelist)) { | 367 IsCertificateInWhitelist(*cert, ev_whitelist)) { |
| 316 result->status = ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST; | 368 result->status = ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST; |
| 317 } | 369 } |
| 318 } | 370 } |
| 319 | 371 |
| 320 } // namespace | 372 } // namespace |
| 321 | 373 |
| 322 ct::CertPolicyCompliance CTPolicyEnforcer::DoesConformToCertPolicy( | 374 ct::CertPolicyCompliance CTPolicyEnforcer::DoesConformToCertPolicy( |
| 323 X509Certificate* cert, | 375 X509Certificate* cert, |
| 324 const ct::SCTList& verified_scts, | 376 const ct::SCTList& verified_scts, |
| 325 const BoundNetLog& net_log) { | 377 const BoundNetLog& net_log) { |
| 326 // If the build is not timely, no certificate is considered compliant | 378 // If the build is not timely, no certificate is considered compliant |
| 327 // with CT policy. The reasoning is that, for example, a log might | 379 // with CT policy. The reasoning is that, for example, a log might |
| 328 // have been pulled and is no longer considered valid; thus, a client | 380 // have been pulled and is no longer considered valid; thus, a client |
| 329 // needs up-to-date information about logs to consider certificates to | 381 // needs up-to-date information about logs to consider certificates to |
| 330 // be compliant with policy. | 382 // be compliant with policy. |
| 331 bool build_timely = IsBuildTimely(); | 383 bool build_timely = IsBuildTimely(); |
| 332 ct::CertPolicyCompliance compliance; | 384 ct::CertPolicyCompliance compliance; |
| 333 if (!build_timely) { | 385 if (!build_timely) { |
| 334 compliance = ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY; | 386 compliance = ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY; |
| 335 } else { | 387 } else { |
| 336 compliance = CheckCertPolicyCompliance(cert, verified_scts, net_log); | 388 compliance = CheckCertPolicyCompliance(*cert, verified_scts); |
| 337 } | 389 } |
| 338 | 390 |
| 339 NetLog::ParametersCallback net_log_callback = | 391 NetLog::ParametersCallback net_log_callback = |
| 340 base::Bind(&NetLogCertComplianceCheckResultCallback, | 392 base::Bind(&NetLogCertComplianceCheckResultCallback, |
| 341 base::Unretained(cert), build_timely, compliance); | 393 base::Unretained(cert), build_timely, compliance); |
| 342 | 394 |
| 343 net_log.AddEvent(NetLog::TYPE_CERT_CT_COMPLIANCE_CHECKED, net_log_callback); | 395 net_log.AddEvent(NetLog::TYPE_CERT_CT_COMPLIANCE_CHECKED, net_log_callback); |
| 344 | 396 |
| 345 return compliance; | 397 return compliance; |
| 346 } | 398 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 373 | 425 |
| 374 if (!details.build_timely) | 426 if (!details.build_timely) |
| 375 return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; | 427 return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; |
| 376 | 428 |
| 377 LogEVPolicyComplianceToUMA(details.status, ev_whitelist); | 429 LogEVPolicyComplianceToUMA(details.status, ev_whitelist); |
| 378 | 430 |
| 379 return details.status; | 431 return details.status; |
| 380 } | 432 } |
| 381 | 433 |
| 382 } // namespace net | 434 } // namespace net |
| OLD | NEW |