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_client_stream.h"
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/crypto/proof_verifier.h"
11 #include "net/quic/quic_client_session_base.h"
12 #include "net/quic/quic_protocol.h"
13 #include "net/quic/quic_session.h"
17 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
18 QuicCryptoClientStream* stream)
21 QuicCryptoClientStream::ProofVerifierCallbackImpl::
22 ~ProofVerifierCallbackImpl() {}
24 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
26 const string& error_details,
27 scoped_ptr<ProofVerifyDetails>* details) {
28 if (stream_ == NULL) {
32 stream_->verify_ok_ = ok;
33 stream_->verify_error_details_ = error_details;
34 stream_->verify_details_.reset(details->release());
35 stream_->proof_verify_callback_ = NULL;
36 stream_->DoHandshakeLoop(NULL);
38 // The ProofVerifier owns this object and will delete it when this method
42 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
46 QuicCryptoClientStream::QuicCryptoClientStream(
47 const QuicServerId& server_id,
48 QuicClientSessionBase* session,
49 ProofVerifyContext* verify_context,
50 QuicCryptoClientConfig* crypto_config)
51 : QuicCryptoStream(session),
52 next_state_(STATE_IDLE),
53 num_client_hellos_(0),
54 crypto_config_(crypto_config),
55 server_id_(server_id),
56 generation_counter_(0),
57 proof_verify_callback_(NULL),
58 verify_context_(verify_context) {
61 QuicCryptoClientStream::~QuicCryptoClientStream() {
62 if (proof_verify_callback_) {
63 proof_verify_callback_->Cancel();
67 void QuicCryptoClientStream::OnHandshakeMessage(
68 const CryptoHandshakeMessage& message) {
69 QuicCryptoStream::OnHandshakeMessage(message);
71 DoHandshakeLoop(&message);
74 bool QuicCryptoClientStream::CryptoConnect() {
75 next_state_ = STATE_INITIALIZE;
76 DoHandshakeLoop(NULL);
80 int QuicCryptoClientStream::num_sent_client_hellos() const {
81 return num_client_hellos_;
84 // kMaxClientHellos is the maximum number of times that we'll send a client
85 // hello. The value 3 accounts for:
86 // * One failure due to an incorrect or missing source-address token.
87 // * One failure due the server's certificate chain being unavailible and the
88 // server being unwilling to send it without a valid source-address token.
89 static const int kMaxClientHellos = 3;
91 void QuicCryptoClientStream::DoHandshakeLoop(
92 const CryptoHandshakeMessage* in) {
93 CryptoHandshakeMessage out;
96 QuicCryptoClientConfig::CachedState* cached =
97 crypto_config_->LookupOrCreate(server_id_);
100 DVLOG(1) << "Client: Received " << in->DebugString();
104 const State state = next_state_;
105 next_state_ = STATE_IDLE;
107 case STATE_INITIALIZE: {
108 if (!cached->IsEmpty() && !cached->signature().empty() &&
109 server_id_.is_https()) {
110 DCHECK(crypto_config_->proof_verifier());
111 // If the cached state needs to be verified, do it now.
112 next_state_ = STATE_VERIFY_PROOF;
114 next_state_ = STATE_SEND_CHLO;
118 case STATE_SEND_CHLO: {
119 // Send the client hello in plaintext.
120 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
121 if (num_client_hellos_ > kMaxClientHellos) {
122 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
125 num_client_hellos_++;
127 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
128 crypto_config_->FillInchoateClientHello(
130 session()->connection()->supported_versions().front(),
131 cached, &crypto_negotiated_params_, &out);
132 // Pad the inchoate client hello to fill up a packet.
133 const size_t kFramingOverhead = 50; // A rough estimate.
134 const size_t max_packet_size =
135 session()->connection()->options()->max_packet_length;
136 if (max_packet_size <= kFramingOverhead) {
137 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
138 << ") has no room for framing overhead.";
139 CloseConnection(QUIC_INTERNAL_ERROR);
142 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
143 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
144 CloseConnection(QUIC_INTERNAL_ERROR);
147 out.set_minimum_size(max_packet_size - kFramingOverhead);
148 next_state_ = STATE_RECV_REJ;
149 DVLOG(1) << "Client: Sending " << out.DebugString();
150 SendHandshakeMessage(out);
153 session()->config()->ToHandshakeMessage(&out);
154 error = crypto_config_->FillClientHello(
156 session()->connection()->connection_id(),
157 session()->connection()->supported_versions().front(),
158 session()->connection()->max_flow_control_receive_window_bytes(),
160 session()->connection()->clock()->WallNow(),
161 session()->connection()->random_generator(),
162 &crypto_negotiated_params_,
165 if (error != QUIC_NO_ERROR) {
166 // Flush the cached config so that, if it's bad, the server has a
167 // chance to send us another in the future.
168 cached->InvalidateServerConfig();
169 CloseConnectionWithDetails(error, error_details);
172 if (cached->proof_verify_details()) {
173 client_session()->OnProofVerifyDetailsAvailable(
174 *cached->proof_verify_details());
176 next_state_ = STATE_RECV_SHLO;
177 DVLOG(1) << "Client: Sending " << out.DebugString();
178 SendHandshakeMessage(out);
179 // Be prepared to decrypt with the new server write key.
180 session()->connection()->SetAlternativeDecrypter(
181 crypto_negotiated_params_.initial_crypters.decrypter.release(),
183 true /* latch once used */);
184 // Send subsequent packets under encryption on the assumption that the
185 // server will accept the handshake.
186 session()->connection()->SetEncrypter(
188 crypto_negotiated_params_.initial_crypters.encrypter.release());
189 session()->connection()->SetDefaultEncryptionLevel(
191 if (!encryption_established_) {
192 encryption_established_ = true;
193 session()->OnCryptoHandshakeEvent(
194 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
196 session()->OnCryptoHandshakeEvent(
197 QuicSession::ENCRYPTION_REESTABLISHED);
202 // We sent a dummy CHLO because we didn't have enough information to
203 // perform a handshake, or we sent a full hello that the server
204 // rejected. Here we hope to have a REJ that contains the information
206 if (in->tag() != kREJ) {
207 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
211 error = crypto_config_->ProcessRejection(
212 *in, session()->connection()->clock()->WallNow(), cached,
213 &crypto_negotiated_params_, &error_details);
214 if (error != QUIC_NO_ERROR) {
215 CloseConnectionWithDetails(error, error_details);
218 if (!cached->proof_valid()) {
219 if (!server_id_.is_https()) {
220 // We don't check the certificates for insecure QUIC connections.
221 SetCachedProofValid(cached);
222 } else if (!cached->signature().empty()) {
223 next_state_ = STATE_VERIFY_PROOF;
227 next_state_ = STATE_SEND_CHLO;
229 case STATE_VERIFY_PROOF: {
230 ProofVerifier* verifier = crypto_config_->proof_verifier();
232 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
233 generation_counter_ = cached->generation_counter();
235 ProofVerifierCallbackImpl* proof_verify_callback =
236 new ProofVerifierCallbackImpl(this);
240 ProofVerifier::Status status = verifier->VerifyProof(
242 cached->server_config(),
245 verify_context_.get(),
246 &verify_error_details_,
248 proof_verify_callback);
251 case ProofVerifier::PENDING:
252 proof_verify_callback_ = proof_verify_callback;
253 DVLOG(1) << "Doing VerifyProof";
255 case ProofVerifier::FAILURE:
256 delete proof_verify_callback;
258 case ProofVerifier::SUCCESS:
259 delete proof_verify_callback;
265 case STATE_VERIFY_PROOF_COMPLETE:
267 client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
268 CloseConnectionWithDetails(
269 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
272 // Check if generation_counter has changed between STATE_VERIFY_PROOF
273 // and STATE_VERIFY_PROOF_COMPLETE state changes.
274 if (generation_counter_ != cached->generation_counter()) {
275 next_state_ = STATE_VERIFY_PROOF;
277 SetCachedProofValid(cached);
278 cached->SetProofVerifyDetails(verify_details_.release());
279 next_state_ = STATE_SEND_CHLO;
282 case STATE_RECV_SHLO: {
283 // We sent a CHLO that we expected to be accepted and now we're hoping
284 // for a SHLO from the server to confirm that.
285 if (in->tag() == kREJ) {
286 // alternative_decrypter will be NULL if the original alternative
287 // decrypter latched and became the primary decrypter. That happens
288 // if we received a message encrypted with the INITIAL key.
289 if (session()->connection()->alternative_decrypter() == NULL) {
290 // The rejection was sent encrypted!
291 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
292 "encrypted REJ message");
295 next_state_ = STATE_RECV_REJ;
298 if (in->tag() != kSHLO) {
299 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
300 "Expected SHLO or REJ");
303 // alternative_decrypter will be NULL if the original alternative
304 // decrypter latched and became the primary decrypter. That happens
305 // if we received a message encrypted with the INITIAL key.
306 if (session()->connection()->alternative_decrypter() != NULL) {
307 // The server hello was sent without encryption.
308 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
309 "unencrypted SHLO message");
312 error = crypto_config_->ProcessServerHello(
313 *in, session()->connection()->connection_id(),
314 session()->connection()->server_supported_versions(),
315 cached, &crypto_negotiated_params_, &error_details);
317 if (error != QUIC_NO_ERROR) {
318 CloseConnectionWithDetails(
319 error, "Server hello invalid: " + error_details);
323 session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
324 if (error != QUIC_NO_ERROR) {
325 CloseConnectionWithDetails(
326 error, "Server hello invalid: " + error_details);
329 session()->OnConfigNegotiated();
331 CrypterPair* crypters =
332 &crypto_negotiated_params_.forward_secure_crypters;
333 // TODO(agl): we don't currently latch this decrypter because the idea
334 // has been floated that the server shouldn't send packets encrypted
335 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
336 // packet from the client.
337 session()->connection()->SetAlternativeDecrypter(
338 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE,
339 false /* don't latch */);
340 session()->connection()->SetEncrypter(
341 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
342 session()->connection()->SetDefaultEncryptionLevel(
343 ENCRYPTION_FORWARD_SECURE);
345 handshake_confirmed_ = true;
346 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
350 // This means that the peer sent us a message that we weren't expecting.
351 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
357 void QuicCryptoClientStream::SetCachedProofValid(
358 QuicCryptoClientConfig::CachedState* cached) {
359 cached->SetProofValid();
360 client_session()->OnProofValid(*cached);
363 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
364 return reinterpret_cast<QuicClientSessionBase*>(session());