Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: net/quic/quic_crypto_client_stream.cc

Issue 17385010: OpenSSL/NSS implementation of ProofVerfifier. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Implement generation counter and wtc/agl's comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
8 #include "net/base/net_errors.h"
7 #include "net/quic/crypto/crypto_protocol.h" 9 #include "net/quic/crypto/crypto_protocol.h"
8 #include "net/quic/crypto/crypto_utils.h" 10 #include "net/quic/crypto/crypto_utils.h"
9 #include "net/quic/crypto/null_encrypter.h" 11 #include "net/quic/crypto/null_encrypter.h"
10 #include "net/quic/crypto/proof_verifier.h" 12 #include "net/quic/crypto/proof_verifier.h"
11 #include "net/quic/quic_protocol.h" 13 #include "net/quic/quic_protocol.h"
12 #include "net/quic/quic_session.h" 14 #include "net/quic/quic_session.h"
13 15
14 namespace net { 16 namespace net {
15 17
16 QuicCryptoClientStream::QuicCryptoClientStream( 18 QuicCryptoClientStream::QuicCryptoClientStream(
17 const string& server_hostname, 19 const string& server_hostname,
18 QuicSession* session, 20 QuicSession* session,
19 QuicCryptoClientConfig* crypto_config) 21 QuicCryptoClientConfig* crypto_config)
20 : QuicCryptoStream(session), 22 : QuicCryptoStream(session),
23 weak_factory_(this),
21 next_state_(STATE_IDLE), 24 next_state_(STATE_IDLE),
22 num_client_hellos_(0), 25 num_client_hellos_(0),
23 crypto_config_(crypto_config), 26 crypto_config_(crypto_config),
24 server_hostname_(server_hostname) { 27 server_hostname_(server_hostname) {
25 } 28 }
26 29
27 QuicCryptoClientStream::~QuicCryptoClientStream() { 30 QuicCryptoClientStream::~QuicCryptoClientStream() {
28 } 31 }
29 32
30 void QuicCryptoClientStream::OnHandshakeMessage( 33 void QuicCryptoClientStream::OnHandshakeMessage(
31 const CryptoHandshakeMessage& message) { 34 const CryptoHandshakeMessage& message) {
32 DoHandshakeLoop(&message); 35 DoHandshakeLoop(&message, OK);
33 } 36 }
34 37
35 bool QuicCryptoClientStream::CryptoConnect() { 38 bool QuicCryptoClientStream::CryptoConnect() {
36 next_state_ = STATE_SEND_CHLO; 39 next_state_ = STATE_SEND_CHLO;
37 DoHandshakeLoop(NULL); 40 DoHandshakeLoop(NULL, OK);
38 return true; 41 return true;
39 } 42 }
40 43
41 int QuicCryptoClientStream::num_sent_client_hellos() const { 44 int QuicCryptoClientStream::num_sent_client_hellos() const {
42 return num_client_hellos_; 45 return num_client_hellos_;
43 } 46 }
44 47
45 // kMaxClientHellos is the maximum number of times that we'll send a client 48 // kMaxClientHellos is the maximum number of times that we'll send a client
46 // hello. The value 3 accounts for: 49 // hello. The value 3 accounts for:
47 // * One failure due to an incorrect or missing source-address token. 50 // * One failure due to an incorrect or missing source-address token.
48 // * One failure due the server's certificate chain being unavailible and the 51 // * One failure due the server's certificate chain being unavailible and the
49 // server being unwilling to send it without a valid source-address token. 52 // server being unwilling to send it without a valid source-address token.
50 static const int kMaxClientHellos = 3; 53 static const int kMaxClientHellos = 3;
51 54
52 void QuicCryptoClientStream::DoHandshakeLoop( 55 void QuicCryptoClientStream::DoHandshakeLoop(
53 const CryptoHandshakeMessage* in) { 56 const CryptoHandshakeMessage* in,
57 int result) {
54 CryptoHandshakeMessage out; 58 CryptoHandshakeMessage out;
55 QuicErrorCode error; 59 QuicErrorCode error;
56 string error_details; 60 string error_details;
57 QuicCryptoClientConfig::CachedState* cached = 61 QuicCryptoClientConfig::CachedState* cached =
58 crypto_config_->LookupOrCreate(server_hostname_); 62 crypto_config_->LookupOrCreate(server_hostname_);
59 63
60 if (in != NULL) { 64 if (in != NULL) {
61 DVLOG(1) << "Client received: " << in->DebugString(); 65 DVLOG(1) << "Client received: " << in->DebugString();
62 } 66 }
63 67
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 return; 136 return;
133 } 137 }
134 error = crypto_config_->ProcessRejection( 138 error = crypto_config_->ProcessRejection(
135 cached, *in, session()->connection()->clock()->WallNow(), 139 cached, *in, session()->connection()->clock()->WallNow(),
136 &crypto_negotiated_params_, &error_details); 140 &crypto_negotiated_params_, &error_details);
137 if (error != QUIC_NO_ERROR) { 141 if (error != QUIC_NO_ERROR) {
138 CloseConnectionWithDetails(error, error_details); 142 CloseConnectionWithDetails(error, error_details);
139 return; 143 return;
140 } 144 }
141 if (!cached->proof_valid()) { 145 if (!cached->proof_valid()) {
142 const ProofVerifier* verifier = crypto_config_->proof_verifier(); 146 ProofVerifier* verifier = session()->proof_verifier();
143 if (!verifier) { 147 if (verifier && !cached->signature().empty()) {
144 // If no verifier is set then we don't check the certificates. 148 next_state_ = STATE_VERIFY_PROOF;
145 cached->SetProofValid(); 149 continue;
146 } else if (!cached->signature().empty()) {
147 // TODO(rtenneti): In Chromium, we will need to make VerifyProof()
148 // asynchronous.
149 if (!verifier->VerifyProof(server_hostname_,
150 cached->server_config(),
151 cached->certs(),
152 cached->signature(),
153 &error_details)) {
154 CloseConnectionWithDetails(QUIC_PROOF_INVALID,
155 "Proof invalid: " + error_details);
156 return;
157 }
158 cached->SetProofValid();
159 } 150 }
160 } 151 }
152 // If proof is valid or if there is no verifier is set or if
153 // cached->signature is empty then we don't check the certificates.
agl 2013/07/02 15:20:08 We can receive multiple REJ in a handshake. At the
ramant (doing other things) 2013/07/02 19:45:51 Reorganized the code. Could you take another look.
154 result = OK;
155 next_state_ = STATE_VERIFY_PROOF_COMPLETED;
156 break;
157 case STATE_VERIFY_PROOF: {
158 // We will verify proof if there is a verifier.
159 ProofVerifier* verifier = session()->proof_verifier();
160 DCHECK_EQ(verifier->generation_counter(), 0u);
agl 2013/07/02 15:20:08 Why should the generation counter always be zero?
ramant (doing other things) 2013/07/02 19:45:51 Done.
161 DCHECK_GT(cached->generation_counter(), 0u);
162 result = verifier->VerifyProof(
163 server_hostname_,
164 cached->server_config(),
165 cached->certs(),
166 cached->signature(),
167 cached->generation_counter(),
168 base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete,
169 weak_factory_.GetWeakPtr()));
170 if (result == ERR_IO_PENDING) {
171 DVLOG(1) << "Doing VerifyProof";
172 return;
173 }
174 next_state_ = STATE_VERIFY_PROOF_COMPLETED;
175 break;
176 }
177 case STATE_VERIFY_PROOF_COMPLETED: {
178 if (!cached->proof_valid()) {
179 ProofVerifier* verifier = session()->proof_verifier();
180 if (result != OK) {
181 CloseConnectionWithDetails(QUIC_PROOF_INVALID,
182 "Proof invalid: " + verifier->error_details());
183 return;
184 }
185 // Check if generation_counter has changed between STATE_VERIFY_PROOF
186 // and STATE_VERIFY_PROOF_COMPLETED state changes.
187 if (verifier && verifier->generation_counter() > 0 &&
188 verifier->generation_counter() != cached->generation_counter()) {
189 CloseConnectionWithDetails(QUIC_PROOF_INVALID,
agl 2013/07/02 15:20:08 The generation counter changing isn't an error. We
ramant (doing other things) 2013/07/02 19:45:51 Done.
190 "Proof invalid: server certs have changed");
191 return;
192 }
193 cached->SetProofValid();
194 }
161 // Send the subsequent client hello in plaintext. 195 // Send the subsequent client hello in plaintext.
162 session()->connection()->SetDefaultEncryptionLevel( 196 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
163 ENCRYPTION_NONE);
164 next_state_ = STATE_SEND_CHLO; 197 next_state_ = STATE_SEND_CHLO;
165 break; 198 break;
199 }
166 case STATE_RECV_SHLO: { 200 case STATE_RECV_SHLO: {
167 // We sent a CHLO that we expected to be accepted and now we're hoping 201 // We sent a CHLO that we expected to be accepted and now we're hoping
168 // for a SHLO from the server to confirm that. 202 // for a SHLO from the server to confirm that.
169 if (in->tag() == kREJ) { 203 if (in->tag() == kREJ) {
170 // alternative_decrypter will be NULL if the original alternative 204 // alternative_decrypter will be NULL if the original alternative
171 // decrypter latched and became the primary decrypter. That happens 205 // decrypter latched and became the primary decrypter. That happens
172 // if we received a message encrypted with the INITIAL key. 206 // if we received a message encrypted with the INITIAL key.
173 if (session()->connection()->alternative_decrypter() == NULL) { 207 if (session()->connection()->alternative_decrypter() == NULL) {
174 // The rejection was sent encrypted! 208 // The rejection was sent encrypted!
175 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, 209 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 return; 259 return;
226 } 260 }
227 case STATE_IDLE: 261 case STATE_IDLE:
228 // This means that the peer sent us a message that we weren't expecting. 262 // This means that the peer sent us a message that we weren't expecting.
229 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); 263 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
230 return; 264 return;
231 } 265 }
232 } 266 }
233 } 267 }
234 268
269 void QuicCryptoClientStream::OnVerifyProofComplete(int result) {
270 DVLOG(1) << "VerifyProof completed: " << result;
agl 2013/07/02 15:20:08 Is it ensured that this callback is always made on
ramant (doing other things) 2013/07/02 19:45:51 Added the comment to VerifyProof. Done.
271 next_state_ = STATE_VERIFY_PROOF_COMPLETED;
272 DoHandshakeLoop(NULL, result);
273 }
274
235 } // namespace net 275 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698