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