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" |
(...skipping 25 matching lines...) Expand all Loading... |
36 | 36 |
37 // The ProofVerifier owns this object and will delete it when this method | 37 // The ProofVerifier owns this object and will delete it when this method |
38 // returns. | 38 // returns. |
39 } | 39 } |
40 | 40 |
41 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { | 41 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { |
42 stream_ = NULL; | 42 stream_ = NULL; |
43 } | 43 } |
44 | 44 |
45 QuicCryptoClientStream::QuicCryptoClientStream( | 45 QuicCryptoClientStream::QuicCryptoClientStream( |
46 const QuicSessionKey& server_key, | 46 const QuicServerId& server_id, |
47 QuicClientSessionBase* session, | 47 QuicClientSessionBase* session, |
48 ProofVerifyContext* verify_context, | 48 ProofVerifyContext* verify_context, |
49 QuicCryptoClientConfig* crypto_config) | 49 QuicCryptoClientConfig* crypto_config) |
50 : QuicCryptoStream(session), | 50 : QuicCryptoStream(session), |
51 next_state_(STATE_IDLE), | 51 next_state_(STATE_IDLE), |
52 num_client_hellos_(0), | 52 num_client_hellos_(0), |
53 crypto_config_(crypto_config), | 53 crypto_config_(crypto_config), |
54 server_key_(server_key), | 54 server_id_(server_id), |
55 generation_counter_(0), | 55 generation_counter_(0), |
56 proof_verify_callback_(NULL), | 56 proof_verify_callback_(NULL), |
57 verify_context_(verify_context) { | 57 verify_context_(verify_context) { |
58 } | 58 } |
59 | 59 |
60 QuicCryptoClientStream::~QuicCryptoClientStream() { | 60 QuicCryptoClientStream::~QuicCryptoClientStream() { |
61 if (proof_verify_callback_) { | 61 if (proof_verify_callback_) { |
62 proof_verify_callback_->Cancel(); | 62 proof_verify_callback_->Cancel(); |
63 } | 63 } |
64 } | 64 } |
(...skipping 21 matching lines...) Expand all Loading... |
86 // * One failure due the server's certificate chain being unavailible and the | 86 // * One failure due the server's certificate chain being unavailible and the |
87 // server being unwilling to send it without a valid source-address token. | 87 // server being unwilling to send it without a valid source-address token. |
88 static const int kMaxClientHellos = 3; | 88 static const int kMaxClientHellos = 3; |
89 | 89 |
90 void QuicCryptoClientStream::DoHandshakeLoop( | 90 void QuicCryptoClientStream::DoHandshakeLoop( |
91 const CryptoHandshakeMessage* in) { | 91 const CryptoHandshakeMessage* in) { |
92 CryptoHandshakeMessage out; | 92 CryptoHandshakeMessage out; |
93 QuicErrorCode error; | 93 QuicErrorCode error; |
94 string error_details; | 94 string error_details; |
95 QuicCryptoClientConfig::CachedState* cached = | 95 QuicCryptoClientConfig::CachedState* cached = |
96 crypto_config_->LookupOrCreate(server_key_); | 96 crypto_config_->LookupOrCreate(server_id_); |
97 | 97 |
98 if (in != NULL) { | 98 if (in != NULL) { |
99 DVLOG(1) << "Client: Received " << in->DebugString(); | 99 DVLOG(1) << "Client: Received " << in->DebugString(); |
100 } | 100 } |
101 | 101 |
102 for (;;) { | 102 for (;;) { |
103 const State state = next_state_; | 103 const State state = next_state_; |
104 next_state_ = STATE_IDLE; | 104 next_state_ = STATE_IDLE; |
105 switch (state) { | 105 switch (state) { |
106 case STATE_INITIALIZE: { | 106 case STATE_INITIALIZE: { |
107 if (!cached->IsEmpty() && !cached->signature().empty() && | 107 if (!cached->IsEmpty() && !cached->signature().empty() && |
108 server_key_.is_https()) { | 108 server_id_.is_https()) { |
109 DCHECK(crypto_config_->proof_verifier()); | 109 DCHECK(crypto_config_->proof_verifier()); |
110 // If the cached state needs to be verified, do it now. | 110 // If the cached state needs to be verified, do it now. |
111 next_state_ = STATE_VERIFY_PROOF; | 111 next_state_ = STATE_VERIFY_PROOF; |
112 } else { | 112 } else { |
113 next_state_ = STATE_SEND_CHLO; | 113 next_state_ = STATE_SEND_CHLO; |
114 } | 114 } |
115 break; | 115 break; |
116 } | 116 } |
117 case STATE_SEND_CHLO: { | 117 case STATE_SEND_CHLO: { |
118 // Send the client hello in plaintext. | 118 // Send the client hello in plaintext. |
119 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); | 119 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); |
120 if (num_client_hellos_ > kMaxClientHellos) { | 120 if (num_client_hellos_ > kMaxClientHellos) { |
121 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); | 121 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); |
122 return; | 122 return; |
123 } | 123 } |
124 num_client_hellos_++; | 124 num_client_hellos_++; |
125 | 125 |
126 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { | 126 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { |
127 crypto_config_->FillInchoateClientHello( | 127 crypto_config_->FillInchoateClientHello( |
128 server_key_, | 128 server_id_, |
129 session()->connection()->supported_versions().front(), | 129 session()->connection()->supported_versions().front(), |
130 cached, &crypto_negotiated_params_, &out); | 130 cached, |
| 131 &crypto_negotiated_params_, |
| 132 &out); |
131 // Pad the inchoate client hello to fill up a packet. | 133 // Pad the inchoate client hello to fill up a packet. |
132 const size_t kFramingOverhead = 50; // A rough estimate. | 134 const size_t kFramingOverhead = 50; // A rough estimate. |
133 const size_t max_packet_size = | 135 const size_t max_packet_size = |
134 session()->connection()->options()->max_packet_length; | 136 session()->connection()->options()->max_packet_length; |
135 if (max_packet_size <= kFramingOverhead) { | 137 if (max_packet_size <= kFramingOverhead) { |
136 DLOG(DFATAL) << "max_packet_length (" << max_packet_size | 138 DLOG(DFATAL) << "max_packet_length (" << max_packet_size |
137 << ") has no room for framing overhead."; | 139 << ") has no room for framing overhead."; |
138 CloseConnection(QUIC_INTERNAL_ERROR); | 140 CloseConnection(QUIC_INTERNAL_ERROR); |
139 return; | 141 return; |
140 } | 142 } |
141 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { | 143 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { |
142 DLOG(DFATAL) << "Client hello won't fit in a single packet."; | 144 DLOG(DFATAL) << "Client hello won't fit in a single packet."; |
143 CloseConnection(QUIC_INTERNAL_ERROR); | 145 CloseConnection(QUIC_INTERNAL_ERROR); |
144 return; | 146 return; |
145 } | 147 } |
146 out.set_minimum_size(max_packet_size - kFramingOverhead); | 148 out.set_minimum_size(max_packet_size - kFramingOverhead); |
147 next_state_ = STATE_RECV_REJ; | 149 next_state_ = STATE_RECV_REJ; |
148 DVLOG(1) << "Client: Sending " << out.DebugString(); | 150 DVLOG(1) << "Client: Sending " << out.DebugString(); |
149 SendHandshakeMessage(out); | 151 SendHandshakeMessage(out); |
150 return; | 152 return; |
151 } | 153 } |
152 session()->config()->ToHandshakeMessage(&out); | 154 session()->config()->ToHandshakeMessage(&out); |
153 error = crypto_config_->FillClientHello( | 155 error = crypto_config_->FillClientHello( |
154 server_key_, | 156 server_id_, |
155 session()->connection()->connection_id(), | 157 session()->connection()->connection_id(), |
156 session()->connection()->supported_versions().front(), | 158 session()->connection()->supported_versions().front(), |
157 session()->connection()->max_flow_control_receive_window_bytes(), | 159 session()->connection()->max_flow_control_receive_window_bytes(), |
158 cached, | 160 cached, |
159 session()->connection()->clock()->WallNow(), | 161 session()->connection()->clock()->WallNow(), |
160 session()->connection()->random_generator(), | 162 session()->connection()->random_generator(), |
161 &crypto_negotiated_params_, | 163 &crypto_negotiated_params_, |
162 &out, | 164 &out, |
163 &error_details); | 165 &error_details); |
164 if (error != QUIC_NO_ERROR) { | 166 if (error != QUIC_NO_ERROR) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 return; | 209 return; |
208 } | 210 } |
209 error = crypto_config_->ProcessRejection( | 211 error = crypto_config_->ProcessRejection( |
210 *in, session()->connection()->clock()->WallNow(), cached, | 212 *in, session()->connection()->clock()->WallNow(), cached, |
211 &crypto_negotiated_params_, &error_details); | 213 &crypto_negotiated_params_, &error_details); |
212 if (error != QUIC_NO_ERROR) { | 214 if (error != QUIC_NO_ERROR) { |
213 CloseConnectionWithDetails(error, error_details); | 215 CloseConnectionWithDetails(error, error_details); |
214 return; | 216 return; |
215 } | 217 } |
216 if (!cached->proof_valid()) { | 218 if (!cached->proof_valid()) { |
217 if (!server_key_.is_https()) { | 219 if (!server_id_.is_https()) { |
218 // We don't check the certificates for insecure QUIC connections. | 220 // We don't check the certificates for insecure QUIC connections. |
219 SetCachedProofValid(cached); | 221 SetCachedProofValid(cached); |
220 } else if (!cached->signature().empty()) { | 222 } else if (!cached->signature().empty()) { |
221 next_state_ = STATE_VERIFY_PROOF; | 223 next_state_ = STATE_VERIFY_PROOF; |
222 break; | 224 break; |
223 } | 225 } |
224 } | 226 } |
225 next_state_ = STATE_SEND_CHLO; | 227 next_state_ = STATE_SEND_CHLO; |
226 break; | 228 break; |
227 case STATE_VERIFY_PROOF: { | 229 case STATE_VERIFY_PROOF: { |
228 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 230 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
229 DCHECK(verifier); | 231 DCHECK(verifier); |
230 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | 232 next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
231 generation_counter_ = cached->generation_counter(); | 233 generation_counter_ = cached->generation_counter(); |
232 | 234 |
233 ProofVerifierCallbackImpl* proof_verify_callback = | 235 ProofVerifierCallbackImpl* proof_verify_callback = |
234 new ProofVerifierCallbackImpl(this); | 236 new ProofVerifierCallbackImpl(this); |
235 | 237 |
236 verify_ok_ = false; | 238 verify_ok_ = false; |
237 | 239 |
238 ProofVerifier::Status status = verifier->VerifyProof( | 240 ProofVerifier::Status status = verifier->VerifyProof( |
239 server_key_.host(), | 241 server_id_.host(), |
240 cached->server_config(), | 242 cached->server_config(), |
241 cached->certs(), | 243 cached->certs(), |
242 cached->signature(), | 244 cached->signature(), |
243 verify_context_.get(), | 245 verify_context_.get(), |
244 &verify_error_details_, | 246 &verify_error_details_, |
245 &verify_details_, | 247 &verify_details_, |
246 proof_verify_callback); | 248 proof_verify_callback); |
247 | 249 |
248 switch (status) { | 250 switch (status) { |
249 case ProofVerifier::PENDING: | 251 case ProofVerifier::PENDING: |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 QuicCryptoClientConfig::CachedState* cached) { | 354 QuicCryptoClientConfig::CachedState* cached) { |
353 cached->SetProofValid(); | 355 cached->SetProofValid(); |
354 client_session()->OnProofValid(*cached); | 356 client_session()->OnProofValid(*cached); |
355 } | 357 } |
356 | 358 |
357 QuicClientSessionBase* QuicCryptoClientStream::client_session() { | 359 QuicClientSessionBase* QuicCryptoClientStream::client_session() { |
358 return reinterpret_cast<QuicClientSessionBase*>(session()); | 360 return reinterpret_cast<QuicClientSessionBase*>(session()); |
359 } | 361 } |
360 | 362 |
361 } // namespace net | 363 } // namespace net |
OLD | NEW |