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 3 // found in the LICENSE file. 4 5 #include "net/quic/crypto/quic_crypto_server_config.h" 6 7 #include <stdlib.h> 8 #include <algorithm> 9 10 #include "base/stl_util.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "crypto/hkdf.h" 13 #include "crypto/secure_hash.h" 14 #include "net/base/net_util.h" 15 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h" 16 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" 17 #include "net/quic/crypto/cert_compressor.h" 18 #include "net/quic/crypto/chacha20_poly1305_encrypter.h" 19 #include "net/quic/crypto/channel_id.h" 20 #include "net/quic/crypto/crypto_framer.h" 21 #include "net/quic/crypto/crypto_server_config_protobuf.h" 22 #include "net/quic/crypto/crypto_utils.h" 23 #include "net/quic/crypto/curve25519_key_exchange.h" 24 #include "net/quic/crypto/ephemeral_key_source.h" 25 #include "net/quic/crypto/key_exchange.h" 26 #include "net/quic/crypto/local_strike_register_client.h" 27 #include "net/quic/crypto/p256_key_exchange.h" 28 #include "net/quic/crypto/proof_source.h" 29 #include "net/quic/crypto/quic_decrypter.h" 30 #include "net/quic/crypto/quic_encrypter.h" 31 #include "net/quic/crypto/quic_random.h" 32 #include "net/quic/crypto/source_address_token.h" 33 #include "net/quic/crypto/strike_register.h" 34 #include "net/quic/crypto/strike_register_client.h" 35 #include "net/quic/quic_clock.h" 36 #include "net/quic/quic_flags.h" 37 #include "net/quic/quic_protocol.h" 38 #include "net/quic/quic_socket_address_coder.h" 39 #include "net/quic/quic_utils.h" 40 41 using base::StringPiece; 42 using crypto::SecureHash; 43 using std::map; 44 using std::sort; 45 using std::string; 46 using std::vector; 47 48 namespace net { 49 50 namespace { 51 52 string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) { 53 crypto::HKDF hkdf(source_address_token_secret, 54 StringPiece() /* no salt */, 55 "QUIC source address token key", 56 CryptoSecretBoxer::GetKeySize(), 57 0 /* no fixed IV needed */); 58 return hkdf.server_write_key().as_string(); 59 } 60 61 } // namespace 62 63 // ClientHelloInfo contains information about a client hello message that is 64 // only kept for as long as it's being processed. 65 struct ClientHelloInfo { 66 ClientHelloInfo(const IPEndPoint& in_client_ip, QuicWallTime in_now) 67 : client_ip(in_client_ip), 68 now(in_now), 69 valid_source_address_token(false), 70 client_nonce_well_formed(false), 71 unique(false) {} 72 73 // Inputs to EvaluateClientHello. 74 const IPEndPoint client_ip; 75 const QuicWallTime now; 76 77 // Outputs from EvaluateClientHello. 78 bool valid_source_address_token; 79 bool client_nonce_well_formed; 80 bool unique; 81 StringPiece sni; 82 StringPiece client_nonce; 83 StringPiece server_nonce; 84 StringPiece user_agent_id; 85 86 // Errors from EvaluateClientHello. 87 vector<uint32> reject_reasons; 88 }; 89 90 struct ValidateClientHelloResultCallback::Result { 91 Result(const CryptoHandshakeMessage& in_client_hello, 92 IPEndPoint in_client_ip, 93 QuicWallTime in_now) 94 : client_hello(in_client_hello), 95 info(in_client_ip, in_now), 96 error_code(QUIC_NO_ERROR) { 97 } 98 99 CryptoHandshakeMessage client_hello; 100 ClientHelloInfo info; 101 QuicErrorCode error_code; 102 string error_details; 103 }; 104 105 class ValidateClientHelloHelper { 106 public: 107 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result, 108 ValidateClientHelloResultCallback* done_cb) 109 : result_(result), done_cb_(done_cb) { 110 } 111 112 ~ValidateClientHelloHelper() { 113 LOG_IF(DFATAL, done_cb_ != NULL) 114 << "Deleting ValidateClientHelloHelper with a pending callback."; 115 } 116 117 void ValidationComplete(QuicErrorCode error_code, const char* error_details) { 118 result_->error_code = error_code; 119 result_->error_details = error_details; 120 done_cb_->Run(result_); 121 DetachCallback(); 122 } 123 124 void StartedAsyncCallback() { 125 DetachCallback(); 126 } 127 128 private: 129 void DetachCallback() { 130 LOG_IF(DFATAL, done_cb_ == NULL) << "Callback already detached."; 131 done_cb_ = NULL; 132 } 133 134 ValidateClientHelloResultCallback::Result* result_; 135 ValidateClientHelloResultCallback* done_cb_; 136 137 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper); 138 }; 139 140 class VerifyNonceIsValidAndUniqueCallback 141 : public StrikeRegisterClient::ResultCallback { 142 public: 143 VerifyNonceIsValidAndUniqueCallback( 144 ValidateClientHelloResultCallback::Result* result, 145 ValidateClientHelloResultCallback* done_cb) 146 : result_(result), done_cb_(done_cb) { 147 } 148 149 protected: 150 virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE { 151 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique; 152 result_->info.unique = nonce_is_valid_and_unique; 153 // TODO(rtenneti): Implement capturing of error from strike register. 154 // Temporarily treat them as CLIENT_NONCE_UNKNOWN_FAILURE. 155 if (!nonce_is_valid_and_unique) { 156 result_->info.reject_reasons.push_back( 157 static_cast<uint32>(CLIENT_NONCE_UNKNOWN_FAILURE)); 158 } 159 done_cb_->Run(result_); 160 } 161 162 private: 163 ValidateClientHelloResultCallback::Result* result_; 164 ValidateClientHelloResultCallback* done_cb_; 165 166 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback); 167 }; 168 169 // static 170 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing"; 171 172 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() { 173 } 174 175 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() { 176 } 177 178 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() { 179 } 180 181 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() { 182 } 183 184 void ValidateClientHelloResultCallback::Run(const Result* result) { 185 RunImpl(result->client_hello, *result); 186 delete result; 187 delete this; 188 } 189 190 QuicCryptoServerConfig::ConfigOptions::ConfigOptions() 191 : expiry_time(QuicWallTime::Zero()), 192 channel_id_enabled(false), 193 p256(false) {} 194 195 QuicCryptoServerConfig::QuicCryptoServerConfig( 196 StringPiece source_address_token_secret, 197 QuicRandom* rand) 198 : replay_protection_(true), 199 configs_lock_(), 200 primary_config_(NULL), 201 next_config_promotion_time_(QuicWallTime::Zero()), 202 server_nonce_strike_register_lock_(), 203 strike_register_no_startup_period_(false), 204 strike_register_max_entries_(1 << 10), 205 strike_register_window_secs_(600), 206 source_address_token_future_secs_(3600), 207 source_address_token_lifetime_secs_(86400), 208 server_nonce_strike_register_max_entries_(1 << 10), 209 server_nonce_strike_register_window_secs_(120) { 210 default_source_address_token_boxer_.SetKey( 211 DeriveSourceAddressTokenKey(source_address_token_secret)); 212 213 // Generate a random key and orbit for server nonces. 214 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_)); 215 const size_t key_size = server_nonce_boxer_.GetKeySize(); 216 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); 217 rand->RandBytes(key_bytes.get(), key_size); 218 219 server_nonce_boxer_.SetKey( 220 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size)); 221 } 222 223 QuicCryptoServerConfig::~QuicCryptoServerConfig() { 224 primary_config_ = NULL; 225 } 226 227 // static 228 QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig( 229 QuicRandom* rand, 230 const QuicClock* clock, 231 const ConfigOptions& options) { 232 CryptoHandshakeMessage msg; 233 234 const string curve25519_private_key = 235 Curve25519KeyExchange::NewPrivateKey(rand); 236 scoped_ptr<Curve25519KeyExchange> curve25519( 237 Curve25519KeyExchange::New(curve25519_private_key)); 238 StringPiece curve25519_public_value = curve25519->public_value(); 239 240 string encoded_public_values; 241 // First three bytes encode the length of the public value. 242 encoded_public_values.push_back(curve25519_public_value.size()); 243 encoded_public_values.push_back(curve25519_public_value.size() >> 8); 244 encoded_public_values.push_back(curve25519_public_value.size() >> 16); 245 encoded_public_values.append(curve25519_public_value.data(), 246 curve25519_public_value.size()); 247 248 string p256_private_key; 249 if (options.p256) { 250 p256_private_key = P256KeyExchange::NewPrivateKey(); 251 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key)); 252 StringPiece p256_public_value = p256->public_value(); 253 254 encoded_public_values.push_back(p256_public_value.size()); 255 encoded_public_values.push_back(p256_public_value.size() >> 8); 256 encoded_public_values.push_back(p256_public_value.size() >> 16); 257 encoded_public_values.append(p256_public_value.data(), 258 p256_public_value.size()); 259 } 260 261 msg.set_tag(kSCFG); 262 if (options.p256) { 263 msg.SetTaglist(kKEXS, kC255, kP256, 0); 264 } else { 265 msg.SetTaglist(kKEXS, kC255, 0); 266 } 267 if (ChaCha20Poly1305Encrypter::IsSupported()) { 268 msg.SetTaglist(kAEAD, kAESG, kCC12, 0); 269 } else { 270 msg.SetTaglist(kAEAD, kAESG, 0); 271 } 272 msg.SetStringPiece(kPUBS, encoded_public_values); 273 274 if (options.expiry_time.IsZero()) { 275 const QuicWallTime now = clock->WallNow(); 276 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds( 277 60 * 60 * 24 * 180 /* 180 days, ~six months */)); 278 const uint64 expiry_seconds = expiry.ToUNIXSeconds(); 279 msg.SetValue(kEXPY, expiry_seconds); 280 } else { 281 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds()); 282 } 283 284 char orbit_bytes[kOrbitSize]; 285 if (options.orbit.size() == sizeof(orbit_bytes)) { 286 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes)); 287 } else { 288 DCHECK(options.orbit.empty()); 289 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes)); 290 } 291 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes))); 292 293 if (options.channel_id_enabled) { 294 msg.SetTaglist(kPDMD, kCHID, 0); 295 } 296 297 if (options.id.empty()) { 298 // We need to ensure that the SCID changes whenever the server config does 299 // thus we make it a hash of the rest of the server config. 300 scoped_ptr<QuicData> serialized( 301 CryptoFramer::ConstructHandshakeMessage(msg)); 302 scoped_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256)); 303 hash->Update(serialized->data(), serialized->length()); 304 305 char scid_bytes[16]; 306 hash->Finish(scid_bytes, sizeof(scid_bytes)); 307 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes))); 308 } else { 309 msg.SetStringPiece(kSCID, options.id); 310 } 311 // Don't put new tags below this point. The SCID generation should hash over 312 // everything but itself and so extra tags should be added prior to the 313 // preceeding if block. 314 315 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg)); 316 317 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf); 318 config->set_config(serialized->AsStringPiece()); 319 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key(); 320 curve25519_key->set_tag(kC255); 321 curve25519_key->set_private_key(curve25519_private_key); 322 323 if (options.p256) { 324 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key(); 325 p256_key->set_tag(kP256); 326 p256_key->set_private_key(p256_private_key); 327 } 328 329 return config.release(); 330 } 331 332 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig( 333 QuicServerConfigProtobuf* protobuf, 334 const QuicWallTime now) { 335 scoped_ptr<CryptoHandshakeMessage> msg( 336 CryptoFramer::ParseMessage(protobuf->config())); 337 338 if (!msg.get()) { 339 LOG(WARNING) << "Failed to parse server config message"; 340 return NULL; 341 } 342 343 scoped_refptr<Config> config(ParseConfigProtobuf(protobuf)); 344 if (!config.get()) { 345 LOG(WARNING) << "Failed to parse server config message"; 346 return NULL; 347 } 348 349 { 350 base::AutoLock locked(configs_lock_); 351 if (configs_.find(config->id) != configs_.end()) { 352 LOG(WARNING) << "Failed to add config because another with the same " 353 "server config id already exists: " 354 << base::HexEncode(config->id.data(), config->id.size()); 355 return NULL; 356 } 357 358 configs_[config->id] = config; 359 SelectNewPrimaryConfig(now); 360 DCHECK(primary_config_.get()); 361 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_); 362 } 363 364 return msg.release(); 365 } 366 367 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig( 368 QuicRandom* rand, 369 const QuicClock* clock, 370 const ConfigOptions& options) { 371 scoped_ptr<QuicServerConfigProtobuf> config( 372 GenerateConfig(rand, clock, options)); 373 return AddConfig(config.get(), clock->WallNow()); 374 } 375 376 bool QuicCryptoServerConfig::SetConfigs( 377 const vector<QuicServerConfigProtobuf*>& protobufs, 378 const QuicWallTime now) { 379 vector<scoped_refptr<Config> > parsed_configs; 380 bool ok = true; 381 382 for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin(); 383 i != protobufs.end(); ++i) { 384 scoped_refptr<Config> config(ParseConfigProtobuf(*i)); 385 if (!config.get()) { 386 ok = false; 387 break; 388 } 389 390 parsed_configs.push_back(config); 391 } 392 393 if (parsed_configs.empty()) { 394 LOG(WARNING) << "New config list is empty."; 395 ok = false; 396 } 397 398 if (!ok) { 399 LOG(WARNING) << "Rejecting QUIC configs because of above errors"; 400 } else { 401 VLOG(1) << "Updating configs:"; 402 403 base::AutoLock locked(configs_lock_); 404 ConfigMap new_configs; 405 406 for (vector<scoped_refptr<Config> >::const_iterator i = 407 parsed_configs.begin(); 408 i != parsed_configs.end(); ++i) { 409 scoped_refptr<Config> config = *i; 410 411 ConfigMap::iterator it = configs_.find(config->id); 412 if (it != configs_.end()) { 413 VLOG(1) 414 << "Keeping scid: " << base::HexEncode( 415 config->id.data(), config->id.size()) 416 << " orbit: " << base::HexEncode( 417 reinterpret_cast<const char *>(config->orbit), kOrbitSize) 418 << " new primary_time " << config->primary_time.ToUNIXSeconds() 419 << " old primary_time " << it->second->primary_time.ToUNIXSeconds() 420 << " new priority " << config->priority 421 << " old priority " << it->second->priority; 422 // Update primary_time and priority. 423 it->second->primary_time = config->primary_time; 424 it->second->priority = config->priority; 425 new_configs.insert(*it); 426 } else { 427 VLOG(1) << "Adding scid: " << base::HexEncode( 428 config->id.data(), config->id.size()) 429 << " orbit: " << base::HexEncode( 430 reinterpret_cast<const char *>(config->orbit), kOrbitSize) 431 << " primary_time " << config->primary_time.ToUNIXSeconds() 432 << " priority " << config->priority; 433 new_configs.insert(make_pair(config->id, config)); 434 } 435 } 436 437 configs_.swap(new_configs); 438 SelectNewPrimaryConfig(now); 439 DCHECK(primary_config_); 440 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_); 441 } 442 443 return ok; 444 } 445 446 void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const { 447 base::AutoLock locked(configs_lock_); 448 for (ConfigMap::const_iterator it = configs_.begin(); 449 it != configs_.end(); ++it) { 450 scids->push_back(it->first); 451 } 452 } 453 454 void QuicCryptoServerConfig::ValidateClientHello( 455 const CryptoHandshakeMessage& client_hello, 456 IPEndPoint client_ip, 457 const QuicClock* clock, 458 ValidateClientHelloResultCallback* done_cb) const { 459 const QuicWallTime now(clock->WallNow()); 460 461 ValidateClientHelloResultCallback::Result* result = 462 new ValidateClientHelloResultCallback::Result( 463 client_hello, client_ip, now); 464 465 StringPiece requested_scid; 466 client_hello.GetStringPiece(kSCID, &requested_scid); 467 468 uint8 primary_orbit[kOrbitSize]; 469 scoped_refptr<Config> requested_config; 470 { 471 base::AutoLock locked(configs_lock_); 472 473 if (!primary_config_.get()) { 474 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR; 475 result->error_details = "No configurations loaded"; 476 } else { 477 if (!next_config_promotion_time_.IsZero() && 478 next_config_promotion_time_.IsAfter(now)) { 479 SelectNewPrimaryConfig(now); 480 DCHECK(primary_config_); 481 DCHECK(configs_.find(primary_config_->id)->second == primary_config_); 482 } 483 484 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit)); 485 } 486 487 requested_config = GetConfigWithScid(requested_scid); 488 } 489 490 if (result->error_code == QUIC_NO_ERROR) { 491 EvaluateClientHello(primary_orbit, requested_config, result, done_cb); 492 } else { 493 done_cb->Run(result); 494 } 495 } 496 497 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( 498 const ValidateClientHelloResultCallback::Result& validate_chlo_result, 499 QuicConnectionId connection_id, 500 IPEndPoint client_address, 501 QuicVersion version, 502 const QuicVersionVector& supported_versions, 503 const QuicClock* clock, 504 QuicRandom* rand, 505 QuicCryptoNegotiatedParameters *params, 506 CryptoHandshakeMessage* out, 507 string* error_details) const { 508 DCHECK(error_details); 509 510 const CryptoHandshakeMessage& client_hello = 511 validate_chlo_result.client_hello; 512 const ClientHelloInfo& info = validate_chlo_result.info; 513 514 // If the client's preferred version is not the version we are currently 515 // speaking, then the client went through a version negotiation. In this 516 // case, we need to make sure that we actually do not support this version 517 // and that it wasn't a downgrade attack. 518 QuicTag client_version_tag; 519 if (client_hello.GetUint32(kVER, &client_version_tag) != QUIC_NO_ERROR) { 520 *error_details = "client hello missing version list"; 521 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 522 } 523 QuicVersion client_version = QuicTagToQuicVersion(client_version_tag); 524 if (client_version != version) { 525 // Just because client_version is a valid version enum doesn't mean that 526 // this server actually supports that version, so we check to see if 527 // it's actually in the supported versions list. 528 for (size_t i = 0; i < supported_versions.size(); ++i) { 529 if (client_version == supported_versions[i]) { 530 *error_details = "Downgrade attack detected"; 531 return QUIC_VERSION_NEGOTIATION_MISMATCH; 532 } 533 } 534 } 535 536 StringPiece requested_scid; 537 client_hello.GetStringPiece(kSCID, &requested_scid); 538 const QuicWallTime now(clock->WallNow()); 539 540 scoped_refptr<Config> requested_config; 541 scoped_refptr<Config> primary_config; 542 { 543 base::AutoLock locked(configs_lock_); 544 545 if (!primary_config_.get()) { 546 *error_details = "No configurations loaded"; 547 return QUIC_CRYPTO_INTERNAL_ERROR; 548 } 549 550 if (!next_config_promotion_time_.IsZero() && 551 next_config_promotion_time_.IsAfter(now)) { 552 SelectNewPrimaryConfig(now); 553 DCHECK(primary_config_); 554 DCHECK(configs_.find(primary_config_->id)->second == primary_config_); 555 } 556 557 // We'll use the config that the client requested in order to do 558 // key-agreement. Otherwise we'll give it a copy of |primary_config_| 559 // to use. 560 primary_config = primary_config_; 561 562 requested_config = GetConfigWithScid(requested_scid); 563 } 564 565 if (validate_chlo_result.error_code != QUIC_NO_ERROR) { 566 *error_details = validate_chlo_result.error_details; 567 return validate_chlo_result.error_code; 568 } 569 570 out->Clear(); 571 572 if (!info.valid_source_address_token || 573 !info.client_nonce_well_formed || 574 !info.unique || 575 !requested_config.get()) { 576 BuildRejection(*primary_config, client_hello, info, rand, out); 577 return QUIC_NO_ERROR; 578 } 579 580 const QuicTag* their_aeads; 581 const QuicTag* their_key_exchanges; 582 size_t num_their_aeads, num_their_key_exchanges; 583 if (client_hello.GetTaglist(kAEAD, &their_aeads, 584 &num_their_aeads) != QUIC_NO_ERROR || 585 client_hello.GetTaglist(kKEXS, &their_key_exchanges, 586 &num_their_key_exchanges) != QUIC_NO_ERROR || 587 num_their_aeads != 1 || 588 num_their_key_exchanges != 1) { 589 *error_details = "Missing or invalid AEAD or KEXS"; 590 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 591 } 592 593 size_t key_exchange_index; 594 if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads, 595 num_their_aeads, QuicUtils::LOCAL_PRIORITY, 596 ¶ms->aead, NULL) || 597 !QuicUtils::FindMutualTag( 598 requested_config->kexs, their_key_exchanges, num_their_key_exchanges, 599 QuicUtils::LOCAL_PRIORITY, ¶ms->key_exchange, 600 &key_exchange_index)) { 601 *error_details = "Unsupported AEAD or KEXS"; 602 return QUIC_CRYPTO_NO_SUPPORT; 603 } 604 605 StringPiece public_value; 606 if (!client_hello.GetStringPiece(kPUBS, &public_value)) { 607 *error_details = "Missing public value"; 608 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 609 } 610 611 const KeyExchange* key_exchange = 612 requested_config->key_exchanges[key_exchange_index]; 613 if (!key_exchange->CalculateSharedKey(public_value, 614 ¶ms->initial_premaster_secret)) { 615 *error_details = "Invalid public value"; 616 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 617 } 618 619 if (!info.sni.empty()) { 620 scoped_ptr<char[]> sni_tmp(new char[info.sni.length() + 1]); 621 memcpy(sni_tmp.get(), info.sni.data(), info.sni.length()); 622 sni_tmp[info.sni.length()] = 0; 623 params->sni = CryptoUtils::NormalizeHostname(sni_tmp.get()); 624 } 625 626 string hkdf_suffix; 627 const QuicData& client_hello_serialized = client_hello.GetSerialized(); 628 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() + 629 requested_config->serialized.size()); 630 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id), 631 sizeof(connection_id)); 632 hkdf_suffix.append(client_hello_serialized.data(), 633 client_hello_serialized.length()); 634 hkdf_suffix.append(requested_config->serialized); 635 636 StringPiece cetv_ciphertext; 637 if (requested_config->channel_id_enabled && 638 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) { 639 CryptoHandshakeMessage client_hello_copy(client_hello); 640 client_hello_copy.Erase(kCETV); 641 client_hello_copy.Erase(kPAD); 642 643 const QuicData& client_hello_serialized = client_hello_copy.GetSerialized(); 644 string hkdf_input; 645 hkdf_input.append(QuicCryptoConfig::kCETVLabel, 646 strlen(QuicCryptoConfig::kCETVLabel) + 1); 647 hkdf_input.append(reinterpret_cast<char*>(&connection_id), 648 sizeof(connection_id)); 649 hkdf_input.append(client_hello_serialized.data(), 650 client_hello_serialized.length()); 651 hkdf_input.append(requested_config->serialized); 652 653 CrypterPair crypters; 654 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead, 655 info.client_nonce, info.server_nonce, 656 hkdf_input, CryptoUtils::SERVER, &crypters)) { 657 *error_details = "Symmetric key setup failed"; 658 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; 659 } 660 661 scoped_ptr<QuicData> cetv_plaintext(crypters.decrypter->DecryptPacket( 662 0 /* sequence number */, StringPiece() /* associated data */, 663 cetv_ciphertext)); 664 if (!cetv_plaintext.get()) { 665 *error_details = "CETV decryption failure"; 666 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 667 } 668 669 scoped_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage( 670 cetv_plaintext->AsStringPiece())); 671 if (!cetv.get()) { 672 *error_details = "CETV parse error"; 673 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 674 } 675 676 StringPiece key, signature; 677 if (cetv->GetStringPiece(kCIDK, &key) && 678 cetv->GetStringPiece(kCIDS, &signature)) { 679 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) { 680 *error_details = "ChannelID signature failure"; 681 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 682 } 683 684 params->channel_id = key.as_string(); 685 } 686 } 687 688 string hkdf_input; 689 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; 690 hkdf_input.reserve(label_len + hkdf_suffix.size()); 691 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); 692 hkdf_input.append(hkdf_suffix); 693 694 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead, 695 info.client_nonce, info.server_nonce, hkdf_input, 696 CryptoUtils::SERVER, 697 ¶ms->initial_crypters)) { 698 *error_details = "Symmetric key setup failed"; 699 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; 700 } 701 702 string forward_secure_public_value; 703 if (ephemeral_key_source_.get()) { 704 params->forward_secure_premaster_secret = 705 ephemeral_key_source_->CalculateForwardSecureKey( 706 key_exchange, rand, clock->ApproximateNow(), public_value, 707 &forward_secure_public_value); 708 } else { 709 scoped_ptr<KeyExchange> forward_secure_key_exchange( 710 key_exchange->NewKeyPair(rand)); 711 forward_secure_public_value = 712 forward_secure_key_exchange->public_value().as_string(); 713 if (!forward_secure_key_exchange->CalculateSharedKey( 714 public_value, ¶ms->forward_secure_premaster_secret)) { 715 *error_details = "Invalid public value"; 716 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 717 } 718 } 719 720 string forward_secure_hkdf_input; 721 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; 722 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size()); 723 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, 724 label_len); 725 forward_secure_hkdf_input.append(hkdf_suffix); 726 727 if (!CryptoUtils::DeriveKeys( 728 params->forward_secure_premaster_secret, params->aead, 729 info.client_nonce, info.server_nonce, forward_secure_hkdf_input, 730 CryptoUtils::SERVER, ¶ms->forward_secure_crypters)) { 731 *error_details = "Symmetric key setup failed"; 732 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; 733 } 734 735 out->set_tag(kSHLO); 736 QuicTagVector supported_version_tags; 737 for (size_t i = 0; i < supported_versions.size(); ++i) { 738 supported_version_tags.push_back 739 (QuicVersionToQuicTag(supported_versions[i])); 740 } 741 out->SetVector(kVER, supported_version_tags); 742 out->SetStringPiece(kSourceAddressTokenTag, 743 NewSourceAddressToken( 744 *requested_config, 745 client_address, rand, 746 info.now)); 747 QuicSocketAddressCoder address_coder(client_address); 748 out->SetStringPiece(kCADR, address_coder.Encode()); 749 out->SetStringPiece(kPUBS, forward_secure_public_value); 750 751 return QUIC_NO_ERROR; 752 } 753 754 scoped_refptr<QuicCryptoServerConfig::Config> 755 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const { 756 // In Chromium, we will dead lock if the lock is held by the current thread. 757 // Chromium doesn't have AssertReaderHeld API call. 758 // configs_lock_.AssertReaderHeld(); 759 760 if (!requested_scid.empty()) { 761 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string()); 762 if (it != configs_.end()) { 763 // We'll use the config that the client requested in order to do 764 // key-agreement. 765 return scoped_refptr<Config>(it->second); 766 } 767 } 768 769 return scoped_refptr<Config>(); 770 } 771 772 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for 773 // Config's based on their primary_time. 774 // static 775 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan( 776 const scoped_refptr<Config>& a, 777 const scoped_refptr<Config>& b) { 778 if (a->primary_time.IsBefore(b->primary_time) || 779 b->primary_time.IsBefore(a->primary_time)) { 780 // Primary times differ. 781 return a->primary_time.IsBefore(b->primary_time); 782 } else if (a->priority != b->priority) { 783 // Primary times are equal, sort backwards by priority. 784 return a->priority < b->priority; 785 } else { 786 // Primary times and priorities are equal, sort by config id. 787 return a->id < b->id; 788 } 789 } 790 791 void QuicCryptoServerConfig::SelectNewPrimaryConfig( 792 const QuicWallTime now) const { 793 vector<scoped_refptr<Config> > configs; 794 configs.reserve(configs_.size()); 795 796 for (ConfigMap::const_iterator it = configs_.begin(); 797 it != configs_.end(); ++it) { 798 // TODO(avd) Exclude expired configs? 799 configs.push_back(it->second); 800 } 801 802 if (configs.empty()) { 803 if (primary_config_.get()) { 804 LOG(DFATAL) << "No valid QUIC server config. Keeping the current config."; 805 } else { 806 LOG(DFATAL) << "No valid QUIC server config."; 807 } 808 return; 809 } 810 811 sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan); 812 813 Config* best_candidate = configs[0]; 814 815 for (size_t i = 0; i < configs.size(); ++i) { 816 const scoped_refptr<Config> config(configs[i]); 817 if (!config->primary_time.IsAfter(now)) { 818 if (config->primary_time.IsAfter(best_candidate->primary_time)) { 819 best_candidate = config; 820 } 821 continue; 822 } 823 824 // This is the first config with a primary_time in the future. Thus the 825 // previous Config should be the primary and this one should determine the 826 // next_config_promotion_time_. 827 scoped_refptr<Config> new_primary(best_candidate); 828 if (i == 0) { 829 // We need the primary_time of the next config. 830 if (configs.size() > 1) { 831 next_config_promotion_time_ = configs[1]->primary_time; 832 } else { 833 next_config_promotion_time_ = QuicWallTime::Zero(); 834 } 835 } else { 836 next_config_promotion_time_ = config->primary_time; 837 } 838 839 if (primary_config_.get()) { 840 primary_config_->is_primary = false; 841 } 842 primary_config_ = new_primary; 843 new_primary->is_primary = true; 844 DVLOG(1) << "New primary config. orbit: " 845 << base::HexEncode( 846 reinterpret_cast<const char*>(primary_config_->orbit), 847 kOrbitSize); 848 if (primary_config_changed_cb_.get() != NULL) { 849 primary_config_changed_cb_->Run(primary_config_->id); 850 } 851 852 return; 853 } 854 855 // All config's primary times are in the past. We should make the most recent 856 // and highest priority candidate primary. 857 scoped_refptr<Config> new_primary(best_candidate); 858 if (primary_config_.get()) { 859 primary_config_->is_primary = false; 860 } 861 primary_config_ = new_primary; 862 new_primary->is_primary = true; 863 DVLOG(1) << "New primary config. orbit: " 864 << base::HexEncode( 865 reinterpret_cast<const char*>(primary_config_->orbit), 866 kOrbitSize) 867 << " scid: " << base::HexEncode(primary_config_->id.data(), 868 primary_config_->id.size()); 869 next_config_promotion_time_ = QuicWallTime::Zero(); 870 if (primary_config_changed_cb_.get() != NULL) { 871 primary_config_changed_cb_->Run(primary_config_->id); 872 } 873 } 874 875 void QuicCryptoServerConfig::EvaluateClientHello( 876 const uint8* primary_orbit, 877 scoped_refptr<Config> requested_config, 878 ValidateClientHelloResultCallback::Result* client_hello_state, 879 ValidateClientHelloResultCallback* done_cb) const { 880 ValidateClientHelloHelper helper(client_hello_state, done_cb); 881 882 const CryptoHandshakeMessage& client_hello = 883 client_hello_state->client_hello; 884 ClientHelloInfo* info = &(client_hello_state->info); 885 886 if (client_hello.size() < kClientHelloMinimumSize) { 887 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH, 888 "Client hello too small"); 889 return; 890 } 891 892 if (client_hello.GetStringPiece(kSNI, &info->sni) && 893 !CryptoUtils::IsValidSNI(info->sni)) { 894 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, 895 "Invalid SNI name"); 896 return; 897 } 898 899 client_hello.GetStringPiece(kUAID, &info->user_agent_id); 900 901 if (!requested_config.get()) { 902 StringPiece requested_scid; 903 if (client_hello.GetStringPiece(kSCID, &requested_scid)) { 904 info->reject_reasons.push_back( 905 static_cast<uint32>(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE)); 906 } else { 907 info->reject_reasons.push_back( 908 static_cast<uint32>(SERVER_CONFIG_INCHOATE_HELLO_FAILURE)); 909 } 910 // No server config with the requested ID. 911 helper.ValidationComplete(QUIC_NO_ERROR, ""); 912 return; 913 } 914 915 HandshakeFailureReason source_address_token_error; 916 StringPiece srct; 917 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) { 918 source_address_token_error = 919 ValidateSourceAddressToken(*requested_config, 920 srct, 921 info->client_ip, 922 info->now); 923 info->valid_source_address_token = 924 (source_address_token_error == HANDSHAKE_OK); 925 } else { 926 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE; 927 } 928 929 bool found_error = false; 930 if (source_address_token_error != HANDSHAKE_OK) { 931 info->reject_reasons.push_back( 932 static_cast<uint32>(source_address_token_error)); 933 // No valid source address token. 934 if (FLAGS_use_early_return_when_verifying_chlo) { 935 helper.ValidationComplete(QUIC_NO_ERROR, ""); 936 return; 937 } 938 found_error = true; 939 } 940 941 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) && 942 info->client_nonce.size() == kNonceSize) { 943 info->client_nonce_well_formed = true; 944 } else { 945 info->reject_reasons.push_back( 946 static_cast<uint32>(CLIENT_NONCE_INVALID_FAILURE)); 947 // Invalid client nonce. 948 DVLOG(1) << "Invalid client nonce."; 949 if (FLAGS_use_early_return_when_verifying_chlo) { 950 helper.ValidationComplete(QUIC_NO_ERROR, ""); 951 return; 952 } 953 found_error = true; 954 } 955 956 if (!replay_protection_) { 957 if (!found_error) { 958 info->unique = true; 959 } 960 DVLOG(1) << "No replay protection."; 961 helper.ValidationComplete(QUIC_NO_ERROR, ""); 962 return; 963 } 964 965 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce); 966 if (!info->server_nonce.empty()) { 967 // If the server nonce is present, use it to establish uniqueness. 968 HandshakeFailureReason server_nonce_error = 969 ValidateServerNonce(info->server_nonce, info->now); 970 if (server_nonce_error == HANDSHAKE_OK) { 971 info->unique = true; 972 } else { 973 info->reject_reasons.push_back(static_cast<uint32>(server_nonce_error)); 974 info->unique = false; 975 } 976 DVLOG(1) << "Using server nonce, unique: " << info->unique; 977 helper.ValidationComplete(QUIC_NO_ERROR, ""); 978 return; 979 } 980 981 // We want to contact strike register if there are no errors because it is 982 // a RPC call and is expensive. 983 if (found_error) { 984 helper.ValidationComplete(QUIC_NO_ERROR, ""); 985 return; 986 } 987 988 // Use the client nonce to establish uniqueness. 989 StrikeRegisterClient* strike_register_client; 990 { 991 base::AutoLock locked(strike_register_client_lock_); 992 993 if (strike_register_client_.get() == NULL) { 994 strike_register_client_.reset(new LocalStrikeRegisterClient( 995 strike_register_max_entries_, 996 static_cast<uint32>(info->now.ToUNIXSeconds()), 997 strike_register_window_secs_, 998 primary_orbit, 999 strike_register_no_startup_period_ ? 1000 StrikeRegister::NO_STARTUP_PERIOD_NEEDED : 1001 StrikeRegister::DENY_REQUESTS_AT_STARTUP)); 1002 } 1003 strike_register_client = strike_register_client_.get(); 1004 } 1005 1006 strike_register_client->VerifyNonceIsValidAndUnique( 1007 info->client_nonce, 1008 info->now, 1009 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb)); 1010 helper.StartedAsyncCallback(); 1011 } 1012 1013 void QuicCryptoServerConfig::BuildRejection( 1014 const Config& config, 1015 const CryptoHandshakeMessage& client_hello, 1016 const ClientHelloInfo& info, 1017 QuicRandom* rand, 1018 CryptoHandshakeMessage* out) const { 1019 out->set_tag(kREJ); 1020 out->SetStringPiece(kSCFG, config.serialized); 1021 out->SetStringPiece(kSourceAddressTokenTag, 1022 NewSourceAddressToken( 1023 config, 1024 info.client_ip, 1025 rand, 1026 info.now)); 1027 if (replay_protection_) { 1028 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now)); 1029 } 1030 1031 if (FLAGS_send_quic_crypto_reject_reason) { 1032 // Send client the reject reason for debugging purposes. 1033 DCHECK_LT(0u, info.reject_reasons.size()); 1034 out->SetVector(kRREJ, info.reject_reasons); 1035 } 1036 1037 // The client may have requested a certificate chain. 1038 const QuicTag* their_proof_demands; 1039 size_t num_their_proof_demands; 1040 1041 if (proof_source_.get() == NULL || 1042 client_hello.GetTaglist(kPDMD, &their_proof_demands, 1043 &num_their_proof_demands) != 1044 QUIC_NO_ERROR) { 1045 return; 1046 } 1047 1048 bool x509_supported = false, x509_ecdsa_supported = false; 1049 for (size_t i = 0; i < num_their_proof_demands; i++) { 1050 switch (their_proof_demands[i]) { 1051 case kX509: 1052 x509_supported = true; 1053 x509_ecdsa_supported = true; 1054 break; 1055 case kX59R: 1056 x509_supported = true; 1057 break; 1058 } 1059 } 1060 1061 if (!x509_supported) { 1062 return; 1063 } 1064 1065 const vector<string>* certs; 1066 string signature; 1067 if (!proof_source_->GetProof(info.sni.as_string(), config.serialized, 1068 x509_ecdsa_supported, &certs, &signature)) { 1069 return; 1070 } 1071 1072 StringPiece their_common_set_hashes; 1073 StringPiece their_cached_cert_hashes; 1074 client_hello.GetStringPiece(kCCS, &their_common_set_hashes); 1075 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes); 1076 1077 const string compressed = CertCompressor::CompressChain( 1078 *certs, their_common_set_hashes, their_cached_cert_hashes, 1079 config.common_cert_sets); 1080 1081 // kREJOverheadBytes is a very rough estimate of how much of a REJ 1082 // message is taken up by things other than the certificates. 1083 // STK: 56 bytes 1084 // SNO: 56 bytes 1085 // SCFG 1086 // SCID: 16 bytes 1087 // PUBS: 38 bytes 1088 const size_t kREJOverheadBytes = 166; 1089 // kMultiplier is the multiple of the CHLO message size that a REJ message 1090 // must stay under when the client doesn't present a valid source-address 1091 // token. 1092 const size_t kMultiplier = 2; 1093 // max_unverified_size is the number of bytes that the certificate chain 1094 // and signature can consume before we will demand a valid source-address 1095 // token. 1096 const size_t max_unverified_size = 1097 client_hello.size() * kMultiplier - kREJOverheadBytes; 1098 COMPILE_ASSERT(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes, 1099 overhead_calculation_may_underflow); 1100 if (info.valid_source_address_token || 1101 signature.size() + compressed.size() < max_unverified_size) { 1102 out->SetStringPiece(kCertificateTag, compressed); 1103 out->SetStringPiece(kPROF, signature); 1104 } 1105 } 1106 1107 scoped_refptr<QuicCryptoServerConfig::Config> 1108 QuicCryptoServerConfig::ParseConfigProtobuf( 1109 QuicServerConfigProtobuf* protobuf) { 1110 scoped_ptr<CryptoHandshakeMessage> msg( 1111 CryptoFramer::ParseMessage(protobuf->config())); 1112 1113 if (msg->tag() != kSCFG) { 1114 LOG(WARNING) << "Server config message has tag " << msg->tag() 1115 << " expected " << kSCFG; 1116 return NULL; 1117 } 1118 1119 scoped_refptr<Config> config(new Config); 1120 config->serialized = protobuf->config(); 1121 1122 if (!protobuf->has_source_address_token_secret_override()) { 1123 // Use the default boxer. 1124 config->source_address_token_boxer = &default_source_address_token_boxer_; 1125 } else { 1126 // Create override boxer instance. 1127 CryptoSecretBoxer* boxer = new CryptoSecretBoxer; 1128 boxer->SetKey(DeriveSourceAddressTokenKey( 1129 protobuf->source_address_token_secret_override())); 1130 config->source_address_token_boxer_storage.reset(boxer); 1131 config->source_address_token_boxer = boxer; 1132 } 1133 1134 if (protobuf->has_primary_time()) { 1135 config->primary_time = 1136 QuicWallTime::FromUNIXSeconds(protobuf->primary_time()); 1137 } 1138 1139 config->priority = protobuf->priority(); 1140 1141 StringPiece scid; 1142 if (!msg->GetStringPiece(kSCID, &scid)) { 1143 LOG(WARNING) << "Server config message is missing SCID"; 1144 return NULL; 1145 } 1146 config->id = scid.as_string(); 1147 1148 const QuicTag* aead_tags; 1149 size_t aead_len; 1150 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) { 1151 LOG(WARNING) << "Server config message is missing AEAD"; 1152 return NULL; 1153 } 1154 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len); 1155 1156 const QuicTag* kexs_tags; 1157 size_t kexs_len; 1158 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) { 1159 LOG(WARNING) << "Server config message is missing KEXS"; 1160 return NULL; 1161 } 1162 1163 StringPiece orbit; 1164 if (!msg->GetStringPiece(kORBT, &orbit)) { 1165 LOG(WARNING) << "Server config message is missing ORBT"; 1166 return NULL; 1167 } 1168 1169 if (orbit.size() != kOrbitSize) { 1170 LOG(WARNING) << "Orbit value in server config is the wrong length." 1171 " Got " << orbit.size() << " want " << kOrbitSize; 1172 return NULL; 1173 } 1174 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size); 1175 memcpy(config->orbit, orbit.data(), sizeof(config->orbit)); 1176 1177 { 1178 StrikeRegisterClient* strike_register_client; 1179 { 1180 base::AutoLock locked(strike_register_client_lock_); 1181 strike_register_client = strike_register_client_.get(); 1182 } 1183 1184 if (strike_register_client != NULL && 1185 !strike_register_client->IsKnownOrbit(orbit)) { 1186 LOG(WARNING) 1187 << "Rejecting server config with orbit that the strike register " 1188 "client doesn't know about."; 1189 return NULL; 1190 } 1191 } 1192 1193 if (kexs_len != protobuf->key_size()) { 1194 LOG(WARNING) << "Server config has " << kexs_len 1195 << " key exchange methods configured, but " 1196 << protobuf->key_size() << " private keys"; 1197 return NULL; 1198 } 1199 1200 const QuicTag* proof_demand_tags; 1201 size_t num_proof_demand_tags; 1202 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) == 1203 QUIC_NO_ERROR) { 1204 for (size_t i = 0; i < num_proof_demand_tags; i++) { 1205 if (proof_demand_tags[i] == kCHID) { 1206 config->channel_id_enabled = true; 1207 break; 1208 } 1209 } 1210 } 1211 1212 for (size_t i = 0; i < kexs_len; i++) { 1213 const QuicTag tag = kexs_tags[i]; 1214 string private_key; 1215 1216 config->kexs.push_back(tag); 1217 1218 for (size_t j = 0; j < protobuf->key_size(); j++) { 1219 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i); 1220 if (key.tag() == tag) { 1221 private_key = key.private_key(); 1222 break; 1223 } 1224 } 1225 1226 if (private_key.empty()) { 1227 LOG(WARNING) << "Server config contains key exchange method without " 1228 "corresponding private key: " << tag; 1229 return NULL; 1230 } 1231 1232 scoped_ptr<KeyExchange> ka; 1233 switch (tag) { 1234 case kC255: 1235 ka.reset(Curve25519KeyExchange::New(private_key)); 1236 if (!ka.get()) { 1237 LOG(WARNING) << "Server config contained an invalid curve25519" 1238 " private key."; 1239 return NULL; 1240 } 1241 break; 1242 case kP256: 1243 ka.reset(P256KeyExchange::New(private_key)); 1244 if (!ka.get()) { 1245 LOG(WARNING) << "Server config contained an invalid P-256" 1246 " private key."; 1247 return NULL; 1248 } 1249 break; 1250 default: 1251 LOG(WARNING) << "Server config message contains unknown key exchange " 1252 "method: " << tag; 1253 return NULL; 1254 } 1255 1256 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin(); 1257 i != config->key_exchanges.end(); ++i) { 1258 if ((*i)->tag() == tag) { 1259 LOG(WARNING) << "Duplicate key exchange in config: " << tag; 1260 return NULL; 1261 } 1262 } 1263 1264 config->key_exchanges.push_back(ka.release()); 1265 } 1266 1267 return config; 1268 } 1269 1270 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) { 1271 proof_source_.reset(proof_source); 1272 } 1273 1274 void QuicCryptoServerConfig::SetEphemeralKeySource( 1275 EphemeralKeySource* ephemeral_key_source) { 1276 ephemeral_key_source_.reset(ephemeral_key_source); 1277 } 1278 1279 void QuicCryptoServerConfig::SetStrikeRegisterClient( 1280 StrikeRegisterClient* strike_register_client) { 1281 base::AutoLock locker(strike_register_client_lock_); 1282 DCHECK(!strike_register_client_.get()); 1283 strike_register_client_.reset(strike_register_client); 1284 } 1285 1286 void QuicCryptoServerConfig::set_replay_protection(bool on) { 1287 replay_protection_ = on; 1288 } 1289 1290 void QuicCryptoServerConfig::set_strike_register_no_startup_period() { 1291 base::AutoLock locker(strike_register_client_lock_); 1292 DCHECK(!strike_register_client_.get()); 1293 strike_register_no_startup_period_ = true; 1294 } 1295 1296 void QuicCryptoServerConfig::set_strike_register_max_entries( 1297 uint32 max_entries) { 1298 base::AutoLock locker(strike_register_client_lock_); 1299 DCHECK(!strike_register_client_.get()); 1300 strike_register_max_entries_ = max_entries; 1301 } 1302 1303 void QuicCryptoServerConfig::set_strike_register_window_secs( 1304 uint32 window_secs) { 1305 base::AutoLock locker(strike_register_client_lock_); 1306 DCHECK(!strike_register_client_.get()); 1307 strike_register_window_secs_ = window_secs; 1308 } 1309 1310 void QuicCryptoServerConfig::set_source_address_token_future_secs( 1311 uint32 future_secs) { 1312 source_address_token_future_secs_ = future_secs; 1313 } 1314 1315 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs( 1316 uint32 lifetime_secs) { 1317 source_address_token_lifetime_secs_ = lifetime_secs; 1318 } 1319 1320 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries( 1321 uint32 max_entries) { 1322 DCHECK(!server_nonce_strike_register_.get()); 1323 server_nonce_strike_register_max_entries_ = max_entries; 1324 } 1325 1326 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs( 1327 uint32 window_secs) { 1328 DCHECK(!server_nonce_strike_register_.get()); 1329 server_nonce_strike_register_window_secs_ = window_secs; 1330 } 1331 1332 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb( 1333 PrimaryConfigChangedCallback* cb) { 1334 base::AutoLock locked(configs_lock_); 1335 primary_config_changed_cb_.reset(cb); 1336 } 1337 1338 string QuicCryptoServerConfig::NewSourceAddressToken(const Config& config, 1339 const IPEndPoint& ip, 1340 QuicRandom* rand, 1341 QuicWallTime now) const { 1342 SourceAddressToken source_address_token; 1343 IPAddressNumber ip_address = ip.address(); 1344 if (ip.GetSockAddrFamily() == AF_INET) { 1345 ip_address = ConvertIPv4NumberToIPv6Number(ip_address); 1346 } 1347 source_address_token.set_ip(IPAddressToPackedString(ip_address)); 1348 source_address_token.set_timestamp(now.ToUNIXSeconds()); 1349 1350 return config.source_address_token_boxer->Box( 1351 rand, source_address_token.SerializeAsString()); 1352 } 1353 1354 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressToken( 1355 const Config& config, 1356 StringPiece token, 1357 const IPEndPoint& ip, 1358 QuicWallTime now) const { 1359 string storage; 1360 StringPiece plaintext; 1361 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) { 1362 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE; 1363 } 1364 1365 SourceAddressToken source_address_token; 1366 if (!source_address_token.ParseFromArray(plaintext.data(), 1367 plaintext.size())) { 1368 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE; 1369 } 1370 1371 IPAddressNumber ip_address = ip.address(); 1372 if (ip.GetSockAddrFamily() == AF_INET) { 1373 ip_address = ConvertIPv4NumberToIPv6Number(ip_address); 1374 } 1375 if (source_address_token.ip() != IPAddressToPackedString(ip_address)) { 1376 // It's for a different IP address. 1377 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE; 1378 } 1379 1380 const QuicWallTime timestamp( 1381 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp())); 1382 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp)); 1383 1384 if (now.IsBefore(timestamp) && 1385 delta.ToSeconds() > source_address_token_future_secs_) { 1386 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE; 1387 } 1388 1389 if (now.IsAfter(timestamp) && 1390 delta.ToSeconds() > source_address_token_lifetime_secs_) { 1391 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE; 1392 } 1393 1394 return HANDSHAKE_OK; 1395 } 1396 1397 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server 1398 // nonce. 1399 static const size_t kServerNoncePlaintextSize = 1400 4 /* timestamp */ + 20 /* random bytes */; 1401 1402 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand, 1403 QuicWallTime now) const { 1404 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds()); 1405 1406 uint8 server_nonce[kServerNoncePlaintextSize]; 1407 COMPILE_ASSERT(sizeof(server_nonce) > sizeof(timestamp), nonce_too_small); 1408 server_nonce[0] = static_cast<uint8>(timestamp >> 24); 1409 server_nonce[1] = static_cast<uint8>(timestamp >> 16); 1410 server_nonce[2] = static_cast<uint8>(timestamp >> 8); 1411 server_nonce[3] = static_cast<uint8>(timestamp); 1412 rand->RandBytes(&server_nonce[sizeof(timestamp)], 1413 sizeof(server_nonce) - sizeof(timestamp)); 1414 1415 return server_nonce_boxer_.Box( 1416 rand, 1417 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce))); 1418 } 1419 1420 HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce( 1421 StringPiece token, 1422 QuicWallTime now) const { 1423 string storage; 1424 StringPiece plaintext; 1425 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) { 1426 return SERVER_NONCE_DECRYPTION_FAILURE; 1427 } 1428 1429 // plaintext contains: 1430 // uint32 timestamp 1431 // uint8[20] random bytes 1432 1433 if (plaintext.size() != kServerNoncePlaintextSize) { 1434 // This should never happen because the value decrypted correctly. 1435 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length."; 1436 return SERVER_NONCE_INVALID_FAILURE; 1437 } 1438 1439 uint8 server_nonce[32]; 1440 memcpy(server_nonce, plaintext.data(), 4); 1441 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_)); 1442 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4, 1443 20); 1444 COMPILE_ASSERT(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce), 1445 bad_nonce_buffer_length); 1446 1447 bool is_unique; 1448 { 1449 base::AutoLock auto_lock(server_nonce_strike_register_lock_); 1450 if (server_nonce_strike_register_.get() == NULL) { 1451 server_nonce_strike_register_.reset(new StrikeRegister( 1452 server_nonce_strike_register_max_entries_, 1453 static_cast<uint32>(now.ToUNIXSeconds()), 1454 server_nonce_strike_register_window_secs_, server_nonce_orbit_, 1455 StrikeRegister::NO_STARTUP_PERIOD_NEEDED)); 1456 } 1457 is_unique = server_nonce_strike_register_->Insert( 1458 server_nonce, static_cast<uint32>(now.ToUNIXSeconds())); 1459 } 1460 1461 return is_unique ? HANDSHAKE_OK : SERVER_NONCE_NOT_UNIQUE_FAILURE; 1462 } 1463 1464 QuicCryptoServerConfig::Config::Config() 1465 : channel_id_enabled(false), 1466 is_primary(false), 1467 primary_time(QuicWallTime::Zero()), 1468 priority(0), 1469 source_address_token_boxer(NULL) {} 1470 1471 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } 1472 1473 } // namespace net 1474