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 3 // found in the LICENSE file. 4 5 #include "net/quic/quic_crypto_client_stream.h" 6 7 #include "net/base/completion_callback.h" 8 #include "net/base/net_errors.h" 9 #include "net/quic/crypto/crypto_protocol.h" 10 #include "net/quic/crypto/crypto_utils.h" 11 #include "net/quic/crypto/null_encrypter.h" 12 #include "net/quic/crypto/proof_verifier.h" 13 #include "net/quic/crypto/proof_verifier_chromium.h" 14 #include "net/quic/quic_protocol.h" 15 #include "net/quic/quic_session.h" 16 #include "net/ssl/ssl_connection_status_flags.h" 17 #include "net/ssl/ssl_info.h" 18 19 namespace net { 20 21 namespace { 22 23 // Copies CertVerifyResult from |verify_details| to |cert_verify_result|. 24 void CopyCertVerifyResult( 25 const ProofVerifyDetails* verify_details, 26 scoped_ptr<CertVerifyResult>* cert_verify_result) { 27 const CertVerifyResult* cert_verify_result_other = 28 &(reinterpret_cast<const ProofVerifyDetailsChromium*>( 29 verify_details))->cert_verify_result; 30 CertVerifyResult* result_copy = new CertVerifyResult; 31 result_copy->CopyFrom(*cert_verify_result_other); 32 cert_verify_result->reset(result_copy); 33 } 34 35 } // namespace 36 37 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( 38 QuicCryptoClientStream* stream) 39 : stream_(stream) {} 40 41 QuicCryptoClientStream::ProofVerifierCallbackImpl:: 42 ~ProofVerifierCallbackImpl() {} 43 44 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( 45 bool ok, 46 const string& error_details, 47 scoped_ptr<ProofVerifyDetails>* details) { 48 if (stream_ == NULL) { 49 return; 50 } 51 52 stream_->verify_ok_ = ok; 53 stream_->verify_error_details_ = error_details; 54 stream_->verify_details_.reset(details->release()); 55 stream_->proof_verify_callback_ = NULL; 56 stream_->DoHandshakeLoop(NULL); 57 58 // The ProofVerifier owns this object and will delete it when this method 59 // returns. 60 } 61 62 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { 63 stream_ = NULL; 64 } 65 66 67 QuicCryptoClientStream::QuicCryptoClientStream( 68 const string& server_hostname, 69 QuicSession* session, 70 QuicCryptoClientConfig* crypto_config) 71 : QuicCryptoStream(session), 72 next_state_(STATE_IDLE), 73 num_client_hellos_(0), 74 crypto_config_(crypto_config), 75 server_hostname_(server_hostname), 76 generation_counter_(0), 77 proof_verify_callback_(NULL) { 78 } 79 80 QuicCryptoClientStream::~QuicCryptoClientStream() { 81 if (proof_verify_callback_) { 82 proof_verify_callback_->Cancel(); 83 } 84 } 85 86 void QuicCryptoClientStream::OnHandshakeMessage( 87 const CryptoHandshakeMessage& message) { 88 QuicCryptoStream::OnHandshakeMessage(message); 89 90 DoHandshakeLoop(&message); 91 } 92 93 bool QuicCryptoClientStream::CryptoConnect() { 94 next_state_ = STATE_SEND_CHLO; 95 DoHandshakeLoop(NULL); 96 return true; 97 } 98 99 int QuicCryptoClientStream::num_sent_client_hellos() const { 100 return num_client_hellos_; 101 } 102 103 // TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways 104 // we learn about SSL info (sync vs async vs cached). 105 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { 106 ssl_info->Reset(); 107 if (!cert_verify_result_) { 108 return false; 109 } 110 111 ssl_info->cert_status = cert_verify_result_->cert_status; 112 ssl_info->cert = cert_verify_result_->verified_cert; 113 114 // TODO(rtenneti): Figure out what to set for the following. 115 // Temporarily hard coded cipher_suite as 0xc031 to represent 116 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from 117 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256. 118 int cipher_suite = 0xc02f; 119 int ssl_connection_status = 0; 120 ssl_connection_status |= 121 (cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) << 122 SSL_CONNECTION_CIPHERSUITE_SHIFT; 123 ssl_connection_status |= 124 (SSL_CONNECTION_VERSION_TLS1_2 & SSL_CONNECTION_VERSION_MASK) << 125 SSL_CONNECTION_VERSION_SHIFT; 126 127 ssl_info->public_key_hashes = cert_verify_result_->public_key_hashes; 128 ssl_info->is_issued_by_known_root = 129 cert_verify_result_->is_issued_by_known_root; 130 131 ssl_info->connection_status = ssl_connection_status; 132 ssl_info->client_cert_sent = false; 133 ssl_info->channel_id_sent = false; 134 ssl_info->security_bits = 256; 135 ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL; 136 return true; 137 } 138 139 // kMaxClientHellos is the maximum number of times that we'll send a client 140 // hello. The value 3 accounts for: 141 // * One failure due to an incorrect or missing source-address token. 142 // * One failure due the server's certificate chain being unavailible and the 143 // server being unwilling to send it without a valid source-address token. 144 static const int kMaxClientHellos = 3; 145 146 void QuicCryptoClientStream::DoHandshakeLoop( 147 const CryptoHandshakeMessage* in) { 148 CryptoHandshakeMessage out; 149 QuicErrorCode error; 150 string error_details; 151 QuicCryptoClientConfig::CachedState* cached = 152 crypto_config_->LookupOrCreate(server_hostname_); 153 154 if (in != NULL) { 155 DVLOG(1) << "Client: Received " << in->DebugString(); 156 } 157 158 for (;;) { 159 const State state = next_state_; 160 next_state_ = STATE_IDLE; 161 switch (state) { 162 case STATE_SEND_CHLO: { 163 // Send the client hello in plaintext. 164 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); 165 if (num_client_hellos_ > kMaxClientHellos) { 166 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); 167 return; 168 } 169 num_client_hellos_++; 170 171 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { 172 crypto_config_->FillInchoateClientHello( 173 server_hostname_, 174 session()->connection()->supported_versions().front(), 175 cached, &crypto_negotiated_params_, &out); 176 // Pad the inchoate client hello to fill up a packet. 177 const size_t kFramingOverhead = 50; // A rough estimate. 178 const size_t max_packet_size = 179 session()->connection()->options()->max_packet_length; 180 if (max_packet_size <= kFramingOverhead) { 181 DLOG(DFATAL) << "max_packet_length (" << max_packet_size 182 << ") has no room for framing overhead."; 183 CloseConnection(QUIC_INTERNAL_ERROR); 184 return; 185 } 186 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) { 187 DLOG(DFATAL) << "Client hello won't fit in a single packet."; 188 CloseConnection(QUIC_INTERNAL_ERROR); 189 return; 190 } 191 out.set_minimum_size(max_packet_size - kFramingOverhead); 192 next_state_ = STATE_RECV_REJ; 193 DVLOG(1) << "Client: Sending " << out.DebugString(); 194 SendHandshakeMessage(out); 195 return; 196 } 197 session()->config()->ToHandshakeMessage(&out); 198 error = crypto_config_->FillClientHello( 199 server_hostname_, 200 session()->connection()->guid(), 201 session()->connection()->supported_versions().front(), 202 cached, 203 session()->connection()->clock()->WallNow(), 204 session()->connection()->random_generator(), 205 &crypto_negotiated_params_, 206 &out, 207 &error_details); 208 if (error != QUIC_NO_ERROR) { 209 // Flush the cached config so that, if it's bad, the server has a 210 // chance to send us another in the future. 211 cached->InvalidateServerConfig(); 212 CloseConnectionWithDetails(error, error_details); 213 return; 214 } 215 if (cached->proof_verify_details()) { 216 CopyCertVerifyResult(cached->proof_verify_details(), 217 &cert_verify_result_); 218 } else { 219 cert_verify_result_.reset(); 220 } 221 next_state_ = STATE_RECV_SHLO; 222 DVLOG(1) << "Client: Sending " << out.DebugString(); 223 SendHandshakeMessage(out); 224 // Be prepared to decrypt with the new server write key. 225 session()->connection()->SetAlternativeDecrypter( 226 crypto_negotiated_params_.initial_crypters.decrypter.release(), 227 true /* latch once used */); 228 // Send subsequent packets under encryption on the assumption that the 229 // server will accept the handshake. 230 session()->connection()->SetEncrypter( 231 ENCRYPTION_INITIAL, 232 crypto_negotiated_params_.initial_crypters.encrypter.release()); 233 session()->connection()->SetDefaultEncryptionLevel( 234 ENCRYPTION_INITIAL); 235 if (!encryption_established_) { 236 encryption_established_ = true; 237 session()->OnCryptoHandshakeEvent( 238 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); 239 } else { 240 session()->OnCryptoHandshakeEvent( 241 QuicSession::ENCRYPTION_REESTABLISHED); 242 } 243 return; 244 } 245 case STATE_RECV_REJ: 246 // We sent a dummy CHLO because we didn't have enough information to 247 // perform a handshake, or we sent a full hello that the server 248 // rejected. Here we hope to have a REJ that contains the information 249 // that we need. 250 if (in->tag() != kREJ) { 251 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, 252 "Expected REJ"); 253 return; 254 } 255 error = crypto_config_->ProcessRejection( 256 *in, session()->connection()->clock()->WallNow(), cached, 257 &crypto_negotiated_params_, &error_details); 258 if (error != QUIC_NO_ERROR) { 259 CloseConnectionWithDetails(error, error_details); 260 return; 261 } 262 if (!cached->proof_valid()) { 263 ProofVerifier* verifier = crypto_config_->proof_verifier(); 264 if (!verifier) { 265 // If no verifier is set then we don't check the certificates. 266 cached->SetProofValid(); 267 } else if (!cached->signature().empty()) { 268 next_state_ = STATE_VERIFY_PROOF; 269 break; 270 } 271 } 272 next_state_ = STATE_SEND_CHLO; 273 break; 274 case STATE_VERIFY_PROOF: { 275 ProofVerifier* verifier = crypto_config_->proof_verifier(); 276 DCHECK(verifier); 277 next_state_ = STATE_VERIFY_PROOF_COMPLETE; 278 generation_counter_ = cached->generation_counter(); 279 280 ProofVerifierCallbackImpl* proof_verify_callback = 281 new ProofVerifierCallbackImpl(this); 282 283 verify_ok_ = false; 284 285 ProofVerifier::Status status = verifier->VerifyProof( 286 server_hostname_, 287 cached->server_config(), 288 cached->certs(), 289 cached->signature(), 290 &verify_error_details_, 291 &verify_details_, 292 proof_verify_callback); 293 294 switch (status) { 295 case ProofVerifier::PENDING: 296 proof_verify_callback_ = proof_verify_callback; 297 DVLOG(1) << "Doing VerifyProof"; 298 return; 299 case ProofVerifier::FAILURE: 300 break; 301 case ProofVerifier::SUCCESS: 302 verify_ok_ = true; 303 break; 304 } 305 break; 306 } 307 case STATE_VERIFY_PROOF_COMPLETE: 308 if (!verify_ok_) { 309 CopyCertVerifyResult(verify_details_.get(), &cert_verify_result_); 310 CloseConnectionWithDetails( 311 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); 312 return; 313 } 314 // Check if generation_counter has changed between STATE_VERIFY_PROOF 315 // and STATE_VERIFY_PROOF_COMPLETE state changes. 316 if (generation_counter_ != cached->generation_counter()) { 317 next_state_ = STATE_VERIFY_PROOF; 318 } else { 319 cached->SetProofValid(); 320 cached->SetProofVerifyDetails(verify_details_.release()); 321 next_state_ = STATE_SEND_CHLO; 322 } 323 break; 324 case STATE_RECV_SHLO: { 325 // We sent a CHLO that we expected to be accepted and now we're hoping 326 // for a SHLO from the server to confirm that. 327 if (in->tag() == kREJ) { 328 // alternative_decrypter will be NULL if the original alternative 329 // decrypter latched and became the primary decrypter. That happens 330 // if we received a message encrypted with the INITIAL key. 331 if (session()->connection()->alternative_decrypter() == NULL) { 332 // The rejection was sent encrypted! 333 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, 334 "encrypted REJ message"); 335 return; 336 } 337 next_state_ = STATE_RECV_REJ; 338 break; 339 } 340 if (in->tag() != kSHLO) { 341 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, 342 "Expected SHLO or REJ"); 343 return; 344 } 345 // alternative_decrypter will be NULL if the original alternative 346 // decrypter latched and became the primary decrypter. That happens 347 // if we received a message encrypted with the INITIAL key. 348 if (session()->connection()->alternative_decrypter() != NULL) { 349 // The server hello was sent without encryption. 350 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, 351 "unencrypted SHLO message"); 352 return; 353 } 354 error = crypto_config_->ProcessServerHello( 355 *in, session()->connection()->guid(), 356 session()->connection()->server_supported_versions(), 357 cached, &crypto_negotiated_params_, &error_details); 358 359 if (error != QUIC_NO_ERROR) { 360 CloseConnectionWithDetails( 361 error, "Server hello invalid: " + error_details); 362 return; 363 } 364 error = session()->config()->ProcessServerHello(*in, &error_details); 365 if (error != QUIC_NO_ERROR) { 366 CloseConnectionWithDetails( 367 error, "Server hello invalid: " + error_details); 368 return; 369 } 370 session()->OnConfigNegotiated(); 371 372 CrypterPair* crypters = 373 &crypto_negotiated_params_.forward_secure_crypters; 374 // TODO(agl): we don't currently latch this decrypter because the idea 375 // has been floated that the server shouldn't send packets encrypted 376 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE 377 // packet from the client. 378 session()->connection()->SetAlternativeDecrypter( 379 crypters->decrypter.release(), false /* don't latch */); 380 session()->connection()->SetEncrypter( 381 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release()); 382 session()->connection()->SetDefaultEncryptionLevel( 383 ENCRYPTION_FORWARD_SECURE); 384 385 handshake_confirmed_ = true; 386 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); 387 return; 388 } 389 case STATE_IDLE: 390 // This means that the peer sent us a message that we weren't expecting. 391 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); 392 return; 393 } 394 } 395 } 396 397 } // namespace net 398