| 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 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 // The ProofVerifier owns this object and will delete it when this method | 37 // The ProofVerifier owns this object and will delete it when this method |
| 38 // returns. | 38 // returns. |
| 39 } | 39 } |
| 40 | 40 |
| 41 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { | 41 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { |
| 42 stream_ = NULL; | 42 stream_ = NULL; |
| 43 } | 43 } |
| 44 | 44 |
| 45 QuicCryptoClientStream::QuicCryptoClientStream( | 45 QuicCryptoClientStream::QuicCryptoClientStream( |
| 46 const QuicSessionKey& server_key, | 46 const QuicServerId& server_id, |
| 47 QuicClientSessionBase* session, | 47 QuicClientSessionBase* session, |
| 48 ProofVerifyContext* verify_context, | 48 ProofVerifyContext* verify_context, |
| 49 QuicCryptoClientConfig* crypto_config) | 49 QuicCryptoClientConfig* crypto_config) |
| 50 : QuicCryptoStream(session), | 50 : QuicCryptoStream(session), |
| 51 next_state_(STATE_IDLE), | 51 next_state_(STATE_IDLE), |
| 52 num_client_hellos_(0), | 52 num_client_hellos_(0), |
| 53 crypto_config_(crypto_config), | 53 crypto_config_(crypto_config), |
| 54 server_key_(server_key), | 54 server_id_(server_id), |
| 55 generation_counter_(0), | 55 generation_counter_(0), |
| 56 proof_verify_callback_(NULL), | 56 proof_verify_callback_(NULL), |
| 57 verify_context_(verify_context) { | 57 verify_context_(verify_context) { |
| 58 } | 58 } |
| 59 | 59 |
| 60 QuicCryptoClientStream::~QuicCryptoClientStream() { | 60 QuicCryptoClientStream::~QuicCryptoClientStream() { |
| 61 if (proof_verify_callback_) { | 61 if (proof_verify_callback_) { |
| 62 proof_verify_callback_->Cancel(); | 62 proof_verify_callback_->Cancel(); |
| 63 } | 63 } |
| 64 } | 64 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 86 // * One failure due the server's certificate chain being unavailible and the | 86 // * One failure due the server's certificate chain being unavailible and the |
| 87 // server being unwilling to send it without a valid source-address token. | 87 // server being unwilling to send it without a valid source-address token. |
| 88 static const int kMaxClientHellos = 3; | 88 static const int kMaxClientHellos = 3; |
| 89 | 89 |
| 90 void QuicCryptoClientStream::DoHandshakeLoop( | 90 void QuicCryptoClientStream::DoHandshakeLoop( |
| 91 const CryptoHandshakeMessage* in) { | 91 const CryptoHandshakeMessage* in) { |
| 92 CryptoHandshakeMessage out; | 92 CryptoHandshakeMessage out; |
| 93 QuicErrorCode error; | 93 QuicErrorCode error; |
| 94 string error_details; | 94 string error_details; |
| 95 QuicCryptoClientConfig::CachedState* cached = | 95 QuicCryptoClientConfig::CachedState* cached = |
| 96 crypto_config_->LookupOrCreate(server_key_); | 96 crypto_config_->LookupOrCreate(server_id_); |
| 97 | 97 |
| 98 if (in != NULL) { | 98 if (in != NULL) { |
| 99 DVLOG(1) << "Client: Received " << in->DebugString(); | 99 DVLOG(1) << "Client: Received " << in->DebugString(); |
| 100 } | 100 } |
| 101 | 101 |
| 102 for (;;) { | 102 for (;;) { |
| 103 const State state = next_state_; | 103 const State state = next_state_; |
| 104 next_state_ = STATE_IDLE; | 104 next_state_ = STATE_IDLE; |
| 105 switch (state) { | 105 switch (state) { |
| 106 case STATE_INITIALIZE: { | 106 case STATE_INITIALIZE: { |
| 107 if (!cached->IsEmpty() && !cached->signature().empty() && | 107 if (!cached->IsEmpty() && !cached->signature().empty() && |
| 108 server_key_.is_https()) { | 108 server_id_.is_https()) { |
| 109 DCHECK(crypto_config_->proof_verifier()); | 109 DCHECK(crypto_config_->proof_verifier()); |
| 110 // If the cached state needs to be verified, do it now. | 110 // If the cached state needs to be verified, do it now. |
| 111 next_state_ = STATE_VERIFY_PROOF; | 111 next_state_ = STATE_VERIFY_PROOF; |
| 112 } else { | 112 } else { |
| 113 next_state_ = STATE_SEND_CHLO; | 113 next_state_ = STATE_SEND_CHLO; |
| 114 } | 114 } |
| 115 break; | 115 break; |
| 116 } | 116 } |
| 117 case STATE_SEND_CHLO: { | 117 case STATE_SEND_CHLO: { |
| 118 // Send the client hello in plaintext. | 118 // Send the client hello in plaintext. |
| 119 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); | 119 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); |
| 120 if (num_client_hellos_ > kMaxClientHellos) { | 120 if (num_client_hellos_ > kMaxClientHellos) { |
| 121 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); | 121 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); |
| 122 return; | 122 return; |
| 123 } | 123 } |
| 124 num_client_hellos_++; | 124 num_client_hellos_++; |
| 125 | 125 |
| 126 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { | 126 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { |
| 127 crypto_config_->FillInchoateClientHello( | 127 crypto_config_->FillInchoateClientHello( |
| 128 server_key_, | 128 server_id_, |
| 129 session()->connection()->supported_versions().front(), | 129 session()->connection()->supported_versions().front(), |
| 130 cached, &crypto_negotiated_params_, &out); | 130 cached, |
| 131 &crypto_negotiated_params_, |
| 132 &out); |
| 131 // Pad the inchoate client hello to fill up a packet. | 133 // Pad the inchoate client hello to fill up a packet. |
| 132 const size_t kFramingOverhead = 50; // A rough estimate. | 134 const size_t kFramingOverhead = 50; // A rough estimate. |
| 133 const size_t max_packet_size = | 135 const size_t max_packet_size = |
| 134 session()->connection()->options()->max_packet_length; | 136 session()->connection()->options()->max_packet_length; |
| 135 if (max_packet_size <= kFramingOverhead) { | 137 if (max_packet_size <= kFramingOverhead) { |
| 136 DLOG(DFATAL) << "max_packet_length (" << max_packet_size | 138 DLOG(DFATAL) << "max_packet_length (" << max_packet_size |
| 137 << ") has no room for framing overhead."; | 139 << ") has no room for framing overhead."; |
| 138 CloseConnection(QUIC_INTERNAL_ERROR); | 140 CloseConnection(QUIC_INTERNAL_ERROR); |
| 139 return; | 141 return; |
| 140 } | 142 } |
| 141 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { | 143 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { |
| 142 DLOG(DFATAL) << "Client hello won't fit in a single packet."; | 144 DLOG(DFATAL) << "Client hello won't fit in a single packet."; |
| 143 CloseConnection(QUIC_INTERNAL_ERROR); | 145 CloseConnection(QUIC_INTERNAL_ERROR); |
| 144 return; | 146 return; |
| 145 } | 147 } |
| 146 out.set_minimum_size(max_packet_size - kFramingOverhead); | 148 out.set_minimum_size(max_packet_size - kFramingOverhead); |
| 147 next_state_ = STATE_RECV_REJ; | 149 next_state_ = STATE_RECV_REJ; |
| 148 DVLOG(1) << "Client: Sending " << out.DebugString(); | 150 DVLOG(1) << "Client: Sending " << out.DebugString(); |
| 149 SendHandshakeMessage(out); | 151 SendHandshakeMessage(out); |
| 150 return; | 152 return; |
| 151 } | 153 } |
| 152 session()->config()->ToHandshakeMessage(&out); | 154 session()->config()->ToHandshakeMessage(&out); |
| 153 error = crypto_config_->FillClientHello( | 155 error = crypto_config_->FillClientHello( |
| 154 server_key_, | 156 server_id_, |
| 155 session()->connection()->connection_id(), | 157 session()->connection()->connection_id(), |
| 156 session()->connection()->supported_versions().front(), | 158 session()->connection()->supported_versions().front(), |
| 157 session()->connection()->max_flow_control_receive_window_bytes(), | 159 session()->connection()->max_flow_control_receive_window_bytes(), |
| 158 cached, | 160 cached, |
| 159 session()->connection()->clock()->WallNow(), | 161 session()->connection()->clock()->WallNow(), |
| 160 session()->connection()->random_generator(), | 162 session()->connection()->random_generator(), |
| 161 &crypto_negotiated_params_, | 163 &crypto_negotiated_params_, |
| 162 &out, | 164 &out, |
| 163 &error_details); | 165 &error_details); |
| 164 if (error != QUIC_NO_ERROR) { | 166 if (error != QUIC_NO_ERROR) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 return; | 209 return; |
| 208 } | 210 } |
| 209 error = crypto_config_->ProcessRejection( | 211 error = crypto_config_->ProcessRejection( |
| 210 *in, session()->connection()->clock()->WallNow(), cached, | 212 *in, session()->connection()->clock()->WallNow(), cached, |
| 211 &crypto_negotiated_params_, &error_details); | 213 &crypto_negotiated_params_, &error_details); |
| 212 if (error != QUIC_NO_ERROR) { | 214 if (error != QUIC_NO_ERROR) { |
| 213 CloseConnectionWithDetails(error, error_details); | 215 CloseConnectionWithDetails(error, error_details); |
| 214 return; | 216 return; |
| 215 } | 217 } |
| 216 if (!cached->proof_valid()) { | 218 if (!cached->proof_valid()) { |
| 217 if (!server_key_.is_https()) { | 219 if (!server_id_.is_https()) { |
| 218 // We don't check the certificates for insecure QUIC connections. | 220 // We don't check the certificates for insecure QUIC connections. |
| 219 SetCachedProofValid(cached); | 221 SetCachedProofValid(cached); |
| 220 } else if (!cached->signature().empty()) { | 222 } else if (!cached->signature().empty()) { |
| 221 next_state_ = STATE_VERIFY_PROOF; | 223 next_state_ = STATE_VERIFY_PROOF; |
| 222 break; | 224 break; |
| 223 } | 225 } |
| 224 } | 226 } |
| 225 next_state_ = STATE_SEND_CHLO; | 227 next_state_ = STATE_SEND_CHLO; |
| 226 break; | 228 break; |
| 227 case STATE_VERIFY_PROOF: { | 229 case STATE_VERIFY_PROOF: { |
| 228 ProofVerifier* verifier = crypto_config_->proof_verifier(); | 230 ProofVerifier* verifier = crypto_config_->proof_verifier(); |
| 229 DCHECK(verifier); | 231 DCHECK(verifier); |
| 230 next_state_ = STATE_VERIFY_PROOF_COMPLETE; | 232 next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
| 231 generation_counter_ = cached->generation_counter(); | 233 generation_counter_ = cached->generation_counter(); |
| 232 | 234 |
| 233 ProofVerifierCallbackImpl* proof_verify_callback = | 235 ProofVerifierCallbackImpl* proof_verify_callback = |
| 234 new ProofVerifierCallbackImpl(this); | 236 new ProofVerifierCallbackImpl(this); |
| 235 | 237 |
| 236 verify_ok_ = false; | 238 verify_ok_ = false; |
| 237 | 239 |
| 238 ProofVerifier::Status status = verifier->VerifyProof( | 240 ProofVerifier::Status status = verifier->VerifyProof( |
| 239 server_key_.host(), | 241 server_id_.host(), |
| 240 cached->server_config(), | 242 cached->server_config(), |
| 241 cached->certs(), | 243 cached->certs(), |
| 242 cached->signature(), | 244 cached->signature(), |
| 243 verify_context_.get(), | 245 verify_context_.get(), |
| 244 &verify_error_details_, | 246 &verify_error_details_, |
| 245 &verify_details_, | 247 &verify_details_, |
| 246 proof_verify_callback); | 248 proof_verify_callback); |
| 247 | 249 |
| 248 switch (status) { | 250 switch (status) { |
| 249 case ProofVerifier::PENDING: | 251 case ProofVerifier::PENDING: |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 QuicCryptoClientConfig::CachedState* cached) { | 354 QuicCryptoClientConfig::CachedState* cached) { |
| 353 cached->SetProofValid(); | 355 cached->SetProofValid(); |
| 354 client_session()->OnProofValid(*cached); | 356 client_session()->OnProofValid(*cached); |
| 355 } | 357 } |
| 356 | 358 |
| 357 QuicClientSessionBase* QuicCryptoClientStream::client_session() { | 359 QuicClientSessionBase* QuicCryptoClientStream::client_session() { |
| 358 return reinterpret_cast<QuicClientSessionBase*>(session()); | 360 return reinterpret_cast<QuicClientSessionBase*>(session()); |
| 359 } | 361 } |
| 360 | 362 |
| 361 } // namespace net | 363 } // namespace net |
| OLD | NEW |