Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: net/quic/quic_crypto_client_stream.cc

Issue 13976007: Land Recent QUIC Changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updated copyright notice Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/quic/quic_crypto_client_stream.h ('k') | net/quic/quic_crypto_client_stream_factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/quic_crypto_client_stream.h" 5 #include "net/quic/quic_crypto_client_stream.h"
6 6
7 #include "net/quic/crypto/crypto_protocol.h" 7 #include "net/quic/crypto/crypto_protocol.h"
8 #include "net/quic/crypto/crypto_utils.h" 8 #include "net/quic/crypto/crypto_utils.h"
9 #include "net/quic/quic_protocol.h" 9 #include "net/quic/quic_protocol.h"
10 #include "net/quic/quic_session.h" 10 #include "net/quic/quic_session.h"
11 11
12 namespace net { 12 namespace net {
13 13
14 QuicCryptoClientStream::QuicCryptoClientStream(QuicSession* session, 14 QuicCryptoClientStream::QuicCryptoClientStream(
15 const string& server_hostname) 15 const string& server_hostname,
16 const QuicConfig& config,
17 QuicSession* session,
18 QuicCryptoClientConfig* crypto_config)
16 : QuicCryptoStream(session), 19 : QuicCryptoStream(session),
17 next_state_(STATE_IDLE), 20 next_state_(STATE_IDLE),
21 num_client_hellos_(0),
22 config_(config),
23 crypto_config_(crypto_config),
18 decrypter_pushed_(false), 24 decrypter_pushed_(false),
19 server_hostname_(server_hostname) { 25 server_hostname_(server_hostname) {
20 config_.SetDefaults();
21 crypto_config_.SetDefaults();
22 } 26 }
23 27
24 QuicCryptoClientStream::~QuicCryptoClientStream() { 28 QuicCryptoClientStream::~QuicCryptoClientStream() {
25 } 29 }
26 30
27 void QuicCryptoClientStream::OnHandshakeMessage( 31 void QuicCryptoClientStream::OnHandshakeMessage(
28 const CryptoHandshakeMessage& message) { 32 const CryptoHandshakeMessage& message) {
29 DoHandshakeLoop(&message); 33 DoHandshakeLoop(&message);
30 } 34 }
31 35
32 bool QuicCryptoClientStream::CryptoConnect() { 36 bool QuicCryptoClientStream::CryptoConnect() {
33 next_state_ = STATE_SEND_CHLO; 37 next_state_ = STATE_SEND_CHLO;
34 DoHandshakeLoop(NULL); 38 DoHandshakeLoop(NULL);
35 return true; 39 return true;
36 } 40 }
37 41
38 const QuicNegotiatedParameters& 42 const QuicNegotiatedParameters&
39 QuicCryptoClientStream::negotiated_params() const { 43 QuicCryptoClientStream::negotiated_params() const {
40 return negotiated_params_; 44 return negotiated_params_;
41 } 45 }
42 46
43 const QuicCryptoNegotiatedParameters& 47 const QuicCryptoNegotiatedParameters&
44 QuicCryptoClientStream::crypto_negotiated_params() const { 48 QuicCryptoClientStream::crypto_negotiated_params() const {
45 return crypto_negotiated_params_; 49 return crypto_negotiated_params_;
46 } 50 }
47 51
52 // kMaxClientHellos is the maximum number of times that we'll send a client
53 // hello. The value 3 accounts for:
54 // * One failure due to an incorrect or missing source-address token.
55 // * One failure due the server's certificate chain being unavailible and the
56 // server being unwilling to send it without a valid source-address token.
57 static const int kMaxClientHellos = 3;
58
48 void QuicCryptoClientStream::DoHandshakeLoop( 59 void QuicCryptoClientStream::DoHandshakeLoop(
49 const CryptoHandshakeMessage* in) { 60 const CryptoHandshakeMessage* in) {
50 CryptoHandshakeMessage out; 61 CryptoHandshakeMessage out;
51 QuicErrorCode error; 62 QuicErrorCode error;
52 string error_details; 63 string error_details;
53 64
54 if (in != NULL) { 65 if (in != NULL) {
55 DLOG(INFO) << "Client received: " << in->DebugString(); 66 DLOG(INFO) << "Client received: " << in->DebugString();
56 } 67 }
57 68
58 for (;;) { 69 for (;;) {
59 const State state = next_state_; 70 const State state = next_state_;
60 next_state_ = STATE_IDLE; 71 next_state_ = STATE_IDLE;
61 switch (state) { 72 switch (state) {
62 case STATE_SEND_CHLO: { 73 case STATE_SEND_CHLO: {
74 if (num_client_hellos_ > kMaxClientHellos) {
75 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
76 return;
77 }
78 num_client_hellos_++;
79
63 const QuicCryptoClientConfig::CachedState* cached = 80 const QuicCryptoClientConfig::CachedState* cached =
64 crypto_config_.Lookup(server_hostname_); 81 crypto_config_->Lookup(server_hostname_);
65 if (!cached || !cached->is_complete()) { 82 if (!cached || !cached->is_complete()) {
66 crypto_config_.FillInchoateClientHello(server_hostname_, cached, 83 crypto_config_->FillInchoateClientHello(server_hostname_, cached,
67 &out); 84 &out);
68 next_state_ = STATE_RECV_REJ; 85 next_state_ = STATE_RECV_REJ;
69 DLOG(INFO) << "Client Sending: " << out.DebugString(); 86 DLOG(INFO) << "Client Sending: " << out.DebugString();
70 SendHandshakeMessage(out); 87 SendHandshakeMessage(out);
71 return; 88 return;
72 } 89 }
73 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); 90 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
74 config_.ToHandshakeMessage(&out); 91 config_.ToHandshakeMessage(&out);
75 error = crypto_config_.FillClientHello( 92 error = crypto_config_->FillClientHello(
76 server_hostname_, 93 server_hostname_,
77 session()->connection()->guid(), 94 session()->connection()->guid(),
78 cached, 95 cached,
79 session()->connection()->clock(), 96 session()->connection()->clock(),
80 session()->connection()->random_generator(), 97 session()->connection()->random_generator(),
81 &crypto_negotiated_params_, 98 &crypto_negotiated_params_,
82 &out, 99 &out,
83 &error_details); 100 &error_details);
84 if (error != QUIC_NO_ERROR) { 101 if (error != QUIC_NO_ERROR) {
85 CloseConnectionWithDetails(error, error_details); 102 CloseConnectionWithDetails(error, error_details);
86 return; 103 return;
87 } 104 }
88 error = config_.ProcessFinalPeerHandshake( 105 error = config_.ProcessFinalPeerHandshake(
89 *scfg, CryptoUtils::PEER_PRIORITY, &negotiated_params_, 106 *scfg, CryptoUtils::PEER_PRIORITY, &negotiated_params_,
90 &error_details); 107 &error_details);
91 if (error != QUIC_NO_ERROR) { 108 if (error != QUIC_NO_ERROR) {
92 CloseConnectionWithDetails(error, error_details); 109 CloseConnectionWithDetails(error, error_details);
93 return; 110 return;
94 } 111 }
95 next_state_ = STATE_RECV_SHLO; 112 next_state_ = STATE_RECV_SHLO;
96 DLOG(INFO) << "Client Sending: " << out.DebugString(); 113 DLOG(INFO) << "Client Sending: " << out.DebugString();
97 SendHandshakeMessage(out); 114 SendHandshakeMessage(out);
98 // Be prepared to decrypt with the new server write key. 115 // Be prepared to decrypt with the new server write key.
99 session()->connection()->PushDecrypter( 116 session()->connection()->PushDecrypter(
100 crypto_negotiated_params_.decrypter.release()); 117 crypto_negotiated_params_.decrypter.release());
101 decrypter_pushed_ = true; 118 decrypter_pushed_ = true;
102 return; 119 return;
103 } 120 }
104 case STATE_RECV_REJ: 121 case STATE_RECV_REJ:
105 // We sent a dummy CHLO because we don't have enough information to 122 // We sent a dummy CHLO because we didn't have enough information to
106 // perform a handshake. Here we hope to have a REJ that contains the 123 // perform a handshake, or we sent a full hello that the server
107 // information that we need. 124 // rejected. Here we hope to have a REJ that contains the information
125 // that we need.
108 if (in->tag() != kREJ) { 126 if (in->tag() != kREJ) {
109 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, 127 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
110 "Expected REJ"); 128 "Expected REJ");
111 return; 129 return;
112 } 130 }
113 error = crypto_config_.ProcessRejection(server_hostname_, *in, 131 error = crypto_config_->ProcessRejection(server_hostname_, *in,
114 &error_details); 132 &crypto_negotiated_params_,
133 &error_details);
115 if (error != QUIC_NO_ERROR) { 134 if (error != QUIC_NO_ERROR) {
116 CloseConnectionWithDetails(error, error_details); 135 CloseConnectionWithDetails(error, error_details);
117 return; 136 return;
118 } 137 }
119 // Clear any new server write key that we may have set before. 138 // Clear any new server write key that we may have set before.
120 if (decrypter_pushed_) { 139 if (decrypter_pushed_) {
121 session()->connection()->PopDecrypter(); 140 session()->connection()->PopDecrypter();
122 decrypter_pushed_ = false; 141 decrypter_pushed_ = false;
123 } 142 }
124 next_state_ = STATE_SEND_CHLO; 143 next_state_ = STATE_SEND_CHLO;
125 break; 144 break;
126 case STATE_RECV_SHLO: 145 case STATE_RECV_SHLO:
127 // We sent a CHLO that we expected to be accepted and now we're hoping 146 // We sent a CHLO that we expected to be accepted and now we're hoping
128 // for a SHLO from the server to confirm that. 147 // for a SHLO from the server to confirm that.
148 if (in->tag() == kREJ) {
149 next_state_ = STATE_RECV_REJ;
150 break;
151 }
129 if (in->tag() != kSHLO) { 152 if (in->tag() != kSHLO) {
130 // TODO(agl): in the future we would attempt the handshake again.
131 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, 153 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
132 "Expected SHLO"); 154 "Expected SHLO or REJ");
133 return; 155 return;
134 } 156 }
135 // Receiving SHLO implies the server must have processed our full 157 // Receiving SHLO implies the server must have processed our full
136 // CHLO and is ready to decrypt with the new client write key. We 158 // CHLO and is ready to decrypt with the new client write key. We
137 // can start to encrypt with the new client write key. 159 // can start to encrypt with the new client write key.
138 // TODO(wtc): when we support 0-RTT, we will need to change the 160 // TODO(wtc): when we support 0-RTT, we will need to change the
139 // encrypter when we send a full CHLO because we will be sending 161 // encrypter when we send a full CHLO because we will be sending
140 // application data immediately after. 162 // application data immediately after.
141 session()->connection()->ChangeEncrypter( 163 session()->connection()->ChangeEncrypter(
142 crypto_negotiated_params_.encrypter.release()); 164 crypto_negotiated_params_.encrypter.release());
143 SetHandshakeComplete(QUIC_NO_ERROR); 165 SetHandshakeComplete(QUIC_NO_ERROR);
144 return; 166 return;
145 case STATE_IDLE: 167 case STATE_IDLE:
146 // This means that the peer sent us a message that we weren't expecting. 168 // This means that the peer sent us a message that we weren't expecting.
147 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); 169 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
148 return; 170 return;
149 } 171 }
150 } 172 }
151 } 173 }
152 174
153 } // namespace net 175 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_crypto_client_stream.h ('k') | net/quic/quic_crypto_client_stream_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698