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/quic/crypto/crypto_protocol.h" | 7 #include "net/quic/crypto/crypto_protocol.h" |
8 #include "net/quic/crypto/crypto_utils.h" | 8 #include "net/quic/crypto/crypto_utils.h" |
9 #include "net/quic/crypto/null_encrypter.h" | 9 #include "net/quic/crypto/null_encrypter.h" |
10 #include "net/quic/crypto/proof_verifier.h" | 10 #include "net/quic/crypto/proof_verifier.h" |
11 #include "net/quic/quic_client_session_base.h" | 11 #include "net/quic/quic_client_session_base.h" |
12 #include "net/quic/quic_protocol.h" | 12 #include "net/quic/quic_protocol.h" |
13 #include "net/quic/quic_session.h" | 13 #include "net/quic/quic_session.h" |
14 | 14 |
15 namespace net { | 15 namespace net { |
16 | 16 |
17 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( | 17 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( |
18 QuicCryptoClientStream* stream) | 18 QuicCryptoClientStream* stream) |
19 : stream_(stream) {} | 19 : stream_(stream) { |
| 20 } |
20 | 21 |
21 QuicCryptoClientStream::ProofVerifierCallbackImpl:: | 22 QuicCryptoClientStream::ProofVerifierCallbackImpl:: |
22 ~ProofVerifierCallbackImpl() {} | 23 ~ProofVerifierCallbackImpl() { |
| 24 } |
23 | 25 |
24 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( | 26 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( |
25 bool ok, | 27 bool ok, |
26 const string& error_details, | 28 const string& error_details, |
27 scoped_ptr<ProofVerifyDetails>* details) { | 29 scoped_ptr<ProofVerifyDetails>* details) { |
28 if (stream_ == NULL) { | 30 if (stream_ == NULL) { |
29 return; | 31 return; |
30 } | 32 } |
31 | 33 |
32 stream_->verify_ok_ = ok; | 34 stream_->verify_ok_ = ok; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 return num_client_hellos_; | 83 return num_client_hellos_; |
82 } | 84 } |
83 | 85 |
84 // kMaxClientHellos is the maximum number of times that we'll send a client | 86 // kMaxClientHellos is the maximum number of times that we'll send a client |
85 // hello. The value 3 accounts for: | 87 // hello. The value 3 accounts for: |
86 // * One failure due to an incorrect or missing source-address token. | 88 // * One failure due to an incorrect or missing source-address token. |
87 // * One failure due the server's certificate chain being unavailible and the | 89 // * One failure due the server's certificate chain being unavailible and the |
88 // server being unwilling to send it without a valid source-address token. | 90 // server being unwilling to send it without a valid source-address token. |
89 static const int kMaxClientHellos = 3; | 91 static const int kMaxClientHellos = 3; |
90 | 92 |
91 void QuicCryptoClientStream::DoHandshakeLoop( | 93 void QuicCryptoClientStream::DoHandshakeLoop(const CryptoHandshakeMessage* in) { |
92 const CryptoHandshakeMessage* in) { | |
93 CryptoHandshakeMessage out; | 94 CryptoHandshakeMessage out; |
94 QuicErrorCode error; | 95 QuicErrorCode error; |
95 string error_details; | 96 string error_details; |
96 QuicCryptoClientConfig::CachedState* cached = | 97 QuicCryptoClientConfig::CachedState* cached = |
97 crypto_config_->LookupOrCreate(server_id_); | 98 crypto_config_->LookupOrCreate(server_id_); |
98 | 99 |
99 if (in != NULL) { | 100 if (in != NULL) { |
100 DVLOG(1) << "Client: Received " << in->DebugString(); | 101 DVLOG(1) << "Client: Received " << in->DebugString(); |
101 } | 102 } |
102 | 103 |
(...skipping 18 matching lines...) Expand all Loading... |
121 if (num_client_hellos_ > kMaxClientHellos) { | 122 if (num_client_hellos_ > kMaxClientHellos) { |
122 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); | 123 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); |
123 return; | 124 return; |
124 } | 125 } |
125 num_client_hellos_++; | 126 num_client_hellos_++; |
126 | 127 |
127 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { | 128 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { |
128 crypto_config_->FillInchoateClientHello( | 129 crypto_config_->FillInchoateClientHello( |
129 server_id_, | 130 server_id_, |
130 session()->connection()->supported_versions().front(), | 131 session()->connection()->supported_versions().front(), |
131 cached, &crypto_negotiated_params_, &out); | 132 cached, |
| 133 &crypto_negotiated_params_, |
| 134 &out); |
132 // Pad the inchoate client hello to fill up a packet. | 135 // Pad the inchoate client hello to fill up a packet. |
133 const size_t kFramingOverhead = 50; // A rough estimate. | 136 const size_t kFramingOverhead = 50; // A rough estimate. |
134 const size_t max_packet_size = | 137 const size_t max_packet_size = |
135 session()->connection()->options()->max_packet_length; | 138 session()->connection()->options()->max_packet_length; |
136 if (max_packet_size <= kFramingOverhead) { | 139 if (max_packet_size <= kFramingOverhead) { |
137 DLOG(DFATAL) << "max_packet_length (" << max_packet_size | 140 DLOG(DFATAL) << "max_packet_length (" << max_packet_size |
138 << ") has no room for framing overhead."; | 141 << ") has no room for framing overhead."; |
139 CloseConnection(QUIC_INTERNAL_ERROR); | 142 CloseConnection(QUIC_INTERNAL_ERROR); |
140 return; | 143 return; |
141 } | 144 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 // Be prepared to decrypt with the new server write key. | 182 // Be prepared to decrypt with the new server write key. |
180 session()->connection()->SetAlternativeDecrypter( | 183 session()->connection()->SetAlternativeDecrypter( |
181 crypto_negotiated_params_.initial_crypters.decrypter.release(), | 184 crypto_negotiated_params_.initial_crypters.decrypter.release(), |
182 ENCRYPTION_INITIAL, | 185 ENCRYPTION_INITIAL, |
183 true /* latch once used */); | 186 true /* latch once used */); |
184 // Send subsequent packets under encryption on the assumption that the | 187 // Send subsequent packets under encryption on the assumption that the |
185 // server will accept the handshake. | 188 // server will accept the handshake. |
186 session()->connection()->SetEncrypter( | 189 session()->connection()->SetEncrypter( |
187 ENCRYPTION_INITIAL, | 190 ENCRYPTION_INITIAL, |
188 crypto_negotiated_params_.initial_crypters.encrypter.release()); | 191 crypto_negotiated_params_.initial_crypters.encrypter.release()); |
189 session()->connection()->SetDefaultEncryptionLevel( | 192 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); |
190 ENCRYPTION_INITIAL); | |
191 if (!encryption_established_) { | 193 if (!encryption_established_) { |
192 encryption_established_ = true; | 194 encryption_established_ = true; |
193 session()->OnCryptoHandshakeEvent( | 195 session()->OnCryptoHandshakeEvent( |
194 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); | 196 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); |
195 } else { | 197 } else { |
196 session()->OnCryptoHandshakeEvent( | 198 session()->OnCryptoHandshakeEvent( |
197 QuicSession::ENCRYPTION_REESTABLISHED); | 199 QuicSession::ENCRYPTION_REESTABLISHED); |
198 } | 200 } |
199 return; | 201 return; |
200 } | 202 } |
201 case STATE_RECV_REJ: | 203 case STATE_RECV_REJ: |
202 // We sent a dummy CHLO because we didn't have enough information to | 204 // We sent a dummy CHLO because we didn't have enough information to |
203 // perform a handshake, or we sent a full hello that the server | 205 // perform a handshake, or we sent a full hello that the server |
204 // rejected. Here we hope to have a REJ that contains the information | 206 // rejected. Here we hope to have a REJ that contains the information |
205 // that we need. | 207 // that we need. |
206 if (in->tag() != kREJ) { | 208 if (in->tag() != kREJ) { |
207 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, | 209 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, |
208 "Expected REJ"); | 210 "Expected REJ"); |
209 return; | 211 return; |
210 } | 212 } |
211 error = crypto_config_->ProcessRejection( | 213 error = crypto_config_->ProcessRejection( |
212 *in, session()->connection()->clock()->WallNow(), cached, | 214 *in, |
213 &crypto_negotiated_params_, &error_details); | 215 session()->connection()->clock()->WallNow(), |
| 216 cached, |
| 217 &crypto_negotiated_params_, |
| 218 &error_details); |
214 if (error != QUIC_NO_ERROR) { | 219 if (error != QUIC_NO_ERROR) { |
215 CloseConnectionWithDetails(error, error_details); | 220 CloseConnectionWithDetails(error, error_details); |
216 return; | 221 return; |
217 } | 222 } |
218 if (!cached->proof_valid()) { | 223 if (!cached->proof_valid()) { |
219 if (!server_id_.is_https()) { | 224 if (!server_id_.is_https()) { |
220 // We don't check the certificates for insecure QUIC connections. | 225 // We don't check the certificates for insecure QUIC connections. |
221 SetCachedProofValid(cached); | 226 SetCachedProofValid(cached); |
222 } else if (!cached->signature().empty()) { | 227 } else if (!cached->signature().empty()) { |
223 next_state_ = STATE_VERIFY_PROOF; | 228 next_state_ = STATE_VERIFY_PROOF; |
224 break; | 229 break; |
225 } | 230 } |
226 } | 231 } |
227 next_state_ = STATE_SEND_CHLO; | 232 next_state_ = STATE_SEND_CHLO; |
228 break; | 233 break; |
229 case STATE_VERIFY_PROOF: { | 234 case STATE_VERIFY_PROOF: { |
230 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 235 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
231 DCHECK(verifier); | 236 DCHECK(verifier); |
232 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | 237 next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
233 generation_counter_ = cached->generation_counter(); | 238 generation_counter_ = cached->generation_counter(); |
234 | 239 |
235 ProofVerifierCallbackImpl* proof_verify_callback = | 240 ProofVerifierCallbackImpl* proof_verify_callback = |
236 new ProofVerifierCallbackImpl(this); | 241 new ProofVerifierCallbackImpl(this); |
237 | 242 |
238 verify_ok_ = false; | 243 verify_ok_ = false; |
239 | 244 |
240 ProofVerifier::Status status = verifier->VerifyProof( | 245 ProofVerifier::Status status = |
241 server_id_.host(), | 246 verifier->VerifyProof(server_id_.host(), |
242 cached->server_config(), | 247 cached->server_config(), |
243 cached->certs(), | 248 cached->certs(), |
244 cached->signature(), | 249 cached->signature(), |
245 verify_context_.get(), | 250 verify_context_.get(), |
246 &verify_error_details_, | 251 &verify_error_details_, |
247 &verify_details_, | 252 &verify_details_, |
248 proof_verify_callback); | 253 proof_verify_callback); |
249 | 254 |
250 switch (status) { | 255 switch (status) { |
251 case ProofVerifier::PENDING: | 256 case ProofVerifier::PENDING: |
252 proof_verify_callback_ = proof_verify_callback; | 257 proof_verify_callback_ = proof_verify_callback; |
253 DVLOG(1) << "Doing VerifyProof"; | 258 DVLOG(1) << "Doing VerifyProof"; |
254 return; | 259 return; |
255 case ProofVerifier::FAILURE: | 260 case ProofVerifier::FAILURE: |
256 delete proof_verify_callback; | 261 delete proof_verify_callback; |
257 break; | 262 break; |
258 case ProofVerifier::SUCCESS: | 263 case ProofVerifier::SUCCESS: |
259 delete proof_verify_callback; | 264 delete proof_verify_callback; |
260 verify_ok_ = true; | 265 verify_ok_ = true; |
261 break; | 266 break; |
262 } | 267 } |
263 break; | 268 break; |
264 } | 269 } |
265 case STATE_VERIFY_PROOF_COMPLETE: | 270 case STATE_VERIFY_PROOF_COMPLETE: |
266 if (!verify_ok_) { | 271 if (!verify_ok_) { |
267 client_session()->OnProofVerifyDetailsAvailable(*verify_details_); | 272 client_session()->OnProofVerifyDetailsAvailable(*verify_details_); |
268 CloseConnectionWithDetails( | 273 CloseConnectionWithDetails(QUIC_PROOF_INVALID, |
269 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); | 274 "Proof invalid: " + verify_error_details_); |
270 return; | 275 return; |
271 } | 276 } |
272 // Check if generation_counter has changed between STATE_VERIFY_PROOF | 277 // Check if generation_counter has changed between STATE_VERIFY_PROOF |
273 // and STATE_VERIFY_PROOF_COMPLETE state changes. | 278 // and STATE_VERIFY_PROOF_COMPLETE state changes. |
274 if (generation_counter_ != cached->generation_counter()) { | 279 if (generation_counter_ != cached->generation_counter()) { |
275 next_state_ = STATE_VERIFY_PROOF; | 280 next_state_ = STATE_VERIFY_PROOF; |
276 } else { | 281 } else { |
277 SetCachedProofValid(cached); | 282 SetCachedProofValid(cached); |
278 cached->SetProofVerifyDetails(verify_details_.release()); | 283 cached->SetProofVerifyDetails(verify_details_.release()); |
279 next_state_ = STATE_SEND_CHLO; | 284 next_state_ = STATE_SEND_CHLO; |
(...skipping 23 matching lines...) Expand all Loading... |
303 // alternative_decrypter will be NULL if the original alternative | 308 // alternative_decrypter will be NULL if the original alternative |
304 // decrypter latched and became the primary decrypter. That happens | 309 // decrypter latched and became the primary decrypter. That happens |
305 // if we received a message encrypted with the INITIAL key. | 310 // if we received a message encrypted with the INITIAL key. |
306 if (session()->connection()->alternative_decrypter() != NULL) { | 311 if (session()->connection()->alternative_decrypter() != NULL) { |
307 // The server hello was sent without encryption. | 312 // The server hello was sent without encryption. |
308 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, | 313 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, |
309 "unencrypted SHLO message"); | 314 "unencrypted SHLO message"); |
310 return; | 315 return; |
311 } | 316 } |
312 error = crypto_config_->ProcessServerHello( | 317 error = crypto_config_->ProcessServerHello( |
313 *in, session()->connection()->connection_id(), | 318 *in, |
| 319 session()->connection()->connection_id(), |
314 session()->connection()->server_supported_versions(), | 320 session()->connection()->server_supported_versions(), |
315 cached, &crypto_negotiated_params_, &error_details); | 321 cached, |
| 322 &crypto_negotiated_params_, |
| 323 &error_details); |
316 | 324 |
317 if (error != QUIC_NO_ERROR) { | 325 if (error != QUIC_NO_ERROR) { |
318 CloseConnectionWithDetails( | 326 CloseConnectionWithDetails(error, |
319 error, "Server hello invalid: " + error_details); | 327 "Server hello invalid: " + error_details); |
320 return; | 328 return; |
321 } | 329 } |
322 error = | 330 error = |
323 session()->config()->ProcessPeerHello(*in, SERVER, &error_details); | 331 session()->config()->ProcessPeerHello(*in, SERVER, &error_details); |
324 if (error != QUIC_NO_ERROR) { | 332 if (error != QUIC_NO_ERROR) { |
325 CloseConnectionWithDetails( | 333 CloseConnectionWithDetails(error, |
326 error, "Server hello invalid: " + error_details); | 334 "Server hello invalid: " + error_details); |
327 return; | 335 return; |
328 } | 336 } |
329 session()->OnConfigNegotiated(); | 337 session()->OnConfigNegotiated(); |
330 | 338 |
331 CrypterPair* crypters = | 339 CrypterPair* crypters = |
332 &crypto_negotiated_params_.forward_secure_crypters; | 340 &crypto_negotiated_params_.forward_secure_crypters; |
333 // TODO(agl): we don't currently latch this decrypter because the idea | 341 // TODO(agl): we don't currently latch this decrypter because the idea |
334 // has been floated that the server shouldn't send packets encrypted | 342 // has been floated that the server shouldn't send packets encrypted |
335 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE | 343 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE |
336 // packet from the client. | 344 // packet from the client. |
337 session()->connection()->SetAlternativeDecrypter( | 345 session()->connection()->SetAlternativeDecrypter( |
338 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE, | 346 crypters->decrypter.release(), |
| 347 ENCRYPTION_FORWARD_SECURE, |
339 false /* don't latch */); | 348 false /* don't latch */); |
340 session()->connection()->SetEncrypter( | 349 session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE, |
341 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release()); | 350 crypters->encrypter.release()); |
342 session()->connection()->SetDefaultEncryptionLevel( | 351 session()->connection()->SetDefaultEncryptionLevel( |
343 ENCRYPTION_FORWARD_SECURE); | 352 ENCRYPTION_FORWARD_SECURE); |
344 | 353 |
345 handshake_confirmed_ = true; | 354 handshake_confirmed_ = true; |
346 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); | 355 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); |
347 return; | 356 return; |
348 } | 357 } |
349 case STATE_IDLE: | 358 case STATE_IDLE: |
350 // This means that the peer sent us a message that we weren't expecting. | 359 // This means that the peer sent us a message that we weren't expecting. |
351 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 360 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
352 return; | 361 return; |
353 } | 362 } |
354 } | 363 } |
355 } | 364 } |
356 | 365 |
357 void QuicCryptoClientStream::SetCachedProofValid( | 366 void QuicCryptoClientStream::SetCachedProofValid( |
358 QuicCryptoClientConfig::CachedState* cached) { | 367 QuicCryptoClientConfig::CachedState* cached) { |
359 cached->SetProofValid(); | 368 cached->SetProofValid(); |
360 client_session()->OnProofValid(*cached); | 369 client_session()->OnProofValid(*cached); |
361 } | 370 } |
362 | 371 |
363 QuicClientSessionBase* QuicCryptoClientStream::client_session() { | 372 QuicClientSessionBase* QuicCryptoClientStream::client_session() { |
364 return reinterpret_cast<QuicClientSessionBase*>(session()); | 373 return reinterpret_cast<QuicClientSessionBase*>(session()); |
365 } | 374 } |
366 | 375 |
367 } // namespace net | 376 } // namespace net |
OLD | NEW |