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
3 // found in the LICENSE file.
4
5 #include "net/quic/quic_crypto_client_stream.h"
6
7 #include "base/metrics/histogram.h"
8 #include "net/quic/crypto/crypto_protocol.h"
9 #include "net/quic/crypto/crypto_utils.h"
10 #include "net/quic/crypto/null_encrypter.h"
11 #include "net/quic/quic_client_session_base.h"
12 #include "net/quic/quic_protocol.h"
13 #include "net/quic/quic_session.h"
14
15 namespace net {
16
17 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
ChannelIDSourceCallbackImpl(QuicCryptoClientStream * stream)18 ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream)
19 : stream_(stream) {}
20
21 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
~ChannelIDSourceCallbackImpl()22 ~ChannelIDSourceCallbackImpl() {}
23
Run(scoped_ptr<ChannelIDKey> * channel_id_key)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_run_ = true;
32 stream_->channel_id_source_callback_ = NULL;
33 stream_->DoHandshakeLoop(NULL);
34
35 // The ChannelIDSource owns this object and will delete it when this method
36 // returns.
37 }
38
Cancel()39 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Cancel() {
40 stream_ = NULL;
41 }
42
ProofVerifierCallbackImpl(QuicCryptoClientStream * stream)43 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
44 QuicCryptoClientStream* stream)
45 : stream_(stream) {}
46
47 QuicCryptoClientStream::ProofVerifierCallbackImpl::
~ProofVerifierCallbackImpl()48 ~ProofVerifierCallbackImpl() {}
49
Run(bool ok,const string & error_details,scoped_ptr<ProofVerifyDetails> * details)50 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
51 bool ok,
52 const string& error_details,
53 scoped_ptr<ProofVerifyDetails>* details) {
54 if (stream_ == NULL) {
55 return;
56 }
57
58 stream_->verify_ok_ = ok;
59 stream_->verify_error_details_ = error_details;
60 stream_->verify_details_.reset(details->release());
61 stream_->proof_verify_callback_ = NULL;
62 stream_->DoHandshakeLoop(NULL);
63
64 // The ProofVerifier owns this object and will delete it when this method
65 // returns.
66 }
67
Cancel()68 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
69 stream_ = NULL;
70 }
71
QuicCryptoClientStream(const QuicServerId & server_id,QuicClientSessionBase * session,ProofVerifyContext * verify_context,QuicCryptoClientConfig * crypto_config)72 QuicCryptoClientStream::QuicCryptoClientStream(
73 const QuicServerId& server_id,
74 QuicClientSessionBase* session,
75 ProofVerifyContext* verify_context,
76 QuicCryptoClientConfig* crypto_config)
77 : QuicCryptoStream(session),
78 next_state_(STATE_IDLE),
79 num_client_hellos_(0),
80 crypto_config_(crypto_config),
81 server_id_(server_id),
82 generation_counter_(0),
83 channel_id_sent_(false),
84 channel_id_source_callback_run_(false),
85 channel_id_source_callback_(NULL),
86 verify_context_(verify_context),
87 proof_verify_callback_(NULL) {
88 }
89
~QuicCryptoClientStream()90 QuicCryptoClientStream::~QuicCryptoClientStream() {
91 if (channel_id_source_callback_) {
92 channel_id_source_callback_->Cancel();
93 }
94 if (proof_verify_callback_) {
95 proof_verify_callback_->Cancel();
96 }
97 }
98
OnHandshakeMessage(const CryptoHandshakeMessage & message)99 void QuicCryptoClientStream::OnHandshakeMessage(
100 const CryptoHandshakeMessage& message) {
101 QuicCryptoStream::OnHandshakeMessage(message);
102
103 if (message.tag() == kSCUP) {
104 if (!handshake_confirmed()) {
105 CloseConnection(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE);
106 return;
107 }
108
109 // |message| is an update from the server, so we treat it differently from a
110 // handshake message.
111 HandleServerConfigUpdateMessage(message);
112 return;
113 }
114
115 // Do not process handshake messages after the handshake is confirmed.
116 if (handshake_confirmed()) {
117 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
118 return;
119 }
120
121 DoHandshakeLoop(&message);
122 }
123
CryptoConnect()124 bool QuicCryptoClientStream::CryptoConnect() {
125 next_state_ = STATE_INITIALIZE;
126 DoHandshakeLoop(NULL);
127 return true;
128 }
129
num_sent_client_hellos() const130 int QuicCryptoClientStream::num_sent_client_hellos() const {
131 return num_client_hellos_;
132 }
133
WasChannelIDSent() const134 bool QuicCryptoClientStream::WasChannelIDSent() const {
135 return channel_id_sent_;
136 }
137
WasChannelIDSourceCallbackRun() const138 bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const {
139 return channel_id_source_callback_run_;
140 }
141
HandleServerConfigUpdateMessage(const CryptoHandshakeMessage & server_config_update)142 void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
143 const CryptoHandshakeMessage& server_config_update) {
144 DCHECK(server_config_update.tag() == kSCUP);
145 string error_details;
146 QuicCryptoClientConfig::CachedState* cached =
147 crypto_config_->LookupOrCreate(server_id_);
148 QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
149 server_config_update,
150 session()->connection()->clock()->WallNow(),
151 cached,
152 &crypto_negotiated_params_,
153 &error_details);
154
155 if (error != QUIC_NO_ERROR) {
156 CloseConnectionWithDetails(
157 error, "Server config update invalid: " + error_details);
158 return;
159 }
160
161 DCHECK(handshake_confirmed());
162 if (proof_verify_callback_) {
163 proof_verify_callback_->Cancel();
164 }
165 next_state_ = STATE_INITIALIZE_SCUP;
166 DoHandshakeLoop(NULL);
167 }
168
169 // kMaxClientHellos is the maximum number of times that we'll send a client
170 // hello. The value 3 accounts for:
171 // * One failure due to an incorrect or missing source-address token.
172 // * One failure due the server's certificate chain being unavailible and the
173 // server being unwilling to send it without a valid source-address token.
174 static const int kMaxClientHellos = 3;
175
DoHandshakeLoop(const CryptoHandshakeMessage * in)176 void QuicCryptoClientStream::DoHandshakeLoop(
177 const CryptoHandshakeMessage* in) {
178 CryptoHandshakeMessage out;
179 QuicErrorCode error;
180 string error_details;
181 QuicCryptoClientConfig::CachedState* cached =
182 crypto_config_->LookupOrCreate(server_id_);
183
184 for (;;) {
185 const State state = next_state_;
186 next_state_ = STATE_IDLE;
187 switch (state) {
188 case STATE_INITIALIZE: {
189 if (!cached->IsEmpty() && !cached->signature().empty() &&
190 server_id_.is_https()) {
191 // Note that we verify the proof even if the cached proof is valid.
192 // This allows us to respond to CA trust changes or certificate
193 // expiration because it may have been a while since we last verified
194 // the proof.
195 DCHECK(crypto_config_->proof_verifier());
196 // If the cached state needs to be verified, do it now.
197 next_state_ = STATE_VERIFY_PROOF;
198 } else {
199 next_state_ = STATE_GET_CHANNEL_ID;
200 }
201 break;
202 }
203 case STATE_SEND_CHLO: {
204 // Send the client hello in plaintext.
205 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
206 if (num_client_hellos_ > kMaxClientHellos) {
207 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
208 return;
209 }
210 num_client_hellos_++;
211
212 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
213 crypto_config_->FillInchoateClientHello(
214 server_id_,
215 session()->connection()->supported_versions().front(),
216 cached, &crypto_negotiated_params_, &out);
217 // Pad the inchoate client hello to fill up a packet.
218 const size_t kFramingOverhead = 50; // A rough estimate.
219 const size_t max_packet_size =
220 session()->connection()->max_packet_length();
221 if (max_packet_size <= kFramingOverhead) {
222 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
223 << ") has no room for framing overhead.";
224 CloseConnection(QUIC_INTERNAL_ERROR);
225 return;
226 }
227 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
228 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
229 CloseConnection(QUIC_INTERNAL_ERROR);
230 return;
231 }
232 out.set_minimum_size(max_packet_size - kFramingOverhead);
233 next_state_ = STATE_RECV_REJ;
234 SendHandshakeMessage(out);
235 return;
236 }
237 session()->config()->ToHandshakeMessage(&out);
238 error = crypto_config_->FillClientHello(
239 server_id_,
240 session()->connection()->connection_id(),
241 session()->connection()->supported_versions().front(),
242 cached,
243 session()->connection()->clock()->WallNow(),
244 session()->connection()->random_generator(),
245 channel_id_key_.get(),
246 &crypto_negotiated_params_,
247 &out,
248 &error_details);
249 if (error != QUIC_NO_ERROR) {
250 // Flush the cached config so that, if it's bad, the server has a
251 // chance to send us another in the future.
252 cached->InvalidateServerConfig();
253 CloseConnectionWithDetails(error, error_details);
254 return;
255 }
256 channel_id_sent_ = (channel_id_key_.get() != NULL);
257 if (cached->proof_verify_details()) {
258 client_session()->OnProofVerifyDetailsAvailable(
259 *cached->proof_verify_details());
260 }
261 next_state_ = STATE_RECV_SHLO;
262 SendHandshakeMessage(out);
263 // Be prepared to decrypt with the new server write key.
264 session()->connection()->SetAlternativeDecrypter(
265 crypto_negotiated_params_.initial_crypters.decrypter.release(),
266 ENCRYPTION_INITIAL,
267 true /* latch once used */);
268 // Send subsequent packets under encryption on the assumption that the
269 // server will accept the handshake.
270 session()->connection()->SetEncrypter(
271 ENCRYPTION_INITIAL,
272 crypto_negotiated_params_.initial_crypters.encrypter.release());
273 session()->connection()->SetDefaultEncryptionLevel(
274 ENCRYPTION_INITIAL);
275 if (!encryption_established_) {
276 encryption_established_ = true;
277 session()->OnCryptoHandshakeEvent(
278 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
279 } else {
280 session()->OnCryptoHandshakeEvent(
281 QuicSession::ENCRYPTION_REESTABLISHED);
282 }
283 return;
284 }
285 case STATE_RECV_REJ:
286 // We sent a dummy CHLO because we didn't have enough information to
287 // perform a handshake, or we sent a full hello that the server
288 // rejected. Here we hope to have a REJ that contains the information
289 // that we need.
290 if (in->tag() != kREJ) {
291 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
292 "Expected REJ");
293 return;
294 }
295 error = crypto_config_->ProcessRejection(
296 *in, session()->connection()->clock()->WallNow(), cached,
297 server_id_.is_https(), &crypto_negotiated_params_, &error_details);
298 if (error != QUIC_NO_ERROR) {
299 CloseConnectionWithDetails(error, error_details);
300 return;
301 }
302 if (!cached->proof_valid()) {
303 if (!server_id_.is_https()) {
304 // We don't check the certificates for insecure QUIC connections.
305 SetCachedProofValid(cached);
306 } else if (!cached->signature().empty()) {
307 // Note that we only verify the proof if the cached proof is not
308 // valid. If the cached proof is valid here, someone else must have
309 // just added the server config to the cache and verified the proof,
310 // so we can assume no CA trust changes or certificate expiration
311 // has happened since then.
312 next_state_ = STATE_VERIFY_PROOF;
313 break;
314 }
315 }
316 next_state_ = STATE_GET_CHANNEL_ID;
317 break;
318 case STATE_VERIFY_PROOF: {
319 if (QUIC_PENDING == DoVerifyProof(cached)) {
320 return;
321 }
322 break;
323 }
324 case STATE_VERIFY_PROOF_COMPLETE:
325 if (QUIC_PROOF_INVALID == DoVerifyProofComplete(cached)) {
326 return;
327 }
328 break;
329 case STATE_GET_CHANNEL_ID: {
330 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
331 channel_id_key_.reset();
332 if (!RequiresChannelID(cached)) {
333 next_state_ = STATE_SEND_CHLO;
334 break;
335 }
336
337 ChannelIDSourceCallbackImpl* channel_id_source_callback =
338 new ChannelIDSourceCallbackImpl(this);
339 QuicAsyncStatus status =
340 crypto_config_->channel_id_source()->GetChannelIDKey(
341 server_id_.host(), &channel_id_key_,
342 channel_id_source_callback);
343
344 switch (status) {
345 case QUIC_PENDING:
346 channel_id_source_callback_ = channel_id_source_callback;
347 DVLOG(1) << "Looking up channel ID";
348 return;
349 case QUIC_FAILURE:
350 delete channel_id_source_callback;
351 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
352 "Channel ID lookup failed");
353 return;
354 case QUIC_SUCCESS:
355 delete channel_id_source_callback;
356 break;
357 }
358 break;
359 }
360 case STATE_GET_CHANNEL_ID_COMPLETE:
361 if (!channel_id_key_.get()) {
362 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
363 "Channel ID lookup failed");
364 return;
365 }
366 next_state_ = STATE_SEND_CHLO;
367 break;
368 case STATE_RECV_SHLO: {
369 // We sent a CHLO that we expected to be accepted and now we're hoping
370 // for a SHLO from the server to confirm that.
371 if (in->tag() == kREJ) {
372 // alternative_decrypter will be NULL if the original alternative
373 // decrypter latched and became the primary decrypter. That happens
374 // if we received a message encrypted with the INITIAL key.
375 if (session()->connection()->alternative_decrypter() == NULL) {
376 // The rejection was sent encrypted!
377 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
378 "encrypted REJ message");
379 return;
380 }
381 next_state_ = STATE_RECV_REJ;
382 break;
383 }
384 if (in->tag() != kSHLO) {
385 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
386 "Expected SHLO or REJ");
387 return;
388 }
389 // alternative_decrypter will be NULL if the original alternative
390 // decrypter latched and became the primary decrypter. That happens
391 // if we received a message encrypted with the INITIAL key.
392 if (session()->connection()->alternative_decrypter() != NULL) {
393 // The server hello was sent without encryption.
394 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
395 "unencrypted SHLO message");
396 return;
397 }
398 error = crypto_config_->ProcessServerHello(
399 *in, session()->connection()->connection_id(),
400 session()->connection()->server_supported_versions(),
401 cached, &crypto_negotiated_params_, &error_details);
402
403 if (error != QUIC_NO_ERROR) {
404 CloseConnectionWithDetails(
405 error, "Server hello invalid: " + error_details);
406 return;
407 }
408 error =
409 session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
410 if (error != QUIC_NO_ERROR) {
411 CloseConnectionWithDetails(
412 error, "Server hello invalid: " + error_details);
413 return;
414 }
415 session()->OnConfigNegotiated();
416
417 CrypterPair* crypters =
418 &crypto_negotiated_params_.forward_secure_crypters;
419 // TODO(agl): we don't currently latch this decrypter because the idea
420 // has been floated that the server shouldn't send packets encrypted
421 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
422 // packet from the client.
423 session()->connection()->SetAlternativeDecrypter(
424 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE,
425 false /* don't latch */);
426 session()->connection()->SetEncrypter(
427 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
428 session()->connection()->SetDefaultEncryptionLevel(
429 ENCRYPTION_FORWARD_SECURE);
430
431 handshake_confirmed_ = true;
432 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
433 session()->connection()->OnHandshakeComplete();
434 return;
435 }
436 case STATE_IDLE:
437 // This means that the peer sent us a message that we weren't expecting.
438 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
439 return;
440 case STATE_INITIALIZE_SCUP:
441 DoInitializeServerConfigUpdate(cached);
442 break;
443 case STATE_VERIFY_PROOF_DONE:
444 return; // We are done.
445 }
446 }
447 }
448
DoInitializeServerConfigUpdate(QuicCryptoClientConfig::CachedState * cached)449 void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
450 QuicCryptoClientConfig::CachedState* cached) {
451 bool update_ignored = false;
452 if (!server_id_.is_https()) {
453 // We don't check the certificates for insecure QUIC connections.
454 SetCachedProofValid(cached);
455 next_state_ = STATE_VERIFY_PROOF_DONE;
456 } else if (!cached->IsEmpty() && !cached->signature().empty()) {
457 // Note that we verify the proof even if the cached proof is valid.
458 DCHECK(crypto_config_->proof_verifier());
459 next_state_ = STATE_VERIFY_PROOF;
460 } else {
461 update_ignored = true;
462 next_state_ = STATE_VERIFY_PROOF_DONE;
463 }
464 UMA_HISTOGRAM_BOOLEAN("Net.QuicNumServerConfig.UpdateMessagesIgnored",
465 update_ignored);
466 }
467
DoVerifyProof(QuicCryptoClientConfig::CachedState * cached)468 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
469 QuicCryptoClientConfig::CachedState* cached) {
470 ProofVerifier* verifier = crypto_config_->proof_verifier();
471 DCHECK(verifier);
472 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
473 generation_counter_ = cached->generation_counter();
474
475 ProofVerifierCallbackImpl* proof_verify_callback =
476 new ProofVerifierCallbackImpl(this);
477
478 verify_ok_ = false;
479
480 QuicAsyncStatus status = verifier->VerifyProof(
481 server_id_.host(),
482 cached->server_config(),
483 cached->certs(),
484 cached->signature(),
485 verify_context_.get(),
486 &verify_error_details_,
487 &verify_details_,
488 proof_verify_callback);
489
490 switch (status) {
491 case QUIC_PENDING:
492 proof_verify_callback_ = proof_verify_callback;
493 DVLOG(1) << "Doing VerifyProof";
494 break;
495 case QUIC_FAILURE:
496 delete proof_verify_callback;
497 break;
498 case QUIC_SUCCESS:
499 delete proof_verify_callback;
500 verify_ok_ = true;
501 break;
502 }
503 return status;
504 }
505
DoVerifyProofComplete(QuicCryptoClientConfig::CachedState * cached)506 QuicErrorCode QuicCryptoClientStream::DoVerifyProofComplete(
507 QuicCryptoClientConfig::CachedState* cached) {
508 if (!verify_ok_) {
509 client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
510 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
511 handshake_confirmed());
512 CloseConnectionWithDetails(
513 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
514 return QUIC_PROOF_INVALID;
515 }
516
517 // Check if generation_counter has changed between STATE_VERIFY_PROOF and
518 // STATE_VERIFY_PROOF_COMPLETE state changes.
519 if (generation_counter_ != cached->generation_counter()) {
520 next_state_ = STATE_VERIFY_PROOF;
521 } else {
522 SetCachedProofValid(cached);
523 cached->SetProofVerifyDetails(verify_details_.release());
524 if (!handshake_confirmed()) {
525 next_state_ = STATE_GET_CHANNEL_ID;
526 } else {
527 next_state_ = STATE_VERIFY_PROOF_DONE;
528 }
529 }
530 return QUIC_NO_ERROR;
531 }
532
SetCachedProofValid(QuicCryptoClientConfig::CachedState * cached)533 void QuicCryptoClientStream::SetCachedProofValid(
534 QuicCryptoClientConfig::CachedState* cached) {
535 cached->SetProofValid();
536 client_session()->OnProofValid(*cached);
537 }
538
RequiresChannelID(QuicCryptoClientConfig::CachedState * cached)539 bool QuicCryptoClientStream::RequiresChannelID(
540 QuicCryptoClientConfig::CachedState* cached) {
541 if (!server_id_.is_https() ||
542 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED ||
543 !crypto_config_->channel_id_source()) {
544 return false;
545 }
546 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
547 if (!scfg) { // scfg may be null when we send an inchoate CHLO.
548 return false;
549 }
550 const QuicTag* their_proof_demands;
551 size_t num_their_proof_demands;
552 if (scfg->GetTaglist(kPDMD, &their_proof_demands,
553 &num_their_proof_demands) != QUIC_NO_ERROR) {
554 return false;
555 }
556 for (size_t i = 0; i < num_their_proof_demands; i++) {
557 if (their_proof_demands[i] == kCHID) {
558 return true;
559 }
560 }
561 return false;
562 }
563
client_session()564 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
565 return reinterpret_cast<QuicClientSessionBase*>(session());
566 }
567
568 } // namespace net
569