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