diff options
author | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-03 10:27:46 +0000 |
---|---|---|
committer | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-03 10:27:46 +0000 |
commit | 2662ed5650f65efe8c59acba3db6366d006e6a7d (patch) | |
tree | 1c571925ab02dbe7f6389364c8f134cabd3ef290 /net/quic/quic_crypto_client_stream.cc | |
parent | d47d11d525fe4de37b7812528875347c38ca4f83 (diff) | |
download | chromium_src-2662ed5650f65efe8c59acba3db6366d006e6a7d.zip chromium_src-2662ed5650f65efe8c59acba3db6366d006e6a7d.tar.gz chromium_src-2662ed5650f65efe8c59acba3db6366d006e6a7d.tar.bz2 |
OpenSSL/NSS implementation of ProofVerfifier.
Changes to make ProofVerifier asynchronous. Each QuicSession's ProofVerifier is used to verify the signature and cert chain.
Implemented generation counter in QuicCryptoClientConfig's CachedState in case certs change when we are verifying the Proof.
Review URL: https://chromiumcodereview.appspot.com/17385010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209946 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic/quic_crypto_client_stream.cc')
-rw-r--r-- | net/quic/quic_crypto_client_stream.cc | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc index 674a441..f0ec9130 100644 --- a/net/quic/quic_crypto_client_stream.cc +++ b/net/quic/quic_crypto_client_stream.cc @@ -4,6 +4,8 @@ #include "net/quic/quic_crypto_client_stream.h" +#include "net/base/completion_callback.h" +#include "net/base/net_errors.h" #include "net/quic/crypto/crypto_protocol.h" #include "net/quic/crypto/crypto_utils.h" #include "net/quic/crypto/null_encrypter.h" @@ -18,10 +20,12 @@ QuicCryptoClientStream::QuicCryptoClientStream( QuicSession* session, QuicCryptoClientConfig* crypto_config) : QuicCryptoStream(session), + weak_factory_(this), next_state_(STATE_IDLE), num_client_hellos_(0), crypto_config_(crypto_config), - server_hostname_(server_hostname) { + server_hostname_(server_hostname), + generation_counter_(0) { } QuicCryptoClientStream::~QuicCryptoClientStream() { @@ -29,12 +33,12 @@ QuicCryptoClientStream::~QuicCryptoClientStream() { void QuicCryptoClientStream::OnHandshakeMessage( const CryptoHandshakeMessage& message) { - DoHandshakeLoop(&message); + DoHandshakeLoop(&message, OK); } bool QuicCryptoClientStream::CryptoConnect() { next_state_ = STATE_SEND_CHLO; - DoHandshakeLoop(NULL); + DoHandshakeLoop(NULL, OK); return true; } @@ -50,7 +54,8 @@ int QuicCryptoClientStream::num_sent_client_hellos() const { static const int kMaxClientHellos = 3; void QuicCryptoClientStream::DoHandshakeLoop( - const CryptoHandshakeMessage* in) { + const CryptoHandshakeMessage* in, + int result) { CryptoHandshakeMessage out; QuicErrorCode error; string error_details; @@ -66,6 +71,8 @@ void QuicCryptoClientStream::DoHandshakeLoop( next_state_ = STATE_IDLE; switch (state) { case STATE_SEND_CHLO: { + // Send the subsequent client hello in plaintext. + session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); if (num_client_hellos_ > kMaxClientHellos) { CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); return; @@ -122,6 +129,7 @@ void QuicCryptoClientStream::DoHandshakeLoop( return; } case STATE_RECV_REJ: + DCHECK_EQ(OK, result); // We sent a dummy CHLO because we didn't have enough information to // perform a handshake, or we sent a full hello that the server // rejected. Here we hope to have a REJ that contains the information @@ -139,30 +147,54 @@ void QuicCryptoClientStream::DoHandshakeLoop( return; } if (!cached->proof_valid()) { - const ProofVerifier* verifier = crypto_config_->proof_verifier(); + ProofVerifier* verifier = session()->proof_verifier(); if (!verifier) { // If no verifier is set then we don't check the certificates. cached->SetProofValid(); } else if (!cached->signature().empty()) { - // TODO(rtenneti): In Chromium, we will need to make VerifyProof() - // asynchronous. - if (!verifier->VerifyProof(server_hostname_, - cached->server_config(), - cached->certs(), - cached->signature(), - &error_details)) { - CloseConnectionWithDetails(QUIC_PROOF_INVALID, - "Proof invalid: " + error_details); - return; - } - cached->SetProofValid(); + next_state_ = STATE_VERIFY_PROOF; + continue; } } - // Send the subsequent client hello in plaintext. - session()->connection()->SetDefaultEncryptionLevel( - ENCRYPTION_NONE); next_state_ = STATE_SEND_CHLO; break; + case STATE_VERIFY_PROOF: { + ProofVerifier* verifier = session()->proof_verifier(); + DCHECK(verifier); + next_state_ = STATE_VERIFY_PROOF_COMPLETED; + generation_counter_ = cached->generation_counter(); + result = verifier->VerifyProof( + server_hostname_, + cached->server_config(), + cached->certs(), + cached->signature(), + &error_details_, + base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete, + weak_factory_.GetWeakPtr())); + if (result == ERR_IO_PENDING) { + DVLOG(1) << "Doing VerifyProof"; + return; + } + break; + } + case STATE_VERIFY_PROOF_COMPLETED: { + if (result != OK) { + CloseConnectionWithDetails( + QUIC_PROOF_INVALID, "Proof invalid: " + error_details_); + return; + } + ProofVerifier* verifier = session()->proof_verifier(); + DCHECK(verifier); + // Check if generation_counter has changed between STATE_VERIFY_PROOF + // and STATE_VERIFY_PROOF_COMPLETED state changes. + if (generation_counter_ != cached->generation_counter()) { + next_state_ = STATE_VERIFY_PROOF; + continue; + } + cached->SetProofValid(); + next_state_ = STATE_SEND_CHLO; + break; + } case STATE_RECV_SHLO: { // We sent a CHLO that we expected to be accepted and now we're hoping // for a SHLO from the server to confirm that. @@ -232,4 +264,10 @@ void QuicCryptoClientStream::DoHandshakeLoop( } } +void QuicCryptoClientStream::OnVerifyProofComplete(int result) { + DCHECK_EQ(STATE_VERIFY_PROOF_COMPLETED, next_state_); + DVLOG(1) << "VerifyProof completed: " << result; + DoHandshakeLoop(NULL, result); +} + } // namespace net |