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