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