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

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: Rebase 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(
18 QuicCryptoClientStream* stream)
Ryan Hamilton 2014/06/25 18:55:15 can you move this to the previous line?
wtc 2014/06/28 16:03:29 Done.
19 : stream_(stream) {}
20
21 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
22 ~ChannelIDSourceCallbackImpl() {}
23
24 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Run(
25 scoped_ptr<ChannelIDKey>* channel_id_key) {
26 if (stream_ == NULL) {
27 return;
28 }
29
30 stream_->channel_id_key_.reset(channel_id_key->release());
31 stream_->channel_id_source_callback_ = NULL;
32 stream_->DoHandshakeLoop(NULL);
33
34 // The ChannelIDSource owns this object and will delete it when this method
35 // returns.
36 }
37
38 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Cancel() {
39 stream_ = NULL;
40 }
41
18 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( 42 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
19 QuicCryptoClientStream* stream) 43 QuicCryptoClientStream* stream)
20 : stream_(stream) {} 44 : stream_(stream) {}
21 45
22 QuicCryptoClientStream::ProofVerifierCallbackImpl:: 46 QuicCryptoClientStream::ProofVerifierCallbackImpl::
23 ~ProofVerifierCallbackImpl() {} 47 ~ProofVerifierCallbackImpl() {}
24 48
25 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( 49 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
26 bool ok, 50 bool ok,
27 const string& error_details, 51 const string& error_details,
(...skipping 20 matching lines...) Expand all
48 const QuicServerId& server_id, 72 const QuicServerId& server_id,
49 QuicClientSessionBase* session, 73 QuicClientSessionBase* session,
50 ProofVerifyContext* verify_context, 74 ProofVerifyContext* verify_context,
51 QuicCryptoClientConfig* crypto_config) 75 QuicCryptoClientConfig* crypto_config)
52 : QuicCryptoStream(session), 76 : QuicCryptoStream(session),
53 next_state_(STATE_IDLE), 77 next_state_(STATE_IDLE),
54 num_client_hellos_(0), 78 num_client_hellos_(0),
55 crypto_config_(crypto_config), 79 crypto_config_(crypto_config),
56 server_id_(server_id), 80 server_id_(server_id),
57 generation_counter_(0), 81 generation_counter_(0),
82 channel_id_source_callback_(NULL),
58 proof_verify_callback_(NULL), 83 proof_verify_callback_(NULL),
59 verify_context_(verify_context) { 84 verify_context_(verify_context) {
60 } 85 }
61 86
62 QuicCryptoClientStream::~QuicCryptoClientStream() { 87 QuicCryptoClientStream::~QuicCryptoClientStream() {
88 if (channel_id_source_callback_) {
89 channel_id_source_callback_->Cancel();
90 }
63 if (proof_verify_callback_) { 91 if (proof_verify_callback_) {
64 proof_verify_callback_->Cancel(); 92 proof_verify_callback_->Cancel();
65 } 93 }
66 } 94 }
67 95
68 void QuicCryptoClientStream::OnHandshakeMessage( 96 void QuicCryptoClientStream::OnHandshakeMessage(
69 const CryptoHandshakeMessage& message) { 97 const CryptoHandshakeMessage& message) {
70 QuicCryptoStream::OnHandshakeMessage(message); 98 QuicCryptoStream::OnHandshakeMessage(message);
71 99
72 DoHandshakeLoop(&message); 100 DoHandshakeLoop(&message);
(...skipping 26 matching lines...) Expand all
99 127
100 if (in != NULL) { 128 if (in != NULL) {
101 DVLOG(1) << "Client: Received " << in->DebugString(); 129 DVLOG(1) << "Client: Received " << in->DebugString();
102 } 130 }
103 131
104 for (;;) { 132 for (;;) {
105 const State state = next_state_; 133 const State state = next_state_;
106 next_state_ = STATE_IDLE; 134 next_state_ = STATE_IDLE;
107 switch (state) { 135 switch (state) {
108 case STATE_INITIALIZE: { 136 case STATE_INITIALIZE: {
109 if (!cached->IsEmpty() && !cached->signature().empty() && 137 if (!cached->IsEmpty() && !cached->proof_valid() &&
110 server_id_.is_https()) { 138 !cached->signature().empty() && server_id_.is_https()) {
111 DCHECK(crypto_config_->proof_verifier()); 139 DCHECK(crypto_config_->proof_verifier());
112 // If the cached state needs to be verified, do it now. 140 // If the cached state needs to be verified, do it now.
113 next_state_ = STATE_VERIFY_PROOF; 141 next_state_ = STATE_VERIFY_PROOF;
114 } else { 142 } else {
115 next_state_ = STATE_SEND_CHLO; 143 next_state_ = STATE_GET_CHANNEL_ID;
116 } 144 }
117 break; 145 break;
118 } 146 }
119 case STATE_SEND_CHLO: { 147 case STATE_SEND_CHLO: {
120 // Send the client hello in plaintext. 148 // Send the client hello in plaintext.
121 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); 149 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
122 if (num_client_hellos_ > kMaxClientHellos) { 150 if (num_client_hellos_ > kMaxClientHellos) {
123 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); 151 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
124 return; 152 return;
125 } 153 }
(...skipping 19 matching lines...) Expand all
145 CloseConnection(QUIC_INTERNAL_ERROR); 173 CloseConnection(QUIC_INTERNAL_ERROR);
146 return; 174 return;
147 } 175 }
148 out.set_minimum_size(max_packet_size - kFramingOverhead); 176 out.set_minimum_size(max_packet_size - kFramingOverhead);
149 next_state_ = STATE_RECV_REJ; 177 next_state_ = STATE_RECV_REJ;
150 DVLOG(1) << "Client: Sending " << out.DebugString(); 178 DVLOG(1) << "Client: Sending " << out.DebugString();
151 SendHandshakeMessage(out); 179 SendHandshakeMessage(out);
152 return; 180 return;
153 } 181 }
154 session()->config()->ToHandshakeMessage(&out); 182 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( 183 error = crypto_config_->FillClientHello(
185 server_id_, 184 server_id_,
186 session()->connection()->connection_id(), 185 session()->connection()->connection_id(),
187 session()->connection()->supported_versions().front(), 186 session()->connection()->supported_versions().front(),
188 cached, 187 cached,
189 session()->connection()->clock()->WallNow(), 188 session()->connection()->clock()->WallNow(),
190 session()->connection()->random_generator(), 189 session()->connection()->random_generator(),
191 channel_id_key.get(), 190 channel_id_key_.get(),
192 &crypto_negotiated_params_, 191 &crypto_negotiated_params_,
193 &out, 192 &out,
194 &error_details); 193 &error_details);
195 if (error != QUIC_NO_ERROR) { 194 if (error != QUIC_NO_ERROR) {
196 // Flush the cached config so that, if it's bad, the server has a 195 // Flush the cached config so that, if it's bad, the server has a
197 // chance to send us another in the future. 196 // chance to send us another in the future.
198 cached->InvalidateServerConfig(); 197 cached->InvalidateServerConfig();
199 CloseConnectionWithDetails(error, error_details); 198 CloseConnectionWithDetails(error, error_details);
200 return; 199 return;
201 } 200 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 } 246 }
248 if (!cached->proof_valid()) { 247 if (!cached->proof_valid()) {
249 if (!server_id_.is_https()) { 248 if (!server_id_.is_https()) {
250 // We don't check the certificates for insecure QUIC connections. 249 // We don't check the certificates for insecure QUIC connections.
251 SetCachedProofValid(cached); 250 SetCachedProofValid(cached);
252 } else if (!cached->signature().empty()) { 251 } else if (!cached->signature().empty()) {
253 next_state_ = STATE_VERIFY_PROOF; 252 next_state_ = STATE_VERIFY_PROOF;
254 break; 253 break;
255 } 254 }
256 } 255 }
257 next_state_ = STATE_SEND_CHLO; 256 next_state_ = STATE_GET_CHANNEL_ID;
258 break; 257 break;
259 case STATE_VERIFY_PROOF: { 258 case STATE_VERIFY_PROOF: {
260 ProofVerifier* verifier = crypto_config_->proof_verifier(); 259 ProofVerifier* verifier = crypto_config_->proof_verifier();
261 DCHECK(verifier); 260 DCHECK(verifier);
262 next_state_ = STATE_VERIFY_PROOF_COMPLETE; 261 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
263 generation_counter_ = cached->generation_counter(); 262 generation_counter_ = cached->generation_counter();
264 263
265 ProofVerifierCallbackImpl* proof_verify_callback = 264 ProofVerifierCallbackImpl* proof_verify_callback =
266 new ProofVerifierCallbackImpl(this); 265 new ProofVerifierCallbackImpl(this);
267 266
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); 298 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
300 return; 299 return;
301 } 300 }
302 // Check if generation_counter has changed between STATE_VERIFY_PROOF 301 // Check if generation_counter has changed between STATE_VERIFY_PROOF
303 // and STATE_VERIFY_PROOF_COMPLETE state changes. 302 // and STATE_VERIFY_PROOF_COMPLETE state changes.
304 if (generation_counter_ != cached->generation_counter()) { 303 if (generation_counter_ != cached->generation_counter()) {
305 next_state_ = STATE_VERIFY_PROOF; 304 next_state_ = STATE_VERIFY_PROOF;
306 } else { 305 } else {
307 SetCachedProofValid(cached); 306 SetCachedProofValid(cached);
308 cached->SetProofVerifyDetails(verify_details_.release()); 307 cached->SetProofVerifyDetails(verify_details_.release());
309 next_state_ = STATE_SEND_CHLO; 308 next_state_ = STATE_GET_CHANNEL_ID;
310 } 309 }
311 break; 310 break;
311 case STATE_GET_CHANNEL_ID: {
312 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
313 channel_id_key_.reset();
314 bool do_channel_id = false;
315 if (server_id_.is_https() &&
316 server_id_.privacy_mode() == PRIVACY_MODE_DISABLED &&
317 crypto_config_->channel_id_source()) {
318 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
319 const QuicTag* their_proof_demands;
320 size_t num_their_proof_demands;
321 if (scfg && // scfg may be null when we send inchoate CHLO.
322 scfg->GetTaglist(kPDMD, &their_proof_demands,
323 &num_their_proof_demands) == QUIC_NO_ERROR) {
324 for (size_t i = 0; i < num_their_proof_demands; i++) {
325 if (their_proof_demands[i] == kCHID) {
326 do_channel_id = true;
327 break;
328 }
329 }
330 }
331 }
Ryan Hamilton 2014/06/25 23:40:26 This method is ... big. Can you factor this block
wtc 2014/06/28 16:03:29 Done.
332
333 if (do_channel_id) {
334 ChannelIDSourceCallbackImpl* channel_id_source_callback =
335 new ChannelIDSourceCallbackImpl(this);
336 QuicAsyncStatus status =
337 crypto_config_->channel_id_source()->GetChannelIDKey(
338 server_id_.host(), &channel_id_key_,
339 channel_id_source_callback);
340 if (status == QUIC_PENDING) {
Ryan Hamilton 2014/06/25 23:40:26 Consider using a switch here to be parallel with t
wtc 2014/06/28 16:03:29 Done. I wrote it this way to avoid duplicating the
Ryan Hamilton 2014/06/30 17:47:03 Oh, fair enough! Feel free to switch both to the p
341 channel_id_source_callback_ = channel_id_source_callback;
342 DVLOG(1) << "Looking up channel ID";
343 return;
344 }
345 delete channel_id_source_callback;
346 if (status == QUIC_FAILURE) {
347 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
348 "Channel ID lookup failed");
349 return;
350 }
351 }
352 break;
353 }
354 case STATE_GET_CHANNEL_ID_COMPLETE:
355 next_state_ = STATE_SEND_CHLO;
Ryan Hamilton 2014/06/25 23:40:26 It seems like the channel id lookup might fail wit
wtc 2014/06/28 16:03:30 You are right -- we should handle synchronous and
356 break;
312 case STATE_RECV_SHLO: { 357 case STATE_RECV_SHLO: {
313 // We sent a CHLO that we expected to be accepted and now we're hoping 358 // 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. 359 // for a SHLO from the server to confirm that.
315 if (in->tag() == kREJ) { 360 if (in->tag() == kREJ) {
316 // alternative_decrypter will be NULL if the original alternative 361 // alternative_decrypter will be NULL if the original alternative
317 // decrypter latched and became the primary decrypter. That happens 362 // decrypter latched and became the primary decrypter. That happens
318 // if we received a message encrypted with the INITIAL key. 363 // if we received a message encrypted with the INITIAL key.
319 if (session()->connection()->alternative_decrypter() == NULL) { 364 if (session()->connection()->alternative_decrypter() == NULL) {
320 // The rejection was sent encrypted! 365 // The rejection was sent encrypted!
321 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, 366 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 QuicCryptoClientConfig::CachedState* cached) { 433 QuicCryptoClientConfig::CachedState* cached) {
389 cached->SetProofValid(); 434 cached->SetProofValid();
390 client_session()->OnProofValid(*cached); 435 client_session()->OnProofValid(*cached);
391 } 436 }
392 437
393 QuicClientSessionBase* QuicCryptoClientStream::client_session() { 438 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
394 return reinterpret_cast<QuicClientSessionBase*>(session()); 439 return reinterpret_cast<QuicClientSessionBase*>(session());
395 } 440 }
396 441
397 } // namespace net 442 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698