Sort unlaunched apps on app list start page by apps grid order.
[chromium-blink-merge.git] / net / quic / crypto / quic_crypto_server_config.cc
blob7c76ba85acd910405ca000ad62b017448362880c
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.
5 #include "net/quic/crypto/quic_crypto_server_config.h"
7 #include <stdlib.h>
8 #include <algorithm>
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_handshake_message.h"
22 #include "net/quic/crypto/crypto_server_config_protobuf.h"
23 #include "net/quic/crypto/crypto_utils.h"
24 #include "net/quic/crypto/curve25519_key_exchange.h"
25 #include "net/quic/crypto/ephemeral_key_source.h"
26 #include "net/quic/crypto/key_exchange.h"
27 #include "net/quic/crypto/local_strike_register_client.h"
28 #include "net/quic/crypto/p256_key_exchange.h"
29 #include "net/quic/crypto/proof_source.h"
30 #include "net/quic/crypto/quic_decrypter.h"
31 #include "net/quic/crypto/quic_encrypter.h"
32 #include "net/quic/crypto/quic_random.h"
33 #include "net/quic/crypto/source_address_token.h"
34 #include "net/quic/crypto/strike_register.h"
35 #include "net/quic/crypto/strike_register_client.h"
36 #include "net/quic/quic_clock.h"
37 #include "net/quic/quic_flags.h"
38 #include "net/quic/quic_protocol.h"
39 #include "net/quic/quic_socket_address_coder.h"
40 #include "net/quic/quic_utils.h"
42 using base::StringPiece;
43 using crypto::SecureHash;
44 using std::map;
45 using std::sort;
46 using std::string;
47 using std::vector;
49 namespace net {
51 namespace {
53 const size_t kMaxTokenAddresses = 4;
55 string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) {
56 crypto::HKDF hkdf(source_address_token_secret,
57 StringPiece() /* no salt */,
58 "QUIC source address token key",
59 CryptoSecretBoxer::GetKeySize(),
60 0 /* no fixed IV needed */,
61 0 /* no subkey secret */);
62 return hkdf.server_write_key().as_string();
65 } // namespace
67 class ValidateClientHelloHelper {
68 public:
69 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result,
70 ValidateClientHelloResultCallback* done_cb)
71 : result_(result), done_cb_(done_cb) {
74 ~ValidateClientHelloHelper() {
75 LOG_IF(DFATAL, done_cb_ != nullptr)
76 << "Deleting ValidateClientHelloHelper with a pending callback.";
79 void ValidationComplete(QuicErrorCode error_code, const char* error_details) {
80 result_->error_code = error_code;
81 result_->error_details = error_details;
82 done_cb_->Run(result_);
83 DetachCallback();
86 void StartedAsyncCallback() {
87 DetachCallback();
90 private:
91 void DetachCallback() {
92 LOG_IF(DFATAL, done_cb_ == nullptr) << "Callback already detached.";
93 done_cb_ = nullptr;
96 ValidateClientHelloResultCallback::Result* result_;
97 ValidateClientHelloResultCallback* done_cb_;
99 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
102 class VerifyNonceIsValidAndUniqueCallback
103 : public StrikeRegisterClient::ResultCallback {
104 public:
105 VerifyNonceIsValidAndUniqueCallback(
106 ValidateClientHelloResultCallback::Result* result,
107 ValidateClientHelloResultCallback* done_cb)
108 : result_(result), done_cb_(done_cb) {
111 protected:
112 void RunImpl(bool nonce_is_valid_and_unique,
113 InsertStatus nonce_error) override {
114 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique
115 << " nonce_error: " << nonce_error;
116 result_->info.unique = nonce_is_valid_and_unique;
117 if (!nonce_is_valid_and_unique) {
118 HandshakeFailureReason client_nonce_error;
119 switch (nonce_error) {
120 case NONCE_INVALID_FAILURE:
121 client_nonce_error = CLIENT_NONCE_INVALID_FAILURE;
122 break;
123 case NONCE_NOT_UNIQUE_FAILURE:
124 client_nonce_error = CLIENT_NONCE_NOT_UNIQUE_FAILURE;
125 break;
126 case NONCE_INVALID_ORBIT_FAILURE:
127 client_nonce_error = CLIENT_NONCE_INVALID_ORBIT_FAILURE;
128 break;
129 case NONCE_INVALID_TIME_FAILURE:
130 client_nonce_error = CLIENT_NONCE_INVALID_TIME_FAILURE;
131 break;
132 case STRIKE_REGISTER_TIMEOUT:
133 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT;
134 break;
135 case STRIKE_REGISTER_FAILURE:
136 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_FAILURE;
137 break;
138 case NONCE_UNKNOWN_FAILURE:
139 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
140 break;
141 case NONCE_OK:
142 default:
143 LOG(DFATAL) << "Unexpected client nonce error: " << nonce_error;
144 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
145 break;
147 result_->info.reject_reasons.push_back(client_nonce_error);
149 done_cb_->Run(result_);
152 private:
153 ValidateClientHelloResultCallback::Result* result_;
154 ValidateClientHelloResultCallback* done_cb_;
156 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
159 // static
160 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
162 ClientHelloInfo::ClientHelloInfo(const IPEndPoint& in_client_ip,
163 QuicWallTime in_now)
164 : client_ip(in_client_ip),
165 now(in_now),
166 valid_source_address_token(false),
167 client_nonce_well_formed(false),
168 unique(false) {
171 ClientHelloInfo::~ClientHelloInfo() {
174 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {
177 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {
180 ValidateClientHelloResultCallback::Result::Result(
181 const CryptoHandshakeMessage& in_client_hello,
182 IPEndPoint in_client_ip,
183 QuicWallTime in_now)
184 : client_hello(in_client_hello),
185 info(in_client_ip, in_now),
186 error_code(QUIC_NO_ERROR) {
189 ValidateClientHelloResultCallback::Result::~Result() {
192 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {
195 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {
198 void ValidateClientHelloResultCallback::Run(const Result* result) {
199 RunImpl(result->client_hello, *result);
200 delete result;
201 delete this;
204 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
205 : expiry_time(QuicWallTime::Zero()),
206 channel_id_enabled(false),
207 p256(false) {}
209 QuicCryptoServerConfig::QuicCryptoServerConfig(
210 StringPiece source_address_token_secret,
211 QuicRandom* rand)
212 : replay_protection_(true),
213 configs_lock_(),
214 primary_config_(nullptr),
215 next_config_promotion_time_(QuicWallTime::Zero()),
216 server_nonce_strike_register_lock_(),
217 strike_register_no_startup_period_(false),
218 strike_register_max_entries_(1 << 10),
219 strike_register_window_secs_(600),
220 source_address_token_future_secs_(3600),
221 source_address_token_lifetime_secs_(86400),
222 server_nonce_strike_register_max_entries_(1 << 10),
223 server_nonce_strike_register_window_secs_(120) {
224 default_source_address_token_boxer_.SetKey(
225 DeriveSourceAddressTokenKey(source_address_token_secret));
227 // Generate a random key and orbit for server nonces.
228 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_));
229 const size_t key_size = server_nonce_boxer_.GetKeySize();
230 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]);
231 rand->RandBytes(key_bytes.get(), key_size);
233 server_nonce_boxer_.SetKey(
234 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size));
237 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
238 primary_config_ = nullptr;
241 // static
242 QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig(
243 QuicRandom* rand,
244 const QuicClock* clock,
245 const ConfigOptions& options) {
246 CryptoHandshakeMessage msg;
248 const string curve25519_private_key =
249 Curve25519KeyExchange::NewPrivateKey(rand);
250 scoped_ptr<Curve25519KeyExchange> curve25519(
251 Curve25519KeyExchange::New(curve25519_private_key));
252 StringPiece curve25519_public_value = curve25519->public_value();
254 string encoded_public_values;
255 // First three bytes encode the length of the public value.
256 DCHECK_LT(curve25519_public_value.size(), (1U << 24));
257 encoded_public_values.push_back(
258 static_cast<char>(curve25519_public_value.size()));
259 encoded_public_values.push_back(
260 static_cast<char>(curve25519_public_value.size() >> 8));
261 encoded_public_values.push_back(
262 static_cast<char>(curve25519_public_value.size() >> 16));
263 encoded_public_values.append(curve25519_public_value.data(),
264 curve25519_public_value.size());
266 string p256_private_key;
267 if (options.p256) {
268 p256_private_key = P256KeyExchange::NewPrivateKey();
269 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
270 StringPiece p256_public_value = p256->public_value();
272 DCHECK_LT(p256_public_value.size(), (1U << 24));
273 encoded_public_values.push_back(
274 static_cast<char>(p256_public_value.size()));
275 encoded_public_values.push_back(
276 static_cast<char>(p256_public_value.size() >> 8));
277 encoded_public_values.push_back(
278 static_cast<char>(p256_public_value.size() >> 16));
279 encoded_public_values.append(p256_public_value.data(),
280 p256_public_value.size());
283 msg.set_tag(kSCFG);
284 if (options.p256) {
285 msg.SetTaglist(kKEXS, kC255, kP256, 0);
286 } else {
287 msg.SetTaglist(kKEXS, kC255, 0);
289 if (ChaCha20Poly1305Encrypter::IsSupported()) {
290 msg.SetTaglist(kAEAD, kAESG, kCC12, 0);
291 } else {
292 msg.SetTaglist(kAEAD, kAESG, 0);
294 msg.SetStringPiece(kPUBS, encoded_public_values);
296 if (options.expiry_time.IsZero()) {
297 const QuicWallTime now = clock->WallNow();
298 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
299 60 * 60 * 24 * 180 /* 180 days, ~six months */));
300 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
301 msg.SetValue(kEXPY, expiry_seconds);
302 } else {
303 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
306 char orbit_bytes[kOrbitSize];
307 if (options.orbit.size() == sizeof(orbit_bytes)) {
308 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
309 } else {
310 DCHECK(options.orbit.empty());
311 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
313 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
315 if (options.channel_id_enabled) {
316 msg.SetTaglist(kPDMD, kCHID, 0);
319 if (options.id.empty()) {
320 // We need to ensure that the SCID changes whenever the server config does
321 // thus we make it a hash of the rest of the server config.
322 scoped_ptr<QuicData> serialized(
323 CryptoFramer::ConstructHandshakeMessage(msg));
324 scoped_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256));
325 hash->Update(serialized->data(), serialized->length());
327 char scid_bytes[16];
328 hash->Finish(scid_bytes, sizeof(scid_bytes));
329 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
330 } else {
331 msg.SetStringPiece(kSCID, options.id);
333 // Don't put new tags below this point. The SCID generation should hash over
334 // everything but itself and so extra tags should be added prior to the
335 // preceeding if block.
337 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
339 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
340 config->set_config(serialized->AsStringPiece());
341 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
342 curve25519_key->set_tag(kC255);
343 curve25519_key->set_private_key(curve25519_private_key);
345 if (options.p256) {
346 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
347 p256_key->set_tag(kP256);
348 p256_key->set_private_key(p256_private_key);
351 return config.release();
354 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
355 QuicServerConfigProtobuf* protobuf,
356 const QuicWallTime now) {
357 scoped_ptr<CryptoHandshakeMessage> msg(
358 CryptoFramer::ParseMessage(protobuf->config()));
360 if (!msg.get()) {
361 LOG(WARNING) << "Failed to parse server config message";
362 return nullptr;
365 scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
366 if (!config.get()) {
367 LOG(WARNING) << "Failed to parse server config message";
368 return nullptr;
372 base::AutoLock locked(configs_lock_);
373 if (configs_.find(config->id) != configs_.end()) {
374 LOG(WARNING) << "Failed to add config because another with the same "
375 "server config id already exists: "
376 << base::HexEncode(config->id.data(), config->id.size());
377 return nullptr;
380 configs_[config->id] = config;
381 SelectNewPrimaryConfig(now);
382 DCHECK(primary_config_.get());
383 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
386 return msg.release();
389 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
390 QuicRandom* rand,
391 const QuicClock* clock,
392 const ConfigOptions& options) {
393 scoped_ptr<QuicServerConfigProtobuf> config(
394 GenerateConfig(rand, clock, options));
395 return AddConfig(config.get(), clock->WallNow());
398 bool QuicCryptoServerConfig::SetConfigs(
399 const vector<QuicServerConfigProtobuf*>& protobufs,
400 const QuicWallTime now) {
401 vector<scoped_refptr<Config> > parsed_configs;
402 bool ok = true;
404 for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin();
405 i != protobufs.end(); ++i) {
406 scoped_refptr<Config> config(ParseConfigProtobuf(*i));
407 if (!config.get()) {
408 ok = false;
409 break;
412 parsed_configs.push_back(config);
415 if (parsed_configs.empty()) {
416 LOG(WARNING) << "New config list is empty.";
417 ok = false;
420 if (!ok) {
421 LOG(WARNING) << "Rejecting QUIC configs because of above errors";
422 } else {
423 VLOG(1) << "Updating configs:";
425 base::AutoLock locked(configs_lock_);
426 ConfigMap new_configs;
428 for (vector<scoped_refptr<Config> >::const_iterator i =
429 parsed_configs.begin();
430 i != parsed_configs.end(); ++i) {
431 scoped_refptr<Config> config = *i;
433 ConfigMap::iterator it = configs_.find(config->id);
434 if (it != configs_.end()) {
435 VLOG(1)
436 << "Keeping scid: " << base::HexEncode(
437 config->id.data(), config->id.size())
438 << " orbit: " << base::HexEncode(
439 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
440 << " new primary_time " << config->primary_time.ToUNIXSeconds()
441 << " old primary_time " << it->second->primary_time.ToUNIXSeconds()
442 << " new priority " << config->priority
443 << " old priority " << it->second->priority;
444 // Update primary_time and priority.
445 it->second->primary_time = config->primary_time;
446 it->second->priority = config->priority;
447 new_configs.insert(*it);
448 } else {
449 VLOG(1) << "Adding scid: " << base::HexEncode(
450 config->id.data(), config->id.size())
451 << " orbit: " << base::HexEncode(
452 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
453 << " primary_time " << config->primary_time.ToUNIXSeconds()
454 << " priority " << config->priority;
455 new_configs.insert(std::make_pair(config->id, config));
459 configs_.swap(new_configs);
460 SelectNewPrimaryConfig(now);
461 DCHECK(primary_config_.get());
462 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
465 return ok;
468 void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
469 base::AutoLock locked(configs_lock_);
470 for (ConfigMap::const_iterator it = configs_.begin();
471 it != configs_.end(); ++it) {
472 scids->push_back(it->first);
476 void QuicCryptoServerConfig::ValidateClientHello(
477 const CryptoHandshakeMessage& client_hello,
478 IPEndPoint client_ip,
479 const QuicClock* clock,
480 ValidateClientHelloResultCallback* done_cb) const {
481 const QuicWallTime now(clock->WallNow());
483 ValidateClientHelloResultCallback::Result* result =
484 new ValidateClientHelloResultCallback::Result(
485 client_hello, client_ip, now);
487 StringPiece requested_scid;
488 client_hello.GetStringPiece(kSCID, &requested_scid);
490 uint8 primary_orbit[kOrbitSize];
491 scoped_refptr<Config> requested_config;
493 base::AutoLock locked(configs_lock_);
495 if (!primary_config_.get()) {
496 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
497 result->error_details = "No configurations loaded";
498 } else {
499 if (!next_config_promotion_time_.IsZero() &&
500 next_config_promotion_time_.IsAfter(now)) {
501 SelectNewPrimaryConfig(now);
502 DCHECK(primary_config_.get());
503 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
506 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit));
509 requested_config = GetConfigWithScid(requested_scid);
512 if (result->error_code == QUIC_NO_ERROR) {
513 EvaluateClientHello(primary_orbit, requested_config, result, done_cb);
514 } else {
515 done_cb->Run(result);
519 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
520 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
521 QuicConnectionId connection_id,
522 const IPEndPoint& server_ip,
523 const IPEndPoint& client_address,
524 QuicVersion version,
525 const QuicVersionVector& supported_versions,
526 const QuicClock* clock,
527 QuicRandom* rand,
528 QuicCryptoNegotiatedParameters* params,
529 CryptoHandshakeMessage* out,
530 string* error_details) const {
531 DCHECK(error_details);
533 const CryptoHandshakeMessage& client_hello =
534 validate_chlo_result.client_hello;
535 const ClientHelloInfo& info = validate_chlo_result.info;
537 // If the client's preferred version is not the version we are currently
538 // speaking, then the client went through a version negotiation. In this
539 // case, we need to make sure that we actually do not support this version
540 // and that it wasn't a downgrade attack.
541 QuicTag client_version_tag;
542 if (client_hello.GetUint32(kVER, &client_version_tag) != QUIC_NO_ERROR) {
543 *error_details = "client hello missing version list";
544 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
546 QuicVersion client_version = QuicTagToQuicVersion(client_version_tag);
547 if (client_version != version) {
548 // Just because client_version is a valid version enum doesn't mean that
549 // this server actually supports that version, so we check to see if
550 // it's actually in the supported versions list.
551 for (size_t i = 0; i < supported_versions.size(); ++i) {
552 if (client_version == supported_versions[i]) {
553 *error_details = "Downgrade attack detected";
554 return QUIC_VERSION_NEGOTIATION_MISMATCH;
559 StringPiece requested_scid;
560 client_hello.GetStringPiece(kSCID, &requested_scid);
561 const QuicWallTime now(clock->WallNow());
563 scoped_refptr<Config> requested_config;
564 scoped_refptr<Config> primary_config;
566 base::AutoLock locked(configs_lock_);
568 if (!primary_config_.get()) {
569 *error_details = "No configurations loaded";
570 return QUIC_CRYPTO_INTERNAL_ERROR;
573 if (!next_config_promotion_time_.IsZero() &&
574 next_config_promotion_time_.IsAfter(now)) {
575 SelectNewPrimaryConfig(now);
576 DCHECK(primary_config_.get());
577 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
580 // We'll use the config that the client requested in order to do
581 // key-agreement. Otherwise we'll give it a copy of |primary_config_|
582 // to use.
583 primary_config = primary_config_;
585 requested_config = GetConfigWithScid(requested_scid);
588 if (validate_chlo_result.error_code != QUIC_NO_ERROR) {
589 *error_details = validate_chlo_result.error_details;
590 return validate_chlo_result.error_code;
593 out->Clear();
595 if (!info.valid_source_address_token ||
596 !info.client_nonce_well_formed ||
597 !info.unique ||
598 !requested_config.get()) {
599 BuildRejection(server_ip, *primary_config.get(), client_hello, info,
600 validate_chlo_result.cached_network_params, rand, params,
601 out);
602 return QUIC_NO_ERROR;
605 const QuicTag* their_aeads;
606 const QuicTag* their_key_exchanges;
607 size_t num_their_aeads, num_their_key_exchanges;
608 if (client_hello.GetTaglist(kAEAD, &their_aeads,
609 &num_their_aeads) != QUIC_NO_ERROR ||
610 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
611 &num_their_key_exchanges) != QUIC_NO_ERROR ||
612 num_their_aeads != 1 ||
613 num_their_key_exchanges != 1) {
614 *error_details = "Missing or invalid AEAD or KEXS";
615 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
618 size_t key_exchange_index;
619 if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads,
620 num_their_aeads, QuicUtils::LOCAL_PRIORITY,
621 &params->aead, nullptr) ||
622 !QuicUtils::FindMutualTag(
623 requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
624 QuicUtils::LOCAL_PRIORITY, &params->key_exchange,
625 &key_exchange_index)) {
626 *error_details = "Unsupported AEAD or KEXS";
627 return QUIC_CRYPTO_NO_SUPPORT;
630 StringPiece public_value;
631 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
632 *error_details = "Missing public value";
633 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
636 const KeyExchange* key_exchange =
637 requested_config->key_exchanges[key_exchange_index];
638 if (!key_exchange->CalculateSharedKey(public_value,
639 &params->initial_premaster_secret)) {
640 *error_details = "Invalid public value";
641 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
644 if (!info.sni.empty()) {
645 scoped_ptr<char[]> sni_tmp(new char[info.sni.length() + 1]);
646 memcpy(sni_tmp.get(), info.sni.data(), info.sni.length());
647 sni_tmp[info.sni.length()] = 0;
648 params->sni = CryptoUtils::NormalizeHostname(sni_tmp.get());
651 string hkdf_suffix;
652 const QuicData& client_hello_serialized = client_hello.GetSerialized();
653 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() +
654 requested_config->serialized.size());
655 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id),
656 sizeof(connection_id));
657 hkdf_suffix.append(client_hello_serialized.data(),
658 client_hello_serialized.length());
659 hkdf_suffix.append(requested_config->serialized);
661 StringPiece cetv_ciphertext;
662 if (requested_config->channel_id_enabled &&
663 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
664 CryptoHandshakeMessage client_hello_copy(client_hello);
665 client_hello_copy.Erase(kCETV);
666 client_hello_copy.Erase(kPAD);
668 const QuicData& client_hello_serialized = client_hello_copy.GetSerialized();
669 string hkdf_input;
670 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
671 strlen(QuicCryptoConfig::kCETVLabel) + 1);
672 hkdf_input.append(reinterpret_cast<char*>(&connection_id),
673 sizeof(connection_id));
674 hkdf_input.append(client_hello_serialized.data(),
675 client_hello_serialized.length());
676 hkdf_input.append(requested_config->serialized);
678 CrypterPair crypters;
679 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
680 info.client_nonce, info.server_nonce,
681 hkdf_input, CryptoUtils::SERVER, &crypters,
682 nullptr /* subkey secret */)) {
683 *error_details = "Symmetric key setup failed";
684 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
687 char plaintext[kMaxPacketSize];
688 size_t plaintext_length = 0;
689 const bool success = crypters.decrypter->DecryptPacket(
690 0 /* sequence number */, StringPiece() /* associated data */,
691 cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
692 if (!success) {
693 *error_details = "CETV decryption failure";
694 return QUIC_PACKET_TOO_LARGE;
696 scoped_ptr<CryptoHandshakeMessage> cetv(
697 CryptoFramer::ParseMessage(StringPiece(plaintext, plaintext_length)));
698 if (!cetv.get()) {
699 *error_details = "CETV parse error";
700 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
703 StringPiece key, signature;
704 if (cetv->GetStringPiece(kCIDK, &key) &&
705 cetv->GetStringPiece(kCIDS, &signature)) {
706 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
707 *error_details = "ChannelID signature failure";
708 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
711 params->channel_id = key.as_string();
715 string hkdf_input;
716 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
717 hkdf_input.reserve(label_len + hkdf_suffix.size());
718 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
719 hkdf_input.append(hkdf_suffix);
721 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
722 info.client_nonce, info.server_nonce, hkdf_input,
723 CryptoUtils::SERVER,
724 &params->initial_crypters,
725 nullptr /* subkey secret */)) {
726 *error_details = "Symmetric key setup failed";
727 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
730 string forward_secure_public_value;
731 if (ephemeral_key_source_.get()) {
732 params->forward_secure_premaster_secret =
733 ephemeral_key_source_->CalculateForwardSecureKey(
734 key_exchange, rand, clock->ApproximateNow(), public_value,
735 &forward_secure_public_value);
736 } else {
737 scoped_ptr<KeyExchange> forward_secure_key_exchange(
738 key_exchange->NewKeyPair(rand));
739 forward_secure_public_value =
740 forward_secure_key_exchange->public_value().as_string();
741 if (!forward_secure_key_exchange->CalculateSharedKey(
742 public_value, &params->forward_secure_premaster_secret)) {
743 *error_details = "Invalid public value";
744 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
748 string forward_secure_hkdf_input;
749 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
750 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
751 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
752 label_len);
753 forward_secure_hkdf_input.append(hkdf_suffix);
755 if (!CryptoUtils::DeriveKeys(
756 params->forward_secure_premaster_secret, params->aead,
757 info.client_nonce, info.server_nonce, forward_secure_hkdf_input,
758 CryptoUtils::SERVER, &params->forward_secure_crypters,
759 &params->subkey_secret)) {
760 *error_details = "Symmetric key setup failed";
761 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
764 out->set_tag(kSHLO);
765 QuicTagVector supported_version_tags;
766 for (size_t i = 0; i < supported_versions.size(); ++i) {
767 supported_version_tags.push_back
768 (QuicVersionToQuicTag(supported_versions[i]));
770 out->SetVector(kVER, supported_version_tags);
771 out->SetStringPiece(
772 kSourceAddressTokenTag,
773 NewSourceAddressToken(*requested_config.get(), info.source_address_tokens,
774 client_address, rand, info.now, nullptr));
775 QuicSocketAddressCoder address_coder(client_address);
776 out->SetStringPiece(kCADR, address_coder.Encode());
777 out->SetStringPiece(kPUBS, forward_secure_public_value);
779 return QUIC_NO_ERROR;
782 scoped_refptr<QuicCryptoServerConfig::Config>
783 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const {
784 // In Chromium, we will dead lock if the lock is held by the current thread.
785 // Chromium doesn't have AssertReaderHeld API call.
786 // configs_lock_.AssertReaderHeld();
788 if (!requested_scid.empty()) {
789 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
790 if (it != configs_.end()) {
791 // We'll use the config that the client requested in order to do
792 // key-agreement.
793 return scoped_refptr<Config>(it->second);
797 return scoped_refptr<Config>();
800 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
801 // Config's based on their primary_time.
802 // static
803 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
804 const scoped_refptr<Config>& a,
805 const scoped_refptr<Config>& b) {
806 if (a->primary_time.IsBefore(b->primary_time) ||
807 b->primary_time.IsBefore(a->primary_time)) {
808 // Primary times differ.
809 return a->primary_time.IsBefore(b->primary_time);
810 } else if (a->priority != b->priority) {
811 // Primary times are equal, sort backwards by priority.
812 return a->priority < b->priority;
813 } else {
814 // Primary times and priorities are equal, sort by config id.
815 return a->id < b->id;
819 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
820 const QuicWallTime now) const {
821 vector<scoped_refptr<Config> > configs;
822 configs.reserve(configs_.size());
824 for (ConfigMap::const_iterator it = configs_.begin();
825 it != configs_.end(); ++it) {
826 // TODO(avd) Exclude expired configs?
827 configs.push_back(it->second);
830 if (configs.empty()) {
831 if (primary_config_.get()) {
832 LOG(DFATAL) << "No valid QUIC server config. Keeping the current config.";
833 } else {
834 LOG(DFATAL) << "No valid QUIC server config.";
836 return;
839 std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
841 Config* best_candidate = configs[0].get();
843 for (size_t i = 0; i < configs.size(); ++i) {
844 const scoped_refptr<Config> config(configs[i]);
845 if (!config->primary_time.IsAfter(now)) {
846 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
847 best_candidate = config.get();
849 continue;
852 // This is the first config with a primary_time in the future. Thus the
853 // previous Config should be the primary and this one should determine the
854 // next_config_promotion_time_.
855 scoped_refptr<Config> new_primary(best_candidate);
856 if (i == 0) {
857 // We need the primary_time of the next config.
858 if (configs.size() > 1) {
859 next_config_promotion_time_ = configs[1]->primary_time;
860 } else {
861 next_config_promotion_time_ = QuicWallTime::Zero();
863 } else {
864 next_config_promotion_time_ = config->primary_time;
867 if (primary_config_.get()) {
868 primary_config_->is_primary = false;
870 primary_config_ = new_primary;
871 new_primary->is_primary = true;
872 DVLOG(1) << "New primary config. orbit: "
873 << base::HexEncode(
874 reinterpret_cast<const char*>(primary_config_->orbit),
875 kOrbitSize);
876 if (primary_config_changed_cb_.get() != nullptr) {
877 primary_config_changed_cb_->Run(primary_config_->id);
880 return;
883 // All config's primary times are in the past. We should make the most recent
884 // and highest priority candidate primary.
885 scoped_refptr<Config> new_primary(best_candidate);
886 if (primary_config_.get()) {
887 primary_config_->is_primary = false;
889 primary_config_ = new_primary;
890 new_primary->is_primary = true;
891 DVLOG(1) << "New primary config. orbit: "
892 << base::HexEncode(
893 reinterpret_cast<const char*>(primary_config_->orbit),
894 kOrbitSize)
895 << " scid: " << base::HexEncode(primary_config_->id.data(),
896 primary_config_->id.size());
897 next_config_promotion_time_ = QuicWallTime::Zero();
898 if (primary_config_changed_cb_.get() != nullptr) {
899 primary_config_changed_cb_->Run(primary_config_->id);
903 void QuicCryptoServerConfig::EvaluateClientHello(
904 const uint8* primary_orbit,
905 scoped_refptr<Config> requested_config,
906 ValidateClientHelloResultCallback::Result* client_hello_state,
907 ValidateClientHelloResultCallback* done_cb) const {
908 ValidateClientHelloHelper helper(client_hello_state, done_cb);
910 const CryptoHandshakeMessage& client_hello =
911 client_hello_state->client_hello;
912 ClientHelloInfo* info = &(client_hello_state->info);
914 if (client_hello.size() < kClientHelloMinimumSize) {
915 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
916 "Client hello too small");
917 return;
920 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
921 !CryptoUtils::IsValidSNI(info->sni)) {
922 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
923 "Invalid SNI name");
924 return;
927 client_hello.GetStringPiece(kUAID, &info->user_agent_id);
929 if (!requested_config.get()) {
930 StringPiece requested_scid;
931 if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
932 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
933 } else {
934 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
936 // No server config with the requested ID.
937 helper.ValidationComplete(QUIC_NO_ERROR, "");
938 return;
941 HandshakeFailureReason source_address_token_error;
942 StringPiece srct;
943 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
944 if (!FLAGS_quic_use_multiple_address_in_source_tokens) {
945 source_address_token_error = ValidateSourceAddressToken(
946 *requested_config.get(), srct, info->client_ip, info->now,
947 &client_hello_state->cached_network_params);
948 } else {
949 source_address_token_error = ParseSourceAddressToken(
950 *requested_config.get(), srct, &info->source_address_tokens);
952 if (source_address_token_error == HANDSHAKE_OK) {
953 source_address_token_error = ValidateSourceAddressTokens(
954 info->source_address_tokens, info->client_ip, info->now,
955 &client_hello_state->cached_network_params);
958 info->valid_source_address_token =
959 (source_address_token_error == HANDSHAKE_OK);
960 } else {
961 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
964 bool found_error = false;
965 if (source_address_token_error != HANDSHAKE_OK) {
966 info->reject_reasons.push_back(source_address_token_error);
967 // No valid source address token.
968 if (FLAGS_use_early_return_when_verifying_chlo) {
969 helper.ValidationComplete(QUIC_NO_ERROR, "");
970 return;
972 found_error = true;
975 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) &&
976 info->client_nonce.size() == kNonceSize) {
977 info->client_nonce_well_formed = true;
978 } else {
979 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
980 // Invalid client nonce.
981 DVLOG(1) << "Invalid client nonce.";
982 if (FLAGS_use_early_return_when_verifying_chlo) {
983 helper.ValidationComplete(QUIC_NO_ERROR, "");
984 return;
986 found_error = true;
989 if (!replay_protection_) {
990 if (!found_error) {
991 info->unique = true;
993 DVLOG(1) << "No replay protection.";
994 helper.ValidationComplete(QUIC_NO_ERROR, "");
995 return;
998 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
999 if (!info->server_nonce.empty()) {
1000 // If the server nonce is present, use it to establish uniqueness.
1001 HandshakeFailureReason server_nonce_error =
1002 ValidateServerNonce(info->server_nonce, info->now);
1003 if (server_nonce_error == HANDSHAKE_OK) {
1004 info->unique = true;
1005 } else {
1006 info->reject_reasons.push_back(server_nonce_error);
1007 info->unique = false;
1009 DVLOG(1) << "Using server nonce, unique: " << info->unique;
1010 helper.ValidationComplete(QUIC_NO_ERROR, "");
1011 return;
1014 // We want to contact strike register only if there are no errors because it
1015 // is a RPC call and is expensive.
1016 if (found_error) {
1017 helper.ValidationComplete(QUIC_NO_ERROR, "");
1018 return;
1021 // Use the client nonce to establish uniqueness.
1022 StrikeRegisterClient* strike_register_client;
1024 base::AutoLock locked(strike_register_client_lock_);
1026 if (strike_register_client_.get() == nullptr) {
1027 strike_register_client_.reset(new LocalStrikeRegisterClient(
1028 strike_register_max_entries_,
1029 static_cast<uint32>(info->now.ToUNIXSeconds()),
1030 strike_register_window_secs_,
1031 primary_orbit,
1032 strike_register_no_startup_period_ ?
1033 StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
1034 StrikeRegister::DENY_REQUESTS_AT_STARTUP));
1036 strike_register_client = strike_register_client_.get();
1039 strike_register_client->VerifyNonceIsValidAndUnique(
1040 info->client_nonce,
1041 info->now,
1042 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
1043 helper.StartedAsyncCallback();
1046 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1047 const SourceAddressTokens& previous_source_address_tokens,
1048 const IPEndPoint& server_ip,
1049 const IPEndPoint& client_ip,
1050 const QuicClock* clock,
1051 QuicRandom* rand,
1052 const QuicCryptoNegotiatedParameters& params,
1053 const CachedNetworkParameters* cached_network_params,
1054 CryptoHandshakeMessage* out) const {
1055 base::AutoLock locked(configs_lock_);
1056 out->set_tag(kSCUP);
1057 out->SetStringPiece(kSCFG, primary_config_->serialized);
1058 out->SetStringPiece(
1059 kSourceAddressTokenTag,
1060 NewSourceAddressToken(*primary_config_.get(),
1061 previous_source_address_tokens, client_ip, rand,
1062 clock->WallNow(), cached_network_params));
1064 if (proof_source_ == nullptr) {
1065 // Insecure QUIC, can send SCFG without proof.
1066 return true;
1069 const vector<string>* certs;
1070 string signature;
1071 if (!proof_source_->GetProof(
1072 server_ip, params.sni, primary_config_->serialized,
1073 params.x509_ecdsa_supported, &certs, &signature)) {
1074 DVLOG(1) << "Server: failed to get proof.";
1075 return false;
1078 const string compressed = CertCompressor::CompressChain(
1079 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes,
1080 primary_config_->common_cert_sets);
1082 out->SetStringPiece(kCertificateTag, compressed);
1083 out->SetStringPiece(kPROF, signature);
1084 return true;
1087 void QuicCryptoServerConfig::BuildRejection(
1088 const IPEndPoint& server_ip,
1089 const Config& config,
1090 const CryptoHandshakeMessage& client_hello,
1091 const ClientHelloInfo& info,
1092 const CachedNetworkParameters& cached_network_params,
1093 QuicRandom* rand,
1094 QuicCryptoNegotiatedParameters* params,
1095 CryptoHandshakeMessage* out) const {
1096 out->set_tag(kREJ);
1097 out->SetStringPiece(kSCFG, config.serialized);
1098 out->SetStringPiece(
1099 kSourceAddressTokenTag,
1100 NewSourceAddressToken(config, info.source_address_tokens, info.client_ip,
1101 rand, info.now, &cached_network_params));
1102 if (replay_protection_) {
1103 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
1106 // Send client the reject reason for debugging purposes.
1107 DCHECK_LT(0u, info.reject_reasons.size());
1108 out->SetVector(kRREJ, info.reject_reasons);
1110 // The client may have requested a certificate chain.
1111 const QuicTag* their_proof_demands;
1112 size_t num_their_proof_demands;
1114 if (proof_source_.get() == nullptr ||
1115 client_hello.GetTaglist(kPDMD, &their_proof_demands,
1116 &num_their_proof_demands) !=
1117 QUIC_NO_ERROR) {
1118 return;
1121 bool x509_supported = false;
1122 for (size_t i = 0; i < num_their_proof_demands; i++) {
1123 switch (their_proof_demands[i]) {
1124 case kX509:
1125 x509_supported = true;
1126 params->x509_ecdsa_supported = true;
1127 break;
1128 case kX59R:
1129 x509_supported = true;
1130 break;
1134 if (!x509_supported) {
1135 return;
1138 const vector<string>* certs;
1139 string signature;
1140 if (!proof_source_->GetProof(server_ip, info.sni.as_string(),
1141 config.serialized, params->x509_ecdsa_supported,
1142 &certs, &signature)) {
1143 return;
1146 StringPiece client_common_set_hashes;
1147 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
1148 params->client_common_set_hashes = client_common_set_hashes.as_string();
1151 StringPiece client_cached_cert_hashes;
1152 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
1153 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string();
1156 const string compressed = CertCompressor::CompressChain(
1157 *certs, params->client_common_set_hashes,
1158 params->client_cached_cert_hashes, config.common_cert_sets);
1160 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1161 // message is taken up by things other than the certificates.
1162 // STK: 56 bytes
1163 // SNO: 56 bytes
1164 // SCFG
1165 // SCID: 16 bytes
1166 // PUBS: 38 bytes
1167 const size_t kREJOverheadBytes = 166;
1168 // kMultiplier is the multiple of the CHLO message size that a REJ message
1169 // must stay under when the client doesn't present a valid source-address
1170 // token.
1171 const size_t kMultiplier = 2;
1172 // max_unverified_size is the number of bytes that the certificate chain
1173 // and signature can consume before we will demand a valid source-address
1174 // token.
1175 const size_t max_unverified_size =
1176 client_hello.size() * kMultiplier - kREJOverheadBytes;
1177 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1178 "overhead calculation may overflow");
1179 if (info.valid_source_address_token ||
1180 signature.size() + compressed.size() < max_unverified_size) {
1181 out->SetStringPiece(kCertificateTag, compressed);
1182 out->SetStringPiece(kPROF, signature);
1186 scoped_refptr<QuicCryptoServerConfig::Config>
1187 QuicCryptoServerConfig::ParseConfigProtobuf(
1188 QuicServerConfigProtobuf* protobuf) {
1189 scoped_ptr<CryptoHandshakeMessage> msg(
1190 CryptoFramer::ParseMessage(protobuf->config()));
1192 if (msg->tag() != kSCFG) {
1193 LOG(WARNING) << "Server config message has tag " << msg->tag()
1194 << " expected " << kSCFG;
1195 return nullptr;
1198 scoped_refptr<Config> config(new Config);
1199 config->serialized = protobuf->config();
1201 if (!protobuf->has_source_address_token_secret_override()) {
1202 // Use the default boxer.
1203 config->source_address_token_boxer = &default_source_address_token_boxer_;
1204 } else {
1205 // Create override boxer instance.
1206 CryptoSecretBoxer* boxer = new CryptoSecretBoxer;
1207 boxer->SetKey(DeriveSourceAddressTokenKey(
1208 protobuf->source_address_token_secret_override()));
1209 config->source_address_token_boxer_storage.reset(boxer);
1210 config->source_address_token_boxer = boxer;
1213 if (protobuf->has_primary_time()) {
1214 config->primary_time =
1215 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1218 config->priority = protobuf->priority();
1220 StringPiece scid;
1221 if (!msg->GetStringPiece(kSCID, &scid)) {
1222 LOG(WARNING) << "Server config message is missing SCID";
1223 return nullptr;
1225 config->id = scid.as_string();
1227 const QuicTag* aead_tags;
1228 size_t aead_len;
1229 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
1230 LOG(WARNING) << "Server config message is missing AEAD";
1231 return nullptr;
1233 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
1235 const QuicTag* kexs_tags;
1236 size_t kexs_len;
1237 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
1238 LOG(WARNING) << "Server config message is missing KEXS";
1239 return nullptr;
1242 StringPiece orbit;
1243 if (!msg->GetStringPiece(kORBT, &orbit)) {
1244 LOG(WARNING) << "Server config message is missing ORBT";
1245 return nullptr;
1248 if (orbit.size() != kOrbitSize) {
1249 LOG(WARNING) << "Orbit value in server config is the wrong length."
1250 " Got " << orbit.size() << " want " << kOrbitSize;
1251 return nullptr;
1253 static_assert(sizeof(config->orbit) == kOrbitSize,
1254 "orbit has incorrect size");
1255 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1258 StrikeRegisterClient* strike_register_client;
1260 base::AutoLock locked(strike_register_client_lock_);
1261 strike_register_client = strike_register_client_.get();
1264 if (strike_register_client != nullptr &&
1265 !strike_register_client->IsKnownOrbit(orbit)) {
1266 LOG(WARNING)
1267 << "Rejecting server config with orbit that the strike register "
1268 "client doesn't know about.";
1269 return nullptr;
1273 if (kexs_len != protobuf->key_size()) {
1274 LOG(WARNING) << "Server config has " << kexs_len
1275 << " key exchange methods configured, but "
1276 << protobuf->key_size() << " private keys";
1277 return nullptr;
1280 const QuicTag* proof_demand_tags;
1281 size_t num_proof_demand_tags;
1282 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
1283 QUIC_NO_ERROR) {
1284 for (size_t i = 0; i < num_proof_demand_tags; i++) {
1285 if (proof_demand_tags[i] == kCHID) {
1286 config->channel_id_enabled = true;
1287 break;
1292 for (size_t i = 0; i < kexs_len; i++) {
1293 const QuicTag tag = kexs_tags[i];
1294 string private_key;
1296 config->kexs.push_back(tag);
1298 for (size_t j = 0; j < protobuf->key_size(); j++) {
1299 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1300 if (key.tag() == tag) {
1301 private_key = key.private_key();
1302 break;
1306 if (private_key.empty()) {
1307 LOG(WARNING) << "Server config contains key exchange method without "
1308 "corresponding private key: " << tag;
1309 return nullptr;
1312 scoped_ptr<KeyExchange> ka;
1313 switch (tag) {
1314 case kC255:
1315 ka.reset(Curve25519KeyExchange::New(private_key));
1316 if (!ka.get()) {
1317 LOG(WARNING) << "Server config contained an invalid curve25519"
1318 " private key.";
1319 return nullptr;
1321 break;
1322 case kP256:
1323 ka.reset(P256KeyExchange::New(private_key));
1324 if (!ka.get()) {
1325 LOG(WARNING) << "Server config contained an invalid P-256"
1326 " private key.";
1327 return nullptr;
1329 break;
1330 default:
1331 LOG(WARNING) << "Server config message contains unknown key exchange "
1332 "method: " << tag;
1333 return nullptr;
1336 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
1337 i != config->key_exchanges.end(); ++i) {
1338 if ((*i)->tag() == tag) {
1339 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1340 return nullptr;
1344 config->key_exchanges.push_back(ka.release());
1347 return config;
1350 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
1351 proof_source_.reset(proof_source);
1354 void QuicCryptoServerConfig::SetEphemeralKeySource(
1355 EphemeralKeySource* ephemeral_key_source) {
1356 ephemeral_key_source_.reset(ephemeral_key_source);
1359 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1360 StrikeRegisterClient* strike_register_client) {
1361 base::AutoLock locker(strike_register_client_lock_);
1362 DCHECK(!strike_register_client_.get());
1363 strike_register_client_.reset(strike_register_client);
1366 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1367 replay_protection_ = on;
1370 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1371 base::AutoLock locker(strike_register_client_lock_);
1372 DCHECK(!strike_register_client_.get());
1373 strike_register_no_startup_period_ = true;
1376 void QuicCryptoServerConfig::set_strike_register_max_entries(
1377 uint32 max_entries) {
1378 base::AutoLock locker(strike_register_client_lock_);
1379 DCHECK(!strike_register_client_.get());
1380 strike_register_max_entries_ = max_entries;
1383 void QuicCryptoServerConfig::set_strike_register_window_secs(
1384 uint32 window_secs) {
1385 base::AutoLock locker(strike_register_client_lock_);
1386 DCHECK(!strike_register_client_.get());
1387 strike_register_window_secs_ = window_secs;
1390 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1391 uint32 future_secs) {
1392 source_address_token_future_secs_ = future_secs;
1395 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1396 uint32 lifetime_secs) {
1397 source_address_token_lifetime_secs_ = lifetime_secs;
1400 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1401 uint32 max_entries) {
1402 DCHECK(!server_nonce_strike_register_.get());
1403 server_nonce_strike_register_max_entries_ = max_entries;
1406 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1407 uint32 window_secs) {
1408 DCHECK(!server_nonce_strike_register_.get());
1409 server_nonce_strike_register_window_secs_ = window_secs;
1412 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1413 PrimaryConfigChangedCallback* cb) {
1414 base::AutoLock locked(configs_lock_);
1415 primary_config_changed_cb_.reset(cb);
1418 string QuicCryptoServerConfig::NewSourceAddressToken(
1419 const Config& config,
1420 const SourceAddressTokens& previous_tokens,
1421 const IPEndPoint& ip,
1422 QuicRandom* rand,
1423 QuicWallTime now,
1424 const CachedNetworkParameters* cached_network_params) const {
1425 IPAddressNumber ip_address = ip.address();
1426 if (ip.GetSockAddrFamily() == AF_INET) {
1427 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1429 SourceAddressTokens source_address_tokens;
1430 SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
1431 source_address_token->set_ip(IPAddressToPackedString(ip_address));
1432 source_address_token->set_timestamp(now.ToUNIXSeconds());
1433 if (cached_network_params != nullptr) {
1434 *(source_address_token->mutable_cached_network_parameters()) =
1435 *cached_network_params;
1438 if (!FLAGS_quic_use_multiple_address_in_source_tokens) {
1439 return config.source_address_token_boxer->Box(
1440 rand, source_address_token->SerializeAsString());
1443 // Append previous tokens.
1444 for (size_t i = 0; i < previous_tokens.tokens_size(); i++) {
1445 const SourceAddressToken& token = previous_tokens.tokens(i);
1446 if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
1447 break;
1450 if (token.ip() == source_address_token->ip()) {
1451 // It's for the same IP address.
1452 continue;
1455 if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
1456 continue;
1459 *(source_address_tokens.add_tokens()) = token;
1462 return config.source_address_token_boxer->Box(
1463 rand, source_address_tokens.SerializeAsString());
1466 bool QuicCryptoServerConfig::HasProofSource() const {
1467 return proof_source_ != nullptr;
1470 HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
1471 const Config& config,
1472 StringPiece token,
1473 SourceAddressTokens* tokens) const {
1474 string storage;
1475 StringPiece plaintext;
1476 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1477 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1480 if (!FLAGS_quic_use_multiple_address_in_source_tokens) {
1481 SourceAddressToken token;
1482 if (!token.ParseFromArray(plaintext.data(), plaintext.size())) {
1483 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1485 *(tokens->add_tokens()) = token;
1486 return HANDSHAKE_OK;
1489 if (!tokens->ParseFromArray(plaintext.data(), plaintext.size())) {
1490 // Some clients might still be using the old source token format so
1491 // attempt to parse that format.
1492 // TODO(rch): remove this code once the new format is ubiquitous.
1493 SourceAddressToken token;
1494 if (!token.ParseFromArray(plaintext.data(), plaintext.size())) {
1495 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1497 *tokens->add_tokens() = token;
1500 return HANDSHAKE_OK;
1503 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressToken(
1504 const Config& config,
1505 StringPiece token,
1506 const IPEndPoint& ip,
1507 QuicWallTime now,
1508 CachedNetworkParameters* cached_network_params) const {
1509 string storage;
1510 StringPiece plaintext;
1511 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1512 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1515 SourceAddressToken source_address_token;
1516 if (!source_address_token.ParseFromArray(plaintext.data(),
1517 plaintext.size())) {
1518 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1521 IPAddressNumber ip_address = ip.address();
1522 if (ip.GetSockAddrFamily() == AF_INET) {
1523 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1525 if (source_address_token.ip() != IPAddressToPackedString(ip_address)) {
1526 // It's for a different IP address.
1527 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1530 const QuicWallTime timestamp(
1531 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1532 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1534 if (now.IsBefore(timestamp) &&
1535 delta.ToSeconds() > source_address_token_future_secs_) {
1536 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1539 if (now.IsAfter(timestamp) &&
1540 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1541 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1544 if (source_address_token.has_cached_network_parameters()) {
1545 *cached_network_params = source_address_token.cached_network_parameters();
1548 return HANDSHAKE_OK;
1551 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
1552 const SourceAddressTokens& source_address_tokens,
1553 const IPEndPoint& ip,
1554 QuicWallTime now,
1555 CachedNetworkParameters* cached_network_params) const {
1556 HandshakeFailureReason reason =
1557 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1558 for (size_t i = 0; i < source_address_tokens.tokens_size(); i++) {
1559 const SourceAddressToken& token = source_address_tokens.tokens(i);
1560 reason = ValidateSingleSourceAddressToken(token, ip, now);
1561 if (reason == HANDSHAKE_OK) {
1562 if (token.has_cached_network_parameters()) {
1563 *cached_network_params = token.cached_network_parameters();
1565 break;
1568 return reason;
1571 HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1572 const SourceAddressToken& source_address_token,
1573 const IPEndPoint& ip,
1574 QuicWallTime now) const {
1575 IPAddressNumber ip_address = ip.address();
1576 if (ip.GetSockAddrFamily() == AF_INET) {
1577 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1579 if (source_address_token.ip() != IPAddressToPackedString(ip_address)) {
1580 // It's for a different IP address.
1581 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1584 return ValidateSourceAddressTokenTimestamp(source_address_token, now);
1587 HandshakeFailureReason
1588 QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1589 const SourceAddressToken& source_address_token,
1590 QuicWallTime now) const {
1591 const QuicWallTime timestamp(
1592 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1593 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1595 if (now.IsBefore(timestamp) &&
1596 delta.ToSeconds() > source_address_token_future_secs_) {
1597 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1600 if (now.IsAfter(timestamp) &&
1601 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1602 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1605 return HANDSHAKE_OK;
1608 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1609 // nonce.
1610 static const size_t kServerNoncePlaintextSize =
1611 4 /* timestamp */ + 20 /* random bytes */;
1613 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1614 QuicWallTime now) const {
1615 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds());
1617 uint8 server_nonce[kServerNoncePlaintextSize];
1618 static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
1619 server_nonce[0] = static_cast<uint8>(timestamp >> 24);
1620 server_nonce[1] = static_cast<uint8>(timestamp >> 16);
1621 server_nonce[2] = static_cast<uint8>(timestamp >> 8);
1622 server_nonce[3] = static_cast<uint8>(timestamp);
1623 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1624 sizeof(server_nonce) - sizeof(timestamp));
1626 return server_nonce_boxer_.Box(
1627 rand,
1628 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
1631 HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
1632 StringPiece token,
1633 QuicWallTime now) const {
1634 string storage;
1635 StringPiece plaintext;
1636 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
1637 return SERVER_NONCE_DECRYPTION_FAILURE;
1640 // plaintext contains:
1641 // uint32 timestamp
1642 // uint8[20] random bytes
1644 if (plaintext.size() != kServerNoncePlaintextSize) {
1645 // This should never happen because the value decrypted correctly.
1646 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
1647 return SERVER_NONCE_INVALID_FAILURE;
1650 uint8 server_nonce[32];
1651 memcpy(server_nonce, plaintext.data(), 4);
1652 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
1653 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
1654 20);
1655 static_assert(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
1656 "bad nonce buffer length");
1658 InsertStatus nonce_error;
1660 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
1661 if (server_nonce_strike_register_.get() == nullptr) {
1662 server_nonce_strike_register_.reset(new StrikeRegister(
1663 server_nonce_strike_register_max_entries_,
1664 static_cast<uint32>(now.ToUNIXSeconds()),
1665 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
1666 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
1668 nonce_error = server_nonce_strike_register_->Insert(
1669 server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
1672 switch (nonce_error) {
1673 case NONCE_OK:
1674 return HANDSHAKE_OK;
1675 case NONCE_INVALID_FAILURE:
1676 case NONCE_INVALID_ORBIT_FAILURE:
1677 return SERVER_NONCE_INVALID_FAILURE;
1678 case NONCE_NOT_UNIQUE_FAILURE:
1679 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1680 case NONCE_INVALID_TIME_FAILURE:
1681 return SERVER_NONCE_INVALID_TIME_FAILURE;
1682 case NONCE_UNKNOWN_FAILURE:
1683 case STRIKE_REGISTER_TIMEOUT:
1684 case STRIKE_REGISTER_FAILURE:
1685 default:
1686 LOG(DFATAL) << "Unexpected server nonce error: " << nonce_error;
1687 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1691 QuicCryptoServerConfig::Config::Config()
1692 : channel_id_enabled(false),
1693 is_primary(false),
1694 primary_time(QuicWallTime::Zero()),
1695 priority(0),
1696 source_address_token_boxer(nullptr) {}
1698 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
1700 } // namespace net