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

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: Can't use a token called "ERROR" on Windows. Created 7 years, 4 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 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
22 QuicCryptoClientStream* stream)
23 : stream_(stream) {}
24
25 QuicCryptoClientStream::ProofVerifierCallbackImpl::
26 ~ProofVerifierCallbackImpl() {}
27
28 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
29 bool ok,
30 const string& error_details,
31 scoped_ptr<ProofVerifyDetails>* details) {
32 if (stream_ == NULL) {
33 return;
34 }
35
36 stream_->verify_ok_ = ok;
37 stream_->verify_error_details_ = error_details;
38 stream_->verify_details_.reset(details->release());
39 stream_->proof_verify_callback_ = NULL;
40 stream_->DoHandshakeLoop(NULL);
41
42 // The ProofVerifier owns this object and will delete it when this method
43 // returns.
44 }
45
46 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
47 stream_ = NULL;
48 }
49
50
20 QuicCryptoClientStream::QuicCryptoClientStream( 51 QuicCryptoClientStream::QuicCryptoClientStream(
21 const string& server_hostname, 52 const string& server_hostname,
22 QuicSession* session, 53 QuicSession* session,
23 QuicCryptoClientConfig* crypto_config) 54 QuicCryptoClientConfig* crypto_config)
24 : QuicCryptoStream(session), 55 : QuicCryptoStream(session),
25 weak_factory_(this),
26 next_state_(STATE_IDLE), 56 next_state_(STATE_IDLE),
27 num_client_hellos_(0), 57 num_client_hellos_(0),
28 crypto_config_(crypto_config), 58 crypto_config_(crypto_config),
29 server_hostname_(server_hostname), 59 server_hostname_(server_hostname),
30 generation_counter_(0) { 60 generation_counter_(0),
61 proof_verify_callback_(NULL) {
31 } 62 }
32 63
33 QuicCryptoClientStream::~QuicCryptoClientStream() { 64 QuicCryptoClientStream::~QuicCryptoClientStream() {
65 if (proof_verify_callback_) {
66 proof_verify_callback_->Cancel();
67 }
34 } 68 }
35 69
36 void QuicCryptoClientStream::OnHandshakeMessage( 70 void QuicCryptoClientStream::OnHandshakeMessage(
37 const CryptoHandshakeMessage& message) { 71 const CryptoHandshakeMessage& message) {
38 DoHandshakeLoop(&message, OK); 72 DoHandshakeLoop(&message);
39 } 73 }
40 74
41 bool QuicCryptoClientStream::CryptoConnect() { 75 bool QuicCryptoClientStream::CryptoConnect() {
42 next_state_ = STATE_SEND_CHLO; 76 next_state_ = STATE_SEND_CHLO;
43 DoHandshakeLoop(NULL, OK); 77 DoHandshakeLoop(NULL);
44 return true; 78 return true;
45 } 79 }
46 80
47 int QuicCryptoClientStream::num_sent_client_hellos() const { 81 int QuicCryptoClientStream::num_sent_client_hellos() const {
48 return num_client_hellos_; 82 return num_client_hellos_;
49 } 83 }
50 84
51 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { 85 bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) {
52 ssl_info->Reset(); 86 ssl_info->Reset();
53 QuicCryptoClientConfig::CachedState* cached = 87 QuicCryptoClientConfig::CachedState* cached =
54 crypto_config_->LookupOrCreate(server_hostname_); 88 crypto_config_->LookupOrCreate(server_hostname_);
55 DCHECK(cached); 89 DCHECK(cached);
56 if (!cached) { 90 if (!cached) {
57 return false; 91 return false;
58 } 92 }
59 const CertVerifyResult* cert_verify_result = 93 const CertVerifyResult* cert_verify_result =
60 cached->cert_verify_result(); 94 &(reinterpret_cast<const ProofVerifyDetailsChromium*>(
95 cached->proof_verify_details()))->cert_verify_result;
61 96
62 ssl_info->cert_status = cert_verify_result->cert_status; 97 ssl_info->cert_status = cert_verify_result->cert_status;
63 ssl_info->cert = cert_verify_result->verified_cert; 98 ssl_info->cert = cert_verify_result->verified_cert;
64 99
65 // TODO(rtenneti): Figure out what to set for the following. 100 // TODO(rtenneti): Figure out what to set for the following.
66 // Temporarily hard coded cipher_suite as 0xc031 to represent 101 // Temporarily hard coded cipher_suite as 0xc031 to represent
67 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from 102 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (from
68 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256. 103 // net/ssl/ssl_cipher_suite_names.cc) and encryption as 256.
69 int cipher_suite = 0xc02f; 104 int cipher_suite = 0xc02f;
70 int ssl_connection_status = 0; 105 int ssl_connection_status = 0;
(...skipping 17 matching lines...) Expand all
88 } 123 }
89 124
90 // kMaxClientHellos is the maximum number of times that we'll send a client 125 // kMaxClientHellos is the maximum number of times that we'll send a client
91 // hello. The value 3 accounts for: 126 // hello. The value 3 accounts for:
92 // * One failure due to an incorrect or missing source-address token. 127 // * One failure due to an incorrect or missing source-address token.
93 // * One failure due the server's certificate chain being unavailible and the 128 // * 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. 129 // server being unwilling to send it without a valid source-address token.
95 static const int kMaxClientHellos = 3; 130 static const int kMaxClientHellos = 3;
96 131
97 void QuicCryptoClientStream::DoHandshakeLoop( 132 void QuicCryptoClientStream::DoHandshakeLoop(
98 const CryptoHandshakeMessage* in, 133 const CryptoHandshakeMessage* in) {
99 int result) {
100 CryptoHandshakeMessage out; 134 CryptoHandshakeMessage out;
101 QuicErrorCode error; 135 QuicErrorCode error;
102 string error_details; 136 string error_details;
103 QuicCryptoClientConfig::CachedState* cached = 137 QuicCryptoClientConfig::CachedState* cached =
104 crypto_config_->LookupOrCreate(server_hostname_); 138 crypto_config_->LookupOrCreate(server_hostname_);
105 139
106 if (in != NULL) { 140 if (in != NULL) {
107 DVLOG(1) << "Client received: " << in->DebugString(); 141 DVLOG(1) << "Client received: " << in->DebugString();
108 } 142 }
109 143
110 for (;;) { 144 for (;;) {
111 const State state = next_state_; 145 const State state = next_state_;
112 next_state_ = STATE_IDLE; 146 next_state_ = STATE_IDLE;
113 switch (state) { 147 switch (state) {
114 case STATE_SEND_CHLO: { 148 case STATE_SEND_CHLO: {
115 DCHECK_EQ(OK, result);
116 // Send the client hello in plaintext. 149 // Send the client hello in plaintext.
117 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); 150 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
118 if (num_client_hellos_ > kMaxClientHellos) { 151 if (num_client_hellos_ > kMaxClientHellos) {
119 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS); 152 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
120 return; 153 return;
121 } 154 }
122 num_client_hellos_++; 155 num_client_hellos_++;
123 156
124 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { 157 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
125 crypto_config_->FillInchoateClientHello( 158 crypto_config_->FillInchoateClientHello(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 encryption_established_ = true; 197 encryption_established_ = true;
165 session()->OnCryptoHandshakeEvent( 198 session()->OnCryptoHandshakeEvent(
166 QuicSession::ENCRYPTION_FIRST_ESTABLISHED); 199 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
167 } else { 200 } else {
168 session()->OnCryptoHandshakeEvent( 201 session()->OnCryptoHandshakeEvent(
169 QuicSession::ENCRYPTION_REESTABLISHED); 202 QuicSession::ENCRYPTION_REESTABLISHED);
170 } 203 }
171 return; 204 return;
172 } 205 }
173 case STATE_RECV_REJ: 206 case STATE_RECV_REJ:
174 DCHECK_EQ(OK, result);
175 // We sent a dummy CHLO because we didn't have enough information to 207 // 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 208 // 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 209 // rejected. Here we hope to have a REJ that contains the information
178 // that we need. 210 // that we need.
179 if (in->tag() != kREJ) { 211 if (in->tag() != kREJ) {
180 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, 212 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
181 "Expected REJ"); 213 "Expected REJ");
182 return; 214 return;
183 } 215 }
184 error = crypto_config_->ProcessRejection( 216 error = crypto_config_->ProcessRejection(
(...skipping 13 matching lines...) Expand all
198 break; 230 break;
199 } 231 }
200 } 232 }
201 next_state_ = STATE_SEND_CHLO; 233 next_state_ = STATE_SEND_CHLO;
202 break; 234 break;
203 case STATE_VERIFY_PROOF: { 235 case STATE_VERIFY_PROOF: {
204 ProofVerifier* verifier = crypto_config_->proof_verifier(); 236 ProofVerifier* verifier = crypto_config_->proof_verifier();
205 DCHECK(verifier); 237 DCHECK(verifier);
206 next_state_ = STATE_VERIFY_PROOF_COMPLETE; 238 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
207 generation_counter_ = cached->generation_counter(); 239 generation_counter_ = cached->generation_counter();
208 result = verifier->VerifyProof( 240
241 ProofVerifierCallbackImpl* proof_verify_callback =
242 new ProofVerifierCallbackImpl(this);
243
244 verify_ok_ = false;
245
246 ProofVerifier::Status status = verifier->VerifyProof(
209 server_hostname_, 247 server_hostname_,
210 cached->server_config(), 248 cached->server_config(),
211 cached->certs(), 249 cached->certs(),
212 cached->signature(), 250 cached->signature(),
213 &error_details_, 251 &error_details,
214 &cert_verify_result_, 252 &verify_details_,
215 base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete, 253 proof_verify_callback);
216 weak_factory_.GetWeakPtr())); 254
217 if (result == ERR_IO_PENDING) { 255 switch (status) {
218 DVLOG(1) << "Doing VerifyProof"; 256 case ProofVerifier::PENDING:
219 return; 257 proof_verify_callback_ = proof_verify_callback;
258 DVLOG(1) << "Doing VerifyProof";
259 return;
260 case ProofVerifier::FAILURE:
261 CloseConnectionWithDetails(
262 QUIC_PROOF_INVALID, "Proof invalid: " + error_details);
263 return;
264 case ProofVerifier::SUCCESS:
265 verify_ok_ = true;
266 break;
220 } 267 }
221 break; 268 break;
222 } 269 }
223 case STATE_VERIFY_PROOF_COMPLETE: 270 case STATE_VERIFY_PROOF_COMPLETE:
224 if (result != OK) { 271 if (!verify_ok_) {
225 CloseConnectionWithDetails( 272 CloseConnectionWithDetails(
226 QUIC_PROOF_INVALID, "Proof invalid: " + error_details_); 273 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
227 return; 274 return;
228 } 275 }
229 // Check if generation_counter has changed between STATE_VERIFY_PROOF 276 // Check if generation_counter has changed between STATE_VERIFY_PROOF
230 // and STATE_VERIFY_PROOF_COMPLETE state changes. 277 // and STATE_VERIFY_PROOF_COMPLETE state changes.
231 if (generation_counter_ != cached->generation_counter()) { 278 if (generation_counter_ != cached->generation_counter()) {
232 next_state_ = STATE_VERIFY_PROOF; 279 next_state_ = STATE_VERIFY_PROOF;
233 } else { 280 } else {
234 cached->SetProofValid(); 281 cached->SetProofValid();
235 cached->SetCertVerifyResult(cert_verify_result_); 282 cached->SetProofVerifyDetails(verify_details_.release());
236 next_state_ = STATE_SEND_CHLO; 283 next_state_ = STATE_SEND_CHLO;
237 } 284 }
238 break; 285 break;
239 case STATE_RECV_SHLO: { 286 case STATE_RECV_SHLO: {
240 // We sent a CHLO that we expected to be accepted and now we're hoping 287 // 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. 288 // for a SHLO from the server to confirm that.
242 if (in->tag() == kREJ) { 289 if (in->tag() == kREJ) {
243 // alternative_decrypter will be NULL if the original alternative 290 // alternative_decrypter will be NULL if the original alternative
244 // decrypter latched and became the primary decrypter. That happens 291 // decrypter latched and became the primary decrypter. That happens
245 // if we received a message encrypted with the INITIAL key. 292 // if we received a message encrypted with the INITIAL key.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 return; 345 return;
299 } 346 }
300 case STATE_IDLE: 347 case STATE_IDLE:
301 // This means that the peer sent us a message that we weren't expecting. 348 // This means that the peer sent us a message that we weren't expecting.
302 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); 349 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
303 return; 350 return;
304 } 351 }
305 } 352 }
306 } 353 }
307 354
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 355 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698