Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / net / quic / quic_crypto_server_stream.cc
blob7bd2c034d93b2d39bfc1c718f033739dc874710b
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/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/quic_config.h"
13 #include "net/quic/quic_protocol.h"
14 #include "net/quic/quic_session.h"
16 namespace net {
18 QuicCryptoServerStream::QuicCryptoServerStream(
19 const QuicCryptoServerConfig& crypto_config,
20 QuicSession* session)
21 : QuicCryptoStream(session),
22 crypto_config_(crypto_config),
23 validate_client_hello_cb_(NULL),
24 num_handshake_messages_(0) {
27 QuicCryptoServerStream::~QuicCryptoServerStream() {
28 CancelOutstandingCallbacks();
31 void QuicCryptoServerStream::CancelOutstandingCallbacks() {
32 // Detach from the validation callback. Calling this multiple times is safe.
33 if (validate_client_hello_cb_ != NULL) {
34 validate_client_hello_cb_->Cancel();
38 void QuicCryptoServerStream::OnHandshakeMessage(
39 const CryptoHandshakeMessage& message) {
40 QuicCryptoStream::OnHandshakeMessage(message);
41 ++num_handshake_messages_;
43 // Do not process handshake messages after the handshake is confirmed.
44 if (handshake_confirmed_) {
45 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
46 return;
49 if (message.tag() != kCHLO) {
50 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
51 return;
54 if (validate_client_hello_cb_ != NULL) {
55 // Already processing some other handshake message. The protocol
56 // does not allow for clients to send multiple handshake messages
57 // before the server has a chance to respond.
58 CloseConnection(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO);
59 return;
62 validate_client_hello_cb_ = new ValidateCallback(this);
63 return crypto_config_.ValidateClientHello(
64 message,
65 session()->connection()->peer_address(),
66 session()->connection()->clock(),
67 validate_client_hello_cb_);
70 void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
71 const CryptoHandshakeMessage& message,
72 const ValidateClientHelloResultCallback::Result& result) {
73 // Clear the callback that got us here.
74 DCHECK(validate_client_hello_cb_ != NULL);
75 validate_client_hello_cb_ = NULL;
77 string error_details;
78 CryptoHandshakeMessage reply;
79 QuicErrorCode error = ProcessClientHello(
80 message, result, &reply, &error_details);
82 if (error != QUIC_NO_ERROR) {
83 CloseConnectionWithDetails(error, error_details);
84 return;
87 if (reply.tag() != kSHLO) {
88 SendHandshakeMessage(reply);
89 return;
92 // If we are returning a SHLO then we accepted the handshake.
93 QuicConfig* config = session()->config();
94 OverrideQuicConfigDefaults(config);
95 error = config->ProcessPeerHello(message, CLIENT, &error_details);
96 if (error != QUIC_NO_ERROR) {
97 CloseConnectionWithDetails(error, error_details);
98 return;
100 session()->OnConfigNegotiated();
102 config->ToHandshakeMessage(&reply);
104 // Receiving a full CHLO implies the client is prepared to decrypt with
105 // the new server write key. We can start to encrypt with the new server
106 // write key.
108 // NOTE: the SHLO will be encrypted with the new server write key.
109 session()->connection()->SetEncrypter(
110 ENCRYPTION_INITIAL,
111 crypto_negotiated_params_.initial_crypters.encrypter.release());
112 session()->connection()->SetDefaultEncryptionLevel(
113 ENCRYPTION_INITIAL);
114 // Set the decrypter immediately so that we no longer accept unencrypted
115 // packets.
116 session()->connection()->SetDecrypter(
117 crypto_negotiated_params_.initial_crypters.decrypter.release(),
118 ENCRYPTION_INITIAL);
119 SendHandshakeMessage(reply);
121 session()->connection()->SetEncrypter(
122 ENCRYPTION_FORWARD_SECURE,
123 crypto_negotiated_params_.forward_secure_crypters.encrypter.release());
124 session()->connection()->SetDefaultEncryptionLevel(
125 ENCRYPTION_FORWARD_SECURE);
126 session()->connection()->SetAlternativeDecrypter(
127 crypto_negotiated_params_.forward_secure_crypters.decrypter.release(),
128 ENCRYPTION_FORWARD_SECURE, false /* don't latch */);
130 encryption_established_ = true;
131 handshake_confirmed_ = true;
132 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
135 bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
136 string* output) const {
137 if (!encryption_established_ ||
138 crypto_negotiated_params_.channel_id.empty()) {
139 return false;
142 const string& channel_id(crypto_negotiated_params_.channel_id);
143 scoped_ptr<crypto::SecureHash> hash(
144 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
145 hash->Update(channel_id.data(), channel_id.size());
146 uint8 digest[32];
147 hash->Finish(digest, sizeof(digest));
149 base::Base64Encode(string(
150 reinterpret_cast<const char*>(digest), sizeof(digest)), output);
151 // Remove padding.
152 size_t len = output->size();
153 if (len >= 2) {
154 if ((*output)[len - 1] == '=') {
155 len--;
156 if ((*output)[len - 1] == '=') {
157 len--;
159 output->resize(len);
162 return true;
165 QuicErrorCode QuicCryptoServerStream::ProcessClientHello(
166 const CryptoHandshakeMessage& message,
167 const ValidateClientHelloResultCallback::Result& result,
168 CryptoHandshakeMessage* reply,
169 string* error_details) {
170 return crypto_config_.ProcessClientHello(
171 result,
172 session()->connection()->connection_id(),
173 session()->connection()->peer_address(),
174 session()->connection()->version(),
175 session()->connection()->supported_versions(),
176 session()->connection()->clock(),
177 session()->connection()->random_generator(),
178 &crypto_negotiated_params_, reply, error_details);
181 void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) {
184 QuicCryptoServerStream::ValidateCallback::ValidateCallback(
185 QuicCryptoServerStream* parent) : parent_(parent) {
188 void QuicCryptoServerStream::ValidateCallback::Cancel() {
189 parent_ = NULL;
192 void QuicCryptoServerStream::ValidateCallback::RunImpl(
193 const CryptoHandshakeMessage& client_hello,
194 const Result& result) {
195 if (parent_ != NULL) {
196 parent_->FinishProcessingHandshakeMessage(client_hello, result);
200 } // namespace net