OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/quic/crypto/proof_verifier_chromium.h" | 5 #include "net/quic/crypto/proof_verifier_chromium.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 const std::string& server_config, | 71 const std::string& server_config, |
72 QuicVersion quic_version, | 72 QuicVersion quic_version, |
73 base::StringPiece chlo_hash, | 73 base::StringPiece chlo_hash, |
74 const std::vector<std::string>& certs, | 74 const std::vector<std::string>& certs, |
75 const std::string& cert_sct, | 75 const std::string& cert_sct, |
76 const std::string& signature, | 76 const std::string& signature, |
77 std::string* error_details, | 77 std::string* error_details, |
78 std::unique_ptr<ProofVerifyDetails>* verify_details, | 78 std::unique_ptr<ProofVerifyDetails>* verify_details, |
79 ProofVerifierCallback* callback); | 79 ProofVerifierCallback* callback); |
80 | 80 |
81 // Starts the certificate chain verification of |certs|. If |QUIC_PENDING| is | |
82 // returned, then |callback| will be invoked asynchronously when the | |
83 // verification completes. | |
84 QuicAsyncStatus VerifyCertChain( | |
85 const std::string& hostname, | |
86 const uint16_t port, | |
87 const std::vector<std::string>& certs, | |
88 std::string* error_details, | |
89 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
90 ProofVerifierCallback* callback); | |
91 | |
81 private: | 92 private: |
82 enum State { | 93 enum State { |
83 STATE_NONE, | 94 STATE_NONE, |
84 STATE_VERIFY_CERT, | 95 STATE_VERIFY_CERT, |
85 STATE_VERIFY_CERT_COMPLETE, | 96 STATE_VERIFY_CERT_COMPLETE, |
86 }; | 97 }; |
87 | 98 |
99 // Convert |certs| to |cert_|(X509Certificate). Returns true if successful. | |
100 bool GetX509Certificate(const vector<string>& certs, | |
101 std::string* error_details, | |
102 std::unique_ptr<ProofVerifyDetails>* verify_details); | |
103 | |
104 // Start the cert verification. | |
105 QuicAsyncStatus VerifyCert( | |
106 const string& hostname, | |
107 const uint16_t port, | |
108 std::string* error_details, | |
109 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
110 ProofVerifierCallback* callback); | |
111 | |
88 int DoLoop(int last_io_result); | 112 int DoLoop(int last_io_result); |
89 void OnIOComplete(int result); | 113 void OnIOComplete(int result); |
90 int DoVerifyCert(int result); | 114 int DoVerifyCert(int result); |
91 int DoVerifyCertComplete(int result); | 115 int DoVerifyCertComplete(int result); |
92 | 116 |
93 bool VerifySignature(const std::string& signed_data, | 117 bool VerifySignature(const std::string& signed_data, |
94 QuicVersion quic_version, | 118 QuicVersion quic_version, |
95 StringPiece chlo_hash, | 119 StringPiece chlo_hash, |
96 const std::string& signature, | 120 const std::string& signature, |
97 const std::string& cert); | 121 const std::string& cert); |
(...skipping 20 matching lines...) Expand all Loading... | |
118 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_; | 142 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_; |
119 std::string error_details_; | 143 std::string error_details_; |
120 | 144 |
121 // X509Certificate from a chain of DER encoded certificates. | 145 // X509Certificate from a chain of DER encoded certificates. |
122 scoped_refptr<X509Certificate> cert_; | 146 scoped_refptr<X509Certificate> cert_; |
123 | 147 |
124 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is | 148 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is |
125 // passed to CertVerifier::Verify. | 149 // passed to CertVerifier::Verify. |
126 int cert_verify_flags_; | 150 int cert_verify_flags_; |
127 | 151 |
152 // If set to true, enforces policy checking in DoVerifyCertComplete(). | |
153 bool enforce_policy_checking_; | |
ramant (doing other things)
2016/07/07 19:31:49
Hi Ryan,
As we had discussed offline, added this
| |
154 | |
128 State next_state_; | 155 State next_state_; |
129 | 156 |
130 base::TimeTicks start_time_; | 157 base::TimeTicks start_time_; |
131 | 158 |
132 BoundNetLog net_log_; | 159 BoundNetLog net_log_; |
133 | 160 |
134 DISALLOW_COPY_AND_ASSIGN(Job); | 161 DISALLOW_COPY_AND_ASSIGN(Job); |
135 }; | 162 }; |
136 | 163 |
137 ProofVerifierChromium::Job::Job( | 164 ProofVerifierChromium::Job::Job( |
138 ProofVerifierChromium* proof_verifier, | 165 ProofVerifierChromium* proof_verifier, |
139 CertVerifier* cert_verifier, | 166 CertVerifier* cert_verifier, |
140 CTPolicyEnforcer* ct_policy_enforcer, | 167 CTPolicyEnforcer* ct_policy_enforcer, |
141 TransportSecurityState* transport_security_state, | 168 TransportSecurityState* transport_security_state, |
142 CTVerifier* cert_transparency_verifier, | 169 CTVerifier* cert_transparency_verifier, |
143 int cert_verify_flags, | 170 int cert_verify_flags, |
144 const BoundNetLog& net_log) | 171 const BoundNetLog& net_log) |
145 : proof_verifier_(proof_verifier), | 172 : proof_verifier_(proof_verifier), |
146 verifier_(cert_verifier), | 173 verifier_(cert_verifier), |
147 policy_enforcer_(ct_policy_enforcer), | 174 policy_enforcer_(ct_policy_enforcer), |
148 transport_security_state_(transport_security_state), | 175 transport_security_state_(transport_security_state), |
149 cert_transparency_verifier_(cert_transparency_verifier), | 176 cert_transparency_verifier_(cert_transparency_verifier), |
150 cert_verify_flags_(cert_verify_flags), | 177 cert_verify_flags_(cert_verify_flags), |
178 enforce_policy_checking_(true), | |
151 next_state_(STATE_NONE), | 179 next_state_(STATE_NONE), |
152 start_time_(base::TimeTicks::Now()), | 180 start_time_(base::TimeTicks::Now()), |
153 net_log_(net_log) { | 181 net_log_(net_log) { |
154 CHECK(proof_verifier_); | 182 CHECK(proof_verifier_); |
155 CHECK(verifier_); | 183 CHECK(verifier_); |
156 CHECK(policy_enforcer_); | 184 CHECK(policy_enforcer_); |
157 CHECK(transport_security_state_); | 185 CHECK(transport_security_state_); |
158 CHECK(cert_transparency_verifier_); | 186 CHECK(cert_transparency_verifier_); |
159 } | 187 } |
160 | 188 |
(...skipping 27 matching lines...) Expand all Loading... | |
188 error_details->clear(); | 216 error_details->clear(); |
189 | 217 |
190 if (STATE_NONE != next_state_) { | 218 if (STATE_NONE != next_state_) { |
191 *error_details = "Certificate is already set and VerifyProof has begun"; | 219 *error_details = "Certificate is already set and VerifyProof has begun"; |
192 DLOG(DFATAL) << *error_details; | 220 DLOG(DFATAL) << *error_details; |
193 return QUIC_FAILURE; | 221 return QUIC_FAILURE; |
194 } | 222 } |
195 | 223 |
196 verify_details_.reset(new ProofVerifyDetailsChromium); | 224 verify_details_.reset(new ProofVerifyDetailsChromium); |
197 | 225 |
198 if (certs.empty()) { | 226 // Converts |certs| to |cert_|. |
199 *error_details = "Failed to create certificate chain. Certs are empty."; | 227 if (!GetX509Certificate(certs, error_details, verify_details)) { |
200 DLOG(WARNING) << *error_details; | |
201 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
202 *verify_details = std::move(verify_details_); | |
203 return QUIC_FAILURE; | 228 return QUIC_FAILURE; |
204 } | 229 } |
205 | 230 |
206 // Convert certs to X509Certificate. | |
207 vector<StringPiece> cert_pieces(certs.size()); | |
208 for (unsigned i = 0; i < certs.size(); i++) { | |
209 cert_pieces[i] = base::StringPiece(certs[i]); | |
210 } | |
211 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); | |
212 if (!cert_.get()) { | |
213 *error_details = "Failed to create certificate chain"; | |
214 DLOG(WARNING) << *error_details; | |
215 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
216 *verify_details = std::move(verify_details_); | |
217 return QUIC_FAILURE; | |
218 } | |
219 | |
220 if (!cert_sct.empty()) { | 231 if (!cert_sct.empty()) { |
221 // Note that this is a completely synchronous operation: The CT Log Verifier | 232 // Note that this is a completely synchronous operation: The CT Log Verifier |
222 // gets all the data it needs for SCT verification and does not do any | 233 // gets all the data it needs for SCT verification and does not do any |
223 // external communication. | 234 // external communication. |
224 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, | 235 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, |
225 &verify_details_->ct_verify_result, | 236 &verify_details_->ct_verify_result, |
226 net_log_); | 237 net_log_); |
227 } | 238 } |
228 | 239 |
229 // We call VerifySignature first to avoid copying of server_config and | 240 // We call VerifySignature first to avoid copying of server_config and |
230 // signature. | 241 // signature. |
231 if (!VerifySignature(server_config, quic_version, chlo_hash, signature, | 242 if (!VerifySignature(server_config, quic_version, chlo_hash, signature, |
232 certs[0])) { | 243 certs[0])) { |
233 *error_details = "Failed to verify signature of server config"; | 244 *error_details = "Failed to verify signature of server config"; |
234 DLOG(WARNING) << *error_details; | 245 DLOG(WARNING) << *error_details; |
235 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | 246 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
236 *verify_details = std::move(verify_details_); | 247 *verify_details = std::move(verify_details_); |
237 return QUIC_FAILURE; | 248 return QUIC_FAILURE; |
238 } | 249 } |
239 | 250 |
251 DCHECK(enforce_policy_checking_); | |
252 return VerifyCert(hostname, port, error_details, verify_details, callback); | |
253 } | |
254 | |
255 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( | |
256 const string& hostname, | |
257 const uint16_t port, | |
258 const vector<string>& certs, | |
259 std::string* error_details, | |
260 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
261 ProofVerifierCallback* callback) { | |
262 DCHECK(error_details); | |
263 DCHECK(verify_details); | |
264 DCHECK(callback); | |
265 | |
266 error_details->clear(); | |
267 | |
268 if (STATE_NONE != next_state_) { | |
269 *error_details = "Certificate is already set and VerifyCertChain has begun"; | |
270 DLOG(DFATAL) << *error_details; | |
271 return QUIC_FAILURE; | |
272 } | |
273 | |
274 verify_details_.reset(new ProofVerifyDetailsChromium); | |
275 | |
276 // Converts |certs| to |cert_|. | |
277 if (!GetX509Certificate(certs, error_details, verify_details)) { | |
278 return QUIC_FAILURE; | |
279 } | |
280 | |
281 enforce_policy_checking_ = false; | |
282 return VerifyCert(hostname, port, error_details, verify_details, callback); | |
283 } | |
284 | |
285 bool ProofVerifierChromium::Job::GetX509Certificate( | |
286 const vector<string>& certs, | |
287 std::string* error_details, | |
288 std::unique_ptr<ProofVerifyDetails>* verify_details) { | |
289 if (certs.empty()) { | |
290 *error_details = "Failed to create certificate chain. Certs are empty."; | |
291 DLOG(WARNING) << *error_details; | |
292 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
293 *verify_details = std::move(verify_details_); | |
294 return false; | |
295 } | |
296 | |
297 // Convert certs to X509Certificate. | |
298 vector<StringPiece> cert_pieces(certs.size()); | |
299 for (unsigned i = 0; i < certs.size(); i++) { | |
300 cert_pieces[i] = base::StringPiece(certs[i]); | |
301 } | |
302 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); | |
303 if (!cert_.get()) { | |
304 *error_details = "Failed to create certificate chain"; | |
305 DLOG(WARNING) << *error_details; | |
306 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
307 *verify_details = std::move(verify_details_); | |
308 return false; | |
309 } | |
310 return true; | |
311 } | |
312 | |
313 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert( | |
314 const string& hostname, | |
315 const uint16_t port, | |
316 std::string* error_details, | |
317 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
318 ProofVerifierCallback* callback) { | |
240 hostname_ = hostname; | 319 hostname_ = hostname; |
241 port_ = port; | 320 port_ = port; |
242 | 321 |
243 next_state_ = STATE_VERIFY_CERT; | 322 next_state_ = STATE_VERIFY_CERT; |
244 switch (DoLoop(OK)) { | 323 switch (DoLoop(OK)) { |
245 case OK: | 324 case OK: |
246 *verify_details = std::move(verify_details_); | 325 *verify_details = std::move(verify_details_); |
247 return QUIC_SUCCESS; | 326 return QUIC_SUCCESS; |
248 case ERR_IO_PENDING: | 327 case ERR_IO_PENDING: |
249 callback_.reset(callback); | 328 callback_.reset(callback); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 | 387 |
309 const CertVerifyResult& cert_verify_result = | 388 const CertVerifyResult& cert_verify_result = |
310 verify_details_->cert_verify_result; | 389 verify_details_->cert_verify_result; |
311 const CertStatus cert_status = cert_verify_result.cert_status; | 390 const CertStatus cert_status = cert_verify_result.cert_status; |
312 verify_details_->ct_verify_result.ct_policies_applied = result == OK; | 391 verify_details_->ct_verify_result.ct_policies_applied = result == OK; |
313 verify_details_->ct_verify_result.ev_policy_compliance = | 392 verify_details_->ct_verify_result.ev_policy_compliance = |
314 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; | 393 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; |
315 | 394 |
316 // If the connection was good, check HPKP and CT status simultaneously, | 395 // If the connection was good, check HPKP and CT status simultaneously, |
317 // but prefer to treat the HPKP error as more serious, if there was one. | 396 // but prefer to treat the HPKP error as more serious, if there was one. |
318 if ((result == OK || | 397 if (enforce_policy_checking_ && |
398 (result == OK || | |
319 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { | 399 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { |
320 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { | 400 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { |
321 ct::EVPolicyCompliance ev_policy_compliance = | 401 ct::EVPolicyCompliance ev_policy_compliance = |
322 policy_enforcer_->DoesConformToCTEVPolicy( | 402 policy_enforcer_->DoesConformToCTEVPolicy( |
323 cert_verify_result.verified_cert.get(), | 403 cert_verify_result.verified_cert.get(), |
324 SSLConfigService::GetEVCertsWhitelist().get(), | 404 SSLConfigService::GetEVCertsWhitelist().get(), |
325 verify_details_->ct_verify_result.verified_scts, net_log_); | 405 verify_details_->ct_verify_result.verified_scts, net_log_); |
326 verify_details_->ct_verify_result.ev_policy_compliance = | 406 verify_details_->ct_verify_result.ev_policy_compliance = |
327 ev_policy_compliance; | 407 ev_policy_compliance; |
328 if (ev_policy_compliance != | 408 if (ev_policy_compliance != |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 chromium_context->cert_verify_flags, chromium_context->net_log)); | 584 chromium_context->cert_verify_flags, chromium_context->net_log)); |
505 QuicAsyncStatus status = job->VerifyProof( | 585 QuicAsyncStatus status = job->VerifyProof( |
506 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, | 586 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, |
507 signature, error_details, verify_details, callback); | 587 signature, error_details, verify_details, callback); |
508 if (status == QUIC_PENDING) { | 588 if (status == QUIC_PENDING) { |
509 active_jobs_.insert(job.release()); | 589 active_jobs_.insert(job.release()); |
510 } | 590 } |
511 return status; | 591 return status; |
512 } | 592 } |
513 | 593 |
594 QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( | |
595 const std::string& hostname, | |
596 const uint16_t port, | |
597 const std::vector<std::string>& certs, | |
598 const ProofVerifyContext* verify_context, | |
599 std::string* error_details, | |
600 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
601 ProofVerifierCallback* callback) { | |
602 if (!verify_context) { | |
603 *error_details = "Missing context"; | |
604 return QUIC_FAILURE; | |
605 } | |
606 const ProofVerifyContextChromium* chromium_context = | |
607 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); | |
608 std::unique_ptr<Job> job( | |
609 new Job(this, cert_verifier_, ct_policy_enforcer_, | |
610 transport_security_state_, cert_transparency_verifier_, | |
611 chromium_context->cert_verify_flags, chromium_context->net_log)); | |
612 QuicAsyncStatus status = job->VerifyCertChain( | |
613 hostname, port, certs, error_details, verify_details, callback); | |
614 if (status == QUIC_PENDING) { | |
615 active_jobs_.insert(job.release()); | |
616 } | |
Ryan Hamilton
2016/07/07 21:36:12
nit: no {}s
ramant (doing other things)
2016/07/07 22:18:27
Done. Used no {}s in chromium specific files. They
| |
617 return status; | |
618 } | |
619 | |
514 void ProofVerifierChromium::OnJobComplete(Job* job) { | 620 void ProofVerifierChromium::OnJobComplete(Job* job) { |
515 active_jobs_.erase(job); | 621 active_jobs_.erase(job); |
516 delete job; | 622 delete job; |
517 } | 623 } |
518 | 624 |
519 } // namespace net | 625 } // namespace net |
OLD | NEW |