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