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