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