Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / net / quic / crypto / quic_crypto_server_config.cc
blob5a650b6073035455723effdc2cc353d17b806e5b
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 string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) {
54 crypto::HKDF hkdf(source_address_token_secret,
55 StringPiece() /* no salt */,
56 "QUIC source address token key",
57 CryptoSecretBoxer::GetKeySize(),
58 0 /* no fixed IV needed */,
59 0 /* no subkey secret */);
60 return hkdf.server_write_key().as_string();
63 } // namespace
65 class ValidateClientHelloHelper {
66 public:
67 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result,
68 ValidateClientHelloResultCallback* done_cb)
69 : result_(result), done_cb_(done_cb) {
72 ~ValidateClientHelloHelper() {
73 LOG_IF(DFATAL, done_cb_ != nullptr)
74 << "Deleting ValidateClientHelloHelper with a pending callback.";
77 void ValidationComplete(QuicErrorCode error_code, const char* error_details) {
78 result_->error_code = error_code;
79 result_->error_details = error_details;
80 done_cb_->Run(result_);
81 DetachCallback();
84 void StartedAsyncCallback() {
85 DetachCallback();
88 private:
89 void DetachCallback() {
90 LOG_IF(DFATAL, done_cb_ == nullptr) << "Callback already detached.";
91 done_cb_ = nullptr;
94 ValidateClientHelloResultCallback::Result* result_;
95 ValidateClientHelloResultCallback* done_cb_;
97 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
100 class VerifyNonceIsValidAndUniqueCallback
101 : public StrikeRegisterClient::ResultCallback {
102 public:
103 VerifyNonceIsValidAndUniqueCallback(
104 ValidateClientHelloResultCallback::Result* result,
105 ValidateClientHelloResultCallback* done_cb)
106 : result_(result), done_cb_(done_cb) {
109 protected:
110 void RunImpl(bool nonce_is_valid_and_unique,
111 InsertStatus nonce_error) override {
112 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique
113 << " nonce_error: " << nonce_error;
114 result_->info.unique = nonce_is_valid_and_unique;
115 if (!nonce_is_valid_and_unique) {
116 HandshakeFailureReason client_nonce_error;
117 switch (nonce_error) {
118 case NONCE_INVALID_FAILURE:
119 client_nonce_error = CLIENT_NONCE_INVALID_FAILURE;
120 break;
121 case NONCE_NOT_UNIQUE_FAILURE:
122 client_nonce_error = CLIENT_NONCE_NOT_UNIQUE_FAILURE;
123 break;
124 case NONCE_INVALID_ORBIT_FAILURE:
125 client_nonce_error = CLIENT_NONCE_INVALID_ORBIT_FAILURE;
126 break;
127 case NONCE_INVALID_TIME_FAILURE:
128 client_nonce_error = CLIENT_NONCE_INVALID_TIME_FAILURE;
129 break;
130 case STRIKE_REGISTER_TIMEOUT:
131 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT;
132 break;
133 case STRIKE_REGISTER_FAILURE:
134 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_FAILURE;
135 break;
136 case NONCE_UNKNOWN_FAILURE:
137 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
138 break;
139 case NONCE_OK:
140 default:
141 LOG(DFATAL) << "Unexpected client nonce error: " << nonce_error;
142 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
143 break;
145 result_->info.reject_reasons.push_back(client_nonce_error);
147 done_cb_->Run(result_);
150 private:
151 ValidateClientHelloResultCallback::Result* result_;
152 ValidateClientHelloResultCallback* done_cb_;
154 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
157 // static
158 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
160 ClientHelloInfo::ClientHelloInfo(const IPEndPoint& in_client_ip,
161 QuicWallTime in_now)
162 : client_ip(in_client_ip),
163 now(in_now),
164 valid_source_address_token(false),
165 client_nonce_well_formed(false),
166 unique(false) {
169 ClientHelloInfo::~ClientHelloInfo() {
172 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {
175 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {
178 ValidateClientHelloResultCallback::Result::Result(
179 const CryptoHandshakeMessage& in_client_hello,
180 IPEndPoint in_client_ip,
181 QuicWallTime in_now)
182 : client_hello(in_client_hello),
183 info(in_client_ip, in_now),
184 error_code(QUIC_NO_ERROR) {
187 ValidateClientHelloResultCallback::Result::~Result() {
190 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {
193 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {
196 void ValidateClientHelloResultCallback::Run(const Result* result) {
197 RunImpl(result->client_hello, *result);
198 delete result;
199 delete this;
202 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
203 : expiry_time(QuicWallTime::Zero()),
204 channel_id_enabled(false),
205 p256(false) {}
207 QuicCryptoServerConfig::QuicCryptoServerConfig(
208 StringPiece source_address_token_secret,
209 QuicRandom* rand)
210 : replay_protection_(true),
211 configs_lock_(),
212 primary_config_(nullptr),
213 next_config_promotion_time_(QuicWallTime::Zero()),
214 server_nonce_strike_register_lock_(),
215 strike_register_no_startup_period_(false),
216 strike_register_max_entries_(1 << 10),
217 strike_register_window_secs_(600),
218 source_address_token_future_secs_(3600),
219 source_address_token_lifetime_secs_(86400),
220 server_nonce_strike_register_max_entries_(1 << 10),
221 server_nonce_strike_register_window_secs_(120) {
222 default_source_address_token_boxer_.SetKey(
223 DeriveSourceAddressTokenKey(source_address_token_secret));
225 // Generate a random key and orbit for server nonces.
226 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_));
227 const size_t key_size = server_nonce_boxer_.GetKeySize();
228 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]);
229 rand->RandBytes(key_bytes.get(), key_size);
231 server_nonce_boxer_.SetKey(
232 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size));
235 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
236 primary_config_ = nullptr;
239 // static
240 QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig(
241 QuicRandom* rand,
242 const QuicClock* clock,
243 const ConfigOptions& options) {
244 CryptoHandshakeMessage msg;
246 const string curve25519_private_key =
247 Curve25519KeyExchange::NewPrivateKey(rand);
248 scoped_ptr<Curve25519KeyExchange> curve25519(
249 Curve25519KeyExchange::New(curve25519_private_key));
250 StringPiece curve25519_public_value = curve25519->public_value();
252 string encoded_public_values;
253 // First three bytes encode the length of the public value.
254 encoded_public_values.push_back(curve25519_public_value.size());
255 encoded_public_values.push_back(curve25519_public_value.size() >> 8);
256 encoded_public_values.push_back(curve25519_public_value.size() >> 16);
257 encoded_public_values.append(curve25519_public_value.data(),
258 curve25519_public_value.size());
260 string p256_private_key;
261 if (options.p256) {
262 p256_private_key = P256KeyExchange::NewPrivateKey();
263 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
264 StringPiece p256_public_value = p256->public_value();
266 encoded_public_values.push_back(p256_public_value.size());
267 encoded_public_values.push_back(p256_public_value.size() >> 8);
268 encoded_public_values.push_back(p256_public_value.size() >> 16);
269 encoded_public_values.append(p256_public_value.data(),
270 p256_public_value.size());
273 msg.set_tag(kSCFG);
274 if (options.p256) {
275 msg.SetTaglist(kKEXS, kC255, kP256, 0);
276 } else {
277 msg.SetTaglist(kKEXS, kC255, 0);
279 if (ChaCha20Poly1305Encrypter::IsSupported()) {
280 msg.SetTaglist(kAEAD, kAESG, kCC12, 0);
281 } else {
282 msg.SetTaglist(kAEAD, kAESG, 0);
284 msg.SetStringPiece(kPUBS, encoded_public_values);
286 if (options.expiry_time.IsZero()) {
287 const QuicWallTime now = clock->WallNow();
288 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
289 60 * 60 * 24 * 180 /* 180 days, ~six months */));
290 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
291 msg.SetValue(kEXPY, expiry_seconds);
292 } else {
293 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
296 char orbit_bytes[kOrbitSize];
297 if (options.orbit.size() == sizeof(orbit_bytes)) {
298 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
299 } else {
300 DCHECK(options.orbit.empty());
301 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
303 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
305 if (options.channel_id_enabled) {
306 msg.SetTaglist(kPDMD, kCHID, 0);
309 if (options.id.empty()) {
310 // We need to ensure that the SCID changes whenever the server config does
311 // thus we make it a hash of the rest of the server config.
312 scoped_ptr<QuicData> serialized(
313 CryptoFramer::ConstructHandshakeMessage(msg));
314 scoped_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256));
315 hash->Update(serialized->data(), serialized->length());
317 char scid_bytes[16];
318 hash->Finish(scid_bytes, sizeof(scid_bytes));
319 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
320 } else {
321 msg.SetStringPiece(kSCID, options.id);
323 // Don't put new tags below this point. The SCID generation should hash over
324 // everything but itself and so extra tags should be added prior to the
325 // preceeding if block.
327 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
329 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
330 config->set_config(serialized->AsStringPiece());
331 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
332 curve25519_key->set_tag(kC255);
333 curve25519_key->set_private_key(curve25519_private_key);
335 if (options.p256) {
336 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
337 p256_key->set_tag(kP256);
338 p256_key->set_private_key(p256_private_key);
341 return config.release();
344 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
345 QuicServerConfigProtobuf* protobuf,
346 const QuicWallTime now) {
347 scoped_ptr<CryptoHandshakeMessage> msg(
348 CryptoFramer::ParseMessage(protobuf->config()));
350 if (!msg.get()) {
351 LOG(WARNING) << "Failed to parse server config message";
352 return nullptr;
355 scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
356 if (!config.get()) {
357 LOG(WARNING) << "Failed to parse server config message";
358 return nullptr;
362 base::AutoLock locked(configs_lock_);
363 if (configs_.find(config->id) != configs_.end()) {
364 LOG(WARNING) << "Failed to add config because another with the same "
365 "server config id already exists: "
366 << base::HexEncode(config->id.data(), config->id.size());
367 return nullptr;
370 configs_[config->id] = config;
371 SelectNewPrimaryConfig(now);
372 DCHECK(primary_config_.get());
373 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
376 return msg.release();
379 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
380 QuicRandom* rand,
381 const QuicClock* clock,
382 const ConfigOptions& options) {
383 scoped_ptr<QuicServerConfigProtobuf> config(
384 GenerateConfig(rand, clock, options));
385 return AddConfig(config.get(), clock->WallNow());
388 bool QuicCryptoServerConfig::SetConfigs(
389 const vector<QuicServerConfigProtobuf*>& protobufs,
390 const QuicWallTime now) {
391 vector<scoped_refptr<Config> > parsed_configs;
392 bool ok = true;
394 for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin();
395 i != protobufs.end(); ++i) {
396 scoped_refptr<Config> config(ParseConfigProtobuf(*i));
397 if (!config.get()) {
398 ok = false;
399 break;
402 parsed_configs.push_back(config);
405 if (parsed_configs.empty()) {
406 LOG(WARNING) << "New config list is empty.";
407 ok = false;
410 if (!ok) {
411 LOG(WARNING) << "Rejecting QUIC configs because of above errors";
412 } else {
413 VLOG(1) << "Updating configs:";
415 base::AutoLock locked(configs_lock_);
416 ConfigMap new_configs;
418 for (vector<scoped_refptr<Config> >::const_iterator i =
419 parsed_configs.begin();
420 i != parsed_configs.end(); ++i) {
421 scoped_refptr<Config> config = *i;
423 ConfigMap::iterator it = configs_.find(config->id);
424 if (it != configs_.end()) {
425 VLOG(1)
426 << "Keeping scid: " << base::HexEncode(
427 config->id.data(), config->id.size())
428 << " orbit: " << base::HexEncode(
429 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
430 << " new primary_time " << config->primary_time.ToUNIXSeconds()
431 << " old primary_time " << it->second->primary_time.ToUNIXSeconds()
432 << " new priority " << config->priority
433 << " old priority " << it->second->priority;
434 // Update primary_time and priority.
435 it->second->primary_time = config->primary_time;
436 it->second->priority = config->priority;
437 new_configs.insert(*it);
438 } else {
439 VLOG(1) << "Adding scid: " << base::HexEncode(
440 config->id.data(), config->id.size())
441 << " orbit: " << base::HexEncode(
442 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
443 << " primary_time " << config->primary_time.ToUNIXSeconds()
444 << " priority " << config->priority;
445 new_configs.insert(make_pair(config->id, config));
449 configs_.swap(new_configs);
450 SelectNewPrimaryConfig(now);
451 DCHECK(primary_config_.get());
452 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
455 return ok;
458 void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
459 base::AutoLock locked(configs_lock_);
460 for (ConfigMap::const_iterator it = configs_.begin();
461 it != configs_.end(); ++it) {
462 scids->push_back(it->first);
466 void QuicCryptoServerConfig::ValidateClientHello(
467 const CryptoHandshakeMessage& client_hello,
468 IPEndPoint client_ip,
469 const QuicClock* clock,
470 ValidateClientHelloResultCallback* done_cb) const {
471 const QuicWallTime now(clock->WallNow());
473 ValidateClientHelloResultCallback::Result* result =
474 new ValidateClientHelloResultCallback::Result(
475 client_hello, client_ip, now);
477 StringPiece requested_scid;
478 client_hello.GetStringPiece(kSCID, &requested_scid);
480 uint8 primary_orbit[kOrbitSize];
481 scoped_refptr<Config> requested_config;
483 base::AutoLock locked(configs_lock_);
485 if (!primary_config_.get()) {
486 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
487 result->error_details = "No configurations loaded";
488 } else {
489 if (!next_config_promotion_time_.IsZero() &&
490 next_config_promotion_time_.IsAfter(now)) {
491 SelectNewPrimaryConfig(now);
492 DCHECK(primary_config_.get());
493 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
496 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit));
499 requested_config = GetConfigWithScid(requested_scid);
502 if (result->error_code == QUIC_NO_ERROR) {
503 EvaluateClientHello(primary_orbit, requested_config, result, done_cb);
504 } else {
505 done_cb->Run(result);
509 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
510 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
511 QuicConnectionId connection_id,
512 IPEndPoint client_address,
513 QuicVersion version,
514 const QuicVersionVector& supported_versions,
515 const QuicClock* clock,
516 QuicRandom* rand,
517 QuicCryptoNegotiatedParameters *params,
518 CryptoHandshakeMessage* out,
519 string* error_details) const {
520 DCHECK(error_details);
522 const CryptoHandshakeMessage& client_hello =
523 validate_chlo_result.client_hello;
524 const ClientHelloInfo& info = validate_chlo_result.info;
526 // If the client's preferred version is not the version we are currently
527 // speaking, then the client went through a version negotiation. In this
528 // case, we need to make sure that we actually do not support this version
529 // and that it wasn't a downgrade attack.
530 QuicTag client_version_tag;
531 if (client_hello.GetUint32(kVER, &client_version_tag) != QUIC_NO_ERROR) {
532 *error_details = "client hello missing version list";
533 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
535 QuicVersion client_version = QuicTagToQuicVersion(client_version_tag);
536 if (client_version != version) {
537 // Just because client_version is a valid version enum doesn't mean that
538 // this server actually supports that version, so we check to see if
539 // it's actually in the supported versions list.
540 for (size_t i = 0; i < supported_versions.size(); ++i) {
541 if (client_version == supported_versions[i]) {
542 *error_details = "Downgrade attack detected";
543 return QUIC_VERSION_NEGOTIATION_MISMATCH;
548 StringPiece requested_scid;
549 client_hello.GetStringPiece(kSCID, &requested_scid);
550 const QuicWallTime now(clock->WallNow());
552 scoped_refptr<Config> requested_config;
553 scoped_refptr<Config> primary_config;
555 base::AutoLock locked(configs_lock_);
557 if (!primary_config_.get()) {
558 *error_details = "No configurations loaded";
559 return QUIC_CRYPTO_INTERNAL_ERROR;
562 if (!next_config_promotion_time_.IsZero() &&
563 next_config_promotion_time_.IsAfter(now)) {
564 SelectNewPrimaryConfig(now);
565 DCHECK(primary_config_.get());
566 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
569 // We'll use the config that the client requested in order to do
570 // key-agreement. Otherwise we'll give it a copy of |primary_config_|
571 // to use.
572 primary_config = primary_config_;
574 requested_config = GetConfigWithScid(requested_scid);
577 if (validate_chlo_result.error_code != QUIC_NO_ERROR) {
578 *error_details = validate_chlo_result.error_details;
579 return validate_chlo_result.error_code;
582 out->Clear();
584 if (!info.valid_source_address_token ||
585 !info.client_nonce_well_formed ||
586 !info.unique ||
587 !requested_config.get()) {
588 BuildRejection(*primary_config.get(), client_hello, info,
589 validate_chlo_result.cached_network_params, rand, params,
590 out);
591 return QUIC_NO_ERROR;
594 const QuicTag* their_aeads;
595 const QuicTag* their_key_exchanges;
596 size_t num_their_aeads, num_their_key_exchanges;
597 if (client_hello.GetTaglist(kAEAD, &their_aeads,
598 &num_their_aeads) != QUIC_NO_ERROR ||
599 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
600 &num_their_key_exchanges) != QUIC_NO_ERROR ||
601 num_their_aeads != 1 ||
602 num_their_key_exchanges != 1) {
603 *error_details = "Missing or invalid AEAD or KEXS";
604 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
607 size_t key_exchange_index;
608 if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads,
609 num_their_aeads, QuicUtils::LOCAL_PRIORITY,
610 &params->aead, nullptr) ||
611 !QuicUtils::FindMutualTag(
612 requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
613 QuicUtils::LOCAL_PRIORITY, &params->key_exchange,
614 &key_exchange_index)) {
615 *error_details = "Unsupported AEAD or KEXS";
616 return QUIC_CRYPTO_NO_SUPPORT;
619 StringPiece public_value;
620 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
621 *error_details = "Missing public value";
622 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
625 const KeyExchange* key_exchange =
626 requested_config->key_exchanges[key_exchange_index];
627 if (!key_exchange->CalculateSharedKey(public_value,
628 &params->initial_premaster_secret)) {
629 *error_details = "Invalid public value";
630 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
633 if (!info.sni.empty()) {
634 scoped_ptr<char[]> sni_tmp(new char[info.sni.length() + 1]);
635 memcpy(sni_tmp.get(), info.sni.data(), info.sni.length());
636 sni_tmp[info.sni.length()] = 0;
637 params->sni = CryptoUtils::NormalizeHostname(sni_tmp.get());
640 string hkdf_suffix;
641 const QuicData& client_hello_serialized = client_hello.GetSerialized();
642 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() +
643 requested_config->serialized.size());
644 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id),
645 sizeof(connection_id));
646 hkdf_suffix.append(client_hello_serialized.data(),
647 client_hello_serialized.length());
648 hkdf_suffix.append(requested_config->serialized);
650 StringPiece cetv_ciphertext;
651 if (requested_config->channel_id_enabled &&
652 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
653 CryptoHandshakeMessage client_hello_copy(client_hello);
654 client_hello_copy.Erase(kCETV);
655 client_hello_copy.Erase(kPAD);
657 const QuicData& client_hello_serialized = client_hello_copy.GetSerialized();
658 string hkdf_input;
659 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
660 strlen(QuicCryptoConfig::kCETVLabel) + 1);
661 hkdf_input.append(reinterpret_cast<char*>(&connection_id),
662 sizeof(connection_id));
663 hkdf_input.append(client_hello_serialized.data(),
664 client_hello_serialized.length());
665 hkdf_input.append(requested_config->serialized);
667 CrypterPair crypters;
668 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
669 info.client_nonce, info.server_nonce,
670 hkdf_input, CryptoUtils::SERVER, &crypters,
671 nullptr /* subkey secret */)) {
672 *error_details = "Symmetric key setup failed";
673 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
676 scoped_ptr<QuicData> cetv_plaintext(crypters.decrypter->DecryptPacket(
677 0 /* sequence number */, StringPiece() /* associated data */,
678 cetv_ciphertext));
679 if (!cetv_plaintext.get()) {
680 *error_details = "CETV decryption failure";
681 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
684 scoped_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
685 cetv_plaintext->AsStringPiece()));
686 if (!cetv.get()) {
687 *error_details = "CETV parse error";
688 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
691 StringPiece key, signature;
692 if (cetv->GetStringPiece(kCIDK, &key) &&
693 cetv->GetStringPiece(kCIDS, &signature)) {
694 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
695 *error_details = "ChannelID signature failure";
696 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
699 params->channel_id = key.as_string();
703 string hkdf_input;
704 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
705 hkdf_input.reserve(label_len + hkdf_suffix.size());
706 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
707 hkdf_input.append(hkdf_suffix);
709 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
710 info.client_nonce, info.server_nonce, hkdf_input,
711 CryptoUtils::SERVER,
712 &params->initial_crypters,
713 nullptr /* subkey secret */)) {
714 *error_details = "Symmetric key setup failed";
715 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
718 string forward_secure_public_value;
719 if (ephemeral_key_source_.get()) {
720 params->forward_secure_premaster_secret =
721 ephemeral_key_source_->CalculateForwardSecureKey(
722 key_exchange, rand, clock->ApproximateNow(), public_value,
723 &forward_secure_public_value);
724 } else {
725 scoped_ptr<KeyExchange> forward_secure_key_exchange(
726 key_exchange->NewKeyPair(rand));
727 forward_secure_public_value =
728 forward_secure_key_exchange->public_value().as_string();
729 if (!forward_secure_key_exchange->CalculateSharedKey(
730 public_value, &params->forward_secure_premaster_secret)) {
731 *error_details = "Invalid public value";
732 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
736 string forward_secure_hkdf_input;
737 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
738 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
739 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
740 label_len);
741 forward_secure_hkdf_input.append(hkdf_suffix);
743 if (!CryptoUtils::DeriveKeys(
744 params->forward_secure_premaster_secret, params->aead,
745 info.client_nonce, info.server_nonce, forward_secure_hkdf_input,
746 CryptoUtils::SERVER, &params->forward_secure_crypters,
747 &params->subkey_secret)) {
748 *error_details = "Symmetric key setup failed";
749 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
752 out->set_tag(kSHLO);
753 QuicTagVector supported_version_tags;
754 for (size_t i = 0; i < supported_versions.size(); ++i) {
755 supported_version_tags.push_back
756 (QuicVersionToQuicTag(supported_versions[i]));
758 out->SetVector(kVER, supported_version_tags);
759 out->SetStringPiece(kSourceAddressTokenTag,
760 NewSourceAddressToken(*requested_config.get(),
761 client_address,
762 rand,
763 info.now,
764 nullptr));
765 QuicSocketAddressCoder address_coder(client_address);
766 out->SetStringPiece(kCADR, address_coder.Encode());
767 out->SetStringPiece(kPUBS, forward_secure_public_value);
769 return QUIC_NO_ERROR;
772 scoped_refptr<QuicCryptoServerConfig::Config>
773 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const {
774 // In Chromium, we will dead lock if the lock is held by the current thread.
775 // Chromium doesn't have AssertReaderHeld API call.
776 // configs_lock_.AssertReaderHeld();
778 if (!requested_scid.empty()) {
779 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
780 if (it != configs_.end()) {
781 // We'll use the config that the client requested in order to do
782 // key-agreement.
783 return scoped_refptr<Config>(it->second);
787 return scoped_refptr<Config>();
790 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
791 // Config's based on their primary_time.
792 // static
793 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
794 const scoped_refptr<Config>& a,
795 const scoped_refptr<Config>& b) {
796 if (a->primary_time.IsBefore(b->primary_time) ||
797 b->primary_time.IsBefore(a->primary_time)) {
798 // Primary times differ.
799 return a->primary_time.IsBefore(b->primary_time);
800 } else if (a->priority != b->priority) {
801 // Primary times are equal, sort backwards by priority.
802 return a->priority < b->priority;
803 } else {
804 // Primary times and priorities are equal, sort by config id.
805 return a->id < b->id;
809 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
810 const QuicWallTime now) const {
811 vector<scoped_refptr<Config> > configs;
812 configs.reserve(configs_.size());
814 for (ConfigMap::const_iterator it = configs_.begin();
815 it != configs_.end(); ++it) {
816 // TODO(avd) Exclude expired configs?
817 configs.push_back(it->second);
820 if (configs.empty()) {
821 if (primary_config_.get()) {
822 LOG(DFATAL) << "No valid QUIC server config. Keeping the current config.";
823 } else {
824 LOG(DFATAL) << "No valid QUIC server config.";
826 return;
829 sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
831 Config* best_candidate = configs[0].get();
833 for (size_t i = 0; i < configs.size(); ++i) {
834 const scoped_refptr<Config> config(configs[i]);
835 if (!config->primary_time.IsAfter(now)) {
836 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
837 best_candidate = config.get();
839 continue;
842 // This is the first config with a primary_time in the future. Thus the
843 // previous Config should be the primary and this one should determine the
844 // next_config_promotion_time_.
845 scoped_refptr<Config> new_primary(best_candidate);
846 if (i == 0) {
847 // We need the primary_time of the next config.
848 if (configs.size() > 1) {
849 next_config_promotion_time_ = configs[1]->primary_time;
850 } else {
851 next_config_promotion_time_ = QuicWallTime::Zero();
853 } else {
854 next_config_promotion_time_ = config->primary_time;
857 if (primary_config_.get()) {
858 primary_config_->is_primary = false;
860 primary_config_ = new_primary;
861 new_primary->is_primary = true;
862 DVLOG(1) << "New primary config. orbit: "
863 << base::HexEncode(
864 reinterpret_cast<const char*>(primary_config_->orbit),
865 kOrbitSize);
866 if (primary_config_changed_cb_.get() != nullptr) {
867 primary_config_changed_cb_->Run(primary_config_->id);
870 return;
873 // All config's primary times are in the past. We should make the most recent
874 // and highest priority candidate primary.
875 scoped_refptr<Config> new_primary(best_candidate);
876 if (primary_config_.get()) {
877 primary_config_->is_primary = false;
879 primary_config_ = new_primary;
880 new_primary->is_primary = true;
881 DVLOG(1) << "New primary config. orbit: "
882 << base::HexEncode(
883 reinterpret_cast<const char*>(primary_config_->orbit),
884 kOrbitSize)
885 << " scid: " << base::HexEncode(primary_config_->id.data(),
886 primary_config_->id.size());
887 next_config_promotion_time_ = QuicWallTime::Zero();
888 if (primary_config_changed_cb_.get() != nullptr) {
889 primary_config_changed_cb_->Run(primary_config_->id);
893 void QuicCryptoServerConfig::EvaluateClientHello(
894 const uint8* primary_orbit,
895 scoped_refptr<Config> requested_config,
896 ValidateClientHelloResultCallback::Result* client_hello_state,
897 ValidateClientHelloResultCallback* done_cb) const {
898 ValidateClientHelloHelper helper(client_hello_state, done_cb);
900 const CryptoHandshakeMessage& client_hello =
901 client_hello_state->client_hello;
902 ClientHelloInfo* info = &(client_hello_state->info);
904 if (client_hello.size() < kClientHelloMinimumSize) {
905 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
906 "Client hello too small");
907 return;
910 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
911 !CryptoUtils::IsValidSNI(info->sni)) {
912 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
913 "Invalid SNI name");
914 return;
917 client_hello.GetStringPiece(kUAID, &info->user_agent_id);
919 if (!requested_config.get()) {
920 StringPiece requested_scid;
921 if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
922 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
923 } else {
924 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
926 // No server config with the requested ID.
927 helper.ValidationComplete(QUIC_NO_ERROR, "");
928 return;
931 HandshakeFailureReason source_address_token_error;
932 StringPiece srct;
933 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
934 source_address_token_error =
935 ValidateSourceAddressToken(*requested_config.get(),
936 srct,
937 info->client_ip,
938 info->now,
939 &client_hello_state->cached_network_params);
940 info->valid_source_address_token =
941 (source_address_token_error == HANDSHAKE_OK);
942 } else {
943 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
946 bool found_error = false;
947 if (source_address_token_error != HANDSHAKE_OK) {
948 info->reject_reasons.push_back(source_address_token_error);
949 // No valid source address token.
950 if (FLAGS_use_early_return_when_verifying_chlo) {
951 helper.ValidationComplete(QUIC_NO_ERROR, "");
952 return;
954 found_error = true;
957 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) &&
958 info->client_nonce.size() == kNonceSize) {
959 info->client_nonce_well_formed = true;
960 } else {
961 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
962 // Invalid client nonce.
963 DVLOG(1) << "Invalid client nonce.";
964 if (FLAGS_use_early_return_when_verifying_chlo) {
965 helper.ValidationComplete(QUIC_NO_ERROR, "");
966 return;
968 found_error = true;
971 if (!replay_protection_) {
972 if (!found_error) {
973 info->unique = true;
975 DVLOG(1) << "No replay protection.";
976 helper.ValidationComplete(QUIC_NO_ERROR, "");
977 return;
980 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
981 if (!info->server_nonce.empty()) {
982 // If the server nonce is present, use it to establish uniqueness.
983 HandshakeFailureReason server_nonce_error =
984 ValidateServerNonce(info->server_nonce, info->now);
985 if (server_nonce_error == HANDSHAKE_OK) {
986 info->unique = true;
987 } else {
988 info->reject_reasons.push_back(server_nonce_error);
989 info->unique = false;
991 DVLOG(1) << "Using server nonce, unique: " << info->unique;
992 helper.ValidationComplete(QUIC_NO_ERROR, "");
993 return;
996 // We want to contact strike register only if there are no errors because it
997 // is a RPC call and is expensive.
998 if (found_error) {
999 helper.ValidationComplete(QUIC_NO_ERROR, "");
1000 return;
1003 // Use the client nonce to establish uniqueness.
1004 StrikeRegisterClient* strike_register_client;
1006 base::AutoLock locked(strike_register_client_lock_);
1008 if (strike_register_client_.get() == nullptr) {
1009 strike_register_client_.reset(new LocalStrikeRegisterClient(
1010 strike_register_max_entries_,
1011 static_cast<uint32>(info->now.ToUNIXSeconds()),
1012 strike_register_window_secs_,
1013 primary_orbit,
1014 strike_register_no_startup_period_ ?
1015 StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
1016 StrikeRegister::DENY_REQUESTS_AT_STARTUP));
1018 strike_register_client = strike_register_client_.get();
1021 strike_register_client->VerifyNonceIsValidAndUnique(
1022 info->client_nonce,
1023 info->now,
1024 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
1025 helper.StartedAsyncCallback();
1028 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1029 const IPEndPoint& client_ip,
1030 const QuicClock* clock,
1031 QuicRandom* rand,
1032 const QuicCryptoNegotiatedParameters& params,
1033 const CachedNetworkParameters* cached_network_params,
1034 CryptoHandshakeMessage* out) const {
1035 base::AutoLock locked(configs_lock_);
1036 out->set_tag(kSCUP);
1037 out->SetStringPiece(kSCFG, primary_config_->serialized);
1038 out->SetStringPiece(kSourceAddressTokenTag,
1039 NewSourceAddressToken(*primary_config_.get(),
1040 client_ip,
1041 rand,
1042 clock->WallNow(),
1043 cached_network_params));
1045 if (proof_source_ == nullptr) {
1046 // Insecure QUIC, can send SCFG without proof.
1047 return true;
1050 const vector<string>* certs;
1051 string signature;
1052 if (!proof_source_->GetProof(params.sni, primary_config_->serialized,
1053 params.x509_ecdsa_supported, &certs,
1054 &signature)) {
1055 DVLOG(1) << "Server: failed to get proof.";
1056 return false;
1059 const string compressed = CertCompressor::CompressChain(
1060 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes,
1061 primary_config_->common_cert_sets);
1063 out->SetStringPiece(kCertificateTag, compressed);
1064 out->SetStringPiece(kPROF, signature);
1065 return true;
1068 void QuicCryptoServerConfig::BuildRejection(
1069 const Config& config,
1070 const CryptoHandshakeMessage& client_hello,
1071 const ClientHelloInfo& info,
1072 const CachedNetworkParameters& cached_network_params,
1073 QuicRandom* rand,
1074 QuicCryptoNegotiatedParameters *params,
1075 CryptoHandshakeMessage* out) const {
1076 out->set_tag(kREJ);
1077 out->SetStringPiece(kSCFG, config.serialized);
1078 out->SetStringPiece(kSourceAddressTokenTag,
1079 NewSourceAddressToken(
1080 config,
1081 info.client_ip,
1082 rand,
1083 info.now,
1084 &cached_network_params));
1085 if (replay_protection_) {
1086 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
1089 if (FLAGS_send_quic_crypto_reject_reason) {
1090 // Send client the reject reason for debugging purposes.
1091 DCHECK_LT(0u, info.reject_reasons.size());
1092 out->SetVector(kRREJ, info.reject_reasons);
1095 // The client may have requested a certificate chain.
1096 const QuicTag* their_proof_demands;
1097 size_t num_their_proof_demands;
1099 if (proof_source_.get() == nullptr ||
1100 client_hello.GetTaglist(kPDMD, &their_proof_demands,
1101 &num_their_proof_demands) !=
1102 QUIC_NO_ERROR) {
1103 return;
1106 bool x509_supported = false;
1107 for (size_t i = 0; i < num_their_proof_demands; i++) {
1108 switch (their_proof_demands[i]) {
1109 case kX509:
1110 x509_supported = true;
1111 params->x509_ecdsa_supported = true;
1112 break;
1113 case kX59R:
1114 x509_supported = true;
1115 break;
1119 if (!x509_supported) {
1120 return;
1123 const vector<string>* certs;
1124 string signature;
1125 if (!proof_source_->GetProof(info.sni.as_string(), config.serialized,
1126 params->x509_ecdsa_supported, &certs,
1127 &signature)) {
1128 return;
1131 StringPiece client_common_set_hashes;
1132 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
1133 params->client_common_set_hashes = client_common_set_hashes.as_string();
1136 StringPiece client_cached_cert_hashes;
1137 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
1138 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string();
1141 const string compressed = CertCompressor::CompressChain(
1142 *certs, params->client_common_set_hashes,
1143 params->client_cached_cert_hashes, config.common_cert_sets);
1145 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1146 // message is taken up by things other than the certificates.
1147 // STK: 56 bytes
1148 // SNO: 56 bytes
1149 // SCFG
1150 // SCID: 16 bytes
1151 // PUBS: 38 bytes
1152 const size_t kREJOverheadBytes = 166;
1153 // kMultiplier is the multiple of the CHLO message size that a REJ message
1154 // must stay under when the client doesn't present a valid source-address
1155 // token.
1156 const size_t kMultiplier = 2;
1157 // max_unverified_size is the number of bytes that the certificate chain
1158 // and signature can consume before we will demand a valid source-address
1159 // token.
1160 const size_t max_unverified_size =
1161 client_hello.size() * kMultiplier - kREJOverheadBytes;
1162 COMPILE_ASSERT(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1163 overhead_calculation_may_underflow);
1164 if (info.valid_source_address_token ||
1165 signature.size() + compressed.size() < max_unverified_size) {
1166 out->SetStringPiece(kCertificateTag, compressed);
1167 out->SetStringPiece(kPROF, signature);
1171 scoped_refptr<QuicCryptoServerConfig::Config>
1172 QuicCryptoServerConfig::ParseConfigProtobuf(
1173 QuicServerConfigProtobuf* protobuf) {
1174 scoped_ptr<CryptoHandshakeMessage> msg(
1175 CryptoFramer::ParseMessage(protobuf->config()));
1177 if (msg->tag() != kSCFG) {
1178 LOG(WARNING) << "Server config message has tag " << msg->tag()
1179 << " expected " << kSCFG;
1180 return nullptr;
1183 scoped_refptr<Config> config(new Config);
1184 config->serialized = protobuf->config();
1186 if (!protobuf->has_source_address_token_secret_override()) {
1187 // Use the default boxer.
1188 config->source_address_token_boxer = &default_source_address_token_boxer_;
1189 } else {
1190 // Create override boxer instance.
1191 CryptoSecretBoxer* boxer = new CryptoSecretBoxer;
1192 boxer->SetKey(DeriveSourceAddressTokenKey(
1193 protobuf->source_address_token_secret_override()));
1194 config->source_address_token_boxer_storage.reset(boxer);
1195 config->source_address_token_boxer = boxer;
1198 if (protobuf->has_primary_time()) {
1199 config->primary_time =
1200 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1203 config->priority = protobuf->priority();
1205 StringPiece scid;
1206 if (!msg->GetStringPiece(kSCID, &scid)) {
1207 LOG(WARNING) << "Server config message is missing SCID";
1208 return nullptr;
1210 config->id = scid.as_string();
1212 const QuicTag* aead_tags;
1213 size_t aead_len;
1214 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
1215 LOG(WARNING) << "Server config message is missing AEAD";
1216 return nullptr;
1218 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
1220 const QuicTag* kexs_tags;
1221 size_t kexs_len;
1222 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
1223 LOG(WARNING) << "Server config message is missing KEXS";
1224 return nullptr;
1227 StringPiece orbit;
1228 if (!msg->GetStringPiece(kORBT, &orbit)) {
1229 LOG(WARNING) << "Server config message is missing ORBT";
1230 return nullptr;
1233 if (orbit.size() != kOrbitSize) {
1234 LOG(WARNING) << "Orbit value in server config is the wrong length."
1235 " Got " << orbit.size() << " want " << kOrbitSize;
1236 return nullptr;
1238 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size);
1239 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1242 StrikeRegisterClient* strike_register_client;
1244 base::AutoLock locked(strike_register_client_lock_);
1245 strike_register_client = strike_register_client_.get();
1248 if (strike_register_client != nullptr &&
1249 !strike_register_client->IsKnownOrbit(orbit)) {
1250 LOG(WARNING)
1251 << "Rejecting server config with orbit that the strike register "
1252 "client doesn't know about.";
1253 return nullptr;
1257 if (kexs_len != protobuf->key_size()) {
1258 LOG(WARNING) << "Server config has " << kexs_len
1259 << " key exchange methods configured, but "
1260 << protobuf->key_size() << " private keys";
1261 return nullptr;
1264 const QuicTag* proof_demand_tags;
1265 size_t num_proof_demand_tags;
1266 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
1267 QUIC_NO_ERROR) {
1268 for (size_t i = 0; i < num_proof_demand_tags; i++) {
1269 if (proof_demand_tags[i] == kCHID) {
1270 config->channel_id_enabled = true;
1271 break;
1276 for (size_t i = 0; i < kexs_len; i++) {
1277 const QuicTag tag = kexs_tags[i];
1278 string private_key;
1280 config->kexs.push_back(tag);
1282 for (size_t j = 0; j < protobuf->key_size(); j++) {
1283 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1284 if (key.tag() == tag) {
1285 private_key = key.private_key();
1286 break;
1290 if (private_key.empty()) {
1291 LOG(WARNING) << "Server config contains key exchange method without "
1292 "corresponding private key: " << tag;
1293 return nullptr;
1296 scoped_ptr<KeyExchange> ka;
1297 switch (tag) {
1298 case kC255:
1299 ka.reset(Curve25519KeyExchange::New(private_key));
1300 if (!ka.get()) {
1301 LOG(WARNING) << "Server config contained an invalid curve25519"
1302 " private key.";
1303 return nullptr;
1305 break;
1306 case kP256:
1307 ka.reset(P256KeyExchange::New(private_key));
1308 if (!ka.get()) {
1309 LOG(WARNING) << "Server config contained an invalid P-256"
1310 " private key.";
1311 return nullptr;
1313 break;
1314 default:
1315 LOG(WARNING) << "Server config message contains unknown key exchange "
1316 "method: " << tag;
1317 return nullptr;
1320 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
1321 i != config->key_exchanges.end(); ++i) {
1322 if ((*i)->tag() == tag) {
1323 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1324 return nullptr;
1328 config->key_exchanges.push_back(ka.release());
1331 return config;
1334 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
1335 proof_source_.reset(proof_source);
1338 void QuicCryptoServerConfig::SetEphemeralKeySource(
1339 EphemeralKeySource* ephemeral_key_source) {
1340 ephemeral_key_source_.reset(ephemeral_key_source);
1343 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1344 StrikeRegisterClient* strike_register_client) {
1345 base::AutoLock locker(strike_register_client_lock_);
1346 DCHECK(!strike_register_client_.get());
1347 strike_register_client_.reset(strike_register_client);
1350 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1351 replay_protection_ = on;
1354 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1355 base::AutoLock locker(strike_register_client_lock_);
1356 DCHECK(!strike_register_client_.get());
1357 strike_register_no_startup_period_ = true;
1360 void QuicCryptoServerConfig::set_strike_register_max_entries(
1361 uint32 max_entries) {
1362 base::AutoLock locker(strike_register_client_lock_);
1363 DCHECK(!strike_register_client_.get());
1364 strike_register_max_entries_ = max_entries;
1367 void QuicCryptoServerConfig::set_strike_register_window_secs(
1368 uint32 window_secs) {
1369 base::AutoLock locker(strike_register_client_lock_);
1370 DCHECK(!strike_register_client_.get());
1371 strike_register_window_secs_ = window_secs;
1374 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1375 uint32 future_secs) {
1376 source_address_token_future_secs_ = future_secs;
1379 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1380 uint32 lifetime_secs) {
1381 source_address_token_lifetime_secs_ = lifetime_secs;
1384 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1385 uint32 max_entries) {
1386 DCHECK(!server_nonce_strike_register_.get());
1387 server_nonce_strike_register_max_entries_ = max_entries;
1390 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1391 uint32 window_secs) {
1392 DCHECK(!server_nonce_strike_register_.get());
1393 server_nonce_strike_register_window_secs_ = window_secs;
1396 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1397 PrimaryConfigChangedCallback* cb) {
1398 base::AutoLock locked(configs_lock_);
1399 primary_config_changed_cb_.reset(cb);
1402 string QuicCryptoServerConfig::NewSourceAddressToken(
1403 const Config& config,
1404 const IPEndPoint& ip,
1405 QuicRandom* rand,
1406 QuicWallTime now,
1407 const CachedNetworkParameters* cached_network_params) const {
1408 IPAddressNumber ip_address = ip.address();
1409 if (ip.GetSockAddrFamily() == AF_INET) {
1410 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1412 SourceAddressToken source_address_token;
1413 source_address_token.set_ip(IPAddressToPackedString(ip_address));
1414 source_address_token.set_timestamp(now.ToUNIXSeconds());
1415 if (cached_network_params != nullptr) {
1416 source_address_token.set_cached_network_parameters(*cached_network_params);
1419 return config.source_address_token_boxer->Box(
1420 rand, source_address_token.SerializeAsString());
1423 bool QuicCryptoServerConfig::HasProofSource() const {
1424 return proof_source_ != nullptr;
1427 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressToken(
1428 const Config& config,
1429 StringPiece token,
1430 const IPEndPoint& ip,
1431 QuicWallTime now,
1432 CachedNetworkParameters* cached_network_params) const {
1433 string storage;
1434 StringPiece plaintext;
1435 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1436 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1439 SourceAddressToken source_address_token;
1440 if (!source_address_token.ParseFromArray(plaintext.data(),
1441 plaintext.size())) {
1442 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1445 IPAddressNumber ip_address = ip.address();
1446 if (ip.GetSockAddrFamily() == AF_INET) {
1447 ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
1449 if (source_address_token.ip() != IPAddressToPackedString(ip_address)) {
1450 // It's for a different IP address.
1451 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1454 const QuicWallTime timestamp(
1455 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1456 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1458 if (now.IsBefore(timestamp) &&
1459 delta.ToSeconds() > source_address_token_future_secs_) {
1460 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1463 if (now.IsAfter(timestamp) &&
1464 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1465 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1468 if (source_address_token.has_cached_network_parameters()) {
1469 *cached_network_params = source_address_token.cached_network_parameters();
1472 return HANDSHAKE_OK;
1475 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1476 // nonce.
1477 static const size_t kServerNoncePlaintextSize =
1478 4 /* timestamp */ + 20 /* random bytes */;
1480 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1481 QuicWallTime now) const {
1482 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds());
1484 uint8 server_nonce[kServerNoncePlaintextSize];
1485 COMPILE_ASSERT(sizeof(server_nonce) > sizeof(timestamp), nonce_too_small);
1486 server_nonce[0] = static_cast<uint8>(timestamp >> 24);
1487 server_nonce[1] = static_cast<uint8>(timestamp >> 16);
1488 server_nonce[2] = static_cast<uint8>(timestamp >> 8);
1489 server_nonce[3] = static_cast<uint8>(timestamp);
1490 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1491 sizeof(server_nonce) - sizeof(timestamp));
1493 return server_nonce_boxer_.Box(
1494 rand,
1495 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
1498 HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
1499 StringPiece token,
1500 QuicWallTime now) const {
1501 string storage;
1502 StringPiece plaintext;
1503 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
1504 return SERVER_NONCE_DECRYPTION_FAILURE;
1507 // plaintext contains:
1508 // uint32 timestamp
1509 // uint8[20] random bytes
1511 if (plaintext.size() != kServerNoncePlaintextSize) {
1512 // This should never happen because the value decrypted correctly.
1513 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
1514 return SERVER_NONCE_INVALID_FAILURE;
1517 uint8 server_nonce[32];
1518 memcpy(server_nonce, plaintext.data(), 4);
1519 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
1520 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
1521 20);
1522 COMPILE_ASSERT(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
1523 bad_nonce_buffer_length);
1525 InsertStatus nonce_error;
1527 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
1528 if (server_nonce_strike_register_.get() == nullptr) {
1529 server_nonce_strike_register_.reset(new StrikeRegister(
1530 server_nonce_strike_register_max_entries_,
1531 static_cast<uint32>(now.ToUNIXSeconds()),
1532 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
1533 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
1535 nonce_error = server_nonce_strike_register_->Insert(
1536 server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
1539 switch (nonce_error) {
1540 case NONCE_OK:
1541 return HANDSHAKE_OK;
1542 case NONCE_INVALID_FAILURE:
1543 case NONCE_INVALID_ORBIT_FAILURE:
1544 return SERVER_NONCE_INVALID_FAILURE;
1545 case NONCE_NOT_UNIQUE_FAILURE:
1546 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1547 case NONCE_INVALID_TIME_FAILURE:
1548 return SERVER_NONCE_INVALID_TIME_FAILURE;
1549 case NONCE_UNKNOWN_FAILURE:
1550 case STRIKE_REGISTER_TIMEOUT:
1551 case STRIKE_REGISTER_FAILURE:
1552 default:
1553 LOG(DFATAL) << "Unexpected server nonce error: " << nonce_error;
1554 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
1558 QuicCryptoServerConfig::Config::Config()
1559 : channel_id_enabled(false),
1560 is_primary(false),
1561 primary_time(QuicWallTime::Zero()),
1562 priority(0),
1563 source_address_token_boxer(nullptr) {}
1565 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
1567 } // namespace net