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