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 ¶ms->aead, NULL) ||
628 !QuicUtils::FindMutualTag(
629 requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
630 QuicUtils::LOCAL_PRIORITY, ¶ms->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 ¶ms->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 ¶ms->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, ¶ms->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, ¶ms->forward_secure_crypters,
764 ¶ms->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