Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(762)

Side by Side Diff: net/quic/quic_crypto_client_stream.cc

Issue 346323002: net: Implement ChannelIDSourceChromium, which is based on Chromium's (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/channel_id.h"
8 #include "net/quic/crypto/crypto_protocol.h" 7 #include "net/quic/crypto/crypto_protocol.h"
9 #include "net/quic/crypto/crypto_utils.h" 8 #include "net/quic/crypto/crypto_utils.h"
10 #include "net/quic/crypto/null_encrypter.h" 9 #include "net/quic/crypto/null_encrypter.h"
11 #include "net/quic/crypto/proof_verifier.h"
12 #include "net/quic/quic_client_session_base.h" 10 #include "net/quic/quic_client_session_base.h"
13 #include "net/quic/quic_protocol.h" 11 #include "net/quic/quic_protocol.h"
14 #include "net/quic/quic_session.h" 12 #include "net/quic/quic_session.h"
15 13
16 namespace net { 14 namespace net {
17 15
16 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
17 ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream)
18 : stream_(stream) {}
19
20 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
21 ~ChannelIDSourceCallbackImpl() {}
22
23 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Run(
24 scoped_ptr<ChannelIDKey>* channel_id_key) {
25 if (stream_ == NULL) {
26 return;
27 }
28
29 stream_->channel_id_key_.reset(channel_id_key->release());
30 stream_->channel_id_source_callback_ = NULL;
31 stream_->DoHandshakeLoop(NULL);
32
33 // The ChannelIDSource owns this object and will delete it when this method
34 // returns.
35 }
36
37 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Cancel() {
38 stream_ = NULL;
39 }
40
18 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( 41 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
19 QuicCryptoClientStream* stream) 42 QuicCryptoClientStream* stream)
20 : stream_(stream) {} 43 : stream_(stream) {}
21 44
22 QuicCryptoClientStream::ProofVerifierCallbackImpl:: 45 QuicCryptoClientStream::ProofVerifierCallbackImpl::
23 ~ProofVerifierCallbackImpl() {} 46 ~ProofVerifierCallbackImpl() {}
24 47
25 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( 48 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
26 bool ok, 49 bool ok,
27 const string& error_details, 50 const string& error_details,
(...skipping 20 matching lines...) Expand all
48 const QuicServerId& server_id, 71 const QuicServerId& server_id,
49 QuicClientSessionBase* session, 72 QuicClientSessionBase* session,
50 ProofVerifyContext* verify_context, 73 ProofVerifyContext* verify_context,
51 QuicCryptoClientConfig* crypto_config) 74 QuicCryptoClientConfig* crypto_config)
52 : QuicCryptoStream(session), 75 : QuicCryptoStream(session),
53 next_state_(STATE_IDLE), 76 next_state_(STATE_IDLE),
54 num_client_hellos_(0), 77 num_client_hellos_(0),
55 crypto_config_(crypto_config), 78 crypto_config_(crypto_config),
56 server_id_(server_id), 79 server_id_(server_id),
57 generation_counter_(0), 80 generation_counter_(0),
58 proof_verify_callback_(NULL), 81 channel_id_source_callback_(NULL),
59 verify_context_(verify_context) { 82 verify_context_(verify_context),
83 proof_verify_callback_(NULL) {
60 } 84 }
61 85
62 QuicCryptoClientStream::~QuicCryptoClientStream() { 86 QuicCryptoClientStream::~QuicCryptoClientStream() {
87 if (channel_id_source_callback_) {
88 channel_id_source_callback_->Cancel();
89 }
63 if (proof_verify_callback_) { 90 if (proof_verify_callback_) {
64 proof_verify_callback_->Cancel(); 91 proof_verify_callback_->Cancel();
65 } 92 }
66 } 93 }
67 94
68 void QuicCryptoClientStream::OnHandshakeMessage( 95 void QuicCryptoClientStream::OnHandshakeMessage(
69 const CryptoHandshakeMessage& message) { 96 const CryptoHandshakeMessage& message) {
70 QuicCryptoStream::OnHandshakeMessage(message); 97 QuicCryptoStream::OnHandshakeMessage(message);
71 98
72 DoHandshakeLoop(&message); 99 DoHandshakeLoop(&message);
(...skipping 26 matching lines...) Expand all
99 126
100 if (in != NULL) { 127 if (in != NULL) {
101 DVLOG(1) << "Client: Received " << in->DebugString(); 128 DVLOG(1) << "Client: Received " << in->DebugString();
102 } 129 }
103 130
104 for (;;) { 131 for (;;) {
105 const State state = next_state_; 132 const State state = next_state_;
106 next_state_ = STATE_IDLE; 133 next_state_ = STATE_IDLE;
107 switch (state) { 134 switch (state) {
108 case STATE_INITIALIZE: { 135 case STATE_INITIALIZE: {
109 if (!cached->IsEmpty() && !cached->signature().empty() && 136 if (!cached->IsEmpty() && !cached->proof_valid() &&
110 server_id_.is_https()) { 137 !cached->signature().empty() && server_id_.is_https()) {
111 DCHECK(crypto_config_->proof_verifier()); 138 DCHECK(crypto_config_->proof_verifier());
112 // If the cached state needs to be verified, do it now. 139 // If the cached state needs to be verified, do it now.
113 next_state_ = STATE_VERIFY_PROOF; 140 next_state_ = STATE_VERIFY_PROOF;
114 } else { 141 } else {
115 next_state_ = STATE_SEND_CHLO; 142 next_state_ = STATE_GET_CHANNEL_ID;
116 } 143 }
117 break; 144 break;
118 } 145 }
119 case STATE_SEND_CHLO: { 146 case STATE_SEND_CHLO: {
120 // Send the client hello in plaintext. 147 // Send the client hello in plaintext.
121 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); 148 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
122 if (num_client_hellos_ > kMaxClientHellos) { 149 if (num_client_hellos_ > kMaxClientHellos) {
123 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); 150 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
124 return; 151 return;
125 } 152 }
(...skipping 19 matching lines...) Expand all
145 CloseConnection(QUIC_INTERNAL_ERROR); 172 CloseConnection(QUIC_INTERNAL_ERROR);
146 return; 173 return;
147 } 174 }
148 out.set_minimum_size(max_packet_size - kFramingOverhead); 175 out.set_minimum_size(max_packet_size - kFramingOverhead);
149 next_state_ = STATE_RECV_REJ; 176 next_state_ = STATE_RECV_REJ;
150 DVLOG(1) << "Client: Sending " << out.DebugString(); 177 DVLOG(1) << "Client: Sending " << out.DebugString();
151 SendHandshakeMessage(out); 178 SendHandshakeMessage(out);
152 return; 179 return;
153 } 180 }
154 session()->config()->ToHandshakeMessage(&out); 181 session()->config()->ToHandshakeMessage(&out);
155
156 scoped_ptr<ChannelIDKey> channel_id_key;
157 bool do_channel_id = false;
158 if (crypto_config_->channel_id_source()) {
159 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
160 DCHECK(scfg);
161 const QuicTag* their_proof_demands;
162 size_t num_their_proof_demands;
163 if (scfg->GetTaglist(kPDMD, &their_proof_demands,
164 &num_their_proof_demands) == QUIC_NO_ERROR) {
165 for (size_t i = 0; i < num_their_proof_demands; i++) {
166 if (their_proof_demands[i] == kCHID) {
167 do_channel_id = true;
168 break;
169 }
170 }
171 }
172 }
173 if (do_channel_id) {
174 QuicAsyncStatus status =
175 crypto_config_->channel_id_source()->GetChannelIDKey(
176 server_id_.host(), &channel_id_key, NULL);
177 if (status != QUIC_SUCCESS) {
178 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
179 "Channel ID lookup failed");
180 return;
181 }
182 }
183
184 error = crypto_config_->FillClientHello( 182 error = crypto_config_->FillClientHello(
185 server_id_, 183 server_id_,
186 session()->connection()->connection_id(), 184 session()->connection()->connection_id(),
187 session()->connection()->supported_versions().front(), 185 session()->connection()->supported_versions().front(),
188 cached, 186 cached,
189 session()->connection()->clock()->WallNow(), 187 session()->connection()->clock()->WallNow(),
190 session()->connection()->random_generator(), 188 session()->connection()->random_generator(),
191 channel_id_key.get(), 189 channel_id_key_.get(),
192 &crypto_negotiated_params_, 190 &crypto_negotiated_params_,
193 &out, 191 &out,
194 &error_details); 192 &error_details);
195 if (error != QUIC_NO_ERROR) { 193 if (error != QUIC_NO_ERROR) {
196 // Flush the cached config so that, if it's bad, the server has a 194 // Flush the cached config so that, if it's bad, the server has a
197 // chance to send us another in the future. 195 // chance to send us another in the future.
198 cached->InvalidateServerConfig(); 196 cached->InvalidateServerConfig();
199 CloseConnectionWithDetails(error, error_details); 197 CloseConnectionWithDetails(error, error_details);
200 return; 198 return;
201 } 199 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 } 245 }
248 if (!cached->proof_valid()) { 246 if (!cached->proof_valid()) {
249 if (!server_id_.is_https()) { 247 if (!server_id_.is_https()) {
250 // We don't check the certificates for insecure QUIC connections. 248 // We don't check the certificates for insecure QUIC connections.
251 SetCachedProofValid(cached); 249 SetCachedProofValid(cached);
252 } else if (!cached->signature().empty()) { 250 } else if (!cached->signature().empty()) {
253 next_state_ = STATE_VERIFY_PROOF; 251 next_state_ = STATE_VERIFY_PROOF;
254 break; 252 break;
255 } 253 }
256 } 254 }
257 next_state_ = STATE_SEND_CHLO; 255 next_state_ = STATE_GET_CHANNEL_ID;
258 break; 256 break;
259 case STATE_VERIFY_PROOF: { 257 case STATE_VERIFY_PROOF: {
260 ProofVerifier* verifier = crypto_config_->proof_verifier(); 258 ProofVerifier* verifier = crypto_config_->proof_verifier();
261 DCHECK(verifier); 259 DCHECK(verifier);
262 next_state_ = STATE_VERIFY_PROOF_COMPLETE; 260 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
263 generation_counter_ = cached->generation_counter(); 261 generation_counter_ = cached->generation_counter();
264 262
265 ProofVerifierCallbackImpl* proof_verify_callback = 263 ProofVerifierCallbackImpl* proof_verify_callback =
266 new ProofVerifierCallbackImpl(this); 264 new ProofVerifierCallbackImpl(this);
267 265
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); 297 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
300 return; 298 return;
301 } 299 }
302 // Check if generation_counter has changed between STATE_VERIFY_PROOF 300 // Check if generation_counter has changed between STATE_VERIFY_PROOF
303 // and STATE_VERIFY_PROOF_COMPLETE state changes. 301 // and STATE_VERIFY_PROOF_COMPLETE state changes.
304 if (generation_counter_ != cached->generation_counter()) { 302 if (generation_counter_ != cached->generation_counter()) {
305 next_state_ = STATE_VERIFY_PROOF; 303 next_state_ = STATE_VERIFY_PROOF;
306 } else { 304 } else {
307 SetCachedProofValid(cached); 305 SetCachedProofValid(cached);
308 cached->SetProofVerifyDetails(verify_details_.release()); 306 cached->SetProofVerifyDetails(verify_details_.release());
307 next_state_ = STATE_GET_CHANNEL_ID;
308 }
309 break;
310 case STATE_GET_CHANNEL_ID: {
311 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
312 channel_id_key_.reset();
313 if (!RequiresChannelID(cached)) {
309 next_state_ = STATE_SEND_CHLO; 314 next_state_ = STATE_SEND_CHLO;
315 break;
310 } 316 }
317
318 ChannelIDSourceCallbackImpl* channel_id_source_callback =
319 new ChannelIDSourceCallbackImpl(this);
320 QuicAsyncStatus status =
321 crypto_config_->channel_id_source()->GetChannelIDKey(
322 server_id_.host(), &channel_id_key_,
323 channel_id_source_callback);
324
325 switch (status) {
326 case QUIC_PENDING:
327 channel_id_source_callback_ = channel_id_source_callback;
328 DVLOG(1) << "Looking up channel ID";
329 return;
330 case QUIC_FAILURE:
331 delete channel_id_source_callback;
332 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
333 "Channel ID lookup failed");
334 return;
335 case QUIC_SUCCESS:
336 delete channel_id_source_callback;
337 break;
338 }
339 break;
340 }
341 case STATE_GET_CHANNEL_ID_COMPLETE:
342 if (!channel_id_key_) {
343 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
344 "Channel ID lookup failed");
345 return;
346 }
347 next_state_ = STATE_SEND_CHLO;
311 break; 348 break;
312 case STATE_RECV_SHLO: { 349 case STATE_RECV_SHLO: {
313 // We sent a CHLO that we expected to be accepted and now we're hoping 350 // We sent a CHLO that we expected to be accepted and now we're hoping
314 // for a SHLO from the server to confirm that. 351 // for a SHLO from the server to confirm that.
315 if (in->tag() == kREJ) { 352 if (in->tag() == kREJ) {
316 // alternative_decrypter will be NULL if the original alternative 353 // alternative_decrypter will be NULL if the original alternative
317 // decrypter latched and became the primary decrypter. That happens 354 // decrypter latched and became the primary decrypter. That happens
318 // if we received a message encrypted with the INITIAL key. 355 // if we received a message encrypted with the INITIAL key.
319 if (session()->connection()->alternative_decrypter() == NULL) { 356 if (session()->connection()->alternative_decrypter() == NULL) {
320 // The rejection was sent encrypted! 357 // The rejection was sent encrypted!
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 } 420 }
384 } 421 }
385 } 422 }
386 423
387 void QuicCryptoClientStream::SetCachedProofValid( 424 void QuicCryptoClientStream::SetCachedProofValid(
388 QuicCryptoClientConfig::CachedState* cached) { 425 QuicCryptoClientConfig::CachedState* cached) {
389 cached->SetProofValid(); 426 cached->SetProofValid();
390 client_session()->OnProofValid(*cached); 427 client_session()->OnProofValid(*cached);
391 } 428 }
392 429
430 bool QuicCryptoClientStream::RequiresChannelID(
431 QuicCryptoClientConfig::CachedState* cached) {
432 if (server_id_.is_https() &&
433 server_id_.privacy_mode() == PRIVACY_MODE_DISABLED &&
434 crypto_config_->channel_id_source()) {
435 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
436 const QuicTag* their_proof_demands;
437 size_t num_their_proof_demands;
438 if (scfg && // scfg may be null when we send an inchoate CHLO.
439 scfg->GetTaglist(kPDMD, &their_proof_demands,
440 &num_their_proof_demands) == QUIC_NO_ERROR) {
441 for (size_t i = 0; i < num_their_proof_demands; i++) {
442 if (their_proof_demands[i] == kCHID) {
443 return true;
444 }
445 }
Ryan Hamilton 2014/06/30 17:47:04 Consider using early-returns. if (!server_.is_htt
wtc 2014/06/30 19:35:14 Done.
446 }
447 }
448 return false;
449 }
450
393 QuicClientSessionBase* QuicCryptoClientStream::client_session() { 451 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
394 return reinterpret_cast<QuicClientSessionBase*>(session()); 452 return reinterpret_cast<QuicClientSessionBase*>(session());
395 } 453 }
396 454
397 } // namespace net 455 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698