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