summaryrefslogtreecommitdiffstats
path: root/net/quic/quic_crypto_client_stream.cc
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-03 10:27:46 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-03 10:27:46 +0000
commit2662ed5650f65efe8c59acba3db6366d006e6a7d (patch)
tree1c571925ab02dbe7f6389364c8f134cabd3ef290 /net/quic/quic_crypto_client_stream.cc
parentd47d11d525fe4de37b7812528875347c38ca4f83 (diff)
downloadchromium_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.cc78
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