| 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 |