[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / net / quic / quic_crypto_server_stream.cc
blob435cf4a2af901010acb08075ae2ee4df962c0c48
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.
5 #include "net/quic/quic_crypto_server_stream.h"
7 #include "base/base64.h"
8 #include "crypto/secure_hash.h"
9 #include "net/quic/crypto/cached_network_parameters.h"
10 #include "net/quic/crypto/crypto_protocol.h"
11 #include "net/quic/crypto/crypto_utils.h"
12 #include "net/quic/crypto/quic_crypto_server_config.h"
13 #include "net/quic/quic_config.h"
14 #include "net/quic/quic_protocol.h"
15 #include "net/quic/quic_session.h"
17 using std::string;
19 namespace net {
21 void ServerHelloNotifier::OnAckNotification(
22 int num_retransmitted_packets,
23 int num_retransmitted_bytes,
24 QuicTime::Delta delta_largest_observed) {
25 server_stream_->OnServerHelloAcked();
28 QuicCryptoServerStream::QuicCryptoServerStream(
29 const QuicCryptoServerConfig* crypto_config,
30 QuicSession* session)
31 : QuicCryptoStream(session),
32 crypto_config_(crypto_config),
33 validate_client_hello_cb_(nullptr),
34 num_handshake_messages_(0),
35 num_server_config_update_messages_sent_(0) {
36 DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective());
39 QuicCryptoServerStream::~QuicCryptoServerStream() {
40 CancelOutstandingCallbacks();
43 void QuicCryptoServerStream::CancelOutstandingCallbacks() {
44 // Detach from the validation callback. Calling this multiple times is safe.
45 if (validate_client_hello_cb_ != nullptr) {
46 validate_client_hello_cb_->Cancel();
50 void QuicCryptoServerStream::OnHandshakeMessage(
51 const CryptoHandshakeMessage& message) {
52 QuicCryptoStream::OnHandshakeMessage(message);
53 ++num_handshake_messages_;
55 // Do not process handshake messages after the handshake is confirmed.
56 if (handshake_confirmed_) {
57 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
58 return;
61 if (message.tag() != kCHLO) {
62 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
63 return;
66 if (validate_client_hello_cb_ != nullptr) {
67 // Already processing some other handshake message. The protocol
68 // does not allow for clients to send multiple handshake messages
69 // before the server has a chance to respond.
70 CloseConnection(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO);
71 return;
74 validate_client_hello_cb_ = new ValidateCallback(this);
75 return crypto_config_->ValidateClientHello(
76 message,
77 session()->connection()->peer_address(),
78 session()->connection()->clock(),
79 validate_client_hello_cb_);
82 void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
83 const CryptoHandshakeMessage& message,
84 const ValidateClientHelloResultCallback::Result& result) {
85 // Clear the callback that got us here.
86 DCHECK(validate_client_hello_cb_ != nullptr);
87 validate_client_hello_cb_ = nullptr;
89 string error_details;
90 CryptoHandshakeMessage reply;
91 QuicErrorCode error = ProcessClientHello(
92 message, result, &reply, &error_details);
94 if (error != QUIC_NO_ERROR) {
95 CloseConnectionWithDetails(error, error_details);
96 return;
99 if (reply.tag() != kSHLO) {
100 SendHandshakeMessage(reply);
101 return;
104 // If we are returning a SHLO then we accepted the handshake.
105 QuicConfig* config = session()->config();
106 OverrideQuicConfigDefaults(config);
107 error = config->ProcessPeerHello(message, CLIENT, &error_details);
108 if (error != QUIC_NO_ERROR) {
109 CloseConnectionWithDetails(error, error_details);
110 return;
112 session()->OnConfigNegotiated();
114 config->ToHandshakeMessage(&reply);
116 // Receiving a full CHLO implies the client is prepared to decrypt with
117 // the new server write key. We can start to encrypt with the new server
118 // write key.
120 // NOTE: the SHLO will be encrypted with the new server write key.
121 session()->connection()->SetEncrypter(
122 ENCRYPTION_INITIAL,
123 crypto_negotiated_params_.initial_crypters.encrypter.release());
124 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
125 // Set the decrypter immediately so that we no longer accept unencrypted
126 // packets.
127 session()->connection()->SetDecrypter(
128 crypto_negotiated_params_.initial_crypters.decrypter.release(),
129 ENCRYPTION_INITIAL);
131 // We want to be notified when the SHLO is ACKed so that we can disable
132 // HANDSHAKE_MODE in the sent packet manager.
133 scoped_refptr<ServerHelloNotifier> server_hello_notifier(
134 new ServerHelloNotifier(this));
135 SendHandshakeMessage(reply, server_hello_notifier.get());
137 session()->connection()->SetEncrypter(
138 ENCRYPTION_FORWARD_SECURE,
139 crypto_negotiated_params_.forward_secure_crypters.encrypter.release());
140 session()->connection()->SetAlternativeDecrypter(
141 crypto_negotiated_params_.forward_secure_crypters.decrypter.release(),
142 ENCRYPTION_FORWARD_SECURE, false /* don't latch */);
144 encryption_established_ = true;
145 handshake_confirmed_ = true;
146 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
149 void QuicCryptoServerStream::SendServerConfigUpdate(
150 const CachedNetworkParameters* cached_network_params) {
151 if (!handshake_confirmed_) {
152 return;
155 CryptoHandshakeMessage server_config_update_message;
156 if (!crypto_config_->BuildServerConfigUpdateMessage(
157 previous_source_address_tokens_,
158 session()->connection()->self_address(),
159 session()->connection()->peer_address(),
160 session()->connection()->clock(),
161 session()->connection()->random_generator(),
162 crypto_negotiated_params_, cached_network_params,
163 &server_config_update_message)) {
164 DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
165 return;
168 DVLOG(1) << "Server: Sending server config update: "
169 << server_config_update_message.DebugString();
170 const QuicData& data = server_config_update_message.GetSerialized();
171 WriteOrBufferData(string(data.data(), data.length()), false, nullptr);
173 ++num_server_config_update_messages_sent_;
176 void QuicCryptoServerStream::OnServerHelloAcked() {
177 session()->connection()->OnHandshakeComplete();
180 void QuicCryptoServerStream::set_previous_cached_network_params(
181 CachedNetworkParameters cached_network_params) {
182 previous_cached_network_params_.reset(
183 new CachedNetworkParameters(cached_network_params));
186 bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
187 string* output) const {
188 if (!encryption_established_ ||
189 crypto_negotiated_params_.channel_id.empty()) {
190 return false;
193 const string& channel_id(crypto_negotiated_params_.channel_id);
194 scoped_ptr<crypto::SecureHash> hash(
195 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
196 hash->Update(channel_id.data(), channel_id.size());
197 uint8 digest[32];
198 hash->Finish(digest, sizeof(digest));
200 base::Base64Encode(string(
201 reinterpret_cast<const char*>(digest), sizeof(digest)), output);
202 // Remove padding.
203 size_t len = output->size();
204 if (len >= 2) {
205 if ((*output)[len - 1] == '=') {
206 len--;
207 if ((*output)[len - 1] == '=') {
208 len--;
210 output->resize(len);
213 return true;
216 QuicErrorCode QuicCryptoServerStream::ProcessClientHello(
217 const CryptoHandshakeMessage& message,
218 const ValidateClientHelloResultCallback::Result& result,
219 CryptoHandshakeMessage* reply,
220 string* error_details) {
221 // Store the bandwidth estimate from the client.
222 if (result.cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
223 previous_cached_network_params_.reset(
224 new CachedNetworkParameters(result.cached_network_params));
226 previous_source_address_tokens_ = result.info.source_address_tokens;
228 return crypto_config_->ProcessClientHello(
229 result, session()->connection()->connection_id(),
230 session()->connection()->self_address(),
231 session()->connection()->peer_address(),
232 session()->connection()->version(),
233 session()->connection()->supported_versions(),
234 session()->connection()->clock(),
235 session()->connection()->random_generator(), &crypto_negotiated_params_,
236 reply, error_details);
239 void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) {
242 const CachedNetworkParameters*
243 QuicCryptoServerStream::previous_cached_network_params() const {
244 return previous_cached_network_params_.get();
247 QuicCryptoServerStream::ValidateCallback::ValidateCallback(
248 QuicCryptoServerStream* parent) : parent_(parent) {
251 void QuicCryptoServerStream::ValidateCallback::Cancel() { parent_ = nullptr; }
253 void QuicCryptoServerStream::ValidateCallback::RunImpl(
254 const CryptoHandshakeMessage& client_hello,
255 const Result& result) {
256 if (parent_ != nullptr) {
257 parent_->FinishProcessingHandshakeMessage(client_hello, result);
261 } // namespace net