Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / net / quic / crypto / quic_crypto_server_config.cc
blob3d99e5ed029fb471b691925058b3d6494cb18ac2
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/strike_register.h"
34 #include "net/quic/crypto/strike_register_client.h"
35 #include "net/quic/proto/source_address_token.pb.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 int 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 IPAddressNumber DualstackIPAddress(const IPAddressNumber& ip) {
66 if (ip.size() == kIPv4AddressSize) {
67 return ConvertIPv4NumberToIPv6Number(ip);
69 return ip;
72 } // namespace
74 class ValidateClientHelloHelper {
75 public:
76 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result,
77 ValidateClientHelloResultCallback* done_cb)
78 : result_(result), done_cb_(done_cb) {
81 ~ValidateClientHelloHelper() {
82 LOG_IF(DFATAL, done_cb_ != nullptr)
83 << "Deleting ValidateClientHelloHelper with a pending callback.";
86 void ValidationComplete(QuicErrorCode error_code, const char* error_details) {
87 result_->error_code = error_code;
88 result_->error_details = error_details;
89 done_cb_->Run(result_);
90 DetachCallback();
93 void StartedAsyncCallback() {
94 DetachCallback();
97 private:
98 void DetachCallback() {
99 LOG_IF(DFATAL, done_cb_ == nullptr) << "Callback already detached.";
100 done_cb_ = nullptr;
103 ValidateClientHelloResultCallback::Result* result_;
104 ValidateClientHelloResultCallback* done_cb_;
106 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
109 class VerifyNonceIsValidAndUniqueCallback
110 : public StrikeRegisterClient::ResultCallback {
111 public:
112 VerifyNonceIsValidAndUniqueCallback(
113 ValidateClientHelloResultCallback::Result* result,
114 ValidateClientHelloResultCallback* done_cb)
115 : result_(result), done_cb_(done_cb) {
118 protected:
119 void RunImpl(bool nonce_is_valid_and_unique,
120 InsertStatus nonce_error) override {
121 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique
122 << " nonce_error: " << nonce_error;
123 result_->info.unique = nonce_is_valid_and_unique;
124 if (!nonce_is_valid_and_unique) {
125 HandshakeFailureReason client_nonce_error;
126 switch (nonce_error) {
127 case NONCE_INVALID_FAILURE:
128 client_nonce_error = CLIENT_NONCE_INVALID_FAILURE;
129 break;
130 case NONCE_NOT_UNIQUE_FAILURE:
131 client_nonce_error = CLIENT_NONCE_NOT_UNIQUE_FAILURE;
132 break;
133 case NONCE_INVALID_ORBIT_FAILURE:
134 client_nonce_error = CLIENT_NONCE_INVALID_ORBIT_FAILURE;
135 break;
136 case NONCE_INVALID_TIME_FAILURE:
137 client_nonce_error = CLIENT_NONCE_INVALID_TIME_FAILURE;
138 break;
139 case STRIKE_REGISTER_TIMEOUT:
140 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT;
141 break;
142 case STRIKE_REGISTER_FAILURE:
143 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_FAILURE;
144 break;
145 case NONCE_UNKNOWN_FAILURE:
146 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
147 break;
148 case NONCE_OK:
149 default:
150 LOG(DFATAL) << "Unexpected client nonce error: " << nonce_error;
151 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
152 break;
154 result_->info.reject_reasons.push_back(client_nonce_error);
156 done_cb_->Run(result_);
159 private:
160 ValidateClientHelloResultCallback::Result* result_;
161 ValidateClientHelloResultCallback* done_cb_;
163 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
166 // static
167 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
169 ClientHelloInfo::ClientHelloInfo(const IPAddressNumber& in_client_ip,
170 QuicWallTime in_now)
171 : client_ip(in_client_ip),
172 now(in_now),
173 valid_source_address_token(false),
174 client_nonce_well_formed(false),
175 unique(false) {
178 ClientHelloInfo::~ClientHelloInfo() {
181 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {
184 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {
187 ValidateClientHelloResultCallback::Result::Result(
188 const CryptoHandshakeMessage& in_client_hello,
189 IPAddressNumber in_client_ip,
190 QuicWallTime in_now)
191 : client_hello(in_client_hello),
192 info(in_client_ip, in_now),
193 error_code(QUIC_NO_ERROR) {
196 ValidateClientHelloResultCallback::Result::~Result() {
199 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {
202 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {
205 void ValidateClientHelloResultCallback::Run(const Result* result) {
206 RunImpl(result->client_hello, *result);
207 delete result;
208 delete this;
211 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
212 : expiry_time(QuicWallTime::Zero()),
213 channel_id_enabled(false),
214 p256(false) {}
216 QuicCryptoServerConfig::QuicCryptoServerConfig(
217 StringPiece source_address_token_secret,
218 QuicRandom* rand)
219 : replay_protection_(true),
220 configs_lock_(),
221 primary_config_(nullptr),
222 next_config_promotion_time_(QuicWallTime::Zero()),
223 server_nonce_strike_register_lock_(),
224 strike_register_no_startup_period_(false),
225 strike_register_max_entries_(1 << 10),
226 strike_register_window_secs_(600),
227 source_address_token_future_secs_(3600),
228 source_address_token_lifetime_secs_(86400),
229 server_nonce_strike_register_max_entries_(1 << 10),
230 server_nonce_strike_register_window_secs_(120) {
231 default_source_address_token_boxer_.SetKey(
232 DeriveSourceAddressTokenKey(source_address_token_secret));
234 // Generate a random key and orbit for server nonces.
235 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_));
236 const size_t key_size = server_nonce_boxer_.GetKeySize();
237 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]);
238 rand->RandBytes(key_bytes.get(), key_size);
240 server_nonce_boxer_.SetKey(
241 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size));
244 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
245 primary_config_ = nullptr;
248 // static
249 QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig(
250 QuicRandom* rand,
251 const QuicClock* clock,
252 const ConfigOptions& options) {
253 CryptoHandshakeMessage msg;
255 const string curve25519_private_key =
256 Curve25519KeyExchange::NewPrivateKey(rand);
257 scoped_ptr<Curve25519KeyExchange> curve25519(
258 Curve25519KeyExchange::New(curve25519_private_key));
259 StringPiece curve25519_public_value = curve25519->public_value();
261 string encoded_public_values;
262 // First three bytes encode the length of the public value.
263 DCHECK_LT(curve25519_public_value.size(), (1U << 24));
264 encoded_public_values.push_back(
265 static_cast<char>(curve25519_public_value.size()));
266 encoded_public_values.push_back(
267 static_cast<char>(curve25519_public_value.size() >> 8));
268 encoded_public_values.push_back(
269 static_cast<char>(curve25519_public_value.size() >> 16));
270 encoded_public_values.append(curve25519_public_value.data(),
271 curve25519_public_value.size());
273 string p256_private_key;
274 if (options.p256) {
275 p256_private_key = P256KeyExchange::NewPrivateKey();
276 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
277 StringPiece p256_public_value = p256->public_value();
279 DCHECK_LT(p256_public_value.size(), (1U << 24));
280 encoded_public_values.push_back(
281 static_cast<char>(p256_public_value.size()));
282 encoded_public_values.push_back(
283 static_cast<char>(p256_public_value.size() >> 8));
284 encoded_public_values.push_back(
285 static_cast<char>(p256_public_value.size() >> 16));
286 encoded_public_values.append(p256_public_value.data(),
287 p256_public_value.size());
290 msg.set_tag(kSCFG);
291 if (options.p256) {
292 msg.SetTaglist(kKEXS, kC255, kP256, 0);
293 } else {
294 msg.SetTaglist(kKEXS, kC255, 0);
296 if (ChaCha20Poly1305Encrypter::IsSupported()) {
297 msg.SetTaglist(kAEAD, kAESG, kCC12, 0);
298 } else {
299 msg.SetTaglist(kAEAD, kAESG, 0);
301 msg.SetStringPiece(kPUBS, encoded_public_values);
303 if (options.expiry_time.IsZero()) {
304 const QuicWallTime now = clock->WallNow();
305 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
306 60 * 60 * 24 * 180 /* 180 days, ~six months */));
307 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
308 msg.SetValue(kEXPY, expiry_seconds);
309 } else {
310 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
313 char orbit_bytes[kOrbitSize];
314 if (options.orbit.size() == sizeof(orbit_bytes)) {
315 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
316 } else {
317 DCHECK(options.orbit.empty());
318 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
320 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
322 if (options.channel_id_enabled) {
323 msg.SetTaglist(kPDMD, kCHID, 0);
326 if (options.id.empty()) {
327 // We need to ensure that the SCID changes whenever the server config does
328 // thus we make it a hash of the rest of the server config.
329 scoped_ptr<QuicData> serialized(
330 CryptoFramer::ConstructHandshakeMessage(msg));
331 scoped_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256));
332 hash->Update(serialized->data(), serialized->length());
334 char scid_bytes[16];
335 hash->Finish(scid_bytes, sizeof(scid_bytes));
336 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
337 } else {
338 msg.SetStringPiece(kSCID, options.id);
340 // Don't put new tags below this point. The SCID generation should hash over
341 // everything but itself and so extra tags should be added prior to the
342 // preceeding if block.
344 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
346 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
347 config->set_config(serialized->AsStringPiece());
348 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
349 curve25519_key->set_tag(kC255);
350 curve25519_key->set_private_key(curve25519_private_key);
352 if (options.p256) {
353 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
354 p256_key->set_tag(kP256);
355 p256_key->set_private_key(p256_private_key);
358 return config.release();
361 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
362 QuicServerConfigProtobuf* protobuf,
363 const QuicWallTime now) {
364 scoped_ptr<CryptoHandshakeMessage> msg(
365 CryptoFramer::ParseMessage(protobuf->config()));
367 if (!msg.get()) {
368 LOG(WARNING) << "Failed to parse server config message";
369 return nullptr;
372 scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
373 if (!config.get()) {
374 LOG(WARNING) << "Failed to parse server config message";
375 return nullptr;
379 base::AutoLock locked(configs_lock_);
380 if (configs_.find(config->id) != configs_.end()) {
381 LOG(WARNING) << "Failed to add config because another with the same "
382 "server config id already exists: "
383 << base::HexEncode(config->id.data(), config->id.size());
384 return nullptr;
387 configs_[config->id] = config;
388 SelectNewPrimaryConfig(now);
389 DCHECK(primary_config_.get());
390 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
393 return msg.release();
396 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
397 QuicRandom* rand,
398 const QuicClock* clock,
399 const ConfigOptions& options) {
400 scoped_ptr<QuicServerConfigProtobuf> config(
401 GenerateConfig(rand, clock, options));
402 return AddConfig(config.get(), clock->WallNow());
405 bool QuicCryptoServerConfig::SetConfigs(
406 const vector<QuicServerConfigProtobuf*>& protobufs,
407 const QuicWallTime now) {
408 vector<scoped_refptr<Config> > parsed_configs;
409 bool ok = true;
411 for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin();
412 i != protobufs.end(); ++i) {
413 scoped_refptr<Config> config(ParseConfigProtobuf(*i));
414 if (!config.get()) {
415 ok = false;
416 break;
419 parsed_configs.push_back(config);
422 if (parsed_configs.empty()) {
423 LOG(WARNING) << "New config list is empty.";
424 ok = false;
427 if (!ok) {
428 LOG(WARNING) << "Rejecting QUIC configs because of above errors";
429 } else {
430 VLOG(1) << "Updating configs:";
432 base::AutoLock locked(configs_lock_);
433 ConfigMap new_configs;
435 for (vector<scoped_refptr<Config> >::const_iterator i =
436 parsed_configs.begin();
437 i != parsed_configs.end(); ++i) {
438 scoped_refptr<Config> config = *i;
440 ConfigMap::iterator it = configs_.find(config->id);
441 if (it != configs_.end()) {
442 VLOG(1)
443 << "Keeping scid: " << base::HexEncode(
444 config->id.data(), config->id.size())
445 << " orbit: " << base::HexEncode(
446 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
447 << " new primary_time " << config->primary_time.ToUNIXSeconds()
448 << " old primary_time " << it->second->primary_time.ToUNIXSeconds()
449 << " new priority " << config->priority
450 << " old priority " << it->second->priority;
451 // Update primary_time and priority.
452 it->second->primary_time = config->primary_time;
453 it->second->priority = config->priority;
454 new_configs.insert(*it);
455 } else {
456 VLOG(1) << "Adding scid: " << base::HexEncode(
457 config->id.data(), config->id.size())
458 << " orbit: " << base::HexEncode(
459 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
460 << " primary_time " << config->primary_time.ToUNIXSeconds()
461 << " priority " << config->priority;
462 new_configs.insert(std::make_pair(config->id, config));
466 configs_.swap(new_configs);
467 SelectNewPrimaryConfig(now);
468 DCHECK(primary_config_.get());
469 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
472 return ok;
475 void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
476 base::AutoLock locked(configs_lock_);
477 for (ConfigMap::const_iterator it = configs_.begin();
478 it != configs_.end(); ++it) {
479 scids->push_back(it->first);
483 void QuicCryptoServerConfig::ValidateClientHello(
484 const CryptoHandshakeMessage& client_hello,
485 IPAddressNumber client_ip,
486 const QuicClock* clock,
487 ValidateClientHelloResultCallback* done_cb) const {
488 const QuicWallTime now(clock->WallNow());
490 ValidateClientHelloResultCallback::Result* result =
491 new ValidateClientHelloResultCallback::Result(
492 client_hello, client_ip, now);
494 StringPiece requested_scid;
495 client_hello.GetStringPiece(kSCID, &requested_scid);
497 uint8 primary_orbit[kOrbitSize];
498 scoped_refptr<Config> requested_config;
500 base::AutoLock locked(configs_lock_);
502 if (!primary_config_.get()) {
503 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
504 result->error_details = "No configurations loaded";
505 } else {
506 if (!next_config_promotion_time_.IsZero() &&
507 next_config_promotion_time_.IsAfter(now)) {
508 SelectNewPrimaryConfig(now);
509 DCHECK(primary_config_.get());
510 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
513 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit));
516 requested_config = GetConfigWithScid(requested_scid);
519 if (result->error_code == QUIC_NO_ERROR) {
520 EvaluateClientHello(primary_orbit, requested_config, result, done_cb);
521 } else {
522 done_cb->Run(result);
526 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
527 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
528 QuicConnectionId connection_id,
529 const IPAddressNumber& server_ip,
530 const IPEndPoint& client_address,
531 QuicVersion version,
532 const QuicVersionVector& supported_versions,
533 bool use_stateless_rejects,
534 QuicConnectionId server_designated_connection_id,
535 const QuicClock* clock,
536 QuicRandom* rand,
537 QuicCryptoNegotiatedParameters* params,
538 CryptoHandshakeMessage* out,
539 string* error_details) const {
540 DCHECK(error_details);
542 const CryptoHandshakeMessage& client_hello =
543 validate_chlo_result.client_hello;
544 const ClientHelloInfo& info = validate_chlo_result.info;
546 // If the client's preferred version is not the version we are currently
547 // speaking, then the client went through a version negotiation. In this
548 // case, we need to make sure that we actually do not support this version
549 // and that it wasn't a downgrade attack.
550 QuicTag client_version_tag;
551 if (client_hello.GetUint32(kVER, &client_version_tag) != QUIC_NO_ERROR) {
552 *error_details = "client hello missing version list";
553 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
555 QuicVersion client_version = QuicTagToQuicVersion(client_version_tag);
556 if (client_version != version) {
557 // Just because client_version is a valid version enum doesn't mean that
558 // this server actually supports that version, so we check to see if
559 // it's actually in the supported versions list.
560 for (size_t i = 0; i < supported_versions.size(); ++i) {
561 if (client_version == supported_versions[i]) {
562 *error_details = "Downgrade attack detected";
563 return QUIC_VERSION_NEGOTIATION_MISMATCH;
568 StringPiece requested_scid;
569 client_hello.GetStringPiece(kSCID, &requested_scid);
570 const QuicWallTime now(clock->WallNow());
572 scoped_refptr<Config> requested_config;
573 scoped_refptr<Config> primary_config;
575 base::AutoLock locked(configs_lock_);
577 if (!primary_config_.get()) {
578 *error_details = "No configurations loaded";
579 return QUIC_CRYPTO_INTERNAL_ERROR;
582 if (!next_config_promotion_time_.IsZero() &&
583 next_config_promotion_time_.IsAfter(now)) {
584 SelectNewPrimaryConfig(now);
585 DCHECK(primary_config_.get());
586 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
589 // We'll use the config that the client requested in order to do
590 // key-agreement. Otherwise we'll give it a copy of |primary_config_|
591 // to use.
592 primary_config = primary_config_;
594 requested_config = GetConfigWithScid(requested_scid);
597 if (validate_chlo_result.error_code != QUIC_NO_ERROR) {
598 *error_details = validate_chlo_result.error_details;
599 return validate_chlo_result.error_code;
602 out->Clear();
604 if (!info.valid_source_address_token ||
605 !info.client_nonce_well_formed ||
606 !info.unique ||
607 !requested_config.get()) {
608 BuildRejection(server_ip, *primary_config.get(), client_hello, info,
609 validate_chlo_result.cached_network_params,
610 use_stateless_rejects, server_designated_connection_id, rand,
611 params, out);
612 return QUIC_NO_ERROR;
615 const QuicTag* their_aeads;
616 const QuicTag* their_key_exchanges;
617 size_t num_their_aeads, num_their_key_exchanges;
618 if (client_hello.GetTaglist(kAEAD, &their_aeads,
619 &num_their_aeads) != QUIC_NO_ERROR ||
620 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
621 &num_their_key_exchanges) != QUIC_NO_ERROR ||
622 num_their_aeads != 1 ||
623 num_their_key_exchanges != 1) {
624 *error_details = "Missing or invalid AEAD or KEXS";
625 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
628 size_t key_exchange_index;
629 if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads,
630 num_their_aeads, QuicUtils::LOCAL_PRIORITY,
631 &params->aead, nullptr) ||
632 !QuicUtils::FindMutualTag(
633 requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
634 QuicUtils::LOCAL_PRIORITY, &params->key_exchange,
635 &key_exchange_index)) {
636 *error_details = "Unsupported AEAD or KEXS";
637 return QUIC_CRYPTO_NO_SUPPORT;
640 StringPiece public_value;
641 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
642 *error_details = "Missing public value";
643 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
646 const KeyExchange* key_exchange =
647 requested_config->key_exchanges[key_exchange_index];
648 if (!key_exchange->CalculateSharedKey(public_value,
649 &params->initial_premaster_secret)) {
650 *error_details = "Invalid public value";
651 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
654 if (!info.sni.empty()) {
655 scoped_ptr<char[]> sni_tmp(new char[info.sni.length() + 1]);
656 memcpy(sni_tmp.get(), info.sni.data(), info.sni.length());
657 sni_tmp[info.sni.length()] = 0;
658 params->sni = CryptoUtils::NormalizeHostname(sni_tmp.get());
661 string hkdf_suffix;
662 const QuicData& client_hello_serialized = client_hello.GetSerialized();
663 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() +
664 requested_config->serialized.size());
665 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id),
666 sizeof(connection_id));
667 hkdf_suffix.append(client_hello_serialized.data(),
668 client_hello_serialized.length());
669 hkdf_suffix.append(requested_config->serialized);
671 StringPiece cetv_ciphertext;
672 if (requested_config->channel_id_enabled &&
673 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
674 CryptoHandshakeMessage client_hello_copy(client_hello);
675 client_hello_copy.Erase(kCETV);
676 client_hello_copy.Erase(kPAD);
678 const QuicData& client_hello_copy_serialized =
679 client_hello_copy.GetSerialized();
680 string hkdf_input;
681 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
682 strlen(QuicCryptoConfig::kCETVLabel) + 1);
683 hkdf_input.append(reinterpret_cast<char*>(&connection_id),
684 sizeof(connection_id));
685 hkdf_input.append(client_hello_copy_serialized.data(),
686 client_hello_copy_serialized.length());
687 hkdf_input.append(requested_config->serialized);
689 CrypterPair crypters;
690 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
691 info.client_nonce, info.server_nonce,
692 hkdf_input, Perspective::IS_SERVER, &crypters,
693 nullptr /* subkey secret */)) {
694 *error_details = "Symmetric key setup failed";
695 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
698 char plaintext[kMaxPacketSize];
699 size_t plaintext_length = 0;
700 const bool success = crypters.decrypter->DecryptPacket(
701 0 /* packet number */, StringPiece() /* associated data */,
702 cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
703 if (!success) {
704 *error_details = "CETV decryption failure";
705 return QUIC_PACKET_TOO_LARGE;
707 scoped_ptr<CryptoHandshakeMessage> cetv(
708 CryptoFramer::ParseMessage(StringPiece(plaintext, plaintext_length)));
709 if (!cetv.get()) {
710 *error_details = "CETV parse error";
711 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
714 StringPiece key, signature;
715 if (cetv->GetStringPiece(kCIDK, &key) &&
716 cetv->GetStringPiece(kCIDS, &signature)) {
717 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
718 *error_details = "ChannelID signature failure";
719 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
722 params->channel_id = key.as_string();
726 string hkdf_input;
727 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
728 hkdf_input.reserve(label_len + hkdf_suffix.size());
729 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
730 hkdf_input.append(hkdf_suffix);
732 if (!CryptoUtils::DeriveKeys(
733 params->initial_premaster_secret, params->aead, info.client_nonce,
734 info.server_nonce, hkdf_input, Perspective::IS_SERVER,
735 &params->initial_crypters, nullptr /* subkey secret */)) {
736 *error_details = "Symmetric key setup failed";
737 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
740 string forward_secure_public_value;
741 if (ephemeral_key_source_.get()) {
742 params->forward_secure_premaster_secret =
743 ephemeral_key_source_->CalculateForwardSecureKey(
744 key_exchange, rand, clock->ApproximateNow(), public_value,
745 &forward_secure_public_value);
746 } else {
747 scoped_ptr<KeyExchange> forward_secure_key_exchange(
748 key_exchange->NewKeyPair(rand));
749 forward_secure_public_value =
750 forward_secure_key_exchange->public_value().as_string();
751 if (!forward_secure_key_exchange->CalculateSharedKey(
752 public_value, &params->forward_secure_premaster_secret)) {
753 *error_details = "Invalid public value";
754 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
758 string forward_secure_hkdf_input;
759 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
760 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
761 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
762 label_len);
763 forward_secure_hkdf_input.append(hkdf_suffix);
765 if (!CryptoUtils::DeriveKeys(
766 params->forward_secure_premaster_secret, params->aead,
767 info.client_nonce, info.server_nonce, forward_secure_hkdf_input,
768 Perspective::IS_SERVER, &params->forward_secure_crypters,
769 &params->subkey_secret)) {
770 *error_details = "Symmetric key setup failed";
771 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
774 out->set_tag(kSHLO);
775 QuicTagVector supported_version_tags;
776 for (size_t i = 0; i < supported_versions.size(); ++i) {
777 supported_version_tags.push_back
778 (QuicVersionToQuicTag(supported_versions[i]));
780 out->SetVector(kVER, supported_version_tags);
781 out->SetStringPiece(
782 kSourceAddressTokenTag,
783 NewSourceAddressToken(*requested_config.get(), info.source_address_tokens,
784 client_address.address(), rand, info.now, nullptr));
785 QuicSocketAddressCoder address_coder(client_address);
786 out->SetStringPiece(kCADR, address_coder.Encode());
787 out->SetStringPiece(kPUBS, forward_secure_public_value);
789 return QUIC_NO_ERROR;
792 scoped_refptr<QuicCryptoServerConfig::Config>
793 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const {
794 // In Chromium, we will dead lock if the lock is held by the current thread.
795 // Chromium doesn't have AssertReaderHeld API call.
796 // configs_lock_.AssertReaderHeld();
798 if (!requested_scid.empty()) {
799 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
800 if (it != configs_.end()) {
801 // We'll use the config that the client requested in order to do
802 // key-agreement.
803 return scoped_refptr<Config>(it->second);
807 return scoped_refptr<Config>();
810 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
811 // Config's based on their primary_time.
812 // static
813 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
814 const scoped_refptr<Config>& a,
815 const scoped_refptr<Config>& b) {
816 if (a->primary_time.IsBefore(b->primary_time) ||
817 b->primary_time.IsBefore(a->primary_time)) {
818 // Primary times differ.
819 return a->primary_time.IsBefore(b->primary_time);
820 } else if (a->priority != b->priority) {
821 // Primary times are equal, sort backwards by priority.
822 return a->priority < b->priority;
823 } else {
824 // Primary times and priorities are equal, sort by config id.
825 return a->id < b->id;
829 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
830 const QuicWallTime now) const {
831 vector<scoped_refptr<Config> > configs;
832 configs.reserve(configs_.size());
834 for (ConfigMap::const_iterator it = configs_.begin();
835 it != configs_.end(); ++it) {
836 // TODO(avd) Exclude expired configs?
837 configs.push_back(it->second);
840 if (configs.empty()) {
841 if (primary_config_.get()) {
842 LOG(DFATAL) << "No valid QUIC server config. Keeping the current config.";
843 } else {
844 LOG(DFATAL) << "No valid QUIC server config.";
846 return;
849 std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
851 Config* best_candidate = configs[0].get();
853 for (size_t i = 0; i < configs.size(); ++i) {
854 const scoped_refptr<Config> config(configs[i]);
855 if (!config->primary_time.IsAfter(now)) {
856 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
857 best_candidate = config.get();
859 continue;
862 // This is the first config with a primary_time in the future. Thus the
863 // previous Config should be the primary and this one should determine the
864 // next_config_promotion_time_.
865 scoped_refptr<Config> new_primary(best_candidate);
866 if (i == 0) {
867 // We need the primary_time of the next config.
868 if (configs.size() > 1) {
869 next_config_promotion_time_ = configs[1]->primary_time;
870 } else {
871 next_config_promotion_time_ = QuicWallTime::Zero();
873 } else {
874 next_config_promotion_time_ = config->primary_time;
877 if (primary_config_.get()) {
878 primary_config_->is_primary = false;
880 primary_config_ = new_primary;
881 new_primary->is_primary = true;
882 DVLOG(1) << "New primary config. orbit: "
883 << base::HexEncode(
884 reinterpret_cast<const char*>(primary_config_->orbit),
885 kOrbitSize);
886 if (primary_config_changed_cb_.get() != nullptr) {
887 primary_config_changed_cb_->Run(primary_config_->id);
890 return;
893 // All config's primary times are in the past. We should make the most recent
894 // and highest priority candidate primary.
895 scoped_refptr<Config> new_primary(best_candidate);
896 if (primary_config_.get()) {
897 primary_config_->is_primary = false;
899 primary_config_ = new_primary;
900 new_primary->is_primary = true;
901 DVLOG(1) << "New primary config. orbit: "
902 << base::HexEncode(
903 reinterpret_cast<const char*>(primary_config_->orbit),
904 kOrbitSize)
905 << " scid: " << base::HexEncode(primary_config_->id.data(),
906 primary_config_->id.size());
907 next_config_promotion_time_ = QuicWallTime::Zero();
908 if (primary_config_changed_cb_.get() != nullptr) {
909 primary_config_changed_cb_->Run(primary_config_->id);
913 void QuicCryptoServerConfig::EvaluateClientHello(
914 const uint8* primary_orbit,
915 scoped_refptr<Config> requested_config,
916 ValidateClientHelloResultCallback::Result* client_hello_state,
917 ValidateClientHelloResultCallback* done_cb) const {
918 ValidateClientHelloHelper helper(client_hello_state, done_cb);
920 const CryptoHandshakeMessage& client_hello =
921 client_hello_state->client_hello;
922 ClientHelloInfo* info = &(client_hello_state->info);
924 if (client_hello.size() < kClientHelloMinimumSize) {
925 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
926 "Client hello too small");
927 return;
930 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
931 !CryptoUtils::IsValidSNI(info->sni)) {
932 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
933 "Invalid SNI name");
934 return;
937 client_hello.GetStringPiece(kUAID, &info->user_agent_id);
939 if (!requested_config.get()) {
940 StringPiece requested_scid;
941 if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
942 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
943 } else {
944 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
946 // No server config with the requested ID.
947 helper.ValidationComplete(QUIC_NO_ERROR, "");
948 return;
951 HandshakeFailureReason source_address_token_error;
952 StringPiece srct;
953 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
954 source_address_token_error = ParseSourceAddressToken(
955 *requested_config, srct, &info->source_address_tokens);
957 if (source_address_token_error == HANDSHAKE_OK) {
958 source_address_token_error = ValidateSourceAddressTokens(
959 info->source_address_tokens, info->client_ip, info->now,
960 &client_hello_state->cached_network_params);
962 info->valid_source_address_token =
963 (source_address_token_error == HANDSHAKE_OK);
964 } else {
965 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
968 bool found_error = false;
969 if (source_address_token_error != HANDSHAKE_OK) {
970 info->reject_reasons.push_back(source_address_token_error);
971 // No valid source address token.
972 if (FLAGS_use_early_return_when_verifying_chlo) {
973 helper.ValidationComplete(QUIC_NO_ERROR, "");
974 return;
976 found_error = true;
979 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) &&
980 info->client_nonce.size() == kNonceSize) {
981 info->client_nonce_well_formed = true;
982 } else {
983 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
984 // Invalid client nonce.
985 DVLOG(1) << "Invalid client nonce.";
986 if (FLAGS_use_early_return_when_verifying_chlo) {
987 helper.ValidationComplete(QUIC_NO_ERROR, "");
988 return;
990 found_error = true;
993 if (!replay_protection_) {
994 if (!found_error) {
995 info->unique = true;
997 DVLOG(1) << "No replay protection.";
998 helper.ValidationComplete(QUIC_NO_ERROR, "");
999 return;
1002 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
1003 if (!info->server_nonce.empty()) {
1004 // If the server nonce is present, use it to establish uniqueness.
1005 HandshakeFailureReason server_nonce_error =
1006 ValidateServerNonce(info->server_nonce, info->now);
1007 if (server_nonce_error == HANDSHAKE_OK) {
1008 info->unique = true;
1009 } else {
1010 info->reject_reasons.push_back(server_nonce_error);
1011 info->unique = false;
1013 DVLOG(1) << "Using server nonce, unique: " << info->unique;
1014 helper.ValidationComplete(QUIC_NO_ERROR, "");
1015 return;
1017 // If we hit this block, the server nonce was empty. If we're requiring
1018 // handshake confirmation for DoS reasons and there's no server nonce present,
1019 // reject the CHLO.
1020 if (FLAGS_quic_require_handshake_confirmation) {
1021 info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
1022 helper.ValidationComplete(QUIC_NO_ERROR, "");
1023 return;
1026 // We want to contact strike register only if there are no errors because it
1027 // is a RPC call and is expensive.
1028 if (found_error) {
1029 helper.ValidationComplete(QUIC_NO_ERROR, "");
1030 return;
1033 // Use the client nonce to establish uniqueness.
1034 StrikeRegisterClient* strike_register_client;
1036 base::AutoLock locked(strike_register_client_lock_);
1038 if (strike_register_client_.get() == nullptr) {
1039 strike_register_client_.reset(new LocalStrikeRegisterClient(
1040 strike_register_max_entries_,
1041 static_cast<uint32>(info->now.ToUNIXSeconds()),
1042 strike_register_window_secs_,
1043 primary_orbit,
1044 strike_register_no_startup_period_ ?
1045 StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
1046 StrikeRegister::DENY_REQUESTS_AT_STARTUP));
1048 strike_register_client = strike_register_client_.get();
1051 strike_register_client->VerifyNonceIsValidAndUnique(
1052 info->client_nonce,
1053 info->now,
1054 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
1055 helper.StartedAsyncCallback();
1058 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1059 const SourceAddressTokens& previous_source_address_tokens,
1060 const IPAddressNumber& server_ip,
1061 const IPAddressNumber& client_ip,
1062 const QuicClock* clock,
1063 QuicRandom* rand,
1064 const QuicCryptoNegotiatedParameters& params,
1065 const CachedNetworkParameters* cached_network_params,
1066 CryptoHandshakeMessage* out) const {
1067 base::AutoLock locked(configs_lock_);
1068 out->set_tag(kSCUP);
1069 out->SetStringPiece(kSCFG, primary_config_->serialized);
1070 out->SetStringPiece(
1071 kSourceAddressTokenTag,
1072 NewSourceAddressToken(*primary_config_.get(),
1073 previous_source_address_tokens, client_ip, rand,
1074 clock->WallNow(), cached_network_params));
1076 if (proof_source_ == nullptr) {
1077 // Insecure QUIC, can send SCFG without proof.
1078 return true;
1081 const vector<string>* certs;
1082 string signature;
1083 if (!proof_source_->GetProof(
1084 server_ip, params.sni, primary_config_->serialized,
1085 params.x509_ecdsa_supported, &certs, &signature)) {
1086 DVLOG(1) << "Server: failed to get proof.";
1087 return false;
1090 const string compressed = CertCompressor::CompressChain(
1091 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes,
1092 primary_config_->common_cert_sets);
1094 out->SetStringPiece(kCertificateTag, compressed);
1095 out->SetStringPiece(kPROF, signature);
1096 return true;
1099 void QuicCryptoServerConfig::BuildRejection(
1100 const IPAddressNumber& server_ip,
1101 const Config& config,
1102 const CryptoHandshakeMessage& client_hello,
1103 const ClientHelloInfo& info,
1104 const CachedNetworkParameters& cached_network_params,
1105 bool use_stateless_rejects,
1106 QuicConnectionId server_designated_connection_id,
1107 QuicRandom* rand,
1108 QuicCryptoNegotiatedParameters* params,
1109 CryptoHandshakeMessage* out) const {
1110 if (FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects) {
1111 DVLOG(1) << "QUIC Crypto server config returning stateless reject "
1112 << "with server-designated connection ID "
1113 << server_designated_connection_id;
1114 out->set_tag(kSREJ);
1115 out->SetValue(kRCID, server_designated_connection_id);
1116 } else {
1117 out->set_tag(kREJ);
1119 out->SetStringPiece(kSCFG, config.serialized);
1120 out->SetStringPiece(
1121 kSourceAddressTokenTag,
1122 NewSourceAddressToken(config, info.source_address_tokens, info.client_ip,
1123 rand, info.now, &cached_network_params));
1124 if (replay_protection_) {
1125 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
1128 // Send client the reject reason for debugging purposes.
1129 DCHECK_LT(0u, info.reject_reasons.size());
1130 out->SetVector(kRREJ, info.reject_reasons);
1132 // The client may have requested a certificate chain.
1133 const QuicTag* their_proof_demands;
1134 size_t num_their_proof_demands;
1136 if (proof_source_.get() == nullptr ||
1137 client_hello.GetTaglist(kPDMD, &their_proof_demands,
1138 &num_their_proof_demands) !=
1139 QUIC_NO_ERROR) {
1140 return;
1143 bool x509_supported = false;
1144 for (size_t i = 0; i < num_their_proof_demands; i++) {
1145 switch (their_proof_demands[i]) {
1146 case kX509:
1147 x509_supported = true;
1148 params->x509_ecdsa_supported = true;
1149 break;
1150 case kX59R:
1151 x509_supported = true;
1152 break;
1156 if (!x509_supported) {
1157 return;
1160 const vector<string>* certs;
1161 string signature;
1162 if (!proof_source_->GetProof(server_ip, info.sni.as_string(),
1163 config.serialized, params->x509_ecdsa_supported,
1164 &certs, &signature)) {
1165 return;
1168 StringPiece client_common_set_hashes;
1169 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
1170 params->client_common_set_hashes = client_common_set_hashes.as_string();
1173 StringPiece client_cached_cert_hashes;
1174 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
1175 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string();
1178 const string compressed = CertCompressor::CompressChain(
1179 *certs, params->client_common_set_hashes,
1180 params->client_cached_cert_hashes, config.common_cert_sets);
1182 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1183 // message is taken up by things other than the certificates.
1184 // STK: 56 bytes
1185 // SNO: 56 bytes
1186 // SCFG
1187 // SCID: 16 bytes
1188 // PUBS: 38 bytes
1189 const size_t kREJOverheadBytes = 166;
1190 // kMultiplier is the multiple of the CHLO message size that a REJ message
1191 // must stay under when the client doesn't present a valid source-address
1192 // token.
1193 const size_t kMultiplier = 2;
1194 // max_unverified_size is the number of bytes that the certificate chain
1195 // and signature can consume before we will demand a valid source-address
1196 // token.
1197 const size_t max_unverified_size =
1198 client_hello.size() * kMultiplier - kREJOverheadBytes;
1199 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1200 "overhead calculation may overflow");
1201 if (info.valid_source_address_token ||
1202 signature.size() + compressed.size() < max_unverified_size) {
1203 out->SetStringPiece(kCertificateTag, compressed);
1204 out->SetStringPiece(kPROF, signature);
1208 scoped_refptr<QuicCryptoServerConfig::Config>
1209 QuicCryptoServerConfig::ParseConfigProtobuf(
1210 QuicServerConfigProtobuf* protobuf) {
1211 scoped_ptr<CryptoHandshakeMessage> msg(
1212 CryptoFramer::ParseMessage(protobuf->config()));
1214 if (msg->tag() != kSCFG) {
1215 LOG(WARNING) << "Server config message has tag " << msg->tag()
1216 << " expected " << kSCFG;
1217 return nullptr;
1220 scoped_refptr<Config> config(new Config);
1221 config->serialized = protobuf->config();
1223 if (!protobuf->has_source_address_token_secret_override()) {
1224 // Use the default boxer.
1225 config->source_address_token_boxer = &default_source_address_token_boxer_;
1226 } else {
1227 // Create override boxer instance.
1228 CryptoSecretBoxer* boxer = new CryptoSecretBoxer;
1229 boxer->SetKey(DeriveSourceAddressTokenKey(
1230 protobuf->source_address_token_secret_override()));
1231 config->source_address_token_boxer_storage.reset(boxer);
1232 config->source_address_token_boxer = boxer;
1235 if (protobuf->has_primary_time()) {
1236 config->primary_time =
1237 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1240 config->priority = protobuf->priority();
1242 StringPiece scid;
1243 if (!msg->GetStringPiece(kSCID, &scid)) {
1244 LOG(WARNING) << "Server config message is missing SCID";
1245 return nullptr;
1247 config->id = scid.as_string();
1249 const QuicTag* aead_tags;
1250 size_t aead_len;
1251 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
1252 LOG(WARNING) << "Server config message is missing AEAD";
1253 return nullptr;
1255 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
1257 const QuicTag* kexs_tags;
1258 size_t kexs_len;
1259 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
1260 LOG(WARNING) << "Server config message is missing KEXS";
1261 return nullptr;
1264 StringPiece orbit;
1265 if (!msg->GetStringPiece(kORBT, &orbit)) {
1266 LOG(WARNING) << "Server config message is missing ORBT";
1267 return nullptr;
1270 if (orbit.size() != kOrbitSize) {
1271 LOG(WARNING) << "Orbit value in server config is the wrong length."
1272 " Got " << orbit.size() << " want " << kOrbitSize;
1273 return nullptr;
1275 static_assert(sizeof(config->orbit) == kOrbitSize,
1276 "orbit has incorrect size");
1277 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1280 StrikeRegisterClient* strike_register_client;
1282 base::AutoLock locked(strike_register_client_lock_);
1283 strike_register_client = strike_register_client_.get();
1286 if (strike_register_client != nullptr &&
1287 !strike_register_client->IsKnownOrbit(orbit)) {
1288 LOG(WARNING)
1289 << "Rejecting server config with orbit that the strike register "
1290 "client doesn't know about.";
1291 return nullptr;
1295 if (kexs_len != protobuf->key_size()) {
1296 LOG(WARNING) << "Server config has " << kexs_len
1297 << " key exchange methods configured, but "
1298 << protobuf->key_size() << " private keys";
1299 return nullptr;
1302 const QuicTag* proof_demand_tags;
1303 size_t num_proof_demand_tags;
1304 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
1305 QUIC_NO_ERROR) {
1306 for (size_t i = 0; i < num_proof_demand_tags; i++) {
1307 if (proof_demand_tags[i] == kCHID) {
1308 config->channel_id_enabled = true;
1309 break;
1314 for (size_t i = 0; i < kexs_len; i++) {
1315 const QuicTag tag = kexs_tags[i];
1316 string private_key;
1318 config->kexs.push_back(tag);
1320 for (size_t j = 0; j < protobuf->key_size(); j++) {
1321 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1322 if (key.tag() == tag) {
1323 private_key = key.private_key();
1324 break;
1328 if (private_key.empty()) {
1329 LOG(WARNING) << "Server config contains key exchange method without "
1330 "corresponding private key: " << tag;
1331 return nullptr;
1334 scoped_ptr<KeyExchange> ka;
1335 switch (tag) {
1336 case kC255:
1337 ka.reset(Curve25519KeyExchange::New(private_key));
1338 if (!ka.get()) {
1339 LOG(WARNING) << "Server config contained an invalid curve25519"
1340 " private key.";
1341 return nullptr;
1343 break;
1344 case kP256:
1345 ka.reset(P256KeyExchange::New(private_key));
1346 if (!ka.get()) {
1347 LOG(WARNING) << "Server config contained an invalid P-256"
1348 " private key.";
1349 return nullptr;
1351 break;
1352 default:
1353 LOG(WARNING) << "Server config message contains unknown key exchange "
1354 "method: " << tag;
1355 return nullptr;
1358 for (const KeyExchange* key_exchange : config->key_exchanges) {
1359 if (key_exchange->tag() == tag) {
1360 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1361 return nullptr;
1365 config->key_exchanges.push_back(ka.release());
1368 return config;
1371 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
1372 proof_source_.reset(proof_source);
1375 void QuicCryptoServerConfig::SetEphemeralKeySource(
1376 EphemeralKeySource* ephemeral_key_source) {
1377 ephemeral_key_source_.reset(ephemeral_key_source);
1380 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1381 StrikeRegisterClient* strike_register_client) {
1382 base::AutoLock locker(strike_register_client_lock_);
1383 DCHECK(!strike_register_client_.get());
1384 strike_register_client_.reset(strike_register_client);
1387 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1388 replay_protection_ = on;
1391 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1392 base::AutoLock locker(strike_register_client_lock_);
1393 DCHECK(!strike_register_client_.get());
1394 strike_register_no_startup_period_ = true;
1397 void QuicCryptoServerConfig::set_strike_register_max_entries(
1398 uint32 max_entries) {
1399 base::AutoLock locker(strike_register_client_lock_);
1400 DCHECK(!strike_register_client_.get());
1401 strike_register_max_entries_ = max_entries;
1404 void QuicCryptoServerConfig::set_strike_register_window_secs(
1405 uint32 window_secs) {
1406 base::AutoLock locker(strike_register_client_lock_);
1407 DCHECK(!strike_register_client_.get());
1408 strike_register_window_secs_ = window_secs;
1411 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1412 uint32 future_secs) {
1413 source_address_token_future_secs_ = future_secs;
1416 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1417 uint32 lifetime_secs) {
1418 source_address_token_lifetime_secs_ = lifetime_secs;
1421 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1422 uint32 max_entries) {
1423 DCHECK(!server_nonce_strike_register_.get());
1424 server_nonce_strike_register_max_entries_ = max_entries;
1427 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1428 uint32 window_secs) {
1429 DCHECK(!server_nonce_strike_register_.get());
1430 server_nonce_strike_register_window_secs_ = window_secs;
1433 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1434 PrimaryConfigChangedCallback* cb) {
1435 base::AutoLock locked(configs_lock_);
1436 primary_config_changed_cb_.reset(cb);
1439 string QuicCryptoServerConfig::NewSourceAddressToken(
1440 const Config& config,
1441 const SourceAddressTokens& previous_tokens,
1442 const IPAddressNumber& ip,
1443 QuicRandom* rand,
1444 QuicWallTime now,
1445 const CachedNetworkParameters* cached_network_params) const {
1446 SourceAddressTokens source_address_tokens;
1447 SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
1448 source_address_token->set_ip(IPAddressToPackedString(DualstackIPAddress(ip)));
1449 source_address_token->set_timestamp(now.ToUNIXSeconds());
1450 if (cached_network_params != nullptr) {
1451 *(source_address_token->mutable_cached_network_parameters()) =
1452 *cached_network_params;
1455 // Append previous tokens.
1456 for (const SourceAddressToken& token : previous_tokens.tokens()) {
1457 if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
1458 break;
1461 if (token.ip() == source_address_token->ip()) {
1462 // It's for the same IP address.
1463 continue;
1466 if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
1467 continue;
1470 *(source_address_tokens.add_tokens()) = token;
1473 return config.source_address_token_boxer->Box(
1474 rand, source_address_tokens.SerializeAsString());
1477 bool QuicCryptoServerConfig::HasProofSource() const {
1478 return proof_source_ != nullptr;
1481 int QuicCryptoServerConfig::NumberOfConfigs() const {
1482 base::AutoLock locked(configs_lock_);
1483 return configs_.size();
1486 HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
1487 const Config& config,
1488 StringPiece token,
1489 SourceAddressTokens* tokens) const {
1490 string storage;
1491 StringPiece plaintext;
1492 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1493 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1496 if (!tokens->ParseFromArray(plaintext.data(), plaintext.size())) {
1497 // Some clients might still be using the old source token format so
1498 // attempt to parse that format.
1499 // TODO(rch): remove this code once the new format is ubiquitous.
1500 SourceAddressToken source_address_token;
1501 if (!source_address_token.ParseFromArray(plaintext.data(),
1502 plaintext.size())) {
1503 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1505 *tokens->add_tokens() = source_address_token;
1508 return HANDSHAKE_OK;
1511 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
1512 const SourceAddressTokens& source_address_tokens,
1513 const IPAddressNumber& ip,
1514 QuicWallTime now,
1515 CachedNetworkParameters* cached_network_params) const {
1516 HandshakeFailureReason reason =
1517 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1518 for (const SourceAddressToken& token : source_address_tokens.tokens()) {
1519 reason = ValidateSingleSourceAddressToken(token, ip, now);
1520 if (reason == HANDSHAKE_OK) {
1521 if (token.has_cached_network_parameters()) {
1522 *cached_network_params = token.cached_network_parameters();
1524 break;
1527 return reason;
1530 HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1531 const SourceAddressToken& source_address_token,
1532 const IPAddressNumber& ip,
1533 QuicWallTime now) const {
1534 if (source_address_token.ip() !=
1535 IPAddressToPackedString(DualstackIPAddress(ip))) {
1536 // It's for a different IP address.
1537 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1540 return ValidateSourceAddressTokenTimestamp(source_address_token, now);
1543 HandshakeFailureReason
1544 QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1545 const SourceAddressToken& source_address_token,
1546 QuicWallTime now) const {
1547 const QuicWallTime timestamp(
1548 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1549 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1551 if (now.IsBefore(timestamp) &&
1552 delta.ToSeconds() > source_address_token_future_secs_) {
1553 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1556 if (now.IsAfter(timestamp) &&
1557 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1558 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1561 return HANDSHAKE_OK;
1564 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1565 // nonce.
1566 static const size_t kServerNoncePlaintextSize =
1567 4 /* timestamp */ + 20 /* random bytes */;
1569 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1570 QuicWallTime now) const {
1571 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds());
1573 uint8 server_nonce[kServerNoncePlaintextSize];
1574 static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
1575 server_nonce[0] = static_cast<uint8>(timestamp >> 24);
1576 server_nonce[1] = static_cast<uint8>(timestamp >> 16);
1577 server_nonce[2] = static_cast<uint8>(timestamp >> 8);
1578 server_nonce[3] = static_cast<uint8>(timestamp);
1579 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1580 sizeof(server_nonce) - sizeof(timestamp));
1582 return server_nonce_boxer_.Box(
1583 rand,
1584 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
1587 HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
1588 StringPiece token,
1589 QuicWallTime now) const {
1590 string storage;
1591 StringPiece plaintext;
1592 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
1593 return SERVER_NONCE_DECRYPTION_FAILURE;
1596 // plaintext contains:
1597 // uint32 timestamp
1598 // uint8[20] random bytes
1600 if (plaintext.size() != kServerNoncePlaintextSize) {
1601 // This should never happen because the value decrypted correctly.
1602 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
1603 return SERVER_NONCE_INVALID_FAILURE;
1606 uint8 server_nonce[32];
1607 memcpy(server_nonce, plaintext.data(), 4);
1608 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
1609 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
1610 20);
1611 static_assert(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
1612 "bad nonce buffer length");
1614 InsertStatus nonce_error;
1616 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
1617 if (server_nonce_strike_register_.get() == nullptr) {
1618 server_nonce_strike_register_.reset(new StrikeRegister(
1619 server_nonce_strike_register_max_entries_,
1620 static_cast<uint32>(now.ToUNIXSeconds()),
1621 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
1622 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
1624 nonce_error = server_nonce_strike_register_->Insert(
1625 server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
1628 switch (nonce_error) {
1629 case NONCE_OK:
1630 return HANDSHAKE_OK;
1631 case NONCE_INVALID_FAILURE:
1632 case NONCE_INVALID_ORBIT_FAILURE:
1633 return SERVER_NONCE_INVALID_FAILURE;
1634 case NONCE_NOT_UNIQUE_FAILURE:
1635 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1636 case NONCE_INVALID_TIME_FAILURE:
1637 return SERVER_NONCE_INVALID_TIME_FAILURE;
1638 case NONCE_UNKNOWN_FAILURE:
1639 case STRIKE_REGISTER_TIMEOUT:
1640 case STRIKE_REGISTER_FAILURE:
1641 default:
1642 LOG(DFATAL) << "Unexpected server nonce error: " << nonce_error;
1643 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1647 QuicCryptoServerConfig::Config::Config()
1648 : channel_id_enabled(false),
1649 is_primary(false),
1650 primary_time(QuicWallTime::Zero()),
1651 priority(0),
1652 source_address_token_boxer(nullptr) {}
1654 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
1656 } // namespace net