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