OLD | NEW |
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/crypto/null_encrypter.h" | 9 #include "net/quic/crypto/null_encrypter.h" |
10 #include "net/quic/crypto/proof_verifier.h" | 10 #include "net/quic/crypto/proof_verifier.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 const CryptoHandshakeMessage& message) { | 33 const CryptoHandshakeMessage& message) { |
34 DoHandshakeLoop(&message); | 34 DoHandshakeLoop(&message); |
35 } | 35 } |
36 | 36 |
37 bool QuicCryptoClientStream::CryptoConnect() { | 37 bool QuicCryptoClientStream::CryptoConnect() { |
38 next_state_ = STATE_SEND_CHLO; | 38 next_state_ = STATE_SEND_CHLO; |
39 DoHandshakeLoop(NULL); | 39 DoHandshakeLoop(NULL); |
40 return true; | 40 return true; |
41 } | 41 } |
42 | 42 |
43 const QuicNegotiatedParameters& | |
44 QuicCryptoClientStream::negotiated_params() const { | |
45 return negotiated_params_; | |
46 } | |
47 | |
48 const QuicCryptoNegotiatedParameters& | |
49 QuicCryptoClientStream::crypto_negotiated_params() const { | |
50 return crypto_negotiated_params_; | |
51 } | |
52 | |
53 int QuicCryptoClientStream::num_sent_client_hellos() const { | 43 int QuicCryptoClientStream::num_sent_client_hellos() const { |
54 return num_client_hellos_; | 44 return num_client_hellos_; |
55 } | 45 } |
56 | 46 |
57 // kMaxClientHellos is the maximum number of times that we'll send a client | 47 // kMaxClientHellos is the maximum number of times that we'll send a client |
58 // hello. The value 3 accounts for: | 48 // hello. The value 3 accounts for: |
59 // * One failure due to an incorrect or missing source-address token. | 49 // * One failure due to an incorrect or missing source-address token. |
60 // * One failure due the server's certificate chain being unavailible and the | 50 // * One failure due the server's certificate chain being unavailible and the |
61 // server being unwilling to send it without a valid source-address token. | 51 // server being unwilling to send it without a valid source-address token. |
62 static const int kMaxClientHellos = 3; | 52 static const int kMaxClientHellos = 3; |
(...skipping 28 matching lines...) Expand all Loading... |
91 DLOG(INFO) << "Client Sending: " << out.DebugString(); | 81 DLOG(INFO) << "Client Sending: " << out.DebugString(); |
92 SendHandshakeMessage(out); | 82 SendHandshakeMessage(out); |
93 return; | 83 return; |
94 } | 84 } |
95 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); | 85 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); |
96 config_.ToHandshakeMessage(&out); | 86 config_.ToHandshakeMessage(&out); |
97 error = crypto_config_->FillClientHello( | 87 error = crypto_config_->FillClientHello( |
98 server_hostname_, | 88 server_hostname_, |
99 session()->connection()->guid(), | 89 session()->connection()->guid(), |
100 cached, | 90 cached, |
101 session()->connection()->clock(), | 91 session()->connection()->clock()->WallNow(), |
102 session()->connection()->random_generator(), | 92 session()->connection()->random_generator(), |
103 &crypto_negotiated_params_, | 93 &crypto_negotiated_params_, |
104 &out, | 94 &out, |
105 &error_details); | 95 &error_details); |
106 if (error != QUIC_NO_ERROR) { | 96 if (error != QUIC_NO_ERROR) { |
107 CloseConnectionWithDetails(error, error_details); | 97 CloseConnectionWithDetails(error, error_details); |
108 return; | 98 return; |
109 } | 99 } |
110 error = config_.ProcessFinalPeerHandshake( | 100 error = config_.ProcessFinalPeerHandshake( |
111 *scfg, CryptoUtils::PEER_PRIORITY, &negotiated_params_, | 101 *scfg, CryptoUtils::PEER_PRIORITY, &negotiated_params_, |
112 &error_details); | 102 &error_details); |
113 if (error != QUIC_NO_ERROR) { | 103 if (error != QUIC_NO_ERROR) { |
114 CloseConnectionWithDetails(error, error_details); | 104 CloseConnectionWithDetails(error, error_details); |
115 return; | 105 return; |
116 } | 106 } |
117 next_state_ = STATE_RECV_SHLO; | 107 next_state_ = STATE_RECV_SHLO; |
118 DLOG(INFO) << "Client Sending: " << out.DebugString(); | 108 DLOG(INFO) << "Client Sending: " << out.DebugString(); |
119 SendHandshakeMessage(out); | 109 SendHandshakeMessage(out); |
120 // Be prepared to decrypt with the new server write key. | 110 // Be prepared to decrypt with the new server write key. |
121 session()->connection()->SetAlternativeDecrypter( | 111 session()->connection()->SetAlternativeDecrypter( |
122 crypto_negotiated_params_.decrypter.release(), | 112 crypto_negotiated_params_.initial_crypters.decrypter.release(), |
123 true /* latch once used */); | 113 true /* latch once used */); |
124 // Send subsequent packets under encryption on the assumption that the | 114 // Send subsequent packets under encryption on the assumption that the |
125 // server will accept the handshake. | 115 // server will accept the handshake. |
126 session()->connection()->SetEncrypter( | 116 session()->connection()->SetEncrypter( |
127 ENCRYPTION_INITIAL, | 117 ENCRYPTION_INITIAL, |
128 crypto_negotiated_params_.encrypter.release()); | 118 crypto_negotiated_params_.initial_crypters.encrypter.release()); |
129 session()->connection()->SetDefaultEncryptionLevel( | 119 session()->connection()->SetDefaultEncryptionLevel( |
130 ENCRYPTION_INITIAL); | 120 ENCRYPTION_INITIAL); |
131 if (!encryption_established_) { | 121 if (!encryption_established_) { |
132 session()->OnCryptoHandshakeEvent( | 122 // TODO(agl): the following, commented code should live here and not |
133 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); | 123 // down when the handshake is confirmed. However, it causes |
134 encryption_established_ = true; | 124 // EndToEndTest.LargePost to be flaky (b/8074678), seemingly because |
| 125 // the packets dropped when the client hello is dropped cause the |
| 126 // congestion control to be too conservative and the server times |
| 127 // out. |
| 128 // session()->OnCryptoHandshakeEvent( |
| 129 // QuicSession::ENCRYPTION_FIRST_ESTABLISHED); |
| 130 // encryption_established_ = true; |
135 } else { | 131 } else { |
136 session()->OnCryptoHandshakeEvent( | 132 session()->OnCryptoHandshakeEvent( |
137 QuicSession::ENCRYPTION_REESTABLISHED); | 133 QuicSession::ENCRYPTION_REESTABLISHED); |
138 } | 134 } |
139 return; | 135 return; |
140 } | 136 } |
141 case STATE_RECV_REJ: | 137 case STATE_RECV_REJ: |
142 // We sent a dummy CHLO because we didn't have enough information to | 138 // We sent a dummy CHLO because we didn't have enough information to |
143 // perform a handshake, or we sent a full hello that the server | 139 // perform a handshake, or we sent a full hello that the server |
144 // rejected. Here we hope to have a REJ that contains the information | 140 // rejected. Here we hope to have a REJ that contains the information |
(...skipping 28 matching lines...) Expand all Loading... |
173 return; | 169 return; |
174 } | 170 } |
175 cached->SetProofValid(); | 171 cached->SetProofValid(); |
176 } | 172 } |
177 } | 173 } |
178 // Send the subsequent client hello in plaintext. | 174 // Send the subsequent client hello in plaintext. |
179 session()->connection()->SetDefaultEncryptionLevel( | 175 session()->connection()->SetDefaultEncryptionLevel( |
180 ENCRYPTION_NONE); | 176 ENCRYPTION_NONE); |
181 next_state_ = STATE_SEND_CHLO; | 177 next_state_ = STATE_SEND_CHLO; |
182 break; | 178 break; |
183 case STATE_RECV_SHLO: | 179 case STATE_RECV_SHLO: { |
184 // We sent a CHLO that we expected to be accepted and now we're hoping | 180 // We sent a CHLO that we expected to be accepted and now we're hoping |
185 // for a SHLO from the server to confirm that. | 181 // for a SHLO from the server to confirm that. |
186 if (in->tag() == kREJ) { | 182 if (in->tag() == kREJ) { |
| 183 // alternative_decrypter will be NULL if the original alternative |
| 184 // decrypter latched and became the primary decrypter. That happens |
| 185 // if we received a message encrypted with the INITIAL key. |
| 186 if (session()->connection()->alternative_decrypter() == NULL) { |
| 187 // The rejection was sent encrypted! |
| 188 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, |
| 189 "encrypted REJ message"); |
| 190 return; |
| 191 } |
187 next_state_ = STATE_RECV_REJ; | 192 next_state_ = STATE_RECV_REJ; |
188 break; | 193 break; |
189 } | 194 } |
190 if (in->tag() != kSHLO) { | 195 if (in->tag() != kSHLO) { |
191 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, | 196 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, |
192 "Expected SHLO or REJ"); | 197 "Expected SHLO or REJ"); |
193 return; | 198 return; |
194 } | 199 } |
195 // TODO(agl): enable this once the tests are corrected to permit it. | 200 // alternative_decrypter will be NULL if the original alternative |
196 // DCHECK(session()->connection()->alternative_decrypter() == NULL); | 201 // decrypter latched and became the primary decrypter. That happens |
| 202 // if we received a message encrypted with the INITIAL key. |
| 203 if (session()->connection()->alternative_decrypter() != NULL) { |
| 204 // The server hello was sent without encryption. |
| 205 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, |
| 206 "unencrypted SHLO message"); |
| 207 return; |
| 208 } |
| 209 error = crypto_config_->ProcessServerHello( |
| 210 *in, session()->connection()->guid(), &crypto_negotiated_params_, |
| 211 &error_details); |
| 212 if (error != QUIC_NO_ERROR) { |
| 213 CloseConnectionWithDetails( |
| 214 error, "Server hello invalid: " + error_details); |
| 215 return; |
| 216 } |
| 217 CrypterPair* crypters = |
| 218 &crypto_negotiated_params_.forward_secure_crypters; |
| 219 // TODO(agl): we don't currently latch this decrypter because the idea |
| 220 // has been floated that the server shouldn't send packets encrypted |
| 221 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE |
| 222 // packet from the client. |
| 223 session()->connection()->SetAlternativeDecrypter( |
| 224 crypters->decrypter.release(), false /* don't latch */); |
| 225 session()->connection()->SetEncrypter( |
| 226 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release()); |
| 227 session()->connection()->SetDefaultEncryptionLevel( |
| 228 ENCRYPTION_FORWARD_SECURE); |
| 229 |
| 230 // TODO(agl): this code shouldn't be here. See the TODO further up |
| 231 // about it. |
| 232 session()->OnCryptoHandshakeEvent( |
| 233 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); |
| 234 encryption_established_ = true; |
| 235 |
197 handshake_confirmed_ = true; | 236 handshake_confirmed_ = true; |
198 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); | 237 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); |
199 return; | 238 return; |
| 239 } |
200 case STATE_IDLE: | 240 case STATE_IDLE: |
201 // This means that the peer sent us a message that we weren't expecting. | 241 // This means that the peer sent us a message that we weren't expecting. |
202 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 242 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
203 return; | 243 return; |
204 } | 244 } |
205 } | 245 } |
206 } | 246 } |
207 | 247 |
208 } // namespace net | 248 } // namespace net |
OLD | NEW |