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/base/completion_callback.h" | 7 #include "net/base/completion_callback.h" |
8 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" |
9 #include "net/quic/crypto/crypto_protocol.h" | 9 #include "net/quic/crypto/crypto_protocol.h" |
10 #include "net/quic/crypto/crypto_utils.h" | 10 #include "net/quic/crypto/crypto_utils.h" |
11 #include "net/quic/crypto/null_encrypter.h" | 11 #include "net/quic/crypto/null_encrypter.h" |
12 #include "net/quic/crypto/proof_verifier.h" | 12 #include "net/quic/crypto/proof_verifier.h" |
| 13 #include "net/quic/crypto/proof_verifier_chromium.h" |
13 #include "net/quic/quic_protocol.h" | 14 #include "net/quic/quic_protocol.h" |
14 #include "net/quic/quic_session.h" | 15 #include "net/quic/quic_session.h" |
15 #include "net/ssl/ssl_connection_status_flags.h" | 16 #include "net/ssl/ssl_connection_status_flags.h" |
16 #include "net/ssl/ssl_info.h" | 17 #include "net/ssl/ssl_info.h" |
17 | 18 |
18 namespace net { | 19 namespace net { |
19 | 20 |
| 21 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( |
| 22 QuicCryptoClientStream* stream) |
| 23 : stream_(stream) {} |
| 24 |
| 25 QuicCryptoClientStream::ProofVerifierCallbackImpl:: |
| 26 ~ProofVerifierCallbackImpl() {} |
| 27 |
| 28 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( |
| 29 bool ok, |
| 30 const string& error_details, |
| 31 scoped_ptr<ProofVerifyDetails>* details) { |
| 32 if (stream_ == NULL) { |
| 33 return; |
| 34 } |
| 35 |
| 36 stream_->verify_ok_ = ok; |
| 37 stream_->verify_error_details_ = error_details; |
| 38 stream_->verify_details_.reset(details->release()); |
| 39 stream_->proof_verify_callback_ = NULL; |
| 40 stream_->DoHandshakeLoop(NULL); |
| 41 |
| 42 // The ProofVerifier owns this object and will delete it when this method |
| 43 // returns. |
| 44 } |
| 45 |
| 46 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { |
| 47 stream_ = NULL; |
| 48 } |
| 49 |
| 50 |
20 QuicCryptoClientStream::QuicCryptoClientStream( | 51 QuicCryptoClientStream::QuicCryptoClientStream( |
21 const string& server_hostname, | 52 const string& server_hostname, |
22 QuicSession* session, | 53 QuicSession* session, |
23 QuicCryptoClientConfig* crypto_config) | 54 QuicCryptoClientConfig* crypto_config) |
24 : QuicCryptoStream(session), | 55 : QuicCryptoStream(session), |
25 weak_factory_(this), | |
26 next_state_(STATE_IDLE), | 56 next_state_(STATE_IDLE), |
27 num_client_hellos_(0), | 57 num_client_hellos_(0), |
28 crypto_config_(crypto_config), | 58 crypto_config_(crypto_config), |
29 server_hostname_(server_hostname), | 59 server_hostname_(server_hostname), |
30 generation_counter_(0) { | 60 generation_counter_(0), |
| 61 proof_verify_callback_(NULL) { |
31 } | 62 } |
32 | 63 |
33 QuicCryptoClientStream::~QuicCryptoClientStream() { | 64 QuicCryptoClientStream::~QuicCryptoClientStream() { |
| 65 if (proof_verify_callback_) { |
| 66 proof_verify_callback_->Cancel(); |
| 67 } |
34 } | 68 } |
35 | 69 |
36 void QuicCryptoClientStream::OnHandshakeMessage( | 70 void QuicCryptoClientStream::OnHandshakeMessage( |
37 const CryptoHandshakeMessage& message) { | 71 const CryptoHandshakeMessage& message) { |
38 DoHandshakeLoop(&message, OK); | 72 DoHandshakeLoop(&message); |
39 } | 73 } |
40 | 74 |
41 bool QuicCryptoClientStream::CryptoConnect() { | 75 bool QuicCryptoClientStream::CryptoConnect() { |
42 next_state_ = STATE_SEND_CHLO; | 76 next_state_ = STATE_SEND_CHLO; |
43 DoHandshakeLoop(NULL, OK); | 77 DoHandshakeLoop(NULL); |
44 return true; | 78 return true; |
45 } | 79 } |
46 | 80 |
47 int QuicCryptoClientStream::num_sent_client_hellos() const { | 81 int QuicCryptoClientStream::num_sent_client_hellos() const { |
48 return num_client_hellos_; | 82 return num_client_hellos_; |
49 } | 83 } |
50 | 84 |
51 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { | 85 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { |
52 ssl_info->Reset(); | 86 ssl_info->Reset(); |
53 QuicCryptoClientConfig::CachedState* cached = | 87 QuicCryptoClientConfig::CachedState* cached = |
54 crypto_config_->LookupOrCreate(server_hostname_); | 88 crypto_config_->LookupOrCreate(server_hostname_); |
55 DCHECK(cached); | 89 DCHECK(cached); |
56 if (!cached) { | 90 if (!cached) { |
57 return false; | 91 return false; |
58 } | 92 } |
59 const CertVerifyResult* cert_verify_result = | 93 const CertVerifyResult* cert_verify_result = |
60 cached->cert_verify_result(); | 94 &(reinterpret_cast<const ProofVerifyDetailsChromium*>( |
| 95 cached->proof_verify_details()))->cert_verify_result; |
61 | 96 |
62 ssl_info->cert_status = cert_verify_result->cert_status; | 97 ssl_info->cert_status = cert_verify_result->cert_status; |
63 ssl_info->cert = cert_verify_result->verified_cert; | 98 ssl_info->cert = cert_verify_result->verified_cert; |
64 | 99 |
65 // TODO(rtenneti): Figure out what to set for the following. | 100 // TODO(rtenneti): Figure out what to set for the following. |
66 // Temporarily hard coded cipher_suite as 0xc031 to represent | 101 // Temporarily hard coded cipher_suite as 0xc031 to represent |
67 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from | 102 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from |
68 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256. | 103 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256. |
69 int cipher_suite = 0xc02f; | 104 int cipher_suite = 0xc02f; |
70 int ssl_connection_status = 0; | 105 int ssl_connection_status = 0; |
(...skipping 17 matching lines...) Expand all Loading... |
88 } | 123 } |
89 | 124 |
90 // kMaxClientHellos is the maximum number of times that we'll send a client | 125 // kMaxClientHellos is the maximum number of times that we'll send a client |
91 // hello. The value 3 accounts for: | 126 // hello. The value 3 accounts for: |
92 // * One failure due to an incorrect or missing source-address token. | 127 // * One failure due to an incorrect or missing source-address token. |
93 // * One failure due the server's certificate chain being unavailible and the | 128 // * One failure due the server's certificate chain being unavailible and the |
94 // server being unwilling to send it without a valid source-address token. | 129 // server being unwilling to send it without a valid source-address token. |
95 static const int kMaxClientHellos = 3; | 130 static const int kMaxClientHellos = 3; |
96 | 131 |
97 void QuicCryptoClientStream::DoHandshakeLoop( | 132 void QuicCryptoClientStream::DoHandshakeLoop( |
98 const CryptoHandshakeMessage* in, | 133 const CryptoHandshakeMessage* in) { |
99 int result) { | |
100 CryptoHandshakeMessage out; | 134 CryptoHandshakeMessage out; |
101 QuicErrorCode error; | 135 QuicErrorCode error; |
102 string error_details; | 136 string error_details; |
103 QuicCryptoClientConfig::CachedState* cached = | 137 QuicCryptoClientConfig::CachedState* cached = |
104 crypto_config_->LookupOrCreate(server_hostname_); | 138 crypto_config_->LookupOrCreate(server_hostname_); |
105 | 139 |
106 if (in != NULL) { | 140 if (in != NULL) { |
107 DVLOG(1) << "Client received: " << in->DebugString(); | 141 DVLOG(1) << "Client received: " << in->DebugString(); |
108 } | 142 } |
109 | 143 |
110 for (;;) { | 144 for (;;) { |
111 const State state = next_state_; | 145 const State state = next_state_; |
112 next_state_ = STATE_IDLE; | 146 next_state_ = STATE_IDLE; |
113 switch (state) { | 147 switch (state) { |
114 case STATE_SEND_CHLO: { | 148 case STATE_SEND_CHLO: { |
115 DCHECK_EQ(OK, result); | |
116 // Send the client hello in plaintext. | 149 // Send the client hello in plaintext. |
117 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); | 150 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); |
118 if (num_client_hellos_ > kMaxClientHellos) { | 151 if (num_client_hellos_ > kMaxClientHellos) { |
119 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); | 152 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); |
120 return; | 153 return; |
121 } | 154 } |
122 num_client_hellos_++; | 155 num_client_hellos_++; |
123 | 156 |
124 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { | 157 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { |
125 crypto_config_->FillInchoateClientHello( | 158 crypto_config_->FillInchoateClientHello( |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 encryption_established_ = true; | 197 encryption_established_ = true; |
165 session()->OnCryptoHandshakeEvent( | 198 session()->OnCryptoHandshakeEvent( |
166 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); | 199 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); |
167 } else { | 200 } else { |
168 session()->OnCryptoHandshakeEvent( | 201 session()->OnCryptoHandshakeEvent( |
169 QuicSession::ENCRYPTION_REESTABLISHED); | 202 QuicSession::ENCRYPTION_REESTABLISHED); |
170 } | 203 } |
171 return; | 204 return; |
172 } | 205 } |
173 case STATE_RECV_REJ: | 206 case STATE_RECV_REJ: |
174 DCHECK_EQ(OK, result); | |
175 // We sent a dummy CHLO because we didn't have enough information to | 207 // We sent a dummy CHLO because we didn't have enough information to |
176 // perform a handshake, or we sent a full hello that the server | 208 // perform a handshake, or we sent a full hello that the server |
177 // rejected. Here we hope to have a REJ that contains the information | 209 // rejected. Here we hope to have a REJ that contains the information |
178 // that we need. | 210 // that we need. |
179 if (in->tag() != kREJ) { | 211 if (in->tag() != kREJ) { |
180 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, | 212 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, |
181 "Expected REJ"); | 213 "Expected REJ"); |
182 return; | 214 return; |
183 } | 215 } |
184 error = crypto_config_->ProcessRejection( | 216 error = crypto_config_->ProcessRejection( |
(...skipping 13 matching lines...) Expand all Loading... |
198 break; | 230 break; |
199 } | 231 } |
200 } | 232 } |
201 next_state_ = STATE_SEND_CHLO; | 233 next_state_ = STATE_SEND_CHLO; |
202 break; | 234 break; |
203 case STATE_VERIFY_PROOF: { | 235 case STATE_VERIFY_PROOF: { |
204 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 236 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
205 DCHECK(verifier); | 237 DCHECK(verifier); |
206 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | 238 next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
207 generation_counter_ = cached->generation_counter(); | 239 generation_counter_ = cached->generation_counter(); |
208 result = verifier->VerifyProof( | 240 |
| 241 ProofVerifierCallbackImpl* proof_verify_callback = |
| 242 new ProofVerifierCallbackImpl(this); |
| 243 |
| 244 verify_ok_ = false; |
| 245 |
| 246 ProofVerifier::Status status = verifier->VerifyProof( |
209 server_hostname_, | 247 server_hostname_, |
210 cached->server_config(), | 248 cached->server_config(), |
211 cached->certs(), | 249 cached->certs(), |
212 cached->signature(), | 250 cached->signature(), |
213 &error_details_, | 251 &error_details, |
214 &cert_verify_result_, | 252 &verify_details_, |
215 base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete, | 253 proof_verify_callback); |
216 weak_factory_.GetWeakPtr())); | 254 |
217 if (result == ERR_IO_PENDING) { | 255 switch (status) { |
218 DVLOG(1) << "Doing VerifyProof"; | 256 case ProofVerifier::PENDING: |
219 return; | 257 proof_verify_callback_ = proof_verify_callback; |
| 258 DVLOG(1) << "Doing VerifyProof"; |
| 259 return; |
| 260 case ProofVerifier::FAILURE: |
| 261 CloseConnectionWithDetails( |
| 262 QUIC_PROOF_INVALID, "Proof invalid: " + error_details); |
| 263 return; |
| 264 case ProofVerifier::SUCCESS: |
| 265 verify_ok_ = true; |
| 266 break; |
220 } | 267 } |
221 break; | 268 break; |
222 } | 269 } |
223 case STATE_VERIFY_PROOF_COMPLETE: | 270 case STATE_VERIFY_PROOF_COMPLETE: |
224 if (result != OK) { | 271 if (!verify_ok_) { |
225 CloseConnectionWithDetails( | 272 CloseConnectionWithDetails( |
226 QUIC_PROOF_INVALID, "Proof invalid: " + error_details_); | 273 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); |
227 return; | 274 return; |
228 } | 275 } |
229 // Check if generation_counter has changed between STATE_VERIFY_PROOF | 276 // Check if generation_counter has changed between STATE_VERIFY_PROOF |
230 // and STATE_VERIFY_PROOF_COMPLETE state changes. | 277 // and STATE_VERIFY_PROOF_COMPLETE state changes. |
231 if (generation_counter_ != cached->generation_counter()) { | 278 if (generation_counter_ != cached->generation_counter()) { |
232 next_state_ = STATE_VERIFY_PROOF; | 279 next_state_ = STATE_VERIFY_PROOF; |
233 } else { | 280 } else { |
234 cached->SetProofValid(); | 281 cached->SetProofValid(); |
235 cached->SetCertVerifyResult(cert_verify_result_); | 282 cached->SetProofVerifyDetails(verify_details_.release()); |
236 next_state_ = STATE_SEND_CHLO; | 283 next_state_ = STATE_SEND_CHLO; |
237 } | 284 } |
238 break; | 285 break; |
239 case STATE_RECV_SHLO: { | 286 case STATE_RECV_SHLO: { |
240 // We sent a CHLO that we expected to be accepted and now we're hoping | 287 // We sent a CHLO that we expected to be accepted and now we're hoping |
241 // for a SHLO from the server to confirm that. | 288 // for a SHLO from the server to confirm that. |
242 if (in->tag() == kREJ) { | 289 if (in->tag() == kREJ) { |
243 // alternative_decrypter will be NULL if the original alternative | 290 // alternative_decrypter will be NULL if the original alternative |
244 // decrypter latched and became the primary decrypter. That happens | 291 // decrypter latched and became the primary decrypter. That happens |
245 // if we received a message encrypted with the INITIAL key. | 292 // if we received a message encrypted with the INITIAL key. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 return; | 345 return; |
299 } | 346 } |
300 case STATE_IDLE: | 347 case STATE_IDLE: |
301 // This means that the peer sent us a message that we weren't expecting. | 348 // This means that the peer sent us a message that we weren't expecting. |
302 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | 349 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); |
303 return; | 350 return; |
304 } | 351 } |
305 } | 352 } |
306 } | 353 } |
307 | 354 |
308 void QuicCryptoClientStream::OnVerifyProofComplete(int result) { | |
309 DCHECK_EQ(STATE_VERIFY_PROOF_COMPLETE, next_state_); | |
310 DVLOG(1) << "VerifyProof completed: " << result; | |
311 DoHandshakeLoop(NULL, result); | |
312 } | |
313 | |
314 } // namespace net | 355 } // namespace net |
OLD | NEW |