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/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                                 &params->aead, NULL) ||
    557       !QuicUtils::FindMutualTag(
    558           requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
    559           QuicUtils::LOCAL_PRIORITY, &params->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                                         &params->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                                &params->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, &params->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, &params->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