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 std::unique_ptr<ProofVerifierCallback> callback); | 79 std::unique_ptr<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 std::unique_ptr<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 std::unique_ptr<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, | |
251 std::move(callback)); | |
252 } | |
253 | |
254 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( | |
255 const string& hostname, | |
256 const vector<string>& certs, | |
257 std::string* error_details, | |
258 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
259 std::unique_ptr<ProofVerifierCallback> callback) { | |
260 DCHECK(error_details); | |
261 DCHECK(verify_details); | |
262 DCHECK(callback); | |
263 | |
264 error_details->clear(); | |
265 | |
266 if (STATE_NONE != next_state_) { | |
267 *error_details = "Certificate is already set and VerifyCertChain has begun"; | |
268 DLOG(DFATAL) << *error_details; | |
269 return QUIC_FAILURE; | |
270 } | |
271 | |
272 verify_details_.reset(new ProofVerifyDetailsChromium); | |
273 | |
274 // Converts |certs| to |cert_|. | |
275 if (!GetX509Certificate(certs, error_details, verify_details)) | |
276 return QUIC_FAILURE; | |
277 | |
278 enforce_policy_checking_ = false; | |
279 // |port| is not needed because |enforce_policy_checking_| is false. | |
280 return VerifyCert(hostname, /*port=*/0, error_details, verify_details, | |
281 std::move(callback)); | |
282 } | |
283 | |
284 bool ProofVerifierChromium::Job::GetX509Certificate( | |
285 const vector<string>& certs, | |
286 std::string* error_details, | |
287 std::unique_ptr<ProofVerifyDetails>* verify_details) { | |
288 if (certs.empty()) { | |
289 *error_details = "Failed to create certificate chain. Certs are empty."; | |
290 DLOG(WARNING) << *error_details; | |
291 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
292 *verify_details = std::move(verify_details_); | |
293 return false; | |
294 } | |
295 | |
296 // Convert certs to X509Certificate. | |
297 vector<StringPiece> cert_pieces(certs.size()); | |
298 for (unsigned i = 0; i < certs.size(); i++) { | |
299 cert_pieces[i] = base::StringPiece(certs[i]); | |
300 } | |
301 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); | |
302 if (!cert_.get()) { | |
303 *error_details = "Failed to create certificate chain"; | |
304 DLOG(WARNING) << *error_details; | |
305 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
306 *verify_details = std::move(verify_details_); | |
307 return false; | |
308 } | |
309 return true; | |
310 } | |
311 | |
312 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert( | |
313 const string& hostname, | |
314 const uint16_t port, | |
315 std::string* error_details, | |
316 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
317 std::unique_ptr<ProofVerifierCallback> callback) { | |
318 hostname_ = hostname; | 240 hostname_ = hostname; |
319 port_ = port; | 241 port_ = port; |
320 | 242 |
321 next_state_ = STATE_VERIFY_CERT; | 243 next_state_ = STATE_VERIFY_CERT; |
322 switch (DoLoop(OK)) { | 244 switch (DoLoop(OK)) { |
323 case OK: | 245 case OK: |
324 *verify_details = std::move(verify_details_); | 246 *verify_details = std::move(verify_details_); |
325 return QUIC_SUCCESS; | 247 return QUIC_SUCCESS; |
326 case ERR_IO_PENDING: | 248 case ERR_IO_PENDING: |
327 callback_ = std::move(callback); | 249 callback_ = std::move(callback); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 308 |
387 const CertVerifyResult& cert_verify_result = | 309 const CertVerifyResult& cert_verify_result = |
388 verify_details_->cert_verify_result; | 310 verify_details_->cert_verify_result; |
389 const CertStatus cert_status = cert_verify_result.cert_status; | 311 const CertStatus cert_status = cert_verify_result.cert_status; |
390 verify_details_->ct_verify_result.ct_policies_applied = result == OK; | 312 verify_details_->ct_verify_result.ct_policies_applied = result == OK; |
391 verify_details_->ct_verify_result.ev_policy_compliance = | 313 verify_details_->ct_verify_result.ev_policy_compliance = |
392 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; | 314 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; |
393 | 315 |
394 // If the connection was good, check HPKP and CT status simultaneously, | 316 // If the connection was good, check HPKP and CT status simultaneously, |
395 // 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. |
396 if (enforce_policy_checking_ && | 318 if ((result == OK || |
397 (result == OK || | |
398 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { | 319 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { |
399 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { | 320 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { |
400 ct::EVPolicyCompliance ev_policy_compliance = | 321 ct::EVPolicyCompliance ev_policy_compliance = |
401 policy_enforcer_->DoesConformToCTEVPolicy( | 322 policy_enforcer_->DoesConformToCTEVPolicy( |
402 cert_verify_result.verified_cert.get(), | 323 cert_verify_result.verified_cert.get(), |
403 SSLConfigService::GetEVCertsWhitelist().get(), | 324 SSLConfigService::GetEVCertsWhitelist().get(), |
404 verify_details_->ct_verify_result.verified_scts, net_log_); | 325 verify_details_->ct_verify_result.verified_scts, net_log_); |
405 verify_details_->ct_verify_result.ev_policy_compliance = | 326 verify_details_->ct_verify_result.ev_policy_compliance = |
406 ev_policy_compliance; | 327 ev_policy_compliance; |
407 if (ev_policy_compliance != | 328 if (ev_policy_compliance != |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 } | 498 } |
578 const ProofVerifyContextChromium* chromium_context = | 499 const ProofVerifyContextChromium* chromium_context = |
579 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); | 500 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); |
580 std::unique_ptr<Job> job( | 501 std::unique_ptr<Job> job( |
581 new Job(this, cert_verifier_, ct_policy_enforcer_, | 502 new Job(this, cert_verifier_, ct_policy_enforcer_, |
582 transport_security_state_, cert_transparency_verifier_, | 503 transport_security_state_, cert_transparency_verifier_, |
583 chromium_context->cert_verify_flags, chromium_context->net_log)); | 504 chromium_context->cert_verify_flags, chromium_context->net_log)); |
584 QuicAsyncStatus status = job->VerifyProof( | 505 QuicAsyncStatus status = job->VerifyProof( |
585 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, | 506 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, |
586 signature, error_details, verify_details, std::move(callback)); | 507 signature, error_details, verify_details, std::move(callback)); |
587 if (status == QUIC_PENDING) | 508 if (status == QUIC_PENDING) { |
588 active_jobs_.insert(job.release()); | 509 active_jobs_.insert(job.release()); |
| 510 } |
589 return status; | 511 return status; |
590 } | 512 } |
591 | 513 |
592 QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( | |
593 const std::string& hostname, | |
594 const std::vector<std::string>& certs, | |
595 const ProofVerifyContext* verify_context, | |
596 std::string* error_details, | |
597 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
598 std::unique_ptr<ProofVerifierCallback> callback) { | |
599 if (!verify_context) { | |
600 *error_details = "Missing context"; | |
601 return QUIC_FAILURE; | |
602 } | |
603 const ProofVerifyContextChromium* chromium_context = | |
604 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); | |
605 std::unique_ptr<Job> job( | |
606 new Job(this, cert_verifier_, ct_policy_enforcer_, | |
607 transport_security_state_, cert_transparency_verifier_, | |
608 chromium_context->cert_verify_flags, chromium_context->net_log)); | |
609 QuicAsyncStatus status = job->VerifyCertChain( | |
610 hostname, certs, error_details, verify_details, std::move(callback)); | |
611 if (status == QUIC_PENDING) | |
612 active_jobs_.insert(job.release()); | |
613 return status; | |
614 } | |
615 | |
616 void ProofVerifierChromium::OnJobComplete(Job* job) { | 514 void ProofVerifierChromium::OnJobComplete(Job* job) { |
617 active_jobs_.erase(job); | 515 active_jobs_.erase(job); |
618 delete job; | 516 delete job; |
619 } | 517 } |
620 | 518 |
621 } // namespace net | 519 } // namespace net |
OLD | NEW |