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 ¶ms->aead, NULL) ||
597 !QuicUtils::FindMutualTag(
598 requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
599 QuicUtils::LOCAL_PRIORITY, ¶ms->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 ¶ms->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 ¶ms->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, ¶ms->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, ¶ms->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