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

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

Issue 20047002: net: make QUIC ProofVerifier more generic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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" 7 #include "net/base/completion_callback.h"
8 #include "net/base/net_errors.h" 8 #include "net/base/net_errors.h"
9 #include "net/quic/crypto/crypto_protocol.h" 9 #include "net/quic/crypto/crypto_protocol.h"
10 #include "net/quic/crypto/crypto_utils.h" 10 #include "net/quic/crypto/crypto_utils.h"
11 #include "net/quic/crypto/null_encrypter.h" 11 #include "net/quic/crypto/null_encrypter.h"
12 #include "net/quic/crypto/proof_verifier.h" 12 #include "net/quic/crypto/proof_verifier.h"
13 #include "net/quic/crypto/proof_verifier_chromium.h"
13 #include "net/quic/quic_protocol.h" 14 #include "net/quic/quic_protocol.h"
14 #include "net/quic/quic_session.h" 15 #include "net/quic/quic_session.h"
15 #include "net/ssl/ssl_connection_status_flags.h" 16 #include "net/ssl/ssl_connection_status_flags.h"
16 #include "net/ssl/ssl_info.h" 17 #include "net/ssl/ssl_info.h"
17 18
18 namespace net { 19 namespace net {
19 20
21 // ProofVerifierCallbackClientStream is passed as the callback method to
22 // VerifyProof. The ProofVerifier calls this class with the result of proof
23 // verification when verification is performed asynchronously.
24 class ProofVerifierCallbackClientStream : public ProofVerifierCallback {
Ryan Hamilton 2013/07/23 18:40:50 This code can land in google3, right? (It will ju
agl 2013/07/23 21:04:57 Right.
25 public:
26 explicit ProofVerifierCallbackClientStream(QuicCryptoClientStream* stream)
27 : stream_(stream) {}
28
29 // ProofVerifierCallback interface.
30 virtual void Run(bool ok,
31 string* error_details,
32 ProofVerifyDetails* details) OVERRIDE {
33 if (stream_ == NULL) {
34 delete details;
35 return;
36 }
37
38 stream_->verify_ok_ = ok;
39 stream_->verify_error_details_ = *error_details;
40 stream_->verify_details_.reset(details);
41 stream_->proof_verify_callback_ = NULL;
42 stream_->DoHandshakeLoop(NULL);
43
44 // The ProofVerifier owns this object and will delete it when this method
45 // returns.
46 }
47
48 // Cancel causes any future callbacks to be ignored. It must be called on the
49 // same thread as the callback will be made on.
50 void Cancel() {
51 stream_ = NULL;
52 }
53
54 private:
55 QuicCryptoClientStream* stream_;
56 };
57
20 QuicCryptoClientStream::QuicCryptoClientStream( 58 QuicCryptoClientStream::QuicCryptoClientStream(
21 const string& server_hostname, 59 const string& server_hostname,
22 QuicSession* session, 60 QuicSession* session,
23 QuicCryptoClientConfig* crypto_config) 61 QuicCryptoClientConfig* crypto_config)
24 : QuicCryptoStream(session), 62 : QuicCryptoStream(session),
25 weak_factory_(this),
26 next_state_(STATE_IDLE), 63 next_state_(STATE_IDLE),
27 num_client_hellos_(0), 64 num_client_hellos_(0),
28 crypto_config_(crypto_config), 65 crypto_config_(crypto_config),
29 server_hostname_(server_hostname), 66 server_hostname_(server_hostname),
30 generation_counter_(0) { 67 generation_counter_(0),
68 proof_verify_callback_(NULL) {
31 } 69 }
32 70
33 QuicCryptoClientStream::~QuicCryptoClientStream() { 71 QuicCryptoClientStream::~QuicCryptoClientStream() {
72 if (proof_verify_callback_) {
73 proof_verify_callback_->Cancel();
74 }
34 } 75 }
35 76
36 void QuicCryptoClientStream::OnHandshakeMessage( 77 void QuicCryptoClientStream::OnHandshakeMessage(
37 const CryptoHandshakeMessage& message) { 78 const CryptoHandshakeMessage& message) {
38 DoHandshakeLoop(&message, OK); 79 DoHandshakeLoop(&message);
39 } 80 }
40 81
41 bool QuicCryptoClientStream::CryptoConnect() { 82 bool QuicCryptoClientStream::CryptoConnect() {
42 next_state_ = STATE_SEND_CHLO; 83 next_state_ = STATE_SEND_CHLO;
43 DoHandshakeLoop(NULL, OK); 84 DoHandshakeLoop(NULL);
44 return true; 85 return true;
45 } 86 }
46 87
47 int QuicCryptoClientStream::num_sent_client_hellos() const { 88 int QuicCryptoClientStream::num_sent_client_hellos() const {
48 return num_client_hellos_; 89 return num_client_hellos_;
49 } 90 }
50 91
51 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { 92 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) {
52 ssl_info->Reset(); 93 ssl_info->Reset();
53 QuicCryptoClientConfig::CachedState* cached = 94 QuicCryptoClientConfig::CachedState* cached =
54 crypto_config_->LookupOrCreate(server_hostname_); 95 crypto_config_->LookupOrCreate(server_hostname_);
55 DCHECK(cached); 96 DCHECK(cached);
56 if (!cached) { 97 if (!cached) {
57 return false; 98 return false;
58 } 99 }
59 const CertVerifyResult* cert_verify_result = 100 const CertVerifyResult* cert_verify_result =
60 cached->cert_verify_result(); 101 &(reinterpret_cast<const ProofVerifyDetailsChromium*>(
102 cached->proof_verify_details()))->cert_verify_result;
61 103
62 ssl_info->cert_status = cert_verify_result->cert_status; 104 ssl_info->cert_status = cert_verify_result->cert_status;
63 ssl_info->cert = cert_verify_result->verified_cert; 105 ssl_info->cert = cert_verify_result->verified_cert;
64 106
65 // TODO(rtenneti): Figure out what to set for the following. 107 // TODO(rtenneti): Figure out what to set for the following.
66 // Temporarily hard coded cipher_suite as 0xc031 to represent 108 // Temporarily hard coded cipher_suite as 0xc031 to represent
67 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from 109 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from
68 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256. 110 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256.
69 int cipher_suite = 0xc02f; 111 int cipher_suite = 0xc02f;
70 int ssl_connection_status = 0; 112 int ssl_connection_status = 0;
(...skipping 17 matching lines...) Expand all
88 } 130 }
89 131
90 // kMaxClientHellos is the maximum number of times that we'll send a client 132 // kMaxClientHellos is the maximum number of times that we'll send a client
91 // hello. The value 3 accounts for: 133 // hello. The value 3 accounts for:
92 // * One failure due to an incorrect or missing source-address token. 134 // * One failure due to an incorrect or missing source-address token.
93 // * One failure due the server's certificate chain being unavailible and the 135 // * One failure due the server's certificate chain being unavailible and the
94 // server being unwilling to send it without a valid source-address token. 136 // server being unwilling to send it without a valid source-address token.
95 static const int kMaxClientHellos = 3; 137 static const int kMaxClientHellos = 3;
96 138
97 void QuicCryptoClientStream::DoHandshakeLoop( 139 void QuicCryptoClientStream::DoHandshakeLoop(
98 const CryptoHandshakeMessage* in, 140 const CryptoHandshakeMessage* in) {
99 int result) {
100 CryptoHandshakeMessage out; 141 CryptoHandshakeMessage out;
101 QuicErrorCode error; 142 QuicErrorCode error;
102 string error_details; 143 string error_details;
103 QuicCryptoClientConfig::CachedState* cached = 144 QuicCryptoClientConfig::CachedState* cached =
104 crypto_config_->LookupOrCreate(server_hostname_); 145 crypto_config_->LookupOrCreate(server_hostname_);
105 146
106 if (in != NULL) { 147 if (in != NULL) {
107 DVLOG(1) << "Client received: " << in->DebugString(); 148 DVLOG(1) << "Client received: " << in->DebugString();
108 } 149 }
109 150
110 for (;;) { 151 for (;;) {
111 const State state = next_state_; 152 const State state = next_state_;
112 next_state_ = STATE_IDLE; 153 next_state_ = STATE_IDLE;
113 switch (state) { 154 switch (state) {
114 case STATE_SEND_CHLO: { 155 case STATE_SEND_CHLO: {
115 DCHECK_EQ(OK, result);
116 // Send the client hello in plaintext. 156 // Send the client hello in plaintext.
117 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); 157 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
118 if (num_client_hellos_ > kMaxClientHellos) { 158 if (num_client_hellos_ > kMaxClientHellos) {
119 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); 159 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
120 return; 160 return;
121 } 161 }
122 num_client_hellos_++; 162 num_client_hellos_++;
123 163
124 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { 164 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
125 crypto_config_->FillInchoateClientHello( 165 crypto_config_->FillInchoateClientHello(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 encryption_established_ = true; 204 encryption_established_ = true;
165 session()->OnCryptoHandshakeEvent( 205 session()->OnCryptoHandshakeEvent(
166 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); 206 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
167 } else { 207 } else {
168 session()->OnCryptoHandshakeEvent( 208 session()->OnCryptoHandshakeEvent(
169 QuicSession::ENCRYPTION_REESTABLISHED); 209 QuicSession::ENCRYPTION_REESTABLISHED);
170 } 210 }
171 return; 211 return;
172 } 212 }
173 case STATE_RECV_REJ: 213 case STATE_RECV_REJ:
174 DCHECK_EQ(OK, result);
175 // We sent a dummy CHLO because we didn't have enough information to 214 // We sent a dummy CHLO because we didn't have enough information to
176 // perform a handshake, or we sent a full hello that the server 215 // perform a handshake, or we sent a full hello that the server
177 // rejected. Here we hope to have a REJ that contains the information 216 // rejected. Here we hope to have a REJ that contains the information
178 // that we need. 217 // that we need.
179 if (in->tag() != kREJ) { 218 if (in->tag() != kREJ) {
180 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, 219 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
181 "Expected REJ"); 220 "Expected REJ");
182 return; 221 return;
183 } 222 }
184 error = crypto_config_->ProcessRejection( 223 error = crypto_config_->ProcessRejection(
(...skipping 13 matching lines...) Expand all
198 break; 237 break;
199 } 238 }
200 } 239 }
201 next_state_ = STATE_SEND_CHLO; 240 next_state_ = STATE_SEND_CHLO;
202 break; 241 break;
203 case STATE_VERIFY_PROOF: { 242 case STATE_VERIFY_PROOF: {
204 ProofVerifier* verifier = crypto_config_->proof_verifier(); 243 ProofVerifier* verifier = crypto_config_->proof_verifier();
205 DCHECK(verifier); 244 DCHECK(verifier);
206 next_state_ = STATE_VERIFY_PROOF_COMPLETE; 245 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
207 generation_counter_ = cached->generation_counter(); 246 generation_counter_ = cached->generation_counter();
208 result = verifier->VerifyProof( 247
248 ProofVerifierCallbackClientStream* proof_verify_callback = new
249 ProofVerifierCallbackClientStream(this);
250
251 verify_ok_ = false;
252
253 ProofVerifier::Status status = verifier->VerifyProof(
209 server_hostname_, 254 server_hostname_,
210 cached->server_config(), 255 cached->server_config(),
211 cached->certs(), 256 cached->certs(),
212 cached->signature(), 257 cached->signature(),
213 &error_details_, 258 &error_details,
214 &cert_verify_result_, 259 &verify_details_,
215 base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete, 260 proof_verify_callback);
216 weak_factory_.GetWeakPtr())); 261
217 if (result == ERR_IO_PENDING) { 262 switch (status) {
218 DVLOG(1) << "Doing VerifyProof"; 263 case ProofVerifier::PENDING:
219 return; 264 proof_verify_callback_ = proof_verify_callback;
265 DVLOG(1) << "Doing VerifyProof";
266 return;
267 case ProofVerifier::ERROR:
268 CloseConnectionWithDetails(
269 QUIC_PROOF_INVALID, "Proof invalid: " + error_details);
270 return;
271 case ProofVerifier::OK:
272 verify_ok_ = true;
273 break;
220 } 274 }
221 break; 275 break;
222 } 276 }
223 case STATE_VERIFY_PROOF_COMPLETE: 277 case STATE_VERIFY_PROOF_COMPLETE:
224 if (result != OK) { 278 if (!verify_ok_) {
225 CloseConnectionWithDetails( 279 CloseConnectionWithDetails(
226 QUIC_PROOF_INVALID, "Proof invalid: " + error_details_); 280 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
227 return; 281 return;
228 } 282 }
229 // Check if generation_counter has changed between STATE_VERIFY_PROOF 283 // Check if generation_counter has changed between STATE_VERIFY_PROOF
230 // and STATE_VERIFY_PROOF_COMPLETE state changes. 284 // and STATE_VERIFY_PROOF_COMPLETE state changes.
231 if (generation_counter_ != cached->generation_counter()) { 285 if (generation_counter_ != cached->generation_counter()) {
232 next_state_ = STATE_VERIFY_PROOF; 286 next_state_ = STATE_VERIFY_PROOF;
233 } else { 287 } else {
234 cached->SetProofValid(); 288 cached->SetProofValid();
235 cached->SetCertVerifyResult(cert_verify_result_); 289 cached->SetProofVerifyDetails(verify_details_.release());
236 next_state_ = STATE_SEND_CHLO; 290 next_state_ = STATE_SEND_CHLO;
237 } 291 }
238 break; 292 break;
239 case STATE_RECV_SHLO: { 293 case STATE_RECV_SHLO: {
240 // We sent a CHLO that we expected to be accepted and now we're hoping 294 // We sent a CHLO that we expected to be accepted and now we're hoping
241 // for a SHLO from the server to confirm that. 295 // for a SHLO from the server to confirm that.
242 if (in->tag() == kREJ) { 296 if (in->tag() == kREJ) {
243 // alternative_decrypter will be NULL if the original alternative 297 // alternative_decrypter will be NULL if the original alternative
244 // decrypter latched and became the primary decrypter. That happens 298 // decrypter latched and became the primary decrypter. That happens
245 // if we received a message encrypted with the INITIAL key. 299 // if we received a message encrypted with the INITIAL key.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 return; 352 return;
299 } 353 }
300 case STATE_IDLE: 354 case STATE_IDLE:
301 // This means that the peer sent us a message that we weren't expecting. 355 // This means that the peer sent us a message that we weren't expecting.
302 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); 356 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
303 return; 357 return;
304 } 358 }
305 } 359 }
306 } 360 }
307 361
308 void QuicCryptoClientStream::OnVerifyProofComplete(int result) {
309 DCHECK_EQ(STATE_VERIFY_PROOF_COMPLETE, next_state_);
310 DVLOG(1) << "VerifyProof completed: " << result;
311 DoHandshakeLoop(NULL, result);
312 }
313
314 } // namespace net 362 } // namespace net
OLDNEW
« net/quic/quic_crypto_client_stream.h ('K') | « net/quic/quic_crypto_client_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698