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/channel_id.h"
19 #include "net/quic/crypto/crypto_framer.h"
20 #include "net/quic/crypto/crypto_server_config_protobuf.h"
21 #include "net/quic/crypto/crypto_utils.h"
22 #include "net/quic/crypto/curve25519_key_exchange.h"
23 #include "net/quic/crypto/ephemeral_key_source.h"
24 #include "net/quic/crypto/key_exchange.h"
25 #include "net/quic/crypto/local_strike_register_client.h"
26 #include "net/quic/crypto/p256_key_exchange.h"
27 #include "net/quic/crypto/proof_source.h"
28 #include "net/quic/crypto/quic_decrypter.h"
29 #include "net/quic/crypto/quic_encrypter.h"
30 #include "net/quic/crypto/quic_random.h"
31 #include "net/quic/crypto/source_address_token.h"
32 #include "net/quic/crypto/strike_register.h"
33 #include "net/quic/crypto/strike_register_client.h"
34 #include "net/quic/quic_clock.h"
35 #include "net/quic/quic_protocol.h"
36 #include "net/quic/quic_socket_address_coder.h"
37 #include "net/quic/quic_utils.h"
39 using base::StringPiece;
40 using crypto::SecureHash;
47 // ClientHelloInfo contains information about a client hello message that is
48 // only kept for as long as it's being processed.
49 struct ClientHelloInfo {
50 ClientHelloInfo(const IPEndPoint& in_client_ip, QuicWallTime in_now)
51 : client_ip(in_client_ip),
53 valid_source_address_token(false),
54 client_nonce_well_formed(false),
57 // Inputs to EvaluateClientHello.
58 const IPEndPoint client_ip;
59 const QuicWallTime now;
61 // Outputs from EvaluateClientHello.
62 bool valid_source_address_token;
63 bool client_nonce_well_formed;
66 StringPiece client_nonce;
67 StringPiece server_nonce;
70 struct ValidateClientHelloResultCallback::Result {
71 Result(const CryptoHandshakeMessage& in_client_hello,
72 IPEndPoint in_client_ip,
74 : client_hello(in_client_hello),
75 info(in_client_ip, in_now),
76 error_code(QUIC_NO_ERROR) {
79 CryptoHandshakeMessage client_hello;
81 QuicErrorCode error_code;
85 class ValidateClientHelloHelper {
87 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result,
88 ValidateClientHelloResultCallback* done_cb)
89 : result_(result), done_cb_(done_cb) {
92 ~ValidateClientHelloHelper() {
93 if (done_cb_ != NULL) {
95 "Deleting ValidateClientHelloHelper with a pending callback.";
99 void ValidationComplete(QuicErrorCode error_code, const char* error_details) {
100 result_->error_code = error_code;
101 result_->error_details = error_details;
102 done_cb_->Run(result_);
106 void StartedAsyncCallback() {
111 void DetachCallback() {
112 if (done_cb_ == NULL) {
113 LOG(DFATAL) << "Callback already detached.";
118 ValidateClientHelloResultCallback::Result* result_;
119 ValidateClientHelloResultCallback* done_cb_;
121 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
124 class VerifyNonceIsValidAndUniqueCallback
125 : public StrikeRegisterClient::ResultCallback {
127 VerifyNonceIsValidAndUniqueCallback(
128 ValidateClientHelloResultCallback::Result* result,
129 ValidateClientHelloResultCallback* done_cb)
130 : result_(result), done_cb_(done_cb) {
134 virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE {
135 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique;
136 result_->info.unique = nonce_is_valid_and_unique;
137 done_cb_->Run(result_);
141 ValidateClientHelloResultCallback::Result* result_;
142 ValidateClientHelloResultCallback* done_cb_;
144 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
148 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
151 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {
154 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {
157 void ValidateClientHelloResultCallback::Run(const Result* result) {
158 RunImpl(result->client_hello, *result);
163 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
164 : expiry_time(QuicWallTime::Zero()),
165 channel_id_enabled(false),
168 QuicCryptoServerConfig::QuicCryptoServerConfig(
169 StringPiece source_address_token_secret,
171 : replay_protection_(true),
173 primary_config_(NULL),
174 next_config_promotion_time_(QuicWallTime::Zero()),
175 server_nonce_strike_register_lock_(),
176 strike_register_no_startup_period_(false),
177 strike_register_max_entries_(1 << 10),
178 strike_register_window_secs_(600),
179 source_address_token_future_secs_(3600),
180 source_address_token_lifetime_secs_(86400),
181 server_nonce_strike_register_max_entries_(1 << 10),
182 server_nonce_strike_register_window_secs_(120) {
183 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
184 "QUIC source address token key",
185 CryptoSecretBoxer::GetKeySize(),
186 0 /* no fixed IV needed */);
187 source_address_token_boxer_.SetKey(hkdf.server_write_key());
189 // Generate a random key and orbit for server nonces.
190 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_));
191 const size_t key_size = server_nonce_boxer_.GetKeySize();
192 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]);
193 rand->RandBytes(key_bytes.get(), key_size);
195 server_nonce_boxer_.SetKey(
196 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size));
199 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
200 primary_config_ = NULL;
204 QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig(
206 const QuicClock* clock,
207 const ConfigOptions& options) {
208 CryptoHandshakeMessage msg;
210 const string curve25519_private_key =
211 Curve25519KeyExchange::NewPrivateKey(rand);
212 scoped_ptr<Curve25519KeyExchange> curve25519(
213 Curve25519KeyExchange::New(curve25519_private_key));
214 StringPiece curve25519_public_value = curve25519->public_value();
216 string encoded_public_values;
217 // First three bytes encode the length of the public value.
218 encoded_public_values.push_back(curve25519_public_value.size());
219 encoded_public_values.push_back(curve25519_public_value.size() >> 8);
220 encoded_public_values.push_back(curve25519_public_value.size() >> 16);
221 encoded_public_values.append(curve25519_public_value.data(),
222 curve25519_public_value.size());
224 string p256_private_key;
226 p256_private_key = P256KeyExchange::NewPrivateKey();
227 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
228 StringPiece p256_public_value = p256->public_value();
230 encoded_public_values.push_back(p256_public_value.size());
231 encoded_public_values.push_back(p256_public_value.size() >> 8);
232 encoded_public_values.push_back(p256_public_value.size() >> 16);
233 encoded_public_values.append(p256_public_value.data(),
234 p256_public_value.size());
239 msg.SetTaglist(kKEXS, kC255, kP256, 0);
241 msg.SetTaglist(kKEXS, kC255, 0);
243 msg.SetTaglist(kAEAD, kAESG, 0);
244 // TODO(rch): Remove once we remove QUIC_VERSION_12.
245 msg.SetValue(kVERS, static_cast<uint16>(0));
246 msg.SetStringPiece(kPUBS, encoded_public_values);
248 if (options.expiry_time.IsZero()) {
249 const QuicWallTime now = clock->WallNow();
250 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
251 60 * 60 * 24 * 180 /* 180 days, ~six months */));
252 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
253 msg.SetValue(kEXPY, expiry_seconds);
255 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
258 char orbit_bytes[kOrbitSize];
259 if (options.orbit.size() == sizeof(orbit_bytes)) {
260 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
262 DCHECK(options.orbit.empty());
263 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
265 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
267 if (options.channel_id_enabled) {
268 msg.SetTaglist(kPDMD, kCHID, 0);
271 if (options.id.empty()) {
272 // We need to ensure that the SCID changes whenever the server config does
273 // thus we make it a hash of the rest of the server config.
274 scoped_ptr<QuicData> serialized(
275 CryptoFramer::ConstructHandshakeMessage(msg));
276 scoped_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256));
277 hash->Update(serialized->data(), serialized->length());
280 hash->Finish(scid_bytes, sizeof(scid_bytes));
281 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
283 msg.SetStringPiece(kSCID, options.id);
285 // Don't put new tags below this point. The SCID generation should hash over
286 // everything but itself and so extra tags should be added prior to the
287 // preceeding if block.
289 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
291 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
292 config->set_config(serialized->AsStringPiece());
293 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
294 curve25519_key->set_tag(kC255);
295 curve25519_key->set_private_key(curve25519_private_key);
298 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
299 p256_key->set_tag(kP256);
300 p256_key->set_private_key(p256_private_key);
303 return config.release();
306 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
307 QuicServerConfigProtobuf* protobuf,
308 const QuicWallTime now) {
309 scoped_ptr<CryptoHandshakeMessage> msg(
310 CryptoFramer::ParseMessage(protobuf->config()));
313 LOG(WARNING) << "Failed to parse server config message";
317 scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
319 LOG(WARNING) << "Failed to parse server config message";
324 base::AutoLock locked(configs_lock_);
325 if (configs_.find(config->id) != configs_.end()) {
326 LOG(WARNING) << "Failed to add config because another with the same "
327 "server config id already exists: "
328 << base::HexEncode(config->id.data(), config->id.size());
332 configs_[config->id] = config;
333 SelectNewPrimaryConfig(now);
334 DCHECK(primary_config_.get());
335 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
338 return msg.release();
341 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
343 const QuicClock* clock,
344 const ConfigOptions& options) {
345 scoped_ptr<QuicServerConfigProtobuf> config(
346 GenerateConfig(rand, clock, options));
347 return AddConfig(config.get(), clock->WallNow());
350 bool QuicCryptoServerConfig::SetConfigs(
351 const vector<QuicServerConfigProtobuf*>& protobufs,
352 const QuicWallTime now) {
353 vector<scoped_refptr<Config> > parsed_configs;
356 for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin();
357 i != protobufs.end(); ++i) {
358 scoped_refptr<Config> config(ParseConfigProtobuf(*i));
364 parsed_configs.push_back(config);
367 if (parsed_configs.empty()) {
368 LOG(WARNING) << "New config list is empty.";
373 LOG(WARNING) << "Rejecting QUIC configs because of above errors";
375 VLOG(1) << "Updating configs:";
377 base::AutoLock locked(configs_lock_);
378 ConfigMap new_configs;
380 for (vector<scoped_refptr<Config> >::const_iterator i =
381 parsed_configs.begin();
382 i != parsed_configs.end(); ++i) {
383 scoped_refptr<Config> config = *i;
384 ConfigMap::iterator it = configs_.find(config->id);
385 if (it != configs_.end()) {
387 << "Keeping scid: " << base::HexEncode(
388 config->id.data(), config->id.size())
389 << " orbit: " << base::HexEncode(
390 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
391 << " new primary_time " << config->primary_time.ToUNIXSeconds()
392 << " old primary_time " << it->second->primary_time.ToUNIXSeconds()
393 << " new priority " << config->priority
394 << " old priority " << it->second->priority;
395 // Update primary_time and priority.
396 it->second->primary_time = config->primary_time;
397 it->second->priority = config->priority;
398 new_configs.insert(*it);
400 VLOG(1) << "Adding scid: " << base::HexEncode(
401 config->id.data(), config->id.size())
402 << " orbit: " << base::HexEncode(
403 reinterpret_cast<const char *>(config->orbit), kOrbitSize)
404 << " primary_time " << config->primary_time.ToUNIXSeconds()
405 << " priority " << config->priority;
406 new_configs.insert(make_pair(config->id, config));
410 configs_.swap(new_configs);
411 SelectNewPrimaryConfig(now);
412 DCHECK(primary_config_);
413 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
419 void QuicCryptoServerConfig::ValidateClientHello(
420 const CryptoHandshakeMessage& client_hello,
421 IPEndPoint client_ip,
422 const QuicClock* clock,
423 ValidateClientHelloResultCallback* done_cb) const {
424 const QuicWallTime now(clock->WallNow());
426 ValidateClientHelloResultCallback::Result* result =
427 new ValidateClientHelloResultCallback::Result(
428 client_hello, client_ip, now);
430 uint8 primary_orbit[kOrbitSize];
432 base::AutoLock locked(configs_lock_);
434 if (!primary_config_.get()) {
435 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
436 result->error_details = "No configurations loaded";
438 if (!next_config_promotion_time_.IsZero() &&
439 next_config_promotion_time_.IsAfter(now)) {
440 SelectNewPrimaryConfig(now);
441 DCHECK(primary_config_);
442 DCHECK(configs_.find(primary_config_->id)->second == primary_config_);
445 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit));
449 if (result->error_code == QUIC_NO_ERROR) {
450 EvaluateClientHello(primary_orbit, result, done_cb);
452 done_cb->Run(result);
456 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
457 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
459 IPEndPoint client_address,
461 const QuicVersionVector& supported_versions,
462 const QuicClock* clock,
464 QuicCryptoNegotiatedParameters *params,
465 CryptoHandshakeMessage* out,
466 string* error_details) const {
467 DCHECK(error_details);
469 const CryptoHandshakeMessage& client_hello =
470 validate_chlo_result.client_hello;
471 const ClientHelloInfo& info = validate_chlo_result.info;
473 // If the client's preferred version is not the version we are currently
474 // speaking, then the client went through a version negotiation. In this
475 // case, we need to make sure that we actually do not support this version
476 // and that it wasn't a downgrade attack.
477 QuicTag client_version_tag;
478 // TODO(rch): Make this check mandatory when we remove QUIC_VERSION_12.
479 if (client_hello.GetUint32(kVER, &client_version_tag) == QUIC_NO_ERROR) {
480 QuicVersion client_version = QuicTagToQuicVersion(client_version_tag);
481 if (client_version != version) {
482 // Just because client_version is a valid version enum doesn't mean that
483 // this server actually supports that version, so we check to see if
484 // it's actually in the supported versions list.
485 for (size_t i = 0; i < supported_versions.size(); ++i) {
486 if (client_version == supported_versions[i]) {
487 *error_details = "Downgrade attack detected";
488 return QUIC_VERSION_NEGOTIATION_MISMATCH;
494 StringPiece requested_scid;
495 client_hello.GetStringPiece(kSCID, &requested_scid);
496 const QuicWallTime now(clock->WallNow());
498 scoped_refptr<Config> requested_config;
499 scoped_refptr<Config> primary_config;
501 base::AutoLock locked(configs_lock_);
503 if (!primary_config_.get()) {
504 *error_details = "No configurations loaded";
505 return QUIC_CRYPTO_INTERNAL_ERROR;
508 if (!next_config_promotion_time_.IsZero() &&
509 next_config_promotion_time_.IsAfter(now)) {
510 SelectNewPrimaryConfig(now);
511 DCHECK(primary_config_);
512 DCHECK(configs_.find(primary_config_->id)->second == primary_config_);
515 primary_config = primary_config_;
517 if (!requested_scid.empty()) {
518 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
519 if (it != configs_.end()) {
520 // We'll use the config that the client requested in order to do
521 // key-agreement. Otherwise we'll give it a copy of |primary_config_|
523 requested_config = it->second;
528 if (validate_chlo_result.error_code != QUIC_NO_ERROR) {
529 *error_details = validate_chlo_result.error_details;
530 return validate_chlo_result.error_code;
535 if (!info.valid_source_address_token ||
536 !info.client_nonce_well_formed ||
538 !requested_config.get()) {
539 BuildRejection(primary_config.get(), client_hello, info, rand, out);
540 return QUIC_NO_ERROR;
543 const QuicTag* their_aeads;
544 const QuicTag* their_key_exchanges;
545 size_t num_their_aeads, num_their_key_exchanges;
546 if (client_hello.GetTaglist(kAEAD, &their_aeads,
547 &num_their_aeads) != QUIC_NO_ERROR ||
548 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
549 &num_their_key_exchanges) != QUIC_NO_ERROR ||
550 num_their_aeads != 1 ||
551 num_their_key_exchanges != 1) {
552 *error_details = "Missing or invalid AEAD or KEXS";
553 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
556 size_t key_exchange_index;
557 if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads,
558 num_their_aeads, QuicUtils::LOCAL_PRIORITY,
559 ¶ms->aead, NULL) ||
560 !QuicUtils::FindMutualTag(
561 requested_config->kexs, their_key_exchanges, num_their_key_exchanges,
562 QuicUtils::LOCAL_PRIORITY, ¶ms->key_exchange,
563 &key_exchange_index)) {
564 *error_details = "Unsupported AEAD or KEXS";
565 return QUIC_CRYPTO_NO_SUPPORT;
568 StringPiece public_value;
569 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
570 *error_details = "Missing public value";
571 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
574 const KeyExchange* key_exchange =
575 requested_config->key_exchanges[key_exchange_index];
576 if (!key_exchange->CalculateSharedKey(public_value,
577 ¶ms->initial_premaster_secret)) {
578 *error_details = "Invalid public value";
579 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
582 if (!info.sni.empty()) {
583 scoped_ptr<char[]> sni_tmp(new char[info.sni.length() + 1]);
584 memcpy(sni_tmp.get(), info.sni.data(), info.sni.length());
585 sni_tmp[info.sni.length()] = 0;
586 params->sni = CryptoUtils::NormalizeHostname(sni_tmp.get());
590 const QuicData& client_hello_serialized = client_hello.GetSerialized();
591 hkdf_suffix.reserve(sizeof(guid) + client_hello_serialized.length() +
592 requested_config->serialized.size());
593 hkdf_suffix.append(reinterpret_cast<char*>(&guid), sizeof(guid));
594 hkdf_suffix.append(client_hello_serialized.data(),
595 client_hello_serialized.length());
596 hkdf_suffix.append(requested_config->serialized);
598 StringPiece cetv_ciphertext;
599 if (requested_config->channel_id_enabled &&
600 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
601 CryptoHandshakeMessage client_hello_copy(client_hello);
602 client_hello_copy.Erase(kCETV);
603 client_hello_copy.Erase(kPAD);
605 const QuicData& client_hello_serialized = client_hello_copy.GetSerialized();
607 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
608 strlen(QuicCryptoConfig::kCETVLabel) + 1);
609 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
610 hkdf_input.append(client_hello_serialized.data(),
611 client_hello_serialized.length());
612 hkdf_input.append(requested_config->serialized);
614 CrypterPair crypters;
615 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
616 info.client_nonce, info.server_nonce,
617 hkdf_input, CryptoUtils::SERVER, &crypters)) {
618 *error_details = "Symmetric key setup failed";
619 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
622 scoped_ptr<QuicData> cetv_plaintext(crypters.decrypter->DecryptPacket(
623 0 /* sequence number */, StringPiece() /* associated data */,
625 if (!cetv_plaintext.get()) {
626 *error_details = "CETV decryption failure";
627 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
630 scoped_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
631 cetv_plaintext->AsStringPiece()));
633 *error_details = "CETV parse error";
634 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
637 StringPiece key, signature;
638 if (cetv->GetStringPiece(kCIDK, &key) &&
639 cetv->GetStringPiece(kCIDS, &signature)) {
640 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
641 *error_details = "ChannelID signature failure";
642 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
645 params->channel_id = key.as_string();
650 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
651 hkdf_input.reserve(label_len + hkdf_suffix.size());
652 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
653 hkdf_input.append(hkdf_suffix);
655 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
656 info.client_nonce, info.server_nonce, hkdf_input,
658 ¶ms->initial_crypters)) {
659 *error_details = "Symmetric key setup failed";
660 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
663 string forward_secure_public_value;
664 if (ephemeral_key_source_.get()) {
665 params->forward_secure_premaster_secret =
666 ephemeral_key_source_->CalculateForwardSecureKey(
667 key_exchange, rand, clock->ApproximateNow(), public_value,
668 &forward_secure_public_value);
670 scoped_ptr<KeyExchange> forward_secure_key_exchange(
671 key_exchange->NewKeyPair(rand));
672 forward_secure_public_value =
673 forward_secure_key_exchange->public_value().as_string();
674 if (!forward_secure_key_exchange->CalculateSharedKey(
675 public_value, ¶ms->forward_secure_premaster_secret)) {
676 *error_details = "Invalid public value";
677 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
681 string forward_secure_hkdf_input;
682 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
683 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
684 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
686 forward_secure_hkdf_input.append(hkdf_suffix);
688 if (!CryptoUtils::DeriveKeys(
689 params->forward_secure_premaster_secret, params->aead,
690 info.client_nonce, info.server_nonce, forward_secure_hkdf_input,
691 CryptoUtils::SERVER, ¶ms->forward_secure_crypters)) {
692 *error_details = "Symmetric key setup failed";
693 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
697 QuicTagVector supported_version_tags;
698 for (size_t i = 0; i < supported_versions.size(); ++i) {
699 supported_version_tags.push_back
700 (QuicVersionToQuicTag(supported_versions[i]));
702 out->SetVector(kVER, supported_version_tags);
703 out->SetStringPiece(kSourceAddressTokenTag,
704 NewSourceAddressToken(client_address, rand, info.now));
705 QuicSocketAddressCoder address_coder(client_address);
706 out->SetStringPiece(kCADR, address_coder.Encode());
707 out->SetStringPiece(kPUBS, forward_secure_public_value);
708 return QUIC_NO_ERROR;
711 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
712 // Config's based on their primary_time.
714 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
715 const scoped_refptr<Config>& a,
716 const scoped_refptr<Config>& b) {
717 if (a->primary_time.IsBefore(b->primary_time) ||
718 b->primary_time.IsBefore(a->primary_time)) {
719 // Primary times differ.
720 return a->primary_time.IsBefore(b->primary_time);
721 } else if (a->priority != b->priority) {
722 // Primary times are equal, sort backwards by priority.
723 return a->priority < b->priority;
725 // Primary times and priorities are equal, sort by config id.
726 return a->id < b->id;
730 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
731 const QuicWallTime now) const {
732 vector<scoped_refptr<Config> > configs;
733 configs.reserve(configs_.size());
735 for (ConfigMap::const_iterator it = configs_.begin();
736 it != configs_.end(); ++it) {
737 // TODO(avd) Exclude expired configs?
738 configs.push_back(it->second);
741 if (configs.empty()) {
742 if (primary_config_.get()) {
743 LOG(DFATAL) << "No valid QUIC server config. Keeping the current config.";
745 LOG(DFATAL) << "No valid QUIC server config.";
750 std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
752 Config* best_candidate = configs[0];
754 for (size_t i = 0; i < configs.size(); ++i) {
755 const scoped_refptr<Config> config(configs[i]);
756 if (!config->primary_time.IsAfter(now)) {
757 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
758 best_candidate = config;
763 // This is the first config with a primary_time in the future. Thus the
764 // previous Config should be the primary and this one should determine the
765 // next_config_promotion_time_.
766 scoped_refptr<Config> new_primary(best_candidate);
768 // We need the primary_time of the next config.
769 if (configs.size() > 1) {
770 next_config_promotion_time_ = configs[1]->primary_time;
772 next_config_promotion_time_ = QuicWallTime::Zero();
775 next_config_promotion_time_ = config->primary_time;
778 if (primary_config_.get()) {
779 primary_config_->is_primary = false;
781 primary_config_ = new_primary;
782 new_primary->is_primary = true;
783 DVLOG(1) << "New primary config. orbit: "
785 reinterpret_cast<const char*>(primary_config_->orbit),
791 // All config's primary times are in the past. We should make the most recent
792 // most recent and highest priority candidate primary.
793 scoped_refptr<Config> new_primary(best_candidate);
794 if (primary_config_.get()) {
795 primary_config_->is_primary = false;
797 primary_config_ = new_primary;
798 new_primary->is_primary = true;
799 DVLOG(1) << "New primary config. orbit: "
801 reinterpret_cast<const char*>(primary_config_->orbit),
803 next_config_promotion_time_ = QuicWallTime::Zero();
806 void QuicCryptoServerConfig::EvaluateClientHello(
807 const uint8* primary_orbit,
808 ValidateClientHelloResultCallback::Result* client_hello_state,
809 ValidateClientHelloResultCallback* done_cb) const {
810 ValidateClientHelloHelper helper(client_hello_state, done_cb);
812 const CryptoHandshakeMessage& client_hello =
813 client_hello_state->client_hello;
814 ClientHelloInfo* info = &(client_hello_state->info);
816 if (client_hello.size() < kClientHelloMinimumSizeOld) {
817 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
818 "Client hello too small");
822 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
823 !CryptoUtils::IsValidSNI(info->sni)) {
824 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
830 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) &&
831 ValidateSourceAddressToken(srct, info->client_ip, info->now)) {
832 info->valid_source_address_token = true;
834 // No valid source address token.
835 helper.ValidationComplete(QUIC_NO_ERROR, "");
839 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) &&
840 info->client_nonce.size() == kNonceSize) {
841 info->client_nonce_well_formed = true;
843 // Invalid client nonce.
844 DVLOG(1) << "Invalid client nonce.";
845 helper.ValidationComplete(QUIC_NO_ERROR, "");
849 if (!replay_protection_) {
851 DVLOG(1) << "No replay protection.";
852 helper.ValidationComplete(QUIC_NO_ERROR, "");
856 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
857 if (!info->server_nonce.empty()) {
858 // If the server nonce is present, use it to establish uniqueness.
859 info->unique = ValidateServerNonce(info->server_nonce, info->now);
860 DVLOG(1) << "Using server nonce, unique: " << info->unique;
861 helper.ValidationComplete(QUIC_NO_ERROR, "");
865 // Use the client nonce to establish uniqueness.
866 StrikeRegisterClient* strike_register_client;
868 base::AutoLock locked(strike_register_client_lock_);
870 if (strike_register_client_.get() == NULL) {
871 strike_register_client_.reset(new LocalStrikeRegisterClient(
872 strike_register_max_entries_,
873 static_cast<uint32>(info->now.ToUNIXSeconds()),
874 strike_register_window_secs_,
876 strike_register_no_startup_period_ ?
877 StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
878 StrikeRegister::DENY_REQUESTS_AT_STARTUP));
880 strike_register_client = strike_register_client_.get();
883 strike_register_client->VerifyNonceIsValidAndUnique(
886 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
887 helper.StartedAsyncCallback();
890 void QuicCryptoServerConfig::BuildRejection(
891 const scoped_refptr<Config>& config,
892 const CryptoHandshakeMessage& client_hello,
893 const ClientHelloInfo& info,
895 CryptoHandshakeMessage* out) const {
897 out->SetStringPiece(kSCFG, config->serialized);
898 out->SetStringPiece(kSourceAddressTokenTag,
899 NewSourceAddressToken(info.client_ip, rand, info.now));
900 if (replay_protection_) {
901 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
904 // The client may have requested a certificate chain.
905 const QuicTag* their_proof_demands;
906 size_t num_their_proof_demands;
908 if (proof_source_.get() == NULL ||
909 client_hello.GetTaglist(kPDMD, &their_proof_demands,
910 &num_their_proof_demands) !=
915 bool x509_supported = false, x509_ecdsa_supported = false;
916 for (size_t i = 0; i < num_their_proof_demands; i++) {
917 switch (their_proof_demands[i]) {
919 x509_supported = true;
920 x509_ecdsa_supported = true;
923 x509_supported = true;
928 if (!x509_supported) {
932 const vector<string>* certs;
934 if (!proof_source_->GetProof(info.sni.as_string(), config->serialized,
935 x509_ecdsa_supported, &certs, &signature)) {
939 StringPiece their_common_set_hashes;
940 StringPiece their_cached_cert_hashes;
941 client_hello.GetStringPiece(kCCS, &their_common_set_hashes);
942 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes);
944 const string compressed = CertCompressor::CompressChain(
945 *certs, their_common_set_hashes, their_cached_cert_hashes,
946 config->common_cert_sets);
948 // kREJOverheadBytes is a very rough estimate of how much of a REJ
949 // message is taken up by things other than the certificates.
955 const size_t kREJOverheadBytes = 166;
956 // kMultiplier is the multiple of the CHLO message size that a REJ message
957 // must stay under when the client doesn't present a valid source-address
959 const size_t kMultiplier = 2;
960 // max_unverified_size is the number of bytes that the certificate chain
961 // and signature can consume before we will demand a valid source-address
963 const size_t max_unverified_size =
964 client_hello.size() * kMultiplier - kREJOverheadBytes;
965 COMPILE_ASSERT(kClientHelloMinimumSizeOld * kMultiplier >= kREJOverheadBytes,
966 overhead_calculation_may_underflow);
967 if (info.valid_source_address_token ||
968 signature.size() + compressed.size() < max_unverified_size) {
969 out->SetStringPiece(kCertificateTag, compressed);
970 out->SetStringPiece(kPROF, signature);
974 scoped_refptr<QuicCryptoServerConfig::Config>
975 QuicCryptoServerConfig::ParseConfigProtobuf(
976 QuicServerConfigProtobuf* protobuf) {
977 scoped_ptr<CryptoHandshakeMessage> msg(
978 CryptoFramer::ParseMessage(protobuf->config()));
980 if (msg->tag() != kSCFG) {
981 LOG(WARNING) << "Server config message has tag " << msg->tag()
982 << " expected " << kSCFG;
986 scoped_refptr<Config> config(new Config);
987 config->serialized = protobuf->config();
989 if (protobuf->has_primary_time()) {
990 config->primary_time =
991 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
994 config->priority = protobuf->priority();
997 if (!msg->GetStringPiece(kSCID, &scid)) {
998 LOG(WARNING) << "Server config message is missing SCID";
1001 config->id = scid.as_string();
1003 const QuicTag* aead_tags;
1005 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
1006 LOG(WARNING) << "Server config message is missing AEAD";
1009 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
1011 const QuicTag* kexs_tags;
1013 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
1014 LOG(WARNING) << "Server config message is missing KEXS";
1019 if (!msg->GetStringPiece(kORBT, &orbit)) {
1020 LOG(WARNING) << "Server config message is missing OBIT";
1024 if (orbit.size() != kOrbitSize) {
1025 LOG(WARNING) << "Orbit value in server config is the wrong length."
1026 " Got " << orbit.size() << " want " << kOrbitSize;
1029 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size);
1030 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1033 StrikeRegisterClient* strike_register_client;
1035 base::AutoLock locked(strike_register_client_lock_);
1036 strike_register_client = strike_register_client_.get();
1039 if (strike_register_client != NULL &&
1040 !strike_register_client->IsKnownOrbit(orbit)) {
1042 << "Rejecting server config with orbit that the strike register "
1043 "client doesn't know about.";
1048 if (kexs_len != protobuf->key_size()) {
1049 LOG(WARNING) << "Server config has " << kexs_len
1050 << " key exchange methods configured, but "
1051 << protobuf->key_size() << " private keys";
1055 const QuicTag* proof_demand_tags;
1056 size_t num_proof_demand_tags;
1057 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
1059 for (size_t i = 0; i < num_proof_demand_tags; i++) {
1060 if (proof_demand_tags[i] == kCHID) {
1061 config->channel_id_enabled = true;
1067 for (size_t i = 0; i < kexs_len; i++) {
1068 const QuicTag tag = kexs_tags[i];
1071 config->kexs.push_back(tag);
1073 for (size_t j = 0; j < protobuf->key_size(); j++) {
1074 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1075 if (key.tag() == tag) {
1076 private_key = key.private_key();
1081 if (private_key.empty()) {
1082 LOG(WARNING) << "Server config contains key exchange method without "
1083 "corresponding private key: " << tag;
1087 scoped_ptr<KeyExchange> ka;
1090 ka.reset(Curve25519KeyExchange::New(private_key));
1092 LOG(WARNING) << "Server config contained an invalid curve25519"
1098 ka.reset(P256KeyExchange::New(private_key));
1100 LOG(WARNING) << "Server config contained an invalid P-256"
1106 LOG(WARNING) << "Server config message contains unknown key exchange "
1111 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
1112 i != config->key_exchanges.end(); ++i) {
1113 if ((*i)->tag() == tag) {
1114 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1119 config->key_exchanges.push_back(ka.release());
1125 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
1126 proof_source_.reset(proof_source);
1129 void QuicCryptoServerConfig::SetEphemeralKeySource(
1130 EphemeralKeySource* ephemeral_key_source) {
1131 ephemeral_key_source_.reset(ephemeral_key_source);
1134 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1135 StrikeRegisterClient* strike_register_client) {
1136 base::AutoLock locker(strike_register_client_lock_);
1137 DCHECK(!strike_register_client_.get());
1138 strike_register_client_.reset(strike_register_client);
1141 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1142 replay_protection_ = on;
1145 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1146 base::AutoLock locker(strike_register_client_lock_);
1147 DCHECK(!strike_register_client_.get());
1148 strike_register_no_startup_period_ = true;
1151 void QuicCryptoServerConfig::set_strike_register_max_entries(
1152 uint32 max_entries) {
1153 base::AutoLock locker(strike_register_client_lock_);
1154 DCHECK(!strike_register_client_.get());
1155 strike_register_max_entries_ = max_entries;
1158 void QuicCryptoServerConfig::set_strike_register_window_secs(
1159 uint32 window_secs) {
1160 base::AutoLock locker(strike_register_client_lock_);
1161 DCHECK(!strike_register_client_.get());
1162 strike_register_window_secs_ = window_secs;
1165 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1166 uint32 future_secs) {
1167 source_address_token_future_secs_ = future_secs;
1170 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1171 uint32 lifetime_secs) {
1172 source_address_token_lifetime_secs_ = lifetime_secs;
1175 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1176 uint32 max_entries) {
1177 DCHECK(!server_nonce_strike_register_.get());
1178 server_nonce_strike_register_max_entries_ = max_entries;
1181 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1182 uint32 window_secs) {
1183 DCHECK(!server_nonce_strike_register_.get());
1184 server_nonce_strike_register_window_secs_ = window_secs;
1187 string QuicCryptoServerConfig::NewSourceAddressToken(
1188 const IPEndPoint& ip,
1190 QuicWallTime now) const {
1191 SourceAddressToken source_address_token;
1192 source_address_token.set_ip(IPAddressToPackedString(ip.address()));
1193 source_address_token.set_timestamp(now.ToUNIXSeconds());
1195 return source_address_token_boxer_.Box(
1196 rand, source_address_token.SerializeAsString());
1199 bool QuicCryptoServerConfig::ValidateSourceAddressToken(
1201 const IPEndPoint& ip,
1202 QuicWallTime now) const {
1204 StringPiece plaintext;
1205 if (!source_address_token_boxer_.Unbox(token, &storage, &plaintext)) {
1209 SourceAddressToken source_address_token;
1210 if (!source_address_token.ParseFromArray(plaintext.data(),
1211 plaintext.size())) {
1215 if (source_address_token.ip() != IPAddressToPackedString(ip.address())) {
1216 // It's for a different IP address.
1220 const QuicWallTime timestamp(
1221 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1222 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1224 if (now.IsBefore(timestamp) &&
1225 delta.ToSeconds() > source_address_token_future_secs_) {
1229 if (now.IsAfter(timestamp) &&
1230 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1237 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1239 static const size_t kServerNoncePlaintextSize =
1240 4 /* timestamp */ + 20 /* random bytes */;
1242 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1243 QuicWallTime now) const {
1244 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds());
1246 uint8 server_nonce[kServerNoncePlaintextSize];
1247 COMPILE_ASSERT(sizeof(server_nonce) > sizeof(timestamp), nonce_too_small);
1248 server_nonce[0] = static_cast<uint8>(timestamp >> 24);
1249 server_nonce[1] = static_cast<uint8>(timestamp >> 16);
1250 server_nonce[2] = static_cast<uint8>(timestamp >> 8);
1251 server_nonce[3] = static_cast<uint8>(timestamp);
1252 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1253 sizeof(server_nonce) - sizeof(timestamp));
1255 return server_nonce_boxer_.Box(
1257 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
1260 bool QuicCryptoServerConfig::ValidateServerNonce(StringPiece token,
1261 QuicWallTime now) const {
1263 StringPiece plaintext;
1264 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
1268 // plaintext contains:
1270 // uint8[20] random bytes
1272 if (plaintext.size() != kServerNoncePlaintextSize) {
1273 // This should never happen because the value decrypted correctly.
1274 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
1278 uint8 server_nonce[32];
1279 memcpy(server_nonce, plaintext.data(), 4);
1280 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
1281 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
1283 COMPILE_ASSERT(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
1284 bad_nonce_buffer_length);
1288 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
1289 if (server_nonce_strike_register_.get() == NULL) {
1290 server_nonce_strike_register_.reset(new StrikeRegister(
1291 server_nonce_strike_register_max_entries_,
1292 static_cast<uint32>(now.ToUNIXSeconds()),
1293 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
1294 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
1296 is_unique = server_nonce_strike_register_->Insert(
1297 server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
1303 QuicCryptoServerConfig::Config::Config()
1304 : channel_id_enabled(false),
1306 primary_time(QuicWallTime::Zero()),
1309 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }