Home | History | Annotate | Download | only in crypto
      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                                 &params->aead, NULL) ||
    597       !QuicUtils::FindMutualTag(
    598           requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
    599           QuicUtils::LOCAL_PRIORITY, &params->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                                         &params->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                                &params->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, &params->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, &params->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