| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/crypto/quic_crypto_client_config.h" | 5 #include "net/quic/crypto/quic_crypto_client_config.h" |
| 6 | 6 |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "net/quic/crypto/cert_compressor.h" | 9 #include "net/quic/crypto/cert_compressor.h" |
| 10 #include "net/quic/crypto/chacha20_poly1305_encrypter.h" | 10 #include "net/quic/crypto/chacha20_poly1305_encrypter.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 using base::StringPiece; | 22 using base::StringPiece; |
| 23 using std::find; | 23 using std::find; |
| 24 using std::make_pair; | 24 using std::make_pair; |
| 25 using std::map; | 25 using std::map; |
| 26 using std::string; | 26 using std::string; |
| 27 using std::vector; | 27 using std::vector; |
| 28 | 28 |
| 29 namespace net { | 29 namespace net { |
| 30 | 30 |
| 31 QuicCryptoClientConfig::QuicCryptoClientConfig() | 31 QuicCryptoClientConfig::QuicCryptoClientConfig() : disable_ecdsa_(false) { |
| 32 : disable_ecdsa_(false) {} | 32 } |
| 33 | 33 |
| 34 QuicCryptoClientConfig::~QuicCryptoClientConfig() { | 34 QuicCryptoClientConfig::~QuicCryptoClientConfig() { |
| 35 STLDeleteValues(&cached_states_); | 35 STLDeleteValues(&cached_states_); |
| 36 } | 36 } |
| 37 | 37 |
| 38 QuicCryptoClientConfig::CachedState::CachedState() | 38 QuicCryptoClientConfig::CachedState::CachedState() |
| 39 : server_config_valid_(false), | 39 : server_config_valid_(false), generation_counter_(0) { |
| 40 generation_counter_(0) {} | 40 } |
| 41 | 41 |
| 42 QuicCryptoClientConfig::CachedState::~CachedState() {} | 42 QuicCryptoClientConfig::CachedState::~CachedState() { |
| 43 } |
| 43 | 44 |
| 44 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const { | 45 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const { |
| 45 if (server_config_.empty() || !server_config_valid_) { | 46 if (server_config_.empty() || !server_config_valid_) { |
| 46 return false; | 47 return false; |
| 47 } | 48 } |
| 48 | 49 |
| 49 const CryptoHandshakeMessage* scfg = GetServerConfig(); | 50 const CryptoHandshakeMessage* scfg = GetServerConfig(); |
| 50 if (!scfg) { | 51 if (!scfg) { |
| 51 // Should be impossible short of cache corruption. | 52 // Should be impossible short of cache corruption. |
| 52 DCHECK(false); | 53 DCHECK(false); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 73 } | 74 } |
| 74 | 75 |
| 75 if (!scfg_.get()) { | 76 if (!scfg_.get()) { |
| 76 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); | 77 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); |
| 77 DCHECK(scfg_.get()); | 78 DCHECK(scfg_.get()); |
| 78 } | 79 } |
| 79 return scfg_.get(); | 80 return scfg_.get(); |
| 80 } | 81 } |
| 81 | 82 |
| 82 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( | 83 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( |
| 83 StringPiece server_config, QuicWallTime now, string* error_details) { | 84 StringPiece server_config, |
| 85 QuicWallTime now, |
| 86 string* error_details) { |
| 84 const bool matches_existing = server_config == server_config_; | 87 const bool matches_existing = server_config == server_config_; |
| 85 | 88 |
| 86 // Even if the new server config matches the existing one, we still wish to | 89 // Even if the new server config matches the existing one, we still wish to |
| 87 // reject it if it has expired. | 90 // reject it if it has expired. |
| 88 scoped_ptr<CryptoHandshakeMessage> new_scfg_storage; | 91 scoped_ptr<CryptoHandshakeMessage> new_scfg_storage; |
| 89 const CryptoHandshakeMessage* new_scfg; | 92 const CryptoHandshakeMessage* new_scfg; |
| 90 | 93 |
| 91 if (!matches_existing) { | 94 if (!matches_existing) { |
| 92 new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config)); | 95 new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config)); |
| 93 new_scfg = new_scfg_storage.get(); | 96 new_scfg = new_scfg_storage.get(); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 const vector<string>& certs, | 184 const vector<string>& certs, |
| 182 StringPiece signature, | 185 StringPiece signature, |
| 183 QuicWallTime now) { | 186 QuicWallTime now) { |
| 184 DCHECK(server_config_.empty()); | 187 DCHECK(server_config_.empty()); |
| 185 | 188 |
| 186 if (server_config.empty()) { | 189 if (server_config.empty()) { |
| 187 return false; | 190 return false; |
| 188 } | 191 } |
| 189 | 192 |
| 190 string error_details; | 193 string error_details; |
| 191 QuicErrorCode error = SetServerConfig(server_config, now, | 194 QuicErrorCode error = SetServerConfig(server_config, now, &error_details); |
| 192 &error_details); | |
| 193 if (error != QUIC_NO_ERROR) { | 195 if (error != QUIC_NO_ERROR) { |
| 194 DVLOG(1) << "SetServerConfig failed with " << error_details; | 196 DVLOG(1) << "SetServerConfig failed with " << error_details; |
| 195 return false; | 197 return false; |
| 196 } | 198 } |
| 197 | 199 |
| 198 signature.CopyToString(&server_config_sig_); | 200 signature.CopyToString(&server_config_sig_); |
| 199 source_address_token.CopyToString(&source_address_token_); | 201 source_address_token.CopyToString(&source_address_token_); |
| 200 certs_ = certs; | 202 certs_ = certs; |
| 201 return true; | 203 return true; |
| 202 } | 204 } |
| 203 | 205 |
| 204 const string& QuicCryptoClientConfig::CachedState::server_config() const { | 206 const string& QuicCryptoClientConfig::CachedState::server_config() const { |
| 205 return server_config_; | 207 return server_config_; |
| 206 } | 208 } |
| 207 | 209 |
| 208 const string& | 210 const string& QuicCryptoClientConfig::CachedState::source_address_token() |
| 209 QuicCryptoClientConfig::CachedState::source_address_token() const { | 211 const { |
| 210 return source_address_token_; | 212 return source_address_token_; |
| 211 } | 213 } |
| 212 | 214 |
| 213 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const { | 215 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const { |
| 214 return certs_; | 216 return certs_; |
| 215 } | 217 } |
| 216 | 218 |
| 217 const string& QuicCryptoClientConfig::CachedState::signature() const { | 219 const string& QuicCryptoClientConfig::CachedState::signature() const { |
| 218 return server_config_sig_; | 220 return server_config_sig_; |
| 219 } | 221 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 } | 279 } |
| 278 | 280 |
| 279 CachedState* cached = new CachedState; | 281 CachedState* cached = new CachedState; |
| 280 cached_states_.insert(make_pair(server_id, cached)); | 282 cached_states_.insert(make_pair(server_id, cached)); |
| 281 PopulateFromCanonicalConfig(server_id, cached); | 283 PopulateFromCanonicalConfig(server_id, cached); |
| 282 return cached; | 284 return cached; |
| 283 } | 285 } |
| 284 | 286 |
| 285 void QuicCryptoClientConfig::ClearCachedStates() { | 287 void QuicCryptoClientConfig::ClearCachedStates() { |
| 286 for (CachedStateMap::const_iterator it = cached_states_.begin(); | 288 for (CachedStateMap::const_iterator it = cached_states_.begin(); |
| 287 it != cached_states_.end(); ++it) { | 289 it != cached_states_.end(); |
| 290 ++it) { |
| 288 it->second->Clear(); | 291 it->second->Clear(); |
| 289 } | 292 } |
| 290 } | 293 } |
| 291 | 294 |
| 292 void QuicCryptoClientConfig::FillInchoateClientHello( | 295 void QuicCryptoClientConfig::FillInchoateClientHello( |
| 293 const QuicServerId& server_id, | 296 const QuicServerId& server_id, |
| 294 const QuicVersion preferred_version, | 297 const QuicVersion preferred_version, |
| 295 const CachedState* cached, | 298 const CachedState* cached, |
| 296 QuicCryptoNegotiatedParameters* out_params, | 299 QuicCryptoNegotiatedParameters* out_params, |
| 297 CryptoHandshakeMessage* out) const { | 300 CryptoHandshakeMessage* out) const { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 323 | 326 |
| 324 const vector<string>& certs = cached->certs(); | 327 const vector<string>& certs = cached->certs(); |
| 325 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the | 328 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the |
| 326 // client config is being used for multiple connections, another connection | 329 // client config is being used for multiple connections, another connection |
| 327 // doesn't update the cached certificates and cause us to be unable to | 330 // doesn't update the cached certificates and cause us to be unable to |
| 328 // process the server's compressed certificate chain. | 331 // process the server's compressed certificate chain. |
| 329 out_params->cached_certs = certs; | 332 out_params->cached_certs = certs; |
| 330 if (!certs.empty()) { | 333 if (!certs.empty()) { |
| 331 vector<uint64> hashes; | 334 vector<uint64> hashes; |
| 332 hashes.reserve(certs.size()); | 335 hashes.reserve(certs.size()); |
| 333 for (vector<string>::const_iterator i = certs.begin(); | 336 for (vector<string>::const_iterator i = certs.begin(); i != certs.end(); |
| 334 i != certs.end(); ++i) { | 337 ++i) { |
| 335 hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); | 338 hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); |
| 336 } | 339 } |
| 337 out->SetVector(kCCRT, hashes); | 340 out->SetVector(kCCRT, hashes); |
| 338 } | 341 } |
| 339 } | 342 } |
| 340 | 343 |
| 341 QuicErrorCode QuicCryptoClientConfig::FillClientHello( | 344 QuicErrorCode QuicCryptoClientConfig::FillClientHello( |
| 342 const QuicServerId& server_id, | 345 const QuicServerId& server_id, |
| 343 QuicConnectionId connection_id, | 346 QuicConnectionId connection_id, |
| 344 const QuicVersion preferred_version, | 347 const QuicVersion preferred_version, |
| 345 uint32 initial_flow_control_window_bytes, | 348 uint32 initial_flow_control_window_bytes, |
| 346 const CachedState* cached, | 349 const CachedState* cached, |
| 347 QuicWallTime now, | 350 QuicWallTime now, |
| 348 QuicRandom* rand, | 351 QuicRandom* rand, |
| 349 QuicCryptoNegotiatedParameters* out_params, | 352 QuicCryptoNegotiatedParameters* out_params, |
| 350 CryptoHandshakeMessage* out, | 353 CryptoHandshakeMessage* out, |
| 351 string* error_details) const { | 354 string* error_details) const { |
| 352 DCHECK(error_details != NULL); | 355 DCHECK(error_details != NULL); |
| 353 | 356 |
| 354 FillInchoateClientHello(server_id, preferred_version, cached, | 357 FillInchoateClientHello( |
| 355 out_params, out); | 358 server_id, preferred_version, cached, out_params, out); |
| 356 | 359 |
| 357 // Set initial receive window for flow control. | 360 // Set initial receive window for flow control. |
| 358 out->SetValue(kIFCW, initial_flow_control_window_bytes); | 361 out->SetValue(kIFCW, initial_flow_control_window_bytes); |
| 359 | 362 |
| 360 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); | 363 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); |
| 361 if (!scfg) { | 364 if (!scfg) { |
| 362 // This should never happen as our caller should have checked | 365 // This should never happen as our caller should have checked |
| 363 // cached->IsComplete() before calling this function. | 366 // cached->IsComplete() before calling this function. |
| 364 *error_details = "Handshake not ready"; | 367 *error_details = "Handshake not ready"; |
| 365 return QUIC_CRYPTO_INTERNAL_ERROR; | 368 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 366 } | 369 } |
| 367 | 370 |
| 368 StringPiece scid; | 371 StringPiece scid; |
| 369 if (!scfg->GetStringPiece(kSCID, &scid)) { | 372 if (!scfg->GetStringPiece(kSCID, &scid)) { |
| 370 *error_details = "SCFG missing SCID"; | 373 *error_details = "SCFG missing SCID"; |
| 371 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 374 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 372 } | 375 } |
| 373 out->SetStringPiece(kSCID, scid); | 376 out->SetStringPiece(kSCID, scid); |
| 374 | 377 |
| 375 const QuicTag* their_aeads; | 378 const QuicTag* their_aeads; |
| 376 const QuicTag* their_key_exchanges; | 379 const QuicTag* their_key_exchanges; |
| 377 size_t num_their_aeads, num_their_key_exchanges; | 380 size_t num_their_aeads, num_their_key_exchanges; |
| 378 if (scfg->GetTaglist(kAEAD, &their_aeads, | 381 if (scfg->GetTaglist(kAEAD, &their_aeads, &num_their_aeads) != |
| 379 &num_their_aeads) != QUIC_NO_ERROR || | 382 QUIC_NO_ERROR || |
| 380 scfg->GetTaglist(kKEXS, &their_key_exchanges, | 383 scfg->GetTaglist(kKEXS, &their_key_exchanges, &num_their_key_exchanges) != |
| 381 &num_their_key_exchanges) != QUIC_NO_ERROR) { | 384 QUIC_NO_ERROR) { |
| 382 *error_details = "Missing AEAD or KEXS"; | 385 *error_details = "Missing AEAD or KEXS"; |
| 383 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 386 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 384 } | 387 } |
| 385 | 388 |
| 386 // AEAD: the work loads on the client and server are symmetric. Since the | 389 // AEAD: the work loads on the client and server are symmetric. Since the |
| 387 // client is more likely to be CPU-constrained, break the tie by favoring | 390 // client is more likely to be CPU-constrained, break the tie by favoring |
| 388 // the client's preference. | 391 // the client's preference. |
| 389 // Key exchange: the client does more work than the server, so favor the | 392 // Key exchange: the client does more work than the server, so favor the |
| 390 // client's preference. | 393 // client's preference. |
| 391 size_t key_exchange_index; | 394 size_t key_exchange_index; |
| 392 if (!QuicUtils::FindMutualTag( | 395 if (!QuicUtils::FindMutualTag(aead, |
| 393 aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY, | 396 their_aeads, |
| 394 &out_params->aead, NULL) || | 397 num_their_aeads, |
| 395 !QuicUtils::FindMutualTag( | 398 QuicUtils::LOCAL_PRIORITY, |
| 396 kexs, their_key_exchanges, num_their_key_exchanges, | 399 &out_params->aead, |
| 397 QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange, | 400 NULL) || |
| 398 &key_exchange_index)) { | 401 !QuicUtils::FindMutualTag(kexs, |
| 402 their_key_exchanges, |
| 403 num_their_key_exchanges, |
| 404 QuicUtils::LOCAL_PRIORITY, |
| 405 &out_params->key_exchange, |
| 406 &key_exchange_index)) { |
| 399 *error_details = "Unsupported AEAD or KEXS"; | 407 *error_details = "Unsupported AEAD or KEXS"; |
| 400 return QUIC_CRYPTO_NO_SUPPORT; | 408 return QUIC_CRYPTO_NO_SUPPORT; |
| 401 } | 409 } |
| 402 out->SetTaglist(kAEAD, out_params->aead, 0); | 410 out->SetTaglist(kAEAD, out_params->aead, 0); |
| 403 out->SetTaglist(kKEXS, out_params->key_exchange, 0); | 411 out->SetTaglist(kKEXS, out_params->key_exchange, 0); |
| 404 | 412 |
| 405 StringPiece public_value; | 413 StringPiece public_value; |
| 406 if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) != | 414 if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) != |
| 407 QUIC_NO_ERROR) { | 415 QUIC_NO_ERROR) { |
| 408 *error_details = "Missing public value"; | 416 *error_details = "Missing public value"; |
| 409 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 417 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 410 } | 418 } |
| 411 | 419 |
| 412 StringPiece orbit; | 420 StringPiece orbit; |
| 413 if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) { | 421 if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) { |
| 414 *error_details = "SCFG missing OBIT"; | 422 *error_details = "SCFG missing OBIT"; |
| 415 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | 423 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
| 416 } | 424 } |
| 417 | 425 |
| 418 CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce); | 426 CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce); |
| 419 out->SetStringPiece(kNONC, out_params->client_nonce); | 427 out->SetStringPiece(kNONC, out_params->client_nonce); |
| 420 if (!out_params->server_nonce.empty()) { | 428 if (!out_params->server_nonce.empty()) { |
| 421 out->SetStringPiece(kServerNonceTag, out_params->server_nonce); | 429 out->SetStringPiece(kServerNonceTag, out_params->server_nonce); |
| 422 } | 430 } |
| 423 | 431 |
| 424 switch (out_params->key_exchange) { | 432 switch (out_params->key_exchange) { |
| 425 case kC255: | 433 case kC255: |
| 426 out_params->client_key_exchange.reset(Curve25519KeyExchange::New( | 434 out_params->client_key_exchange.reset(Curve25519KeyExchange::New( |
| 427 Curve25519KeyExchange::NewPrivateKey(rand))); | 435 Curve25519KeyExchange::NewPrivateKey(rand))); |
| 428 break; | 436 break; |
| 429 case kP256: | 437 case kP256: |
| 430 out_params->client_key_exchange.reset(P256KeyExchange::New( | 438 out_params->client_key_exchange.reset( |
| 431 P256KeyExchange::NewPrivateKey())); | 439 P256KeyExchange::New(P256KeyExchange::NewPrivateKey())); |
| 432 break; | 440 break; |
| 433 default: | 441 default: |
| 434 DCHECK(false); | 442 DCHECK(false); |
| 435 *error_details = "Configured to support an unknown key exchange"; | 443 *error_details = "Configured to support an unknown key exchange"; |
| 436 return QUIC_CRYPTO_INTERNAL_ERROR; | 444 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 437 } | 445 } |
| 438 | 446 |
| 439 if (!out_params->client_key_exchange->CalculateSharedKey( | 447 if (!out_params->client_key_exchange->CalculateSharedKey( |
| 440 public_value, &out_params->initial_premaster_secret)) { | 448 public_value, &out_params->initial_premaster_secret)) { |
| 441 *error_details = "Key exchange failure"; | 449 *error_details = "Key exchange failure"; |
| 442 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 450 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 443 } | 451 } |
| 444 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); | 452 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); |
| 445 | 453 |
| 446 bool do_channel_id = false; | 454 bool do_channel_id = false; |
| 447 if (channel_id_signer_.get()) { | 455 if (channel_id_signer_.get()) { |
| 448 const QuicTag* their_proof_demands; | 456 const QuicTag* their_proof_demands; |
| 449 size_t num_their_proof_demands; | 457 size_t num_their_proof_demands; |
| 450 if (scfg->GetTaglist(kPDMD, &their_proof_demands, | 458 if (scfg->GetTaglist(kPDMD, |
| 459 &their_proof_demands, |
| 451 &num_their_proof_demands) == QUIC_NO_ERROR) { | 460 &num_their_proof_demands) == QUIC_NO_ERROR) { |
| 452 for (size_t i = 0; i < num_their_proof_demands; i++) { | 461 for (size_t i = 0; i < num_their_proof_demands; i++) { |
| 453 if (their_proof_demands[i] == kCHID) { | 462 if (their_proof_demands[i] == kCHID) { |
| 454 do_channel_id = true; | 463 do_channel_id = true; |
| 455 break; | 464 break; |
| 456 } | 465 } |
| 457 } | 466 } |
| 458 } | 467 } |
| 459 } | 468 } |
| 460 | 469 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 472 const QuicData& client_hello_serialized = out->GetSerialized(); | 481 const QuicData& client_hello_serialized = out->GetSerialized(); |
| 473 hkdf_input.append(QuicCryptoConfig::kCETVLabel, | 482 hkdf_input.append(QuicCryptoConfig::kCETVLabel, |
| 474 strlen(QuicCryptoConfig::kCETVLabel) + 1); | 483 strlen(QuicCryptoConfig::kCETVLabel) + 1); |
| 475 hkdf_input.append(reinterpret_cast<char*>(&connection_id), | 484 hkdf_input.append(reinterpret_cast<char*>(&connection_id), |
| 476 sizeof(connection_id)); | 485 sizeof(connection_id)); |
| 477 hkdf_input.append(client_hello_serialized.data(), | 486 hkdf_input.append(client_hello_serialized.data(), |
| 478 client_hello_serialized.length()); | 487 client_hello_serialized.length()); |
| 479 hkdf_input.append(cached->server_config()); | 488 hkdf_input.append(cached->server_config()); |
| 480 | 489 |
| 481 string key, signature; | 490 string key, signature; |
| 482 if (!channel_id_signer_->Sign(server_id.host(), hkdf_input, | 491 if (!channel_id_signer_->Sign( |
| 483 &key, &signature)) { | 492 server_id.host(), hkdf_input, &key, &signature)) { |
| 484 *error_details = "Channel ID signature failed"; | 493 *error_details = "Channel ID signature failed"; |
| 485 return QUIC_INVALID_CHANNEL_ID_SIGNATURE; | 494 return QUIC_INVALID_CHANNEL_ID_SIGNATURE; |
| 486 } | 495 } |
| 487 | 496 |
| 488 cetv.SetStringPiece(kCIDK, key); | 497 cetv.SetStringPiece(kCIDK, key); |
| 489 cetv.SetStringPiece(kCIDS, signature); | 498 cetv.SetStringPiece(kCIDS, signature); |
| 490 | 499 |
| 491 CrypterPair crypters; | 500 CrypterPair crypters; |
| 492 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, | 501 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, |
| 493 out_params->aead, out_params->client_nonce, | 502 out_params->aead, |
| 494 out_params->server_nonce, hkdf_input, | 503 out_params->client_nonce, |
| 495 CryptoUtils::CLIENT, &crypters)) { | 504 out_params->server_nonce, |
| 505 hkdf_input, |
| 506 CryptoUtils::CLIENT, |
| 507 &crypters)) { |
| 496 *error_details = "Symmetric key setup failed"; | 508 *error_details = "Symmetric key setup failed"; |
| 497 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 509 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
| 498 } | 510 } |
| 499 | 511 |
| 500 const QuicData& cetv_plaintext = cetv.GetSerialized(); | 512 const QuicData& cetv_plaintext = cetv.GetSerialized(); |
| 501 scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket( | 513 scoped_ptr<QuicData> cetv_ciphertext( |
| 502 0 /* sequence number */, | 514 crypters.encrypter->EncryptPacket(0 /* sequence number */, |
| 503 StringPiece() /* associated data */, | 515 StringPiece() /* associated data */, |
| 504 cetv_plaintext.AsStringPiece())); | 516 cetv_plaintext.AsStringPiece())); |
| 505 if (!cetv_ciphertext.get()) { | 517 if (!cetv_ciphertext.get()) { |
| 506 *error_details = "Packet encryption failed"; | 518 *error_details = "Packet encryption failed"; |
| 507 return QUIC_ENCRYPTION_FAILURE; | 519 return QUIC_ENCRYPTION_FAILURE; |
| 508 } | 520 } |
| 509 | 521 |
| 510 out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece()); | 522 out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece()); |
| 511 out->MarkDirty(); | 523 out->MarkDirty(); |
| 512 | 524 |
| 513 out->set_minimum_size(orig_min_size); | 525 out->set_minimum_size(orig_min_size); |
| 514 } | 526 } |
| 515 | 527 |
| 516 out_params->hkdf_input_suffix.clear(); | 528 out_params->hkdf_input_suffix.clear(); |
| 517 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&connection_id), | 529 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&connection_id), |
| 518 sizeof(connection_id)); | 530 sizeof(connection_id)); |
| 519 const QuicData& client_hello_serialized = out->GetSerialized(); | 531 const QuicData& client_hello_serialized = out->GetSerialized(); |
| 520 out_params->hkdf_input_suffix.append(client_hello_serialized.data(), | 532 out_params->hkdf_input_suffix.append(client_hello_serialized.data(), |
| 521 client_hello_serialized.length()); | 533 client_hello_serialized.length()); |
| 522 out_params->hkdf_input_suffix.append(cached->server_config()); | 534 out_params->hkdf_input_suffix.append(cached->server_config()); |
| 523 | 535 |
| 524 string hkdf_input; | 536 string hkdf_input; |
| 525 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; | 537 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; |
| 526 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); | 538 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); |
| 527 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); | 539 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); |
| 528 hkdf_input.append(out_params->hkdf_input_suffix); | 540 hkdf_input.append(out_params->hkdf_input_suffix); |
| 529 | 541 |
| 530 if (!CryptoUtils::DeriveKeys( | 542 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, |
| 531 out_params->initial_premaster_secret, out_params->aead, | 543 out_params->aead, |
| 532 out_params->client_nonce, out_params->server_nonce, hkdf_input, | 544 out_params->client_nonce, |
| 533 CryptoUtils::CLIENT, &out_params->initial_crypters)) { | 545 out_params->server_nonce, |
| 546 hkdf_input, |
| 547 CryptoUtils::CLIENT, |
| 548 &out_params->initial_crypters)) { |
| 534 *error_details = "Symmetric key setup failed"; | 549 *error_details = "Symmetric key setup failed"; |
| 535 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 550 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
| 536 } | 551 } |
| 537 | 552 |
| 538 return QUIC_NO_ERROR; | 553 return QUIC_NO_ERROR; |
| 539 } | 554 } |
| 540 | 555 |
| 541 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( | 556 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( |
| 542 const CryptoHandshakeMessage& rej, | 557 const CryptoHandshakeMessage& rej, |
| 543 QuicWallTime now, | 558 QuicWallTime now, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 570 StringPiece nonce; | 585 StringPiece nonce; |
| 571 if (rej.GetStringPiece(kServerNonceTag, &nonce)) { | 586 if (rej.GetStringPiece(kServerNonceTag, &nonce)) { |
| 572 out_params->server_nonce = nonce.as_string(); | 587 out_params->server_nonce = nonce.as_string(); |
| 573 } | 588 } |
| 574 | 589 |
| 575 StringPiece proof, cert_bytes; | 590 StringPiece proof, cert_bytes; |
| 576 bool has_proof = rej.GetStringPiece(kPROF, &proof); | 591 bool has_proof = rej.GetStringPiece(kPROF, &proof); |
| 577 bool has_cert = rej.GetStringPiece(kCertificateTag, &cert_bytes); | 592 bool has_cert = rej.GetStringPiece(kCertificateTag, &cert_bytes); |
| 578 if (has_proof && has_cert) { | 593 if (has_proof && has_cert) { |
| 579 vector<string> certs; | 594 vector<string> certs; |
| 580 if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs, | 595 if (!CertCompressor::DecompressChain( |
| 581 common_cert_sets, &certs)) { | 596 cert_bytes, out_params->cached_certs, common_cert_sets, &certs)) { |
| 582 *error_details = "Certificate data invalid"; | 597 *error_details = "Certificate data invalid"; |
| 583 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 598 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 584 } | 599 } |
| 585 | 600 |
| 586 cached->SetProof(certs, proof); | 601 cached->SetProof(certs, proof); |
| 587 } else { | 602 } else { |
| 588 cached->ClearProof(); | 603 cached->ClearProof(); |
| 589 if (has_proof && !has_cert) { | 604 if (has_proof && !has_cert) { |
| 590 *error_details = "Certificate missing"; | 605 *error_details = "Certificate missing"; |
| 591 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 606 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 610 DCHECK(error_details != NULL); | 625 DCHECK(error_details != NULL); |
| 611 | 626 |
| 612 if (server_hello.tag() != kSHLO) { | 627 if (server_hello.tag() != kSHLO) { |
| 613 *error_details = "Bad tag"; | 628 *error_details = "Bad tag"; |
| 614 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; | 629 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; |
| 615 } | 630 } |
| 616 | 631 |
| 617 const QuicTag* supported_version_tags; | 632 const QuicTag* supported_version_tags; |
| 618 size_t num_supported_versions; | 633 size_t num_supported_versions; |
| 619 | 634 |
| 620 if (server_hello.GetTaglist(kVER, &supported_version_tags, | 635 if (server_hello.GetTaglist(kVER, |
| 636 &supported_version_tags, |
| 621 &num_supported_versions) != QUIC_NO_ERROR) { | 637 &num_supported_versions) != QUIC_NO_ERROR) { |
| 622 *error_details = "server hello missing version list"; | 638 *error_details = "server hello missing version list"; |
| 623 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 639 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 624 } | 640 } |
| 625 if (!negotiated_versions.empty()) { | 641 if (!negotiated_versions.empty()) { |
| 626 bool mismatch = num_supported_versions != negotiated_versions.size(); | 642 bool mismatch = num_supported_versions != negotiated_versions.size(); |
| 627 for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) { | 643 for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) { |
| 628 mismatch = QuicTagToQuicVersion(supported_version_tags[i]) != | 644 mismatch = QuicTagToQuicVersion(supported_version_tags[i]) != |
| 629 negotiated_versions[i]; | 645 negotiated_versions[i]; |
| 630 } | 646 } |
| 631 // The server sent a list of supported versions, and the connection | 647 // The server sent a list of supported versions, and the connection |
| 632 // reports that there was a version negotiation during the handshake. | 648 // reports that there was a version negotiation during the handshake. |
| 633 // Ensure that these two lists are identical. | 649 // Ensure that these two lists are identical. |
| 634 if (mismatch) { | 650 if (mismatch) { |
| 635 *error_details = "Downgrade attack detected"; | 651 *error_details = "Downgrade attack detected"; |
| 636 return QUIC_VERSION_NEGOTIATION_MISMATCH; | 652 return QUIC_VERSION_NEGOTIATION_MISMATCH; |
| 637 } | 653 } |
| 638 } | 654 } |
| 639 | 655 |
| 640 // Learn about updated source address tokens. | 656 // Learn about updated source address tokens. |
| 641 StringPiece token; | 657 StringPiece token; |
| 642 if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) { | 658 if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) { |
| 643 cached->set_source_address_token(token); | 659 cached->set_source_address_token(token); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 657 *error_details = "Key exchange failure"; | 673 *error_details = "Key exchange failure"; |
| 658 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 674 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 659 } | 675 } |
| 660 | 676 |
| 661 string hkdf_input; | 677 string hkdf_input; |
| 662 const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; | 678 const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; |
| 663 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); | 679 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); |
| 664 hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len); | 680 hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len); |
| 665 hkdf_input.append(out_params->hkdf_input_suffix); | 681 hkdf_input.append(out_params->hkdf_input_suffix); |
| 666 | 682 |
| 667 if (!CryptoUtils::DeriveKeys( | 683 if (!CryptoUtils::DeriveKeys(out_params->forward_secure_premaster_secret, |
| 668 out_params->forward_secure_premaster_secret, out_params->aead, | 684 out_params->aead, |
| 669 out_params->client_nonce, out_params->server_nonce, hkdf_input, | 685 out_params->client_nonce, |
| 670 CryptoUtils::CLIENT, &out_params->forward_secure_crypters)) { | 686 out_params->server_nonce, |
| 687 hkdf_input, |
| 688 CryptoUtils::CLIENT, |
| 689 &out_params->forward_secure_crypters)) { |
| 671 *error_details = "Symmetric key setup failed"; | 690 *error_details = "Symmetric key setup failed"; |
| 672 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 691 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
| 673 } | 692 } |
| 674 | 693 |
| 675 return QUIC_NO_ERROR; | 694 return QUIC_NO_ERROR; |
| 676 } | 695 } |
| 677 | 696 |
| 678 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { | 697 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { |
| 679 return proof_verifier_.get(); | 698 return proof_verifier_.get(); |
| 680 } | 699 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 DCHECK(server_state->IsEmpty()); | 749 DCHECK(server_state->IsEmpty()); |
| 731 size_t i = 0; | 750 size_t i = 0; |
| 732 for (; i < canoncial_suffixes_.size(); ++i) { | 751 for (; i < canoncial_suffixes_.size(); ++i) { |
| 733 if (EndsWith(server_id.host(), canoncial_suffixes_[i], false)) { | 752 if (EndsWith(server_id.host(), canoncial_suffixes_[i], false)) { |
| 734 break; | 753 break; |
| 735 } | 754 } |
| 736 } | 755 } |
| 737 if (i == canoncial_suffixes_.size()) | 756 if (i == canoncial_suffixes_.size()) |
| 738 return; | 757 return; |
| 739 | 758 |
| 740 QuicServerId suffix_server_id(canoncial_suffixes_[i], server_id.port(), | 759 QuicServerId suffix_server_id(canoncial_suffixes_[i], |
| 760 server_id.port(), |
| 741 server_id.is_https(), | 761 server_id.is_https(), |
| 742 server_id.privacy_mode()); | 762 server_id.privacy_mode()); |
| 743 if (!ContainsKey(canonical_server_map_, suffix_server_id)) { | 763 if (!ContainsKey(canonical_server_map_, suffix_server_id)) { |
| 744 // This is the first host we've seen which matches the suffix, so make it | 764 // This is the first host we've seen which matches the suffix, so make it |
| 745 // canonical. | 765 // canonical. |
| 746 canonical_server_map_[suffix_server_id] = server_id; | 766 canonical_server_map_[suffix_server_id] = server_id; |
| 747 return; | 767 return; |
| 748 } | 768 } |
| 749 | 769 |
| 750 const QuicServerId& canonical_server_id = | 770 const QuicServerId& canonical_server_id = |
| 751 canonical_server_map_[suffix_server_id]; | 771 canonical_server_map_[suffix_server_id]; |
| 752 CachedState* canonical_state = cached_states_[canonical_server_id]; | 772 CachedState* canonical_state = cached_states_[canonical_server_id]; |
| 753 if (!canonical_state->proof_valid()) { | 773 if (!canonical_state->proof_valid()) { |
| 754 return; | 774 return; |
| 755 } | 775 } |
| 756 | 776 |
| 757 // Update canonical version to point at the "most recent" entry. | 777 // Update canonical version to point at the "most recent" entry. |
| 758 canonical_server_map_[suffix_server_id] = server_id; | 778 canonical_server_map_[suffix_server_id] = server_id; |
| 759 | 779 |
| 760 server_state->InitializeFrom(*canonical_state); | 780 server_state->InitializeFrom(*canonical_state); |
| 761 } | 781 } |
| 762 | 782 |
| 763 } // namespace net | 783 } // namespace net |
| OLD | NEW |