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"
10 #include "base/stl_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "crypto/hkdf.h"
13 #include "crypto/secure_hash.h"
14 #include "net/base/net_util.h"
15 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
16 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
17 #include "net/quic/crypto/cert_compressor.h"
18 #include "net/quic/crypto/chacha20_poly1305_encrypter.h"
19 #include "net/quic/crypto/channel_id.h"
20 #include "net/quic/crypto/crypto_framer.h"
21 #include "net/quic/crypto/crypto_server_config_protobuf.h"
22 #include "net/quic/crypto/crypto_utils.h"
23 #include "net/quic/crypto/curve25519_key_exchange.h"
24 #include "net/quic/crypto/ephemeral_key_source.h"
25 #include "net/quic/crypto/key_exchange.h"
26 #include "net/quic/crypto/local_strike_register_client.h"
27 #include "net/quic/crypto/p256_key_exchange.h"
28 #include "net/quic/crypto/proof_source.h"
29 #include "net/quic/crypto/quic_decrypter.h"
30 #include "net/quic/crypto/quic_encrypter.h"
31 #include "net/quic/crypto/quic_random.h"
32 #include "net/quic/crypto/source_address_token.h"
33 #include "net/quic/crypto/strike_register.h"
34 #include "net/quic/crypto/strike_register_client.h"
35 #include "net/quic/quic_clock.h"
36 #include "net/quic/quic_protocol.h"
37 #include "net/quic/quic_socket_address_coder.h"
38 #include "net/quic/quic_utils.h"
40 using base::StringPiece;
41 using crypto::SecureHash;
51 string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) {
52 crypto::HKDF hkdf(source_address_token_secret,
53 StringPiece() /* no salt */,
54 "QUIC source address token key",
55 CryptoSecretBoxer::GetKeySize(),
56 0 /* no fixed IV needed */);
57 return hkdf.server_write_key().as_string();
62 // ClientHelloInfo contains information about a client hello message that is
63 // only kept for as long as it's being processed.
64 struct ClientHelloInfo {
65 ClientHelloInfo(const IPEndPoint& in_client_ip, QuicWallTime in_now)
66 : client_ip(in_client_ip),
68 valid_source_address_token(false),
69 client_nonce_well_formed(false),
72 // Inputs to EvaluateClientHello.
73 const IPEndPoint client_ip;
74 const QuicWallTime now;
76 // Outputs from EvaluateClientHello.
77 bool valid_source_address_token;
78 bool client_nonce_well_formed;
81 StringPiece client_nonce;
82 StringPiece server_nonce;
85 struct ValidateClientHelloResultCallback::Result {
86 Result(const CryptoHandshakeMessage& in_client_hello,
87 IPEndPoint in_client_ip,
89 : client_hello(in_client_hello),
90 info(in_client_ip, in_now),
91 error_code(QUIC_NO_ERROR) {
94 CryptoHandshakeMessage client_hello;
96 QuicErrorCode error_code;
100 class ValidateClientHelloHelper {
102 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result,
103 ValidateClientHelloResultCallback* done_cb)
104 : result_(result), done_cb_(done_cb) {
107 ~ValidateClientHelloHelper() {
108 LOG_IF(DFATAL, done_cb_ != NULL)
109 << "Deleting ValidateClientHelloHelper with a pending callback.";
112 void ValidationComplete(QuicErrorCode error_code, const char* error_details) {
113 result_->error_code = error_code;
114 result_->error_details = error_details;
115 done_cb_->Run(result_);
119 void StartedAsyncCallback() {
124 void DetachCallback() {
125 LOG_IF(DFATAL, done_cb_ == NULL) << "Callback already detached.";
129 ValidateClientHelloResultCallback::Result* result_;
130 ValidateClientHelloResultCallback* done_cb_;
132 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
135 class VerifyNonceIsValidAndUniqueCallback
136 : public StrikeRegisterClient::ResultCallback {
138 VerifyNonceIsValidAndUniqueCallback(
139 ValidateClientHelloResultCallback::Result* result,
140 ValidateClientHelloResultCallback* done_cb)
141 : result_(result), done_cb_(done_cb) {
145 virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE {
146 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique;
147 result_->info.unique = nonce_is_valid_and_unique;
148 done_cb_->Run(result_);
152 ValidateClientHelloResultCallback::Result* result_;
153 ValidateClientHelloResultCallback* done_cb_;
155 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
159 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
161 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {
164 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {
167 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {
170 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {
173 void ValidateClientHelloResultCallback::Run(const Result* result) {
174 RunImpl(result->client_hello, *result);
179 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
180 : expiry_time(QuicWallTime::Zero()),
181 channel_id_enabled(false),
184 QuicCryptoServerConfig::QuicCryptoServerConfig(
185 StringPiece source_address_token_secret,
187 : replay_protection_(true),
189 primary_config_(NULL),
190 next_config_promotion_time_(QuicWallTime::Zero()),
191 server_nonce_strike_register_lock_(),
192 strike_register_no_startup_period_(false),
193 strike_register_max_entries_(1 << 10),
194 strike_register_window_secs_(600),
195 source_address_token_future_secs_(3600),
196 source_address_token_lifetime_secs_(86400),
197 server_nonce_strike_register_max_entries_(1 << 10),
198 server_nonce_strike_register_window_secs_(120) {
199 default_source_address_token_boxer_.SetKey(
200 DeriveSourceAddressTokenKey(source_address_token_secret));
202 // Generate a random key and orbit for server nonces.
203 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_));
204 const size_t key_size = server_nonce_boxer_.GetKeySize();
205 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]);
206 rand->RandBytes(key_bytes.get(), key_size);
208 server_nonce_boxer_.SetKey(
209 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size));
212 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
213 primary_config_ = NULL;
217 QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig(
219 const QuicClock* clock,
220 const ConfigOptions& options) {
221 CryptoHandshakeMessage msg;
223 const string curve25519_private_key =
224 Curve25519KeyExchange::NewPrivateKey(rand);
225 scoped_ptr<Curve25519KeyExchange> curve25519(
226 Curve25519KeyExchange::New(curve25519_private_key));
227 StringPiece curve25519_public_value = curve25519->public_value();
229 string encoded_public_values;
230 // First three bytes encode the length of the public value.
231 encoded_public_values.push_back(curve25519_public_value.size());
232 encoded_public_values.push_back(curve25519_public_value.size() >> 8);
233 encoded_public_values.push_back(curve25519_public_value.size() >> 16);
234 encoded_public_values.append(curve25519_public_value.data(),
235 curve25519_public_value.size());
237 string p256_private_key;
239 p256_private_key = P256KeyExchange::NewPrivateKey();
240 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
241 StringPiece p256_public_value = p256->public_value();
243 encoded_public_values.push_back(p256_public_value.size());
244 encoded_public_values.push_back(p256_public_value.size() >> 8);
245 encoded_public_values.push_back(p256_public_value.size() >> 16);
246 encoded_public_values.append(p256_public_value.data(),
247 p256_public_value.size());
252 msg.SetTaglist(kKEXS, kC255, kP256, 0);
254 msg.SetTaglist(kKEXS, kC255, 0);
256 if (ChaCha20Poly1305Encrypter::IsSupported()) {
257 msg.SetTaglist(kAEAD, kAESG, kCC12, 0);
259 msg.SetTaglist(kAEAD, kAESG, 0);
261 msg.SetStringPiece(kPUBS, encoded_public_values);
263 if (options.expiry_time.IsZero()) {
264 const QuicWallTime now = clock->WallNow();
265 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
266 60 * 60 * 24 * 180 /* 180 days, ~six months */));
267 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
268 msg.SetValue(kEXPY, expiry_seconds);
270 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
273 char orbit_bytes[kOrbitSize];
274 if (options.orbit.size() == sizeof(orbit_bytes)) {
275 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
277 DCHECK(options.orbit.empty());
278 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
280 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
282 if (options.channel_id_enabled) {
283 msg.SetTaglist(kPDMD, kCHID, 0);
286 if (options.id.empty()) {
287 // We need to ensure that the SCID changes whenever the server config does
288 // thus we make it a hash of the rest of the server config.
289 scoped_ptr<QuicData> serialized(
290 CryptoFramer::ConstructHandshakeMessage(msg));
291 scoped_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256));
292 hash->Update(serialized->data(), serialized->length());
295 hash->Finish(scid_bytes, sizeof(scid_bytes));
296 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
298 msg.SetStringPiece(kSCID, options.id);
300 // Don't put new tags below this point. The SCID generation should hash over
301 // everything but itself and so extra tags should be added prior to the
302 // preceeding if block.
304 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
306 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
307 config->set_config(serialized->AsStringPiece());
308 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
309 curve25519_key->set_tag(kC255);
310 curve25519_key->set_private_key(curve25519_private_key);
313 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
314 p256_key->set_tag(kP256);
315 p256_key->set_private_key(p256_private_key);
318 return config.release();
321 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
322 QuicServerConfigProtobuf* protobuf,
323 const QuicWallTime now) {
324 scoped_ptr<CryptoHandshakeMessage> msg(
325 CryptoFramer::ParseMessage(protobuf->config()));
328 LOG(WARNING) << "Failed to parse server config message";
332 scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
334 LOG(WARNING) << "Failed to parse server config message";
339 base::AutoLock locked(configs_lock_);
340 if (configs_.find(config->id) != configs_.end()) {
341 LOG(WARNING) << "Failed to add config because another with the same "
342 "server config id already exists: "
343 << base::HexEncode(config->id.data(), config->id.size());
347 configs_[config->id] = config;
348 SelectNewPrimaryConfig(now);
349 DCHECK(primary_config_.get());
350 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
353 return msg.release();
356 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
358 const QuicClock* clock,
359 const ConfigOptions& options) {
360 scoped_ptr<QuicServerConfigProtobuf> config(
361 GenerateConfig(rand, clock, options));
362 return AddConfig(config.get(), clock->WallNow());
365 bool QuicCryptoServerConfig::SetConfigs(
366 const vector<QuicServerConfigProtobuf*>& protobufs,
367 const QuicWallTime now) {
368 vector<scoped_refptr<Config> > parsed_configs;
371 for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin();
372 i != protobufs.end(); ++i) {
373 scoped_refptr<Config> config(ParseConfigProtobuf(*i));
379 parsed_configs.push_back(config);
382 if (parsed_configs.empty()) {
383 LOG(WARNING) << "New config list is empty.";
388 LOG(WARNING) << "Rejecting QUIC configs because of above errors";
390 VLOG(1) << "Updating configs:";
392 base::AutoLock locked(configs_lock_);
393 ConfigMap new_configs;
395 for (vector<scoped_refptr<Config> >::const_iterator i =
396 parsed_configs.begin();
397 i != parsed_configs.end(); ++i) {
398 scoped_refptr<Config> config = *i;
400 ConfigMap::iterator it = configs_.find(config->id);
401 if (it != configs_.end()) {
403 << "Keeping scid: " << base::HexEncode(
404 config->id.data(), config->id.size())
405 << " orbit: " << base::HexEncode(
406 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
407 << " new primary_time " << config->primary_time.ToUNIXSeconds()
408 << " old primary_time " << it->second->primary_time.ToUNIXSeconds()
409 << " new priority " << config->priority
410 << " old priority " << it->second->priority;
411 // Update primary_time and priority.
412 it->second->primary_time = config->primary_time;
413 it->second->priority = config->priority;
414 new_configs.insert(*it);
416 VLOG(1) << "Adding scid: " << base::HexEncode(
417 config->id.data(), config->id.size())
418 << " orbit: " << base::HexEncode(
419 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
420 << " primary_time " << config->primary_time.ToUNIXSeconds()
421 << " priority " << config->priority;
422 new_configs.insert(make_pair(config->id, config));
426 configs_.swap(new_configs);
427 SelectNewPrimaryConfig(now);
428 DCHECK(primary_config_);
429 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
435 void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
436 base::AutoLock locked(configs_lock_);
437 for (ConfigMap::const_iterator it = configs_.begin();
438 it != configs_.end(); ++it) {
439 scids->push_back(it->first);
443 void QuicCryptoServerConfig::ValidateClientHello(
444 const CryptoHandshakeMessage& client_hello,
445 IPEndPoint client_ip,
446 const QuicClock* clock,
447 ValidateClientHelloResultCallback* done_cb) const {
448 const QuicWallTime now(clock->WallNow());
450 ValidateClientHelloResultCallback::Result* result =
451 new ValidateClientHelloResultCallback::Result(
452 client_hello, client_ip, now);
454 StringPiece requested_scid;
455 client_hello.GetStringPiece(kSCID, &requested_scid);
457 uint8 primary_orbit[kOrbitSize];
458 scoped_refptr<Config> requested_config;
460 base::AutoLock locked(configs_lock_);
462 if (!primary_config_.get()) {
463 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
464 result->error_details = "No configurations loaded";
466 if (!next_config_promotion_time_.IsZero() &&
467 next_config_promotion_time_.IsAfter(now)) {
468 SelectNewPrimaryConfig(now);
469 DCHECK(primary_config_);
470 DCHECK(configs_.find(primary_config_->id)->second == primary_config_);
473 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit));
476 requested_config = GetConfigWithScid(requested_scid);
479 if (result->error_code == QUIC_NO_ERROR) {
480 EvaluateClientHello(primary_orbit, requested_config, result, done_cb);
482 done_cb->Run(result);
486 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
487 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
488 QuicConnectionId connection_id,
489 IPEndPoint client_address,
491 const QuicVersionVector& supported_versions,
492 uint32 initial_flow_control_window_bytes,
493 const QuicClock* clock,
495 QuicCryptoNegotiatedParameters *params,
496 CryptoHandshakeMessage* out,
497 string* error_details) const {
498 DCHECK(error_details);
500 const CryptoHandshakeMessage& client_hello =
501 validate_chlo_result.client_hello;
502 const ClientHelloInfo& info = validate_chlo_result.info;
504 // If the client's preferred version is not the version we are currently
505 // speaking, then the client went through a version negotiation. In this
506 // case, we need to make sure that we actually do not support this version
507 // and that it wasn't a downgrade attack.
508 QuicTag client_version_tag;
509 if (client_hello.GetUint32(kVER, &client_version_tag) != QUIC_NO_ERROR) {
510 *error_details = "client hello missing version list";
511 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
513 QuicVersion client_version = QuicTagToQuicVersion(client_version_tag);
514 if (client_version != version) {
515 // Just because client_version is a valid version enum doesn't mean that
516 // this server actually supports that version, so we check to see if
517 // it's actually in the supported versions list.
518 for (size_t i = 0; i < supported_versions.size(); ++i) {
519 if (client_version == supported_versions[i]) {
520 *error_details = "Downgrade attack detected";
521 return QUIC_VERSION_NEGOTIATION_MISMATCH;
526 StringPiece requested_scid;
527 client_hello.GetStringPiece(kSCID, &requested_scid);
528 const QuicWallTime now(clock->WallNow());
530 scoped_refptr<Config> requested_config;
531 scoped_refptr<Config> primary_config;
533 base::AutoLock locked(configs_lock_);
535 if (!primary_config_.get()) {
536 *error_details = "No configurations loaded";
537 return QUIC_CRYPTO_INTERNAL_ERROR;
540 if (!next_config_promotion_time_.IsZero() &&
541 next_config_promotion_time_.IsAfter(now)) {
542 SelectNewPrimaryConfig(now);
543 DCHECK(primary_config_);
544 DCHECK(configs_.find(primary_config_->id)->second == primary_config_);
547 // We'll use the config that the client requested in order to do
548 // key-agreement. Otherwise we'll give it a copy of |primary_config_|
550 primary_config = primary_config_;
552 requested_config = GetConfigWithScid(requested_scid);
555 if (validate_chlo_result.error_code != QUIC_NO_ERROR) {
556 *error_details = validate_chlo_result.error_details;
557 return validate_chlo_result.error_code;
562 if (!info.valid_source_address_token ||
563 !info.client_nonce_well_formed ||
565 !requested_config.get()) {
566 BuildRejection(*primary_config, client_hello, info, rand, out);
567 return QUIC_NO_ERROR;
570 const QuicTag* their_aeads;
571 const QuicTag* their_key_exchanges;
572 size_t num_their_aeads, num_their_key_exchanges;
573 if (client_hello.GetTaglist(kAEAD, &their_aeads,
574 &num_their_aeads) != QUIC_NO_ERROR ||
575 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
576 &num_their_key_exchanges) != QUIC_NO_ERROR ||
577 num_their_aeads != 1 ||
578 num_their_key_exchanges != 1) {
579 *error_details = "Missing or invalid AEAD or KEXS";
580 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
583 size_t key_exchange_index;
584 if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads,
585 num_their_aeads, QuicUtils::LOCAL_PRIORITY,
586 ¶ms->aead, NULL) ||
587 !QuicUtils::FindMutualTag(
588 requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
589 QuicUtils::LOCAL_PRIORITY, ¶ms->key_exchange,
590 &key_exchange_index)) {
591 *error_details = "Unsupported AEAD or KEXS";
592 return QUIC_CRYPTO_NO_SUPPORT;
595 StringPiece public_value;
596 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
597 *error_details = "Missing public value";
598 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
601 const KeyExchange* key_exchange =
602 requested_config->key_exchanges[key_exchange_index];
603 if (!key_exchange->CalculateSharedKey(public_value,
604 ¶ms->initial_premaster_secret)) {
605 *error_details = "Invalid public value";
606 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
609 if (!info.sni.empty()) {
610 scoped_ptr<char[]> sni_tmp(new char[info.sni.length() + 1]);
611 memcpy(sni_tmp.get(), info.sni.data(), info.sni.length());
612 sni_tmp[info.sni.length()] = 0;
613 params->sni = CryptoUtils::NormalizeHostname(sni_tmp.get());
617 const QuicData& client_hello_serialized = client_hello.GetSerialized();
618 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() +
619 requested_config->serialized.size());
620 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id),
621 sizeof(connection_id));
622 hkdf_suffix.append(client_hello_serialized.data(),
623 client_hello_serialized.length());
624 hkdf_suffix.append(requested_config->serialized);
626 StringPiece cetv_ciphertext;
627 if (requested_config->channel_id_enabled &&
628 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
629 CryptoHandshakeMessage client_hello_copy(client_hello);
630 client_hello_copy.Erase(kCETV);
631 client_hello_copy.Erase(kPAD);
633 const QuicData& client_hello_serialized = client_hello_copy.GetSerialized();
635 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
636 strlen(QuicCryptoConfig::kCETVLabel) + 1);
637 hkdf_input.append(reinterpret_cast<char*>(&connection_id),
638 sizeof(connection_id));
639 hkdf_input.append(client_hello_serialized.data(),
640 client_hello_serialized.length());
641 hkdf_input.append(requested_config->serialized);
643 CrypterPair crypters;
644 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
645 info.client_nonce, info.server_nonce,
646 hkdf_input, CryptoUtils::SERVER, &crypters)) {
647 *error_details = "Symmetric key setup failed";
648 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
651 scoped_ptr<QuicData> cetv_plaintext(crypters.decrypter->DecryptPacket(
652 0 /* sequence number */, StringPiece() /* associated data */,
654 if (!cetv_plaintext.get()) {
655 *error_details = "CETV decryption failure";
656 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
659 scoped_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
660 cetv_plaintext->AsStringPiece()));
662 *error_details = "CETV parse error";
663 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
666 StringPiece key, signature;
667 if (cetv->GetStringPiece(kCIDK, &key) &&
668 cetv->GetStringPiece(kCIDS, &signature)) {
669 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
670 *error_details = "ChannelID signature failure";
671 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
674 params->channel_id = key.as_string();
679 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
680 hkdf_input.reserve(label_len + hkdf_suffix.size());
681 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
682 hkdf_input.append(hkdf_suffix);
684 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
685 info.client_nonce, info.server_nonce, hkdf_input,
687 ¶ms->initial_crypters)) {
688 *error_details = "Symmetric key setup failed";
689 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
692 string forward_secure_public_value;
693 if (ephemeral_key_source_.get()) {
694 params->forward_secure_premaster_secret =
695 ephemeral_key_source_->CalculateForwardSecureKey(
696 key_exchange, rand, clock->ApproximateNow(), public_value,
697 &forward_secure_public_value);
699 scoped_ptr<KeyExchange> forward_secure_key_exchange(
700 key_exchange->NewKeyPair(rand));
701 forward_secure_public_value =
702 forward_secure_key_exchange->public_value().as_string();
703 if (!forward_secure_key_exchange->CalculateSharedKey(
704 public_value, ¶ms->forward_secure_premaster_secret)) {
705 *error_details = "Invalid public value";
706 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
710 string forward_secure_hkdf_input;
711 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
712 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
713 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
715 forward_secure_hkdf_input.append(hkdf_suffix);
717 if (!CryptoUtils::DeriveKeys(
718 params->forward_secure_premaster_secret, params->aead,
719 info.client_nonce, info.server_nonce, forward_secure_hkdf_input,
720 CryptoUtils::SERVER, ¶ms->forward_secure_crypters)) {
721 *error_details = "Symmetric key setup failed";
722 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
726 QuicTagVector supported_version_tags;
727 for (size_t i = 0; i < supported_versions.size(); ++i) {
728 supported_version_tags.push_back
729 (QuicVersionToQuicTag(supported_versions[i]));
731 out->SetVector(kVER, supported_version_tags);
732 out->SetStringPiece(kSourceAddressTokenTag,
733 NewSourceAddressToken(
735 client_address, rand,
737 QuicSocketAddressCoder address_coder(client_address);
738 out->SetStringPiece(kCADR, address_coder.Encode());
739 out->SetStringPiece(kPUBS, forward_secure_public_value);
741 // Set initial receive window for flow control.
742 out->SetValue(kIFCW, initial_flow_control_window_bytes);
744 return QUIC_NO_ERROR;
747 scoped_refptr<QuicCryptoServerConfig::Config>
748 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const {
749 // In Chromium, we will dead lock if the lock is held by the current thread.
750 // Chromium doesn't have AssertReaderHeld API call.
751 // configs_lock_.AssertReaderHeld();
753 if (!requested_scid.empty()) {
754 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
755 if (it != configs_.end()) {
756 // We'll use the config that the client requested in order to do
758 return scoped_refptr<Config>(it->second);
762 return scoped_refptr<Config>();
765 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
766 // Config's based on their primary_time.
768 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
769 const scoped_refptr<Config>& a,
770 const scoped_refptr<Config>& b) {
771 if (a->primary_time.IsBefore(b->primary_time) ||
772 b->primary_time.IsBefore(a->primary_time)) {
773 // Primary times differ.
774 return a->primary_time.IsBefore(b->primary_time);
775 } else if (a->priority != b->priority) {
776 // Primary times are equal, sort backwards by priority.
777 return a->priority < b->priority;
779 // Primary times and priorities are equal, sort by config id.
780 return a->id < b->id;
784 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
785 const QuicWallTime now) const {
786 vector<scoped_refptr<Config> > configs;
787 configs.reserve(configs_.size());
789 for (ConfigMap::const_iterator it = configs_.begin();
790 it != configs_.end(); ++it) {
791 // TODO(avd) Exclude expired configs?
792 configs.push_back(it->second);
795 if (configs.empty()) {
796 if (primary_config_.get()) {
797 LOG(DFATAL) << "No valid QUIC server config. Keeping the current config.";
799 LOG(DFATAL) << "No valid QUIC server config.";
804 sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
806 Config* best_candidate = configs[0];
808 for (size_t i = 0; i < configs.size(); ++i) {
809 const scoped_refptr<Config> config(configs[i]);
810 if (!config->primary_time.IsAfter(now)) {
811 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
812 best_candidate = config;
817 // This is the first config with a primary_time in the future. Thus the
818 // previous Config should be the primary and this one should determine the
819 // next_config_promotion_time_.
820 scoped_refptr<Config> new_primary(best_candidate);
822 // We need the primary_time of the next config.
823 if (configs.size() > 1) {
824 next_config_promotion_time_ = configs[1]->primary_time;
826 next_config_promotion_time_ = QuicWallTime::Zero();
829 next_config_promotion_time_ = config->primary_time;
832 if (primary_config_.get()) {
833 primary_config_->is_primary = false;
835 primary_config_ = new_primary;
836 new_primary->is_primary = true;
837 DVLOG(1) << "New primary config. orbit: "
839 reinterpret_cast<const char*>(primary_config_->orbit),
841 if (primary_config_changed_cb_.get() != NULL) {
842 primary_config_changed_cb_->Run(primary_config_->id);
848 // All config's primary times are in the past. We should make the most recent
849 // and highest priority candidate primary.
850 scoped_refptr<Config> new_primary(best_candidate);
851 if (primary_config_.get()) {
852 primary_config_->is_primary = false;
854 primary_config_ = new_primary;
855 new_primary->is_primary = true;
856 DVLOG(1) << "New primary config. orbit: "
858 reinterpret_cast<const char*>(primary_config_->orbit),
860 << " scid: " << base::HexEncode(primary_config_->id.data(),
861 primary_config_->id.size());
862 next_config_promotion_time_ = QuicWallTime::Zero();
863 if (primary_config_changed_cb_.get() != NULL) {
864 primary_config_changed_cb_->Run(primary_config_->id);
868 void QuicCryptoServerConfig::EvaluateClientHello(
869 const uint8* primary_orbit,
870 scoped_refptr<Config> requested_config,
871 ValidateClientHelloResultCallback::Result* client_hello_state,
872 ValidateClientHelloResultCallback* done_cb) const {
873 ValidateClientHelloHelper helper(client_hello_state, done_cb);
875 const CryptoHandshakeMessage& client_hello =
876 client_hello_state->client_hello;
877 ClientHelloInfo* info = &(client_hello_state->info);
879 if (client_hello.size() < kClientHelloMinimumSize) {
880 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
881 "Client hello too small");
885 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
886 !CryptoUtils::IsValidSNI(info->sni)) {
887 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
893 if (requested_config.get() != NULL &&
894 client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) &&
895 ValidateSourceAddressToken(*requested_config,
899 info->valid_source_address_token = true;
901 // No server config with the requested ID, or no valid source address token.
902 helper.ValidationComplete(QUIC_NO_ERROR, "");
906 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) &&
907 info->client_nonce.size() == kNonceSize) {
908 info->client_nonce_well_formed = true;
910 // Invalid client nonce.
911 DVLOG(1) << "Invalid client nonce.";
912 helper.ValidationComplete(QUIC_NO_ERROR, "");
916 if (!replay_protection_) {
918 DVLOG(1) << "No replay protection.";
919 helper.ValidationComplete(QUIC_NO_ERROR, "");
923 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
924 if (!info->server_nonce.empty()) {
925 // If the server nonce is present, use it to establish uniqueness.
926 info->unique = ValidateServerNonce(info->server_nonce, info->now);
927 DVLOG(1) << "Using server nonce, unique: " << info->unique;
928 helper.ValidationComplete(QUIC_NO_ERROR, "");
932 // Use the client nonce to establish uniqueness.
933 StrikeRegisterClient* strike_register_client;
935 base::AutoLock locked(strike_register_client_lock_);
937 if (strike_register_client_.get() == NULL) {
938 strike_register_client_.reset(new LocalStrikeRegisterClient(
939 strike_register_max_entries_,
940 static_cast<uint32>(info->now.ToUNIXSeconds()),
941 strike_register_window_secs_,
943 strike_register_no_startup_period_ ?
944 StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
945 StrikeRegister::DENY_REQUESTS_AT_STARTUP));
947 strike_register_client = strike_register_client_.get();
950 strike_register_client->VerifyNonceIsValidAndUnique(
953 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
954 helper.StartedAsyncCallback();
957 void QuicCryptoServerConfig::BuildRejection(
958 const Config& config,
959 const CryptoHandshakeMessage& client_hello,
960 const ClientHelloInfo& info,
962 CryptoHandshakeMessage* out) const {
964 out->SetStringPiece(kSCFG, config.serialized);
965 out->SetStringPiece(kSourceAddressTokenTag,
966 NewSourceAddressToken(
971 if (replay_protection_) {
972 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
975 // The client may have requested a certificate chain.
976 const QuicTag* their_proof_demands;
977 size_t num_their_proof_demands;
979 if (proof_source_.get() == NULL ||
980 client_hello.GetTaglist(kPDMD, &their_proof_demands,
981 &num_their_proof_demands) !=
986 bool x509_supported = false, x509_ecdsa_supported = false;
987 for (size_t i = 0; i < num_their_proof_demands; i++) {
988 switch (their_proof_demands[i]) {
990 x509_supported = true;
991 x509_ecdsa_supported = true;
994 x509_supported = true;
999 if (!x509_supported) {
1003 const vector<string>* certs;
1005 if (!proof_source_->GetProof(info.sni.as_string(), config.serialized,
1006 x509_ecdsa_supported, &certs, &signature)) {
1010 StringPiece their_common_set_hashes;
1011 StringPiece their_cached_cert_hashes;
1012 client_hello.GetStringPiece(kCCS, &their_common_set_hashes);
1013 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes);
1015 const string compressed = CertCompressor::CompressChain(
1016 *certs, their_common_set_hashes, their_cached_cert_hashes,
1017 config.common_cert_sets);
1019 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1020 // message is taken up by things other than the certificates.
1026 const size_t kREJOverheadBytes = 166;
1027 // kMultiplier is the multiple of the CHLO message size that a REJ message
1028 // must stay under when the client doesn't present a valid source-address
1030 const size_t kMultiplier = 2;
1031 // max_unverified_size is the number of bytes that the certificate chain
1032 // and signature can consume before we will demand a valid source-address
1034 const size_t max_unverified_size =
1035 client_hello.size() * kMultiplier - kREJOverheadBytes;
1036 COMPILE_ASSERT(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1037 overhead_calculation_may_underflow);
1038 if (info.valid_source_address_token ||
1039 signature.size() + compressed.size() < max_unverified_size) {
1040 out->SetStringPiece(kCertificateTag, compressed);
1041 out->SetStringPiece(kPROF, signature);
1045 scoped_refptr<QuicCryptoServerConfig::Config>
1046 QuicCryptoServerConfig::ParseConfigProtobuf(
1047 QuicServerConfigProtobuf* protobuf) {
1048 scoped_ptr<CryptoHandshakeMessage> msg(
1049 CryptoFramer::ParseMessage(protobuf->config()));
1051 if (msg->tag() != kSCFG) {
1052 LOG(WARNING) << "Server config message has tag " << msg->tag()
1053 << " expected " << kSCFG;
1057 scoped_refptr<Config> config(new Config);
1058 config->serialized = protobuf->config();
1060 if (!protobuf->has_source_address_token_secret_override()) {
1061 // Use the default boxer.
1062 config->source_address_token_boxer = &default_source_address_token_boxer_;
1064 // Create override boxer instance.
1065 CryptoSecretBoxer* boxer = new CryptoSecretBoxer;
1066 boxer->SetKey(DeriveSourceAddressTokenKey(
1067 protobuf->source_address_token_secret_override()));
1068 config->source_address_token_boxer_storage.reset(boxer);
1069 config->source_address_token_boxer = boxer;
1072 if (protobuf->has_primary_time()) {
1073 config->primary_time =
1074 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1077 config->priority = protobuf->priority();
1080 if (!msg->GetStringPiece(kSCID, &scid)) {
1081 LOG(WARNING) << "Server config message is missing SCID";
1084 config->id = scid.as_string();
1086 const QuicTag* aead_tags;
1088 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
1089 LOG(WARNING) << "Server config message is missing AEAD";
1092 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
1094 const QuicTag* kexs_tags;
1096 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
1097 LOG(WARNING) << "Server config message is missing KEXS";
1102 if (!msg->GetStringPiece(kORBT, &orbit)) {
1103 LOG(WARNING) << "Server config message is missing ORBT";
1107 if (orbit.size() != kOrbitSize) {
1108 LOG(WARNING) << "Orbit value in server config is the wrong length."
1109 " Got " << orbit.size() << " want " << kOrbitSize;
1112 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size);
1113 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1116 StrikeRegisterClient* strike_register_client;
1118 base::AutoLock locked(strike_register_client_lock_);
1119 strike_register_client = strike_register_client_.get();
1122 if (strike_register_client != NULL &&
1123 !strike_register_client->IsKnownOrbit(orbit)) {
1125 << "Rejecting server config with orbit that the strike register "
1126 "client doesn't know about.";
1131 if (kexs_len != protobuf->key_size()) {
1132 LOG(WARNING) << "Server config has " << kexs_len
1133 << " key exchange methods configured, but "
1134 << protobuf->key_size() << " private keys";
1138 const QuicTag* proof_demand_tags;
1139 size_t num_proof_demand_tags;
1140 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
1142 for (size_t i = 0; i < num_proof_demand_tags; i++) {
1143 if (proof_demand_tags[i] == kCHID) {
1144 config->channel_id_enabled = true;
1150 for (size_t i = 0; i < kexs_len; i++) {
1151 const QuicTag tag = kexs_tags[i];
1154 config->kexs.push_back(tag);
1156 for (size_t j = 0; j < protobuf->key_size(); j++) {
1157 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1158 if (key.tag() == tag) {
1159 private_key = key.private_key();
1164 if (private_key.empty()) {
1165 LOG(WARNING) << "Server config contains key exchange method without "
1166 "corresponding private key: " << tag;
1170 scoped_ptr<KeyExchange> ka;
1173 ka.reset(Curve25519KeyExchange::New(private_key));
1175 LOG(WARNING) << "Server config contained an invalid curve25519"
1181 ka.reset(P256KeyExchange::New(private_key));
1183 LOG(WARNING) << "Server config contained an invalid P-256"
1189 LOG(WARNING) << "Server config message contains unknown key exchange "
1194 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
1195 i != config->key_exchanges.end(); ++i) {
1196 if ((*i)->tag() == tag) {
1197 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1202 config->key_exchanges.push_back(ka.release());
1208 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
1209 proof_source_.reset(proof_source);
1212 void QuicCryptoServerConfig::SetEphemeralKeySource(
1213 EphemeralKeySource* ephemeral_key_source) {
1214 ephemeral_key_source_.reset(ephemeral_key_source);
1217 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1218 StrikeRegisterClient* strike_register_client) {
1219 base::AutoLock locker(strike_register_client_lock_);
1220 DCHECK(!strike_register_client_.get());
1221 strike_register_client_.reset(strike_register_client);
1224 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1225 replay_protection_ = on;
1228 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1229 base::AutoLock locker(strike_register_client_lock_);
1230 DCHECK(!strike_register_client_.get());
1231 strike_register_no_startup_period_ = true;
1234 void QuicCryptoServerConfig::set_strike_register_max_entries(
1235 uint32 max_entries) {
1236 base::AutoLock locker(strike_register_client_lock_);
1237 DCHECK(!strike_register_client_.get());
1238 strike_register_max_entries_ = max_entries;
1241 void QuicCryptoServerConfig::set_strike_register_window_secs(
1242 uint32 window_secs) {
1243 base::AutoLock locker(strike_register_client_lock_);
1244 DCHECK(!strike_register_client_.get());
1245 strike_register_window_secs_ = window_secs;
1248 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1249 uint32 future_secs) {
1250 source_address_token_future_secs_ = future_secs;
1253 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1254 uint32 lifetime_secs) {
1255 source_address_token_lifetime_secs_ = lifetime_secs;
1258 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1259 uint32 max_entries) {
1260 DCHECK(!server_nonce_strike_register_.get());
1261 server_nonce_strike_register_max_entries_ = max_entries;
1264 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1265 uint32 window_secs) {
1266 DCHECK(!server_nonce_strike_register_.get());
1267 server_nonce_strike_register_window_secs_ = window_secs;
1270 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1271 PrimaryConfigChangedCallback* cb) {
1272 base::AutoLock locked(configs_lock_);
1273 primary_config_changed_cb_.reset(cb);
1276 string QuicCryptoServerConfig::NewSourceAddressToken(const Config& config,
1277 const IPEndPoint& ip,
1279 QuicWallTime now) const {
1280 SourceAddressToken source_address_token;
1281 source_address_token.set_ip(IPAddressToPackedString(ip.address()));
1282 source_address_token.set_timestamp(now.ToUNIXSeconds());
1284 return config.source_address_token_boxer->Box(
1285 rand, source_address_token.SerializeAsString());
1288 bool QuicCryptoServerConfig::ValidateSourceAddressToken(
1289 const Config& config,
1291 const IPEndPoint& ip,
1292 QuicWallTime now) const {
1294 StringPiece plaintext;
1295 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1299 SourceAddressToken source_address_token;
1300 if (!source_address_token.ParseFromArray(plaintext.data(),
1301 plaintext.size())) {
1305 if (source_address_token.ip() != IPAddressToPackedString(ip.address())) {
1306 // It's for a different IP address.
1310 const QuicWallTime timestamp(
1311 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1312 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1314 if (now.IsBefore(timestamp) &&
1315 delta.ToSeconds() > source_address_token_future_secs_) {
1319 if (now.IsAfter(timestamp) &&
1320 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1327 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1329 static const size_t kServerNoncePlaintextSize =
1330 4 /* timestamp */ + 20 /* random bytes */;
1332 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1333 QuicWallTime now) const {
1334 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds());
1336 uint8 server_nonce[kServerNoncePlaintextSize];
1337 COMPILE_ASSERT(sizeof(server_nonce) > sizeof(timestamp), nonce_too_small);
1338 server_nonce[0] = static_cast<uint8>(timestamp >> 24);
1339 server_nonce[1] = static_cast<uint8>(timestamp >> 16);
1340 server_nonce[2] = static_cast<uint8>(timestamp >> 8);
1341 server_nonce[3] = static_cast<uint8>(timestamp);
1342 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1343 sizeof(server_nonce) - sizeof(timestamp));
1345 return server_nonce_boxer_.Box(
1347 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
1350 bool QuicCryptoServerConfig::ValidateServerNonce(StringPiece token,
1351 QuicWallTime now) const {
1353 StringPiece plaintext;
1354 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
1358 // plaintext contains:
1360 // uint8[20] random bytes
1362 if (plaintext.size() != kServerNoncePlaintextSize) {
1363 // This should never happen because the value decrypted correctly.
1364 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
1368 uint8 server_nonce[32];
1369 memcpy(server_nonce, plaintext.data(), 4);
1370 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
1371 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
1373 COMPILE_ASSERT(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
1374 bad_nonce_buffer_length);
1378 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
1379 if (server_nonce_strike_register_.get() == NULL) {
1380 server_nonce_strike_register_.reset(new StrikeRegister(
1381 server_nonce_strike_register_max_entries_,
1382 static_cast<uint32>(now.ToUNIXSeconds()),
1383 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
1384 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
1386 is_unique = server_nonce_strike_register_->Insert(
1387 server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
1393 QuicCryptoServerConfig::Config::Config()
1394 : channel_id_enabled(false),
1396 primary_time(QuicWallTime::Zero()),
1398 source_address_token_boxer(NULL) {}
1400 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }