Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_crypto_server_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_server_stream.h"
6
7 #include "base/base64.h"
8 #include "crypto/secure_hash.h"
9 #include "net/quic/crypto/crypto_protocol.h"
10 #include "net/quic/crypto/crypto_utils.h"
11 #include "net/quic/crypto/quic_crypto_server_config.h"
12 #include "net/quic/crypto/source_address_token.h"
13 #include "net/quic/quic_config.h"
14 #include "net/quic/quic_flags.h"
15 #include "net/quic/quic_protocol.h"
16 #include "net/quic/quic_session.h"
17
18 namespace net {
19
20 void ServerHelloNotifier::OnAckNotification(
21     int num_original_packets,
22     int num_original_bytes,
23     int num_retransmitted_packets,
24     int num_retransmitted_bytes,
25     QuicTime::Delta delta_largest_observed) {
26   server_stream_->OnServerHelloAcked();
27 }
28
29 QuicCryptoServerStream::QuicCryptoServerStream(
30     const QuicCryptoServerConfig& crypto_config,
31     QuicSession* session)
32     : QuicCryptoStream(session),
33       crypto_config_(crypto_config),
34       validate_client_hello_cb_(nullptr),
35       num_handshake_messages_(0),
36       num_server_config_update_messages_sent_(0) {}
37
38 QuicCryptoServerStream::~QuicCryptoServerStream() {
39   CancelOutstandingCallbacks();
40 }
41
42 void QuicCryptoServerStream::CancelOutstandingCallbacks() {
43   // Detach from the validation callback.  Calling this multiple times is safe.
44   if (validate_client_hello_cb_ != nullptr) {
45     validate_client_hello_cb_->Cancel();
46   }
47 }
48
49 void QuicCryptoServerStream::OnHandshakeMessage(
50     const CryptoHandshakeMessage& message) {
51   QuicCryptoStream::OnHandshakeMessage(message);
52   ++num_handshake_messages_;
53
54   // Do not process handshake messages after the handshake is confirmed.
55   if (handshake_confirmed_) {
56     CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
57     return;
58   }
59
60   if (message.tag() != kCHLO) {
61     CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
62     return;
63   }
64
65   if (validate_client_hello_cb_ != nullptr) {
66     // Already processing some other handshake message.  The protocol
67     // does not allow for clients to send multiple handshake messages
68     // before the server has a chance to respond.
69     CloseConnection(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO);
70     return;
71   }
72
73   validate_client_hello_cb_ = new ValidateCallback(this);
74   return crypto_config_.ValidateClientHello(
75       message,
76       session()->connection()->peer_address(),
77       session()->connection()->clock(),
78       validate_client_hello_cb_);
79 }
80
81 void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
82     const CryptoHandshakeMessage& message,
83     const ValidateClientHelloResultCallback::Result& result) {
84   // Clear the callback that got us here.
85   DCHECK(validate_client_hello_cb_ != nullptr);
86   validate_client_hello_cb_ = nullptr;
87
88   string error_details;
89   CryptoHandshakeMessage reply;
90   QuicErrorCode error = ProcessClientHello(
91       message, result, &reply, &error_details);
92
93   if (error != QUIC_NO_ERROR) {
94     CloseConnectionWithDetails(error, error_details);
95     return;
96   }
97
98   if (reply.tag() != kSHLO) {
99     SendHandshakeMessage(reply);
100     return;
101   }
102
103   // If we are returning a SHLO then we accepted the handshake.
104   QuicConfig* config = session()->config();
105   OverrideQuicConfigDefaults(config);
106   error = config->ProcessPeerHello(message, CLIENT, &error_details);
107   if (error != QUIC_NO_ERROR) {
108     CloseConnectionWithDetails(error, error_details);
109     return;
110   }
111   session()->OnConfigNegotiated();
112
113   config->ToHandshakeMessage(&reply);
114
115   // Receiving a full CHLO implies the client is prepared to decrypt with
116   // the new server write key.  We can start to encrypt with the new server
117   // write key.
118   //
119   // NOTE: the SHLO will be encrypted with the new server write key.
120   session()->connection()->SetEncrypter(
121       ENCRYPTION_INITIAL,
122       crypto_negotiated_params_.initial_crypters.encrypter.release());
123   session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
124   // Set the decrypter immediately so that we no longer accept unencrypted
125   // packets.
126   session()->connection()->SetDecrypter(
127       crypto_negotiated_params_.initial_crypters.decrypter.release(),
128       ENCRYPTION_INITIAL);
129
130   // We want to be notified when the SHLO is ACKed so that we can disable
131   // HANDSHAKE_MODE in the sent packet manager.
132   if (session()->connection()->version() <= QUIC_VERSION_21) {
133     SendHandshakeMessage(reply);
134   } else {
135     scoped_refptr<ServerHelloNotifier> server_hello_notifier(
136         new ServerHelloNotifier(this));
137     SendHandshakeMessage(reply, server_hello_notifier.get());
138   }
139
140   session()->connection()->SetEncrypter(
141       ENCRYPTION_FORWARD_SECURE,
142       crypto_negotiated_params_.forward_secure_crypters.encrypter.release());
143   if (!FLAGS_enable_quic_delay_forward_security) {
144     session()->connection()->SetDefaultEncryptionLevel(
145         ENCRYPTION_FORWARD_SECURE);
146   }
147   session()->connection()->SetAlternativeDecrypter(
148       crypto_negotiated_params_.forward_secure_crypters.decrypter.release(),
149       ENCRYPTION_FORWARD_SECURE, false /* don't latch */);
150
151   encryption_established_ = true;
152   handshake_confirmed_ = true;
153   session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
154 }
155
156 void QuicCryptoServerStream::SendServerConfigUpdate(
157     const CachedNetworkParameters* cached_network_params) {
158   if (session()->connection()->version() <= QUIC_VERSION_21 ||
159       !handshake_confirmed_) {
160     return;
161   }
162
163   CryptoHandshakeMessage server_config_update_message;
164   if (!crypto_config_.BuildServerConfigUpdateMessage(
165           session()->connection()->peer_address(),
166           session()->connection()->clock(),
167           session()->connection()->random_generator(),
168           crypto_negotiated_params_,
169           cached_network_params,
170           &server_config_update_message)) {
171     DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
172     return;
173   }
174
175   DVLOG(1) << "Server: Sending server config update: "
176            << server_config_update_message.DebugString();
177   const QuicData& data = server_config_update_message.GetSerialized();
178   WriteOrBufferData(string(data.data(), data.length()), false, nullptr);
179
180   ++num_server_config_update_messages_sent_;
181 }
182
183 void QuicCryptoServerStream::OnServerHelloAcked() {
184   session()->connection()->OnHandshakeComplete();
185 }
186
187 void QuicCryptoServerStream::set_previous_cached_network_params(
188     CachedNetworkParameters cached_network_params) {
189   previous_cached_network_params_.reset(
190       new CachedNetworkParameters(cached_network_params));
191 }
192
193 bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
194     string* output) const {
195   if (!encryption_established_ ||
196       crypto_negotiated_params_.channel_id.empty()) {
197     return false;
198   }
199
200   const string& channel_id(crypto_negotiated_params_.channel_id);
201   scoped_ptr<crypto::SecureHash> hash(
202       crypto::SecureHash::Create(crypto::SecureHash::SHA256));
203   hash->Update(channel_id.data(), channel_id.size());
204   uint8 digest[32];
205   hash->Finish(digest, sizeof(digest));
206
207   base::Base64Encode(string(
208       reinterpret_cast<const char*>(digest), sizeof(digest)), output);
209   // Remove padding.
210   size_t len = output->size();
211   if (len >= 2) {
212     if ((*output)[len - 1] == '=') {
213       len--;
214       if ((*output)[len - 1] == '=') {
215         len--;
216       }
217       output->resize(len);
218     }
219   }
220   return true;
221 }
222
223 QuicErrorCode QuicCryptoServerStream::ProcessClientHello(
224     const CryptoHandshakeMessage& message,
225     const ValidateClientHelloResultCallback::Result& result,
226     CryptoHandshakeMessage* reply,
227     string* error_details) {
228   // Store the bandwidth estimate from the client.
229   if (result.cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
230     previous_cached_network_params_.reset(
231         new CachedNetworkParameters(result.cached_network_params));
232   }
233
234   return crypto_config_.ProcessClientHello(
235       result,
236       session()->connection()->connection_id(),
237       session()->connection()->peer_address(),
238       session()->connection()->version(),
239       session()->connection()->supported_versions(),
240       session()->connection()->clock(),
241       session()->connection()->random_generator(),
242       &crypto_negotiated_params_, reply, error_details);
243 }
244
245 void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) {
246 }
247
248 CachedNetworkParameters*
249 QuicCryptoServerStream::get_previous_cached_network_params() {
250   return previous_cached_network_params_.get();
251 }
252
253 QuicCryptoServerStream::ValidateCallback::ValidateCallback(
254     QuicCryptoServerStream* parent) : parent_(parent) {
255 }
256
257 void QuicCryptoServerStream::ValidateCallback::Cancel() { parent_ = nullptr; }
258
259 void QuicCryptoServerStream::ValidateCallback::RunImpl(
260     const CryptoHandshakeMessage& client_hello,
261     const Result& result) {
262   if (parent_ != nullptr) {
263     parent_->FinishProcessingHandshakeMessage(client_hello, result);
264   }
265 }
266
267 }  // namespace net