OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/quic_crypto_client_stream.h" | 5 #include "net/quic/quic_crypto_client_stream.h" |
6 | 6 |
7 #include "net/base/completion_callback.h" | 7 #include "net/base/completion_callback.h" |
8 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" |
9 #include "net/quic/crypto/crypto_protocol.h" | 9 #include "net/quic/crypto/crypto_protocol.h" |
10 #include "net/quic/crypto/crypto_utils.h" | 10 #include "net/quic/crypto/crypto_utils.h" |
11 #include "net/quic/crypto/null_encrypter.h" | 11 #include "net/quic/crypto/null_encrypter.h" |
12 #include "net/quic/crypto/proof_verifier.h" | 12 #include "net/quic/crypto/proof_verifier.h" |
13 #include "net/quic/crypto/proof_verifier_chromium.h" | |
13 #include "net/quic/quic_protocol.h" | 14 #include "net/quic/quic_protocol.h" |
14 #include "net/quic/quic_session.h" | 15 #include "net/quic/quic_session.h" |
15 #include "net/ssl/ssl_connection_status_flags.h" | 16 #include "net/ssl/ssl_connection_status_flags.h" |
16 #include "net/ssl/ssl_info.h" | 17 #include "net/ssl/ssl_info.h" |
17 | 18 |
18 namespace net { | 19 namespace net { |
19 | 20 |
21 // ProofVerifierCallbackClientStream is passed as the callback method to | |
22 // VerifyProof. The ProofVerifier calls this class with the result of proof | |
23 // verification when verification is performed asynchronously. | |
24 class ProofVerifierCallbackClientStream : public ProofVerifierCallback { | |
Ryan Hamilton
2013/07/23 18:40:50
This code can land in google3, right? (It will ju
agl
2013/07/23 21:04:57
Right.
| |
25 public: | |
26 explicit ProofVerifierCallbackClientStream(QuicCryptoClientStream* stream) | |
27 : stream_(stream) {} | |
28 | |
29 // ProofVerifierCallback interface. | |
30 virtual void Run(bool ok, | |
31 string* error_details, | |
32 ProofVerifyDetails* details) OVERRIDE { | |
33 if (stream_ == NULL) { | |
34 delete details; | |
35 return; | |
36 } | |
37 | |
38 stream_->verify_ok_ = ok; | |
39 stream_->verify_error_details_ = *error_details; | |
40 stream_->verify_details_.reset(details); | |
41 stream_->proof_verify_callback_ = NULL; | |
42 stream_->DoHandshakeLoop(NULL); | |
43 | |
44 // The ProofVerifier owns this object and will delete it when this method | |
45 // returns. | |
46 } | |
47 | |
48 // Cancel causes any future callbacks to be ignored. It must be called on the | |
49 // same thread as the callback will be made on. | |
50 void Cancel() { | |
51 stream_ = NULL; | |
52 } | |
53 | |
54 private: | |
55 QuicCryptoClientStream* stream_; | |
56 }; | |
57 | |
20 QuicCryptoClientStream::QuicCryptoClientStream( | 58 QuicCryptoClientStream::QuicCryptoClientStream( |
21 const string& server_hostname, | 59 const string& server_hostname, |
22 QuicSession* session, | 60 QuicSession* session, |
23 QuicCryptoClientConfig* crypto_config) | 61 QuicCryptoClientConfig* crypto_config) |
24 : QuicCryptoStream(session), | 62 : QuicCryptoStream(session), |
25 weak_factory_(this), | |
26 next_state_(STATE_IDLE), | 63 next_state_(STATE_IDLE), |
27 num_client_hellos_(0), | 64 num_client_hellos_(0), |
28 crypto_config_(crypto_config), | 65 crypto_config_(crypto_config), |
29 server_hostname_(server_hostname), | 66 server_hostname_(server_hostname), |
30 generation_counter_(0) { | 67 generation_counter_(0), |
68 proof_verify_callback_(NULL) { | |
31 } | 69 } |
32 | 70 |
33 QuicCryptoClientStream::~QuicCryptoClientStream() { | 71 QuicCryptoClientStream::~QuicCryptoClientStream() { |
72 if (proof_verify_callback_) { | |
73 proof_verify_callback_->Cancel(); | |
74 } | |
34 } | 75 } |
35 | 76 |
36 void QuicCryptoClientStream::OnHandshakeMessage( | 77 void QuicCryptoClientStream::OnHandshakeMessage( |
37 const CryptoHandshakeMessage& message) { | 78 const CryptoHandshakeMessage& message) { |
38 DoHandshakeLoop(&message, OK); | 79 DoHandshakeLoop(&message); |
39 } | 80 } |
40 | 81 |
41 bool QuicCryptoClientStream::CryptoConnect() { | 82 bool QuicCryptoClientStream::CryptoConnect() { |
42 next_state_ = STATE_SEND_CHLO; | 83 next_state_ = STATE_SEND_CHLO; |
43 DoHandshakeLoop(NULL, OK); | 84 DoHandshakeLoop(NULL); |
44 return true; | 85 return true; |
45 } | 86 } |
46 | 87 |
47 int QuicCryptoClientStream::num_sent_client_hellos() const { | 88 int QuicCryptoClientStream::num_sent_client_hellos() const { |
48 return num_client_hellos_; | 89 return num_client_hellos_; |
49 } | 90 } |
50 | 91 |
51 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { | 92 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { |
52 ssl_info->Reset(); | 93 ssl_info->Reset(); |
53 QuicCryptoClientConfig::CachedState* cached = | 94 QuicCryptoClientConfig::CachedState* cached = |
54 crypto_config_->LookupOrCreate(server_hostname_); | 95 crypto_config_->LookupOrCreate(server_hostname_); |
55 DCHECK(cached); | 96 DCHECK(cached); |
56 if (!cached) { | 97 if (!cached) { |
57 return false; | 98 return false; |
58 } | 99 } |
59 const CertVerifyResult* cert_verify_result = | 100 const CertVerifyResult* cert_verify_result = |
60 cached->cert_verify_result(); | 101 &(reinterpret_cast<const ProofVerifyDetailsChromium*>( |
102 cached->proof_verify_details()))->cert_verify_result; | |
61 | 103 |
62 ssl_info->cert_status = cert_verify_result->cert_status; | 104 ssl_info->cert_status = cert_verify_result->cert_status; |
63 ssl_info->cert = cert_verify_result->verified_cert; | 105 ssl_info->cert = cert_verify_result->verified_cert; |
64 | 106 |
65 // TODO(rtenneti): Figure out what to set for the following. | 107 // TODO(rtenneti): Figure out what to set for the following. |
66 // Temporarily hard coded cipher_suite as 0xc031 to represent | 108 // Temporarily hard coded cipher_suite as 0xc031 to represent |
67 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from | 109 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from |
68 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256. | 110 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256. |
69 int cipher_suite = 0xc02f; | 111 int cipher_suite = 0xc02f; |
70 int ssl_connection_status = 0; | 112 int ssl_connection_status = 0; |
(...skipping 17 matching lines...) Expand all Loading... | |
88 } | 130 } |
89 | 131 |
90 // kMaxClientHellos is the maximum number of times that we'll send a client | 132 // kMaxClientHellos is the maximum number of times that we'll send a client |
91 // hello. The value 3 accounts for: | 133 // hello. The value 3 accounts for: |
92 // * One failure due to an incorrect or missing source-address token. | 134 // * One failure due to an incorrect or missing source-address token. |
93 // * One failure due the server's certificate chain being unavailible and the | 135 // * One failure due the server's certificate chain being unavailible and the |
94 // server being unwilling to send it without a valid source-address token. | 136 // server being unwilling to send it without a valid source-address token. |
95 static const int kMaxClientHellos = 3; | 137 static const int kMaxClientHellos = 3; |
96 | 138 |
97 void QuicCryptoClientStream::DoHandshakeLoop( | 139 void QuicCryptoClientStream::DoHandshakeLoop( |
98 const CryptoHandshakeMessage* in, | 140 const CryptoHandshakeMessage* in) { |
99 int result) { | |
100 CryptoHandshakeMessage out; | 141 CryptoHandshakeMessage out; |
101 QuicErrorCode error; | 142 QuicErrorCode error; |
102 string error_details; | 143 string error_details; |
103 QuicCryptoClientConfig::CachedState* cached = | 144 QuicCryptoClientConfig::CachedState* cached = |
104 crypto_config_->LookupOrCreate(server_hostname_); | 145 crypto_config_->LookupOrCreate(server_hostname_); |
105 | 146 |
106 if (in != NULL) { | 147 if (in != NULL) { |
107 DVLOG(1) << "Client received: " << in->DebugString(); | 148 DVLOG(1) << "Client received: " << in->DebugString(); |
108 } | 149 } |
109 | 150 |
110 for (;;) { | 151 for (;;) { |
111 const State state = next_state_; | 152 const State state = next_state_; |
112 next_state_ = STATE_IDLE; | 153 next_state_ = STATE_IDLE; |
113 switch (state) { | 154 switch (state) { |
114 case STATE_SEND_CHLO: { | 155 case STATE_SEND_CHLO: { |
115 DCHECK_EQ(OK, result); | |
116 // Send the client hello in plaintext. | 156 // Send the client hello in plaintext. |
117 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); | 157 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); |
118 if (num_client_hellos_ > kMaxClientHellos) { | 158 if (num_client_hellos_ > kMaxClientHellos) { |
119 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); | 159 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); |
120 return; | 160 return; |
121 } | 161 } |
122 num_client_hellos_++; | 162 num_client_hellos_++; |
123 | 163 |
124 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { | 164 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { |
125 crypto_config_->FillInchoateClientHello( | 165 crypto_config_->FillInchoateClientHello( |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 encryption_established_ = true; | 204 encryption_established_ = true; |
165 session()->OnCryptoHandshakeEvent( | 205 session()->OnCryptoHandshakeEvent( |
166 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); | 206 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); |
167 } else { | 207 } else { |
168 session()->OnCryptoHandshakeEvent( | 208 session()->OnCryptoHandshakeEvent( |
169 QuicSession::ENCRYPTION_REESTABLISHED); | 209 QuicSession::ENCRYPTION_REESTABLISHED); |
170 } | 210 } |
171 return; | 211 return; |
172 } | 212 } |
173 case STATE_RECV_REJ: | 213 case STATE_RECV_REJ: |
174 DCHECK_EQ(OK, result); | |
175 // We sent a dummy CHLO because we didn't have enough information to | 214 // We sent a dummy CHLO because we didn't have enough information to |
176 // perform a handshake, or we sent a full hello that the server | 215 // perform a handshake, or we sent a full hello that the server |
177 // rejected. Here we hope to have a REJ that contains the information | 216 // rejected. Here we hope to have a REJ that contains the information |
178 // that we need. | 217 // that we need. |
179 if (in->tag() != kREJ) { | 218 if (in->tag() != kREJ) { |
180 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, | 219 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, |
181 "Expected REJ"); | 220 "Expected REJ"); |
182 return; | 221 return; |
183 } | 222 } |
184 error = crypto_config_->ProcessRejection( | 223 error = crypto_config_->ProcessRejection( |
(...skipping 13 matching lines...) Expand all Loading... | |
198 break; | 237 break; |
199 } | 238 } |
200 } | 239 } |
201 next_state_ = STATE_SEND_CHLO; | 240 next_state_ = STATE_SEND_CHLO; |
202 break; | 241 break; |
203 case STATE_VERIFY_PROOF: { | 242 case STATE_VERIFY_PROOF: { |
204 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 243 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
205 DCHECK(verifier); | 244 DCHECK(verifier); |
206 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | 245 next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
207 generation_counter_ = cached->generation_counter(); | 246 generation_counter_ = cached->generation_counter(); |
208 result = verifier->VerifyProof( | 247 |
248 ProofVerifierCallbackClientStream* proof_verify_callback = new | |
249 ProofVerifierCallbackClientStream(this); | |
250 | |
251 verify_ok_ = false; | |
252 | |
253 ProofVerifier::Status status = verifier->VerifyProof( | |
209 server_hostname_, | 254 server_hostname_, |
210 cached->server_config(), | 255 cached->server_config(), |
211 cached->certs(), | 256 cached->certs(), |
212 cached->signature(), | 257 cached->signature(), |
213 &error_details_, | 258 &error_details, |
214 &cert_verify_result_, | 259 &verify_details_, |
215 base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete, | 260 proof_verify_callback); |
216 weak_factory_.GetWeakPtr())); | 261 |
217 if (result == ERR_IO_PENDING) { | 262 switch (status) { |
218 DVLOG(1) << "Doing VerifyProof"; | 263 case ProofVerifier::PENDING: |
219 return; | 264 proof_verify_callback_ = proof_verify_callback; |
265 DVLOG(1) << "Doing VerifyProof"; | |
266 return; | |
267 case ProofVerifier::ERROR: | |
268 CloseConnectionWithDetails( | |
269 QUIC_PROOF_INVALID, "Proof invalid: " + error_details); | |
270 return; | |
271 case ProofVerifier::OK: | |
272 verify_ok_ = true; | |
273 break; | |
220 } | 274 } |
221 break; | 275 break; |
222 } | 276 } |
223 case STATE_VERIFY_PROOF_COMPLETE: | 277 case STATE_VERIFY_PROOF_COMPLETE: |
224 if (result != OK) { | 278 if (!verify_ok_) { |
225 CloseConnectionWithDetails( | 279 CloseConnectionWithDetails( |
226 QUIC_PROOF_INVALID, "Proof invalid: " + error_details_); | 280 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); |
227 return; | 281 return; |
228 } | 282 } |
229 // Check if generation_counter has changed between STATE_VERIFY_PROOF | 283 // Check if generation_counter has changed between STATE_VERIFY_PROOF |
230 // and STATE_VERIFY_PROOF_COMPLETE state changes. | 284 // and STATE_VERIFY_PROOF_COMPLETE state changes. |
231 if (generation_counter_ != cached->generation_counter()) { | 285 if (generation_counter_ != cached->generation_counter()) { |
232 next_state_ = STATE_VERIFY_PROOF; | 286 next_state_ = STATE_VERIFY_PROOF; |
233 } else { | 287 } else { |
234 cached->SetProofValid(); | 288 cached->SetProofValid(); |
235 cached->SetCertVerifyResult(cert_verify_result_); | 289 cached->SetProofVerifyDetails(verify_details_.release()); |
236 next_state_ = STATE_SEND_CHLO; | 290 next_state_ = STATE_SEND_CHLO; |
237 } | 291 } |
238 break; | 292 break; |
239 case STATE_RECV_SHLO: { | 293 case STATE_RECV_SHLO: { |
240 // We sent a CHLO that we expected to be accepted and now we're hoping | 294 // We sent a CHLO that we expected to be accepted and now we're hoping |
241 // for a SHLO from the server to confirm that. | 295 // for a SHLO from the server to confirm that. |
242 if (in->tag() == kREJ) { | 296 if (in->tag() == kREJ) { |
243 // alternative_decrypter will be NULL if the original alternative | 297 // alternative_decrypter will be NULL if the original alternative |
244 // decrypter latched and became the primary decrypter. That happens | 298 // decrypter latched and became the primary decrypter. That happens |
245 // if we received a message encrypted with the INITIAL key. | 299 // if we received a message encrypted with the INITIAL key. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 return; | 352 return; |
299 } | 353 } |
300 case STATE_IDLE: | 354 case STATE_IDLE: |
301 // This means that the peer sent us a message that we weren't expecting. | 355 // This means that the peer sent us a message that we weren't expecting. |
302 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 356 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
303 return; | 357 return; |
304 } | 358 } |
305 } | 359 } |
306 } | 360 } |
307 | 361 |
308 void QuicCryptoClientStream::OnVerifyProofComplete(int result) { | |
309 DCHECK_EQ(STATE_VERIFY_PROOF_COMPLETE, next_state_); | |
310 DVLOG(1) << "VerifyProof completed: " << result; | |
311 DoHandshakeLoop(NULL, result); | |
312 } | |
313 | |
314 } // namespace net | 362 } // namespace net |
OLD | NEW |