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