Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / net / quic / crypto / quic_crypto_server_config.cc
blob22a882387f666bd57a57aa3a8644aa82b177b7a5
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_copy_serialized =
669 client_hello_copy.GetSerialized();
670 string hkdf_input;
671 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
672 strlen(QuicCryptoConfig::kCETVLabel) + 1);
673 hkdf_input.append(reinterpret_cast<char*>(&connection_id),
674 sizeof(connection_id));
675 hkdf_input.append(client_hello_copy_serialized.data(),
676 client_hello_copy_serialized.length());
677 hkdf_input.append(requested_config->serialized);
679 CrypterPair crypters;
680 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
681 info.client_nonce, info.server_nonce,
682 hkdf_input, CryptoUtils::SERVER, &crypters,
683 nullptr /* subkey secret */)) {
684 *error_details = "Symmetric key setup failed";
685 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
688 char plaintext[kMaxPacketSize];
689 size_t plaintext_length = 0;
690 const bool success = crypters.decrypter->DecryptPacket(
691 0 /* sequence number */, StringPiece() /* associated data */,
692 cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
693 if (!success) {
694 *error_details = "CETV decryption failure";
695 return QUIC_PACKET_TOO_LARGE;
697 scoped_ptr<CryptoHandshakeMessage> cetv(
698 CryptoFramer::ParseMessage(StringPiece(plaintext, plaintext_length)));
699 if (!cetv.get()) {
700 *error_details = "CETV parse error";
701 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
704 StringPiece key, signature;
705 if (cetv->GetStringPiece(kCIDK, &key) &&
706 cetv->GetStringPiece(kCIDS, &signature)) {
707 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
708 *error_details = "ChannelID signature failure";
709 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
712 params->channel_id = key.as_string();
716 string hkdf_input;
717 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
718 hkdf_input.reserve(label_len + hkdf_suffix.size());
719 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
720 hkdf_input.append(hkdf_suffix);
722 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
723 info.client_nonce, info.server_nonce, hkdf_input,
724 CryptoUtils::SERVER,
725 &params->initial_crypters,
726 nullptr /* subkey secret */)) {
727 *error_details = "Symmetric key setup failed";
728 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
731 string forward_secure_public_value;
732 if (ephemeral_key_source_.get()) {
733 params->forward_secure_premaster_secret =
734 ephemeral_key_source_->CalculateForwardSecureKey(
735 key_exchange, rand, clock->ApproximateNow(), public_value,
736 &forward_secure_public_value);
737 } else {
738 scoped_ptr<KeyExchange> forward_secure_key_exchange(
739 key_exchange->NewKeyPair(rand));
740 forward_secure_public_value =
741 forward_secure_key_exchange->public_value().as_string();
742 if (!forward_secure_key_exchange->CalculateSharedKey(
743 public_value, &params->forward_secure_premaster_secret)) {
744 *error_details = "Invalid public value";
745 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
749 string forward_secure_hkdf_input;
750 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
751 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
752 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
753 label_len);
754 forward_secure_hkdf_input.append(hkdf_suffix);
756 if (!CryptoUtils::DeriveKeys(
757 params->forward_secure_premaster_secret, params->aead,
758 info.client_nonce, info.server_nonce, forward_secure_hkdf_input,
759 CryptoUtils::SERVER, &params->forward_secure_crypters,
760 &params->subkey_secret)) {
761 *error_details = "Symmetric key setup failed";
762 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
765 out->set_tag(kSHLO);
766 QuicTagVector supported_version_tags;
767 for (size_t i = 0; i < supported_versions.size(); ++i) {
768 supported_version_tags.push_back
769 (QuicVersionToQuicTag(supported_versions[i]));
771 out->SetVector(kVER, supported_version_tags);
772 out->SetStringPiece(
773 kSourceAddressTokenTag,
774 NewSourceAddressToken(*requested_config.get(), info.source_address_tokens,
775 client_address, rand, info.now, nullptr));
776 QuicSocketAddressCoder address_coder(client_address);
777 out->SetStringPiece(kCADR, address_coder.Encode());
778 out->SetStringPiece(kPUBS, forward_secure_public_value);
780 return QUIC_NO_ERROR;
783 scoped_refptr<QuicCryptoServerConfig::Config>
784 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const {
785 // In Chromium, we will dead lock if the lock is held by the current thread.
786 // Chromium doesn't have AssertReaderHeld API call.
787 // configs_lock_.AssertReaderHeld();
789 if (!requested_scid.empty()) {
790 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
791 if (it != configs_.end()) {
792 // We'll use the config that the client requested in order to do
793 // key-agreement.
794 return scoped_refptr<Config>(it->second);
798 return scoped_refptr<Config>();
801 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
802 // Config's based on their primary_time.
803 // static
804 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
805 const scoped_refptr<Config>& a,
806 const scoped_refptr<Config>& b) {
807 if (a->primary_time.IsBefore(b->primary_time) ||
808 b->primary_time.IsBefore(a->primary_time)) {
809 // Primary times differ.
810 return a->primary_time.IsBefore(b->primary_time);
811 } else if (a->priority != b->priority) {
812 // Primary times are equal, sort backwards by priority.
813 return a->priority < b->priority;
814 } else {
815 // Primary times and priorities are equal, sort by config id.
816 return a->id < b->id;
820 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
821 const QuicWallTime now) const {
822 vector<scoped_refptr<Config> > configs;
823 configs.reserve(configs_.size());
825 for (ConfigMap::const_iterator it = configs_.begin();
826 it != configs_.end(); ++it) {
827 // TODO(avd) Exclude expired configs?
828 configs.push_back(it->second);
831 if (configs.empty()) {
832 if (primary_config_.get()) {
833 LOG(DFATAL) << "No valid QUIC server config. Keeping the current config.";
834 } else {
835 LOG(DFATAL) << "No valid QUIC server config.";
837 return;
840 std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
842 Config* best_candidate = configs[0].get();
844 for (size_t i = 0; i < configs.size(); ++i) {
845 const scoped_refptr<Config> config(configs[i]);
846 if (!config->primary_time.IsAfter(now)) {
847 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
848 best_candidate = config.get();
850 continue;
853 // This is the first config with a primary_time in the future. Thus the
854 // previous Config should be the primary and this one should determine the
855 // next_config_promotion_time_.
856 scoped_refptr<Config> new_primary(best_candidate);
857 if (i == 0) {
858 // We need the primary_time of the next config.
859 if (configs.size() > 1) {
860 next_config_promotion_time_ = configs[1]->primary_time;
861 } else {
862 next_config_promotion_time_ = QuicWallTime::Zero();
864 } else {
865 next_config_promotion_time_ = config->primary_time;
868 if (primary_config_.get()) {
869 primary_config_->is_primary = false;
871 primary_config_ = new_primary;
872 new_primary->is_primary = true;
873 DVLOG(1) << "New primary config. orbit: "
874 << base::HexEncode(
875 reinterpret_cast<const char*>(primary_config_->orbit),
876 kOrbitSize);
877 if (primary_config_changed_cb_.get() != nullptr) {
878 primary_config_changed_cb_->Run(primary_config_->id);
881 return;
884 // All config's primary times are in the past. We should make the most recent
885 // and highest priority candidate primary.
886 scoped_refptr<Config> new_primary(best_candidate);
887 if (primary_config_.get()) {
888 primary_config_->is_primary = false;
890 primary_config_ = new_primary;
891 new_primary->is_primary = true;
892 DVLOG(1) << "New primary config. orbit: "
893 << base::HexEncode(
894 reinterpret_cast<const char*>(primary_config_->orbit),
895 kOrbitSize)
896 << " scid: " << base::HexEncode(primary_config_->id.data(),
897 primary_config_->id.size());
898 next_config_promotion_time_ = QuicWallTime::Zero();
899 if (primary_config_changed_cb_.get() != nullptr) {
900 primary_config_changed_cb_->Run(primary_config_->id);
904 void QuicCryptoServerConfig::EvaluateClientHello(
905 const uint8* primary_orbit,
906 scoped_refptr<Config> requested_config,
907 ValidateClientHelloResultCallback::Result* client_hello_state,
908 ValidateClientHelloResultCallback* done_cb) const {
909 ValidateClientHelloHelper helper(client_hello_state, done_cb);
911 const CryptoHandshakeMessage& client_hello =
912 client_hello_state->client_hello;
913 ClientHelloInfo* info = &(client_hello_state->info);
915 if (client_hello.size() < kClientHelloMinimumSize) {
916 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
917 "Client hello too small");
918 return;
921 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
922 !CryptoUtils::IsValidSNI(info->sni)) {
923 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
924 "Invalid SNI name");
925 return;
928 client_hello.GetStringPiece(kUAID, &info->user_agent_id);
930 if (!requested_config.get()) {
931 StringPiece requested_scid;
932 if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
933 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
934 } else {
935 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
937 // No server config with the requested ID.
938 helper.ValidationComplete(QUIC_NO_ERROR, "");
939 return;
942 HandshakeFailureReason source_address_token_error;
943 StringPiece srct;
944 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
945 if (!FLAGS_quic_use_multiple_address_in_source_tokens) {
946 source_address_token_error = ValidateSourceAddressToken(
947 *requested_config.get(), srct, info->client_ip, info->now,
948 &client_hello_state->cached_network_params);
949 } else {
950 source_address_token_error = ParseSourceAddressToken(
951 *requested_config.get(), srct, &info->source_address_tokens);
953 if (source_address_token_error == HANDSHAKE_OK) {
954 source_address_token_error = ValidateSourceAddressTokens(
955 info->source_address_tokens, info->client_ip, info->now,
956 &client_hello_state->cached_network_params);
959 info->valid_source_address_token =
960 (source_address_token_error == HANDSHAKE_OK);
961 } else {
962 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
965 bool found_error = false;
966 if (source_address_token_error != HANDSHAKE_OK) {
967 info->reject_reasons.push_back(source_address_token_error);
968 // No valid source address token.
969 if (FLAGS_use_early_return_when_verifying_chlo) {
970 helper.ValidationComplete(QUIC_NO_ERROR, "");
971 return;
973 found_error = true;
976 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) &&
977 info->client_nonce.size() == kNonceSize) {
978 info->client_nonce_well_formed = true;
979 } else {
980 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
981 // Invalid client nonce.
982 DVLOG(1) << "Invalid client nonce.";
983 if (FLAGS_use_early_return_when_verifying_chlo) {
984 helper.ValidationComplete(QUIC_NO_ERROR, "");
985 return;
987 found_error = true;
990 if (!replay_protection_) {
991 if (!found_error) {
992 info->unique = true;
994 DVLOG(1) << "No replay protection.";
995 helper.ValidationComplete(QUIC_NO_ERROR, "");
996 return;
999 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
1000 if (!info->server_nonce.empty()) {
1001 // If the server nonce is present, use it to establish uniqueness.
1002 HandshakeFailureReason server_nonce_error =
1003 ValidateServerNonce(info->server_nonce, info->now);
1004 if (server_nonce_error == HANDSHAKE_OK) {
1005 info->unique = true;
1006 } else {
1007 info->reject_reasons.push_back(server_nonce_error);
1008 info->unique = false;
1010 DVLOG(1) << "Using server nonce, unique: " << info->unique;
1011 helper.ValidationComplete(QUIC_NO_ERROR, "");
1012 return;
1015 // We want to contact strike register only if there are no errors because it
1016 // is a RPC call and is expensive.
1017 if (found_error) {
1018 helper.ValidationComplete(QUIC_NO_ERROR, "");
1019 return;
1022 // Use the client nonce to establish uniqueness.
1023 StrikeRegisterClient* strike_register_client;
1025 base::AutoLock locked(strike_register_client_lock_);
1027 if (strike_register_client_.get() == nullptr) {
1028 strike_register_client_.reset(new LocalStrikeRegisterClient(
1029 strike_register_max_entries_,
1030 static_cast<uint32>(info->now.ToUNIXSeconds()),
1031 strike_register_window_secs_,
1032 primary_orbit,
1033 strike_register_no_startup_period_ ?
1034 StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
1035 StrikeRegister::DENY_REQUESTS_AT_STARTUP));
1037 strike_register_client = strike_register_client_.get();
1040 strike_register_client->VerifyNonceIsValidAndUnique(
1041 info->client_nonce,
1042 info->now,
1043 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
1044 helper.StartedAsyncCallback();
1047 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1048 const SourceAddressTokens& previous_source_address_tokens,
1049 const IPEndPoint& server_ip,
1050 const IPEndPoint& client_ip,
1051 const QuicClock* clock,
1052 QuicRandom* rand,
1053 const QuicCryptoNegotiatedParameters& params,
1054 const CachedNetworkParameters* cached_network_params,
1055 CryptoHandshakeMessage* out) const {
1056 base::AutoLock locked(configs_lock_);
1057 out->set_tag(kSCUP);
1058 out->SetStringPiece(kSCFG, primary_config_->serialized);
1059 out->SetStringPiece(
1060 kSourceAddressTokenTag,
1061 NewSourceAddressToken(*primary_config_.get(),
1062 previous_source_address_tokens, client_ip, rand,
1063 clock->WallNow(), cached_network_params));
1065 if (proof_source_ == nullptr) {
1066 // Insecure QUIC, can send SCFG without proof.
1067 return true;
1070 const vector<string>* certs;
1071 string signature;
1072 if (!proof_source_->GetProof(
1073 server_ip, params.sni, primary_config_->serialized,
1074 params.x509_ecdsa_supported, &certs, &signature)) {
1075 DVLOG(1) << "Server: failed to get proof.";
1076 return false;
1079 const string compressed = CertCompressor::CompressChain(
1080 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes,
1081 primary_config_->common_cert_sets);
1083 out->SetStringPiece(kCertificateTag, compressed);
1084 out->SetStringPiece(kPROF, signature);
1085 return true;
1088 void QuicCryptoServerConfig::BuildRejection(
1089 const IPEndPoint& server_ip,
1090 const Config& config,
1091 const CryptoHandshakeMessage& client_hello,
1092 const ClientHelloInfo& info,
1093 const CachedNetworkParameters& cached_network_params,
1094 QuicRandom* rand,
1095 QuicCryptoNegotiatedParameters* params,
1096 CryptoHandshakeMessage* out) const {
1097 out->set_tag(kREJ);
1098 out->SetStringPiece(kSCFG, config.serialized);
1099 out->SetStringPiece(
1100 kSourceAddressTokenTag,
1101 NewSourceAddressToken(config, info.source_address_tokens, info.client_ip,
1102 rand, info.now, &cached_network_params));
1103 if (replay_protection_) {
1104 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
1107 // Send client the reject reason for debugging purposes.
1108 DCHECK_LT(0u, info.reject_reasons.size());
1109 out->SetVector(kRREJ, info.reject_reasons);
1111 // The client may have requested a certificate chain.
1112 const QuicTag* their_proof_demands;
1113 size_t num_their_proof_demands;
1115 if (proof_source_.get() == nullptr ||
1116 client_hello.GetTaglist(kPDMD, &their_proof_demands,
1117 &num_their_proof_demands) !=
1118 QUIC_NO_ERROR) {
1119 return;
1122 bool x509_supported = false;
1123 for (size_t i = 0; i < num_their_proof_demands; i++) {
1124 switch (their_proof_demands[i]) {
1125 case kX509:
1126 x509_supported = true;
1127 params->x509_ecdsa_supported = true;
1128 break;
1129 case kX59R:
1130 x509_supported = true;
1131 break;
1135 if (!x509_supported) {
1136 return;
1139 const vector<string>* certs;
1140 string signature;
1141 if (!proof_source_->GetProof(server_ip, info.sni.as_string(),
1142 config.serialized, params->x509_ecdsa_supported,
1143 &certs, &signature)) {
1144 return;
1147 StringPiece client_common_set_hashes;
1148 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
1149 params->client_common_set_hashes = client_common_set_hashes.as_string();
1152 StringPiece client_cached_cert_hashes;
1153 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
1154 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string();
1157 const string compressed = CertCompressor::CompressChain(
1158 *certs, params->client_common_set_hashes,
1159 params->client_cached_cert_hashes, config.common_cert_sets);
1161 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1162 // message is taken up by things other than the certificates.
1163 // STK: 56 bytes
1164 // SNO: 56 bytes
1165 // SCFG
1166 // SCID: 16 bytes
1167 // PUBS: 38 bytes
1168 const size_t kREJOverheadBytes = 166;
1169 // kMultiplier is the multiple of the CHLO message size that a REJ message
1170 // must stay under when the client doesn't present a valid source-address
1171 // token.
1172 const size_t kMultiplier = 2;
1173 // max_unverified_size is the number of bytes that the certificate chain
1174 // and signature can consume before we will demand a valid source-address
1175 // token.
1176 const size_t max_unverified_size =
1177 client_hello.size() * kMultiplier - kREJOverheadBytes;
1178 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1179 "overhead calculation may overflow");
1180 if (info.valid_source_address_token ||
1181 signature.size() + compressed.size() < max_unverified_size) {
1182 out->SetStringPiece(kCertificateTag, compressed);
1183 out->SetStringPiece(kPROF, signature);
1187 scoped_refptr<QuicCryptoServerConfig::Config>
1188 QuicCryptoServerConfig::ParseConfigProtobuf(
1189 QuicServerConfigProtobuf* protobuf) {
1190 scoped_ptr<CryptoHandshakeMessage> msg(
1191 CryptoFramer::ParseMessage(protobuf->config()));
1193 if (msg->tag() != kSCFG) {
1194 LOG(WARNING) << "Server config message has tag " << msg->tag()
1195 << " expected " << kSCFG;
1196 return nullptr;
1199 scoped_refptr<Config> config(new Config);
1200 config->serialized = protobuf->config();
1202 if (!protobuf->has_source_address_token_secret_override()) {
1203 // Use the default boxer.
1204 config->source_address_token_boxer = &default_source_address_token_boxer_;
1205 } else {
1206 // Create override boxer instance.
1207 CryptoSecretBoxer* boxer = new CryptoSecretBoxer;
1208 boxer->SetKey(DeriveSourceAddressTokenKey(
1209 protobuf->source_address_token_secret_override()));
1210 config->source_address_token_boxer_storage.reset(boxer);
1211 config->source_address_token_boxer = boxer;
1214 if (protobuf->has_primary_time()) {
1215 config->primary_time =
1216 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1219 config->priority = protobuf->priority();
1221 StringPiece scid;
1222 if (!msg->GetStringPiece(kSCID, &scid)) {
1223 LOG(WARNING) << "Server config message is missing SCID";
1224 return nullptr;
1226 config->id = scid.as_string();
1228 const QuicTag* aead_tags;
1229 size_t aead_len;
1230 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
1231 LOG(WARNING) << "Server config message is missing AEAD";
1232 return nullptr;
1234 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
1236 const QuicTag* kexs_tags;
1237 size_t kexs_len;
1238 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
1239 LOG(WARNING) << "Server config message is missing KEXS";
1240 return nullptr;
1243 StringPiece orbit;
1244 if (!msg->GetStringPiece(kORBT, &orbit)) {
1245 LOG(WARNING) << "Server config message is missing ORBT";
1246 return nullptr;
1249 if (orbit.size() != kOrbitSize) {
1250 LOG(WARNING) << "Orbit value in server config is the wrong length."
1251 " Got " << orbit.size() << " want " << kOrbitSize;
1252 return nullptr;
1254 static_assert(sizeof(config->orbit) == kOrbitSize,
1255 "orbit has incorrect size");
1256 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1259 StrikeRegisterClient* strike_register_client;
1261 base::AutoLock locked(strike_register_client_lock_);
1262 strike_register_client = strike_register_client_.get();
1265 if (strike_register_client != nullptr &&
1266 !strike_register_client->IsKnownOrbit(orbit)) {
1267 LOG(WARNING)
1268 << "Rejecting server config with orbit that the strike register "
1269 "client doesn't know about.";
1270 return nullptr;
1274 if (kexs_len != protobuf->key_size()) {
1275 LOG(WARNING) << "Server config has " << kexs_len
1276 << " key exchange methods configured, but "
1277 << protobuf->key_size() << " private keys";
1278 return nullptr;
1281 const QuicTag* proof_demand_tags;
1282 size_t num_proof_demand_tags;
1283 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
1284 QUIC_NO_ERROR) {
1285 for (size_t i = 0; i < num_proof_demand_tags; i++) {
1286 if (proof_demand_tags[i] == kCHID) {
1287 config->channel_id_enabled = true;
1288 break;
1293 for (size_t i = 0; i < kexs_len; i++) {
1294 const QuicTag tag = kexs_tags[i];
1295 string private_key;
1297 config->kexs.push_back(tag);
1299 for (size_t j = 0; j < protobuf->key_size(); j++) {
1300 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1301 if (key.tag() == tag) {
1302 private_key = key.private_key();
1303 break;
1307 if (private_key.empty()) {
1308 LOG(WARNING) << "Server config contains key exchange method without "
1309 "corresponding private key: " << tag;
1310 return nullptr;
1313 scoped_ptr<KeyExchange> ka;
1314 switch (tag) {
1315 case kC255:
1316 ka.reset(Curve25519KeyExchange::New(private_key));
1317 if (!ka.get()) {
1318 LOG(WARNING) << "Server config contained an invalid curve25519"
1319 " private key.";
1320 return nullptr;
1322 break;
1323 case kP256:
1324 ka.reset(P256KeyExchange::New(private_key));
1325 if (!ka.get()) {
1326 LOG(WARNING) << "Server config contained an invalid P-256"
1327 " private key.";
1328 return nullptr;
1330 break;
1331 default:
1332 LOG(WARNING) << "Server config message contains unknown key exchange "
1333 "method: " << tag;
1334 return nullptr;
1337 for (vector<KeyExchange*>::const_iterator j = config->key_exchanges.begin();
1338 j != config->key_exchanges.end(); ++j) {
1339 if ((*j)->tag() == tag) {
1340 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1341 return nullptr;
1345 config->key_exchanges.push_back(ka.release());
1348 return config;
1351 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
1352 proof_source_.reset(proof_source);
1355 void QuicCryptoServerConfig::SetEphemeralKeySource(
1356 EphemeralKeySource* ephemeral_key_source) {
1357 ephemeral_key_source_.reset(ephemeral_key_source);
1360 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1361 StrikeRegisterClient* strike_register_client) {
1362 base::AutoLock locker(strike_register_client_lock_);
1363 DCHECK(!strike_register_client_.get());
1364 strike_register_client_.reset(strike_register_client);
1367 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1368 replay_protection_ = on;
1371 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1372 base::AutoLock locker(strike_register_client_lock_);
1373 DCHECK(!strike_register_client_.get());
1374 strike_register_no_startup_period_ = true;
1377 void QuicCryptoServerConfig::set_strike_register_max_entries(
1378 uint32 max_entries) {
1379 base::AutoLock locker(strike_register_client_lock_);
1380 DCHECK(!strike_register_client_.get());
1381 strike_register_max_entries_ = max_entries;
1384 void QuicCryptoServerConfig::set_strike_register_window_secs(
1385 uint32 window_secs) {
1386 base::AutoLock locker(strike_register_client_lock_);
1387 DCHECK(!strike_register_client_.get());
1388 strike_register_window_secs_ = window_secs;
1391 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1392 uint32 future_secs) {
1393 source_address_token_future_secs_ = future_secs;
1396 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1397 uint32 lifetime_secs) {
1398 source_address_token_lifetime_secs_ = lifetime_secs;
1401 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1402 uint32 max_entries) {
1403 DCHECK(!server_nonce_strike_register_.get());
1404 server_nonce_strike_register_max_entries_ = max_entries;
1407 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1408 uint32 window_secs) {
1409 DCHECK(!server_nonce_strike_register_.get());
1410 server_nonce_strike_register_window_secs_ = window_secs;
1413 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1414 PrimaryConfigChangedCallback* cb) {
1415 base::AutoLock locked(configs_lock_);
1416 primary_config_changed_cb_.reset(cb);
1419 string QuicCryptoServerConfig::NewSourceAddressToken(
1420 const Config& config,
1421 const SourceAddressTokens& previous_tokens,
1422 const IPEndPoint& ip,
1423 QuicRandom* rand,
1424 QuicWallTime now,
1425 const CachedNetworkParameters* cached_network_params) const {
1426 IPAddressNumber ip_address = ip.address();
1427 if (ip.GetSockAddrFamily() == AF_INET) {
1428 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1430 SourceAddressTokens source_address_tokens;
1431 SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
1432 source_address_token->set_ip(IPAddressToPackedString(ip_address));
1433 source_address_token->set_timestamp(now.ToUNIXSeconds());
1434 if (cached_network_params != nullptr) {
1435 *(source_address_token->mutable_cached_network_parameters()) =
1436 *cached_network_params;
1439 if (!FLAGS_quic_use_multiple_address_in_source_tokens) {
1440 return config.source_address_token_boxer->Box(
1441 rand, source_address_token->SerializeAsString());
1444 // Append previous tokens.
1445 for (size_t i = 0; i < previous_tokens.tokens_size(); i++) {
1446 const SourceAddressToken& token = previous_tokens.tokens(i);
1447 if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
1448 break;
1451 if (token.ip() == source_address_token->ip()) {
1452 // It's for the same IP address.
1453 continue;
1456 if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
1457 continue;
1460 *(source_address_tokens.add_tokens()) = token;
1463 return config.source_address_token_boxer->Box(
1464 rand, source_address_tokens.SerializeAsString());
1467 bool QuicCryptoServerConfig::HasProofSource() const {
1468 return proof_source_ != nullptr;
1471 HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
1472 const Config& config,
1473 StringPiece token,
1474 SourceAddressTokens* tokens) const {
1475 string storage;
1476 StringPiece plaintext;
1477 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1478 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1481 if (!FLAGS_quic_use_multiple_address_in_source_tokens) {
1482 SourceAddressToken source_address_token;
1483 if (!source_address_token.ParseFromArray(plaintext.data(),
1484 plaintext.size())) {
1485 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1487 *(tokens->add_tokens()) = source_address_token;
1488 return HANDSHAKE_OK;
1491 if (!tokens->ParseFromArray(plaintext.data(), plaintext.size())) {
1492 // Some clients might still be using the old source token format so
1493 // attempt to parse that format.
1494 // TODO(rch): remove this code once the new format is ubiquitous.
1495 SourceAddressToken source_address_token;
1496 if (!source_address_token.ParseFromArray(plaintext.data(),
1497 plaintext.size())) {
1498 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1500 *tokens->add_tokens() = source_address_token;
1503 return HANDSHAKE_OK;
1506 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressToken(
1507 const Config& config,
1508 StringPiece token,
1509 const IPEndPoint& ip,
1510 QuicWallTime now,
1511 CachedNetworkParameters* cached_network_params) const {
1512 string storage;
1513 StringPiece plaintext;
1514 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1515 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1518 SourceAddressToken source_address_token;
1519 if (!source_address_token.ParseFromArray(plaintext.data(),
1520 plaintext.size())) {
1521 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1524 IPAddressNumber ip_address = ip.address();
1525 if (ip.GetSockAddrFamily() == AF_INET) {
1526 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1528 if (source_address_token.ip() != IPAddressToPackedString(ip_address)) {
1529 // It's for a different IP address.
1530 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1533 const QuicWallTime timestamp(
1534 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1535 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1537 if (now.IsBefore(timestamp) &&
1538 delta.ToSeconds() > source_address_token_future_secs_) {
1539 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1542 if (now.IsAfter(timestamp) &&
1543 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1544 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1547 if (source_address_token.has_cached_network_parameters()) {
1548 *cached_network_params = source_address_token.cached_network_parameters();
1551 return HANDSHAKE_OK;
1554 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
1555 const SourceAddressTokens& source_address_tokens,
1556 const IPEndPoint& ip,
1557 QuicWallTime now,
1558 CachedNetworkParameters* cached_network_params) const {
1559 HandshakeFailureReason reason =
1560 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1561 for (size_t i = 0; i < source_address_tokens.tokens_size(); i++) {
1562 const SourceAddressToken& token = source_address_tokens.tokens(i);
1563 reason = ValidateSingleSourceAddressToken(token, ip, now);
1564 if (reason == HANDSHAKE_OK) {
1565 if (token.has_cached_network_parameters()) {
1566 *cached_network_params = token.cached_network_parameters();
1568 break;
1571 return reason;
1574 HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1575 const SourceAddressToken& source_address_token,
1576 const IPEndPoint& ip,
1577 QuicWallTime now) const {
1578 IPAddressNumber ip_address = ip.address();
1579 if (ip.GetSockAddrFamily() == AF_INET) {
1580 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1582 if (source_address_token.ip() != IPAddressToPackedString(ip_address)) {
1583 // It's for a different IP address.
1584 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1587 return ValidateSourceAddressTokenTimestamp(source_address_token, now);
1590 HandshakeFailureReason
1591 QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1592 const SourceAddressToken& source_address_token,
1593 QuicWallTime now) const {
1594 const QuicWallTime timestamp(
1595 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1596 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1598 if (now.IsBefore(timestamp) &&
1599 delta.ToSeconds() > source_address_token_future_secs_) {
1600 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1603 if (now.IsAfter(timestamp) &&
1604 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1605 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1608 return HANDSHAKE_OK;
1611 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1612 // nonce.
1613 static const size_t kServerNoncePlaintextSize =
1614 4 /* timestamp */ + 20 /* random bytes */;
1616 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1617 QuicWallTime now) const {
1618 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds());
1620 uint8 server_nonce[kServerNoncePlaintextSize];
1621 static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
1622 server_nonce[0] = static_cast<uint8>(timestamp >> 24);
1623 server_nonce[1] = static_cast<uint8>(timestamp >> 16);
1624 server_nonce[2] = static_cast<uint8>(timestamp >> 8);
1625 server_nonce[3] = static_cast<uint8>(timestamp);
1626 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1627 sizeof(server_nonce) - sizeof(timestamp));
1629 return server_nonce_boxer_.Box(
1630 rand,
1631 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
1634 HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
1635 StringPiece token,
1636 QuicWallTime now) const {
1637 string storage;
1638 StringPiece plaintext;
1639 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
1640 return SERVER_NONCE_DECRYPTION_FAILURE;
1643 // plaintext contains:
1644 // uint32 timestamp
1645 // uint8[20] random bytes
1647 if (plaintext.size() != kServerNoncePlaintextSize) {
1648 // This should never happen because the value decrypted correctly.
1649 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
1650 return SERVER_NONCE_INVALID_FAILURE;
1653 uint8 server_nonce[32];
1654 memcpy(server_nonce, plaintext.data(), 4);
1655 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
1656 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
1657 20);
1658 static_assert(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
1659 "bad nonce buffer length");
1661 InsertStatus nonce_error;
1663 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
1664 if (server_nonce_strike_register_.get() == nullptr) {
1665 server_nonce_strike_register_.reset(new StrikeRegister(
1666 server_nonce_strike_register_max_entries_,
1667 static_cast<uint32>(now.ToUNIXSeconds()),
1668 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
1669 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
1671 nonce_error = server_nonce_strike_register_->Insert(
1672 server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
1675 switch (nonce_error) {
1676 case NONCE_OK:
1677 return HANDSHAKE_OK;
1678 case NONCE_INVALID_FAILURE:
1679 case NONCE_INVALID_ORBIT_FAILURE:
1680 return SERVER_NONCE_INVALID_FAILURE;
1681 case NONCE_NOT_UNIQUE_FAILURE:
1682 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1683 case NONCE_INVALID_TIME_FAILURE:
1684 return SERVER_NONCE_INVALID_TIME_FAILURE;
1685 case NONCE_UNKNOWN_FAILURE:
1686 case STRIKE_REGISTER_TIMEOUT:
1687 case STRIKE_REGISTER_FAILURE:
1688 default:
1689 LOG(DFATAL) << "Unexpected server nonce error: " << nonce_error;
1690 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1694 QuicCryptoServerConfig::Config::Config()
1695 : channel_id_enabled(false),
1696 is_primary(false),
1697 primary_time(QuicWallTime::Zero()),
1698 priority(0),
1699 source_address_token_boxer(nullptr) {}
1701 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
1703 } // namespace net