blob: 54af8cf90c5a92352a5d0d0e42fdeff251a29fb8 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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.
4
5#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
6
7#include <algorithm>
8#include <cstdlib>
9#include <memory>
vasilvv872e7a32019-03-12 16:42:44 -070010#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "third_party/boringssl/src/include/openssl/sha.h"
13#include "third_party/boringssl/src/include/openssl/ssl.h"
14#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter.h"
15#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.h"
16#include "net/third_party/quiche/src/quic/core/crypto/cert_compressor.h"
17#include "net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter.h"
18#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h"
19#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
20#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
21#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
22#include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h"
23#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
24#include "net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h"
25#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
26#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
27#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
28#include "net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h"
29#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
30#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.pb.h"
31#include "net/third_party/quiche/src/quic/core/proto/source_address_token.pb.h"
32#include "net/third_party/quiche/src/quic/core/quic_packets.h"
33#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
34#include "net/third_party/quiche/src/quic/core/quic_types.h"
35#include "net/third_party/quiche/src/quic/core/quic_utils.h"
36#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
37#include "net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h"
38#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
39#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
40#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
41#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
42#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
43#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
44#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
45#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
46#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050047#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
48#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
49
50namespace quic {
51
52namespace {
53
54// kMultiplier is the multiple of the CHLO message size that a REJ message
55// must stay under when the client doesn't present a valid source-address
56// token. This is used to protect QUIC from amplification attacks.
57// TODO(rch): Reduce this to 2 again once b/25933682 is fixed.
58const size_t kMultiplier = 3;
59
60const int kMaxTokenAddresses = 4;
61
vasilvvc48c8712019-03-11 13:38:16 -070062std::string DeriveSourceAddressTokenKey(
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 QuicStringPiece source_address_token_secret) {
64 QuicHKDF hkdf(source_address_token_secret, QuicStringPiece() /* no salt */,
65 "QUIC source address token key",
66 CryptoSecretBoxer::GetKeySize(), 0 /* no fixed IV needed */,
67 0 /* no subkey secret */);
vasilvvc48c8712019-03-11 13:38:16 -070068 return std::string(hkdf.server_write_key());
QUICHE teama6ef0a62019-03-07 20:34:33 -050069}
70
71// Default source for creating KeyExchange objects.
72class DefaultKeyExchangeSource : public KeyExchangeSource {
73 public:
74 DefaultKeyExchangeSource() = default;
75 ~DefaultKeyExchangeSource() override = default;
76
vasilvvc48c8712019-03-11 13:38:16 -070077 std::unique_ptr<KeyExchange> Create(std::string /*server_config_id*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -050078 QuicTag type,
79 QuicStringPiece private_key) override {
80 if (private_key.empty()) {
81 QUIC_LOG(WARNING) << "Server config contains key exchange method without "
82 "corresponding private key: "
83 << type;
84 return nullptr;
85 }
86
87 std::unique_ptr<KeyExchange> ka;
88 switch (type) {
89 case kC255:
90 ka = Curve25519KeyExchange::New(private_key);
91 if (!ka) {
92 QUIC_LOG(WARNING) << "Server config contained an invalid curve25519"
93 " private key.";
94 return nullptr;
95 }
96 break;
97 case kP256:
98 ka = P256KeyExchange::New(private_key);
99 if (!ka) {
100 QUIC_LOG(WARNING) << "Server config contained an invalid P-256"
101 " private key.";
102 return nullptr;
103 }
104 break;
105 default:
106 QUIC_LOG(WARNING)
107 << "Server config message contains unknown key exchange "
108 "method: "
109 << type;
110 return nullptr;
111 }
112 return ka;
113 }
114};
115
116} // namespace
117
118// static
119std::unique_ptr<KeyExchangeSource> KeyExchangeSource::Default() {
120 return QuicMakeUnique<DefaultKeyExchangeSource>();
121}
122
123class ValidateClientHelloHelper {
124 public:
125 // Note: stores a pointer to a unique_ptr, and std::moves the unique_ptr when
126 // ValidationComplete is called.
127 ValidateClientHelloHelper(
128 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
129 result,
130 std::unique_ptr<ValidateClientHelloResultCallback>* done_cb)
131 : result_(std::move(result)), done_cb_(done_cb) {}
132 ValidateClientHelloHelper(const ValidateClientHelloHelper&) = delete;
133 ValidateClientHelloHelper& operator=(const ValidateClientHelloHelper&) =
134 delete;
135
136 ~ValidateClientHelloHelper() {
137 QUIC_BUG_IF(done_cb_ != nullptr)
138 << "Deleting ValidateClientHelloHelper with a pending callback.";
139 }
140
141 void ValidationComplete(
142 QuicErrorCode error_code,
143 const char* error_details,
144 std::unique_ptr<ProofSource::Details> proof_source_details) {
145 result_->error_code = error_code;
146 result_->error_details = error_details;
147 (*done_cb_)->Run(std::move(result_), std::move(proof_source_details));
148 DetachCallback();
149 }
150
151 void DetachCallback() {
152 QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
153 done_cb_ = nullptr;
154 }
155
156 private:
157 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
158 result_;
159 std::unique_ptr<ValidateClientHelloResultCallback>* done_cb_;
160};
161
162// static
163const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
164
165ClientHelloInfo::ClientHelloInfo(const QuicIpAddress& in_client_ip,
166 QuicWallTime in_now)
167 : client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {}
168
169ClientHelloInfo::ClientHelloInfo(const ClientHelloInfo& other) = default;
170
171ClientHelloInfo::~ClientHelloInfo() {}
172
173PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {}
174
175PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {}
176
177ValidateClientHelloResultCallback::Result::Result(
178 const CryptoHandshakeMessage& in_client_hello,
179 QuicIpAddress in_client_ip,
180 QuicWallTime in_now)
181 : client_hello(in_client_hello),
182 info(in_client_ip, in_now),
183 error_code(QUIC_NO_ERROR) {}
184
185ValidateClientHelloResultCallback::Result::~Result() {}
186
187ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {}
188
189ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {}
190
191ProcessClientHelloResultCallback::ProcessClientHelloResultCallback() {}
192
193ProcessClientHelloResultCallback::~ProcessClientHelloResultCallback() {}
194
195QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
196 : expiry_time(QuicWallTime::Zero()),
197 channel_id_enabled(false),
198 p256(false) {}
199
200QuicCryptoServerConfig::ConfigOptions::ConfigOptions(
201 const ConfigOptions& other) = default;
202
203QuicCryptoServerConfig::ConfigOptions::~ConfigOptions() {}
204
205QuicCryptoServerConfig::QuicCryptoServerConfig(
206 QuicStringPiece source_address_token_secret,
207 QuicRandom* server_nonce_entropy,
208 std::unique_ptr<ProofSource> proof_source,
209 std::unique_ptr<KeyExchangeSource> key_exchange_source,
210 bssl::UniquePtr<SSL_CTX> ssl_ctx)
211 : replay_protection_(true),
212 chlo_multiplier_(kMultiplier),
213 configs_lock_(),
214 primary_config_(nullptr),
215 next_config_promotion_time_(QuicWallTime::Zero()),
216 proof_source_(std::move(proof_source)),
217 key_exchange_source_(std::move(key_exchange_source)),
218 ssl_ctx_(std::move(ssl_ctx)),
219 source_address_token_future_secs_(3600),
220 source_address_token_lifetime_secs_(86400),
221 enable_serving_sct_(false),
222 rejection_observer_(nullptr),
223 pad_rej_(true),
224 pad_shlo_(true),
225 validate_chlo_size_(true),
226 validate_source_address_token_(true) {
227 DCHECK(proof_source_.get());
228 source_address_token_boxer_.SetKeys(
229 {DeriveSourceAddressTokenKey(source_address_token_secret)});
230
231 // Generate a random key and orbit for server nonces.
232 server_nonce_entropy->RandBytes(server_nonce_orbit_,
233 sizeof(server_nonce_orbit_));
234 const size_t key_size = server_nonce_boxer_.GetKeySize();
235 std::unique_ptr<uint8_t[]> key_bytes(new uint8_t[key_size]);
236 server_nonce_entropy->RandBytes(key_bytes.get(), key_size);
237
238 server_nonce_boxer_.SetKeys(
vasilvvc48c8712019-03-11 13:38:16 -0700239 {std::string(reinterpret_cast<char*>(key_bytes.get()), key_size)});
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240}
241
242QuicCryptoServerConfig::~QuicCryptoServerConfig() {}
243
244// static
245std::unique_ptr<QuicServerConfigProtobuf>
246QuicCryptoServerConfig::GenerateConfig(QuicRandom* rand,
247 const QuicClock* clock,
248 const ConfigOptions& options) {
249 CryptoHandshakeMessage msg;
250
vasilvvc48c8712019-03-11 13:38:16 -0700251 const std::string curve25519_private_key =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 Curve25519KeyExchange::NewPrivateKey(rand);
253 std::unique_ptr<Curve25519KeyExchange> curve25519(
254 Curve25519KeyExchange::New(curve25519_private_key));
255 QuicStringPiece curve25519_public_value = curve25519->public_value();
256
vasilvvc48c8712019-03-11 13:38:16 -0700257 std::string encoded_public_values;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 // First three bytes encode the length of the public value.
259 DCHECK_LT(curve25519_public_value.size(), (1U << 24));
260 encoded_public_values.push_back(
261 static_cast<char>(curve25519_public_value.size()));
262 encoded_public_values.push_back(
263 static_cast<char>(curve25519_public_value.size() >> 8));
264 encoded_public_values.push_back(
265 static_cast<char>(curve25519_public_value.size() >> 16));
266 encoded_public_values.append(curve25519_public_value.data(),
267 curve25519_public_value.size());
268
vasilvvc48c8712019-03-11 13:38:16 -0700269 std::string p256_private_key;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500270 if (options.p256) {
271 p256_private_key = P256KeyExchange::NewPrivateKey();
272 std::unique_ptr<P256KeyExchange> p256(
273 P256KeyExchange::New(p256_private_key));
274 QuicStringPiece p256_public_value = p256->public_value();
275
276 DCHECK_LT(p256_public_value.size(), (1U << 24));
277 encoded_public_values.push_back(
278 static_cast<char>(p256_public_value.size()));
279 encoded_public_values.push_back(
280 static_cast<char>(p256_public_value.size() >> 8));
281 encoded_public_values.push_back(
282 static_cast<char>(p256_public_value.size() >> 16));
283 encoded_public_values.append(p256_public_value.data(),
284 p256_public_value.size());
285 }
286
287 msg.set_tag(kSCFG);
288 if (options.p256) {
289 msg.SetVector(kKEXS, QuicTagVector{kC255, kP256});
290 } else {
291 msg.SetVector(kKEXS, QuicTagVector{kC255});
292 }
293 msg.SetVector(kAEAD, QuicTagVector{kAESG, kCC20});
294 msg.SetStringPiece(kPUBS, encoded_public_values);
295
296 if (options.expiry_time.IsZero()) {
297 const QuicWallTime now = clock->WallNow();
298 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
299 60 * 60 * 24 * 180 /* 180 days, ~six months */));
300 const uint64_t expiry_seconds = expiry.ToUNIXSeconds();
301 msg.SetValue(kEXPY, expiry_seconds);
302 } else {
303 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
304 }
305
306 char orbit_bytes[kOrbitSize];
307 if (options.orbit.size() == sizeof(orbit_bytes)) {
308 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
309 } else {
310 DCHECK(options.orbit.empty());
311 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
312 }
313 msg.SetStringPiece(kORBT, QuicStringPiece(orbit_bytes, sizeof(orbit_bytes)));
314
315 if (options.channel_id_enabled) {
316 msg.SetVector(kPDMD, QuicTagVector{kCHID});
317 }
318
319 if (!options.token_binding_params.empty()) {
320 msg.SetVector(kTBKP, options.token_binding_params);
321 }
322
323 if (options.id.empty()) {
324 // We need to ensure that the SCID changes whenever the server config does
325 // thus we make it a hash of the rest of the server config.
QUICHE team3fe6a8b2019-03-14 09:10:38 -0700326 std::unique_ptr<QuicData> serialized =
327 CryptoFramer::ConstructHandshakeMessage(msg);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500328
329 uint8_t scid_bytes[SHA256_DIGEST_LENGTH];
330 SHA256(reinterpret_cast<const uint8_t*>(serialized->data()),
331 serialized->length(), scid_bytes);
332 // The SCID is a truncated SHA-256 digest.
333 static_assert(16 <= SHA256_DIGEST_LENGTH, "SCID length too high.");
334 msg.SetStringPiece(
335 kSCID, QuicStringPiece(reinterpret_cast<const char*>(scid_bytes), 16));
336 } else {
337 msg.SetStringPiece(kSCID, options.id);
338 }
339 // Don't put new tags below this point. The SCID generation should hash over
340 // everything but itself and so extra tags should be added prior to the
341 // preceding if block.
342
QUICHE team3fe6a8b2019-03-14 09:10:38 -0700343 std::unique_ptr<QuicData> serialized =
344 CryptoFramer::ConstructHandshakeMessage(msg);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500345
QUICHE teamea5bdef2019-03-13 15:41:27 -0700346 auto config = QuicMakeUnique<QuicServerConfigProtobuf>();
vasilvvc48c8712019-03-11 13:38:16 -0700347 config->set_config(std::string(serialized->AsStringPiece()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500348 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
349 curve25519_key->set_tag(kC255);
350 curve25519_key->set_private_key(curve25519_private_key);
351
352 if (options.p256) {
353 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
354 p256_key->set_tag(kP256);
355 p256_key->set_private_key(p256_private_key);
356 }
357
358 return config;
359}
360
361CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
362 std::unique_ptr<QuicServerConfigProtobuf> protobuf,
363 const QuicWallTime now) {
364 std::unique_ptr<CryptoHandshakeMessage> msg(
365 CryptoFramer::ParseMessage(protobuf->config()));
366
367 if (!msg.get()) {
368 QUIC_LOG(WARNING) << "Failed to parse server config message";
369 return nullptr;
370 }
371
372 QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
373 if (!config.get()) {
374 QUIC_LOG(WARNING) << "Failed to parse server config message";
375 return nullptr;
376 }
377
378 {
379 QuicWriterMutexLock locked(&configs_lock_);
380 if (configs_.find(config->id) != configs_.end()) {
381 QUIC_LOG(WARNING) << "Failed to add config because another with the same "
382 "server config id already exists: "
383 << QuicTextUtils::HexEncode(config->id);
384 return nullptr;
385 }
386
387 configs_[config->id] = config;
388 SelectNewPrimaryConfig(now);
389 DCHECK(primary_config_.get());
390 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
391 primary_config_.get());
392 }
393
394 return msg.release();
395}
396
397CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
398 QuicRandom* rand,
399 const QuicClock* clock,
400 const ConfigOptions& options) {
401 return AddConfig(GenerateConfig(rand, clock, options), clock->WallNow());
402}
403
404bool QuicCryptoServerConfig::SetConfigs(
405 const std::vector<std::unique_ptr<QuicServerConfigProtobuf>>& protobufs,
406 const QuicWallTime now) {
407 std::vector<QuicReferenceCountedPointer<Config>> parsed_configs;
408 bool ok = true;
409
410 for (auto& protobuf : protobufs) {
411 QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
412 if (!config) {
413 ok = false;
414 break;
415 }
416
417 parsed_configs.push_back(config);
418 }
419
420 if (parsed_configs.empty()) {
421 QUIC_LOG(WARNING) << "New config list is empty.";
422 ok = false;
423 }
424
425 if (!ok) {
426 QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
427 } else {
428 QUIC_LOG(INFO) << "Updating configs:";
429
430 QuicWriterMutexLock locked(&configs_lock_);
431 ConfigMap new_configs;
432
433 for (std::vector<QuicReferenceCountedPointer<Config>>::const_iterator i =
434 parsed_configs.begin();
435 i != parsed_configs.end(); ++i) {
436 QuicReferenceCountedPointer<Config> config = *i;
437
438 auto it = configs_.find(config->id);
439 if (it != configs_.end()) {
440 QUIC_LOG(INFO) << "Keeping scid: "
441 << QuicTextUtils::HexEncode(config->id) << " orbit: "
442 << QuicTextUtils::HexEncode(
443 reinterpret_cast<const char*>(config->orbit),
444 kOrbitSize)
445 << " new primary_time "
446 << config->primary_time.ToUNIXSeconds()
447 << " old primary_time "
448 << it->second->primary_time.ToUNIXSeconds()
449 << " new priority " << config->priority
450 << " old priority " << it->second->priority;
451 // Update primary_time and priority.
452 it->second->primary_time = config->primary_time;
453 it->second->priority = config->priority;
454 new_configs.insert(*it);
455 } else {
456 QUIC_LOG(INFO) << "Adding scid: "
457 << QuicTextUtils::HexEncode(config->id) << " orbit: "
458 << QuicTextUtils::HexEncode(
459 reinterpret_cast<const char*>(config->orbit),
460 kOrbitSize)
461 << " primary_time "
462 << config->primary_time.ToUNIXSeconds() << " priority "
463 << config->priority;
464 new_configs.insert(std::make_pair(config->id, config));
465 }
466 }
467
468 configs_.swap(new_configs);
469 SelectNewPrimaryConfig(now);
470 DCHECK(primary_config_.get());
471 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
472 primary_config_.get());
473 }
474
475 return ok;
476}
477
478void QuicCryptoServerConfig::SetSourceAddressTokenKeys(
vasilvvc48c8712019-03-11 13:38:16 -0700479 const std::vector<std::string>& keys) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500480 source_address_token_boxer_.SetKeys(keys);
481}
482
483void QuicCryptoServerConfig::GetConfigIds(
vasilvvc48c8712019-03-11 13:38:16 -0700484 std::vector<std::string>* scids) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500485 QuicReaderMutexLock locked(&configs_lock_);
486 for (auto it = configs_.begin(); it != configs_.end(); ++it) {
487 scids->push_back(it->first);
488 }
489}
490
491void QuicCryptoServerConfig::ValidateClientHello(
492 const CryptoHandshakeMessage& client_hello,
493 const QuicIpAddress& client_ip,
494 const QuicSocketAddress& server_address,
495 QuicTransportVersion version,
496 const QuicClock* clock,
497 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
498 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
499 const QuicWallTime now(clock->WallNow());
500
501 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result(
502 new ValidateClientHelloResultCallback::Result(client_hello, client_ip,
503 now));
504
505 QuicStringPiece requested_scid;
506 client_hello.GetStringPiece(kSCID, &requested_scid);
507
508 QuicReferenceCountedPointer<Config> requested_config;
509 QuicReferenceCountedPointer<Config> primary_config;
510 {
511 QuicReaderMutexLock locked(&configs_lock_);
512 if (!primary_config_.get()) {
513 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
514 result->error_details = "No configurations loaded";
515 } else {
516 if (IsNextConfigReady(now)) {
517 configs_lock_.ReaderUnlock();
518 configs_lock_.WriterLock();
519 SelectNewPrimaryConfig(now);
520 DCHECK(primary_config_.get());
521 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
522 primary_config_.get());
523 configs_lock_.WriterUnlock();
524 configs_lock_.ReaderLock();
525 }
526 }
527
528 requested_config = GetConfigWithScid(requested_scid);
529 primary_config = primary_config_;
530 signed_config->config = primary_config_;
531 }
532
533 if (result->error_code == QUIC_NO_ERROR) {
534 // QUIC requires a new proof for each CHLO so clear any existing proof.
535 signed_config->chain = nullptr;
536 signed_config->proof.signature = "";
537 signed_config->proof.leaf_cert_scts = "";
538 EvaluateClientHello(server_address, version, requested_config,
539 primary_config, signed_config, result,
540 std::move(done_cb));
541 } else {
542 done_cb->Run(result, /* details = */ nullptr);
543 }
544}
545
546class ProcessClientHelloHelper {
547 public:
548 explicit ProcessClientHelloHelper(
549 std::unique_ptr<ProcessClientHelloResultCallback>* done_cb)
550 : done_cb_(done_cb) {}
551
552 ~ProcessClientHelloHelper() {
553 QUIC_BUG_IF(done_cb_ != nullptr)
554 << "Deleting ProcessClientHelloHelper with a pending callback.";
555 }
556
vasilvvc48c8712019-03-11 13:38:16 -0700557 void Fail(QuicErrorCode error, const std::string& error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500558 (*done_cb_)->Run(error, error_details, nullptr, nullptr, nullptr);
559 DetachCallback();
560 }
561
562 void Succeed(std::unique_ptr<CryptoHandshakeMessage> message,
563 std::unique_ptr<DiversificationNonce> diversification_nonce,
564 std::unique_ptr<ProofSource::Details> proof_source_details) {
vasilvvc48c8712019-03-11 13:38:16 -0700565 (*done_cb_)->Run(QUIC_NO_ERROR, std::string(), std::move(message),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500566 std::move(diversification_nonce),
567 std::move(proof_source_details));
568 DetachCallback();
569 }
570
571 void DetachCallback() {
572 QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
573 done_cb_ = nullptr;
574 }
575
576 private:
577 std::unique_ptr<ProcessClientHelloResultCallback>* done_cb_;
578};
579
580class QuicCryptoServerConfig::ProcessClientHelloCallback
581 : public ProofSource::Callback {
582 public:
583 ProcessClientHelloCallback(
584 const QuicCryptoServerConfig* config,
585 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
586 validate_chlo_result,
587 bool reject_only,
588 QuicConnectionId connection_id,
589 const QuicSocketAddress& client_address,
590 ParsedQuicVersion version,
591 const ParsedQuicVersionVector& supported_versions,
592 bool use_stateless_rejects,
593 QuicConnectionId server_designated_connection_id,
594 const QuicClock* clock,
595 QuicRandom* rand,
596 QuicCompressedCertsCache* compressed_certs_cache,
597 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
598 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
599 QuicByteCount total_framing_overhead,
600 QuicByteCount chlo_packet_size,
601 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
602 requested_config,
603 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
604 primary_config,
605 std::unique_ptr<ProcessClientHelloResultCallback> done_cb)
606 : config_(config),
607 validate_chlo_result_(std::move(validate_chlo_result)),
608 reject_only_(reject_only),
609 connection_id_(connection_id),
610 client_address_(client_address),
611 version_(version),
612 supported_versions_(supported_versions),
613 use_stateless_rejects_(use_stateless_rejects),
614 server_designated_connection_id_(server_designated_connection_id),
615 clock_(clock),
616 rand_(rand),
617 compressed_certs_cache_(compressed_certs_cache),
618 params_(params),
619 signed_config_(signed_config),
620 total_framing_overhead_(total_framing_overhead),
621 chlo_packet_size_(chlo_packet_size),
622 requested_config_(requested_config),
623 primary_config_(primary_config),
624 done_cb_(std::move(done_cb)) {}
625
626 void Run(bool ok,
627 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
628 const QuicCryptoProof& proof,
629 std::unique_ptr<ProofSource::Details> details) override {
630 if (ok) {
631 signed_config_->chain = chain;
632 signed_config_->proof = proof;
633 }
634 config_->ProcessClientHelloAfterGetProof(
635 !ok, std::move(details), validate_chlo_result_, reject_only_,
636 connection_id_, client_address_, version_, supported_versions_,
637 use_stateless_rejects_, server_designated_connection_id_, clock_, rand_,
638 compressed_certs_cache_, params_, signed_config_,
639 total_framing_overhead_, chlo_packet_size_, requested_config_,
640 primary_config_, std::move(done_cb_));
641 }
642
643 private:
644 const QuicCryptoServerConfig* config_;
645 const QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
646 validate_chlo_result_;
647 const bool reject_only_;
648 const QuicConnectionId connection_id_;
649 const QuicSocketAddress client_address_;
650 const ParsedQuicVersion version_;
651 const ParsedQuicVersionVector supported_versions_;
652 const bool use_stateless_rejects_;
653 const QuicConnectionId server_designated_connection_id_;
654 const QuicClock* const clock_;
655 QuicRandom* const rand_;
656 QuicCompressedCertsCache* compressed_certs_cache_;
657 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
658 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
659 const QuicByteCount total_framing_overhead_;
660 const QuicByteCount chlo_packet_size_;
661 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
662 requested_config_;
663 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
664 primary_config_;
665 std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
666};
667
668class QuicCryptoServerConfig::ProcessClientHelloAfterGetProofCallback
669 : public KeyExchange::Callback {
670 public:
671 ProcessClientHelloAfterGetProofCallback(
672 const QuicCryptoServerConfig* config,
673 std::unique_ptr<ProofSource::Details> proof_source_details,
674 const KeyExchange::Factory& key_exchange_factory,
675 std::unique_ptr<CryptoHandshakeMessage> out,
676 QuicStringPiece public_value,
677 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
678 validate_chlo_result,
679 QuicConnectionId connection_id,
680 const QuicSocketAddress& client_address,
681 ParsedQuicVersion version,
682 const ParsedQuicVersionVector& supported_versions,
683 const QuicClock* clock,
684 QuicRandom* rand,
685 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
686 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
687 const QuicReferenceCountedPointer<Config>& requested_config,
688 const QuicReferenceCountedPointer<Config>& primary_config,
689 std::unique_ptr<ProcessClientHelloResultCallback> done_cb)
690 : config_(config),
691 proof_source_details_(std::move(proof_source_details)),
692 key_exchange_factory_(key_exchange_factory),
693 out_(std::move(out)),
694 public_value_(public_value),
695 validate_chlo_result_(std::move(validate_chlo_result)),
696 connection_id_(connection_id),
697 client_address_(client_address),
698 version_(version),
699 supported_versions_(supported_versions),
700 clock_(clock),
701 rand_(rand),
702 params_(params),
703 signed_config_(signed_config),
704 requested_config_(requested_config),
705 primary_config_(primary_config),
706 done_cb_(std::move(done_cb)) {}
707
708 void Run(bool ok) override {
709 config_->ProcessClientHelloAfterCalculateSharedKeys(
710 !ok, std::move(proof_source_details_), key_exchange_factory_,
711 std::move(out_), public_value_, *validate_chlo_result_, connection_id_,
712 client_address_, version_, supported_versions_, clock_, rand_, params_,
713 signed_config_, requested_config_, primary_config_,
714 std::move(done_cb_));
715 }
716
717 private:
718 const QuicCryptoServerConfig* config_;
719 std::unique_ptr<ProofSource::Details> proof_source_details_;
720 const KeyExchange::Factory& key_exchange_factory_;
721 std::unique_ptr<CryptoHandshakeMessage> out_;
vasilvvc48c8712019-03-11 13:38:16 -0700722 std::string public_value_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500723 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
724 validate_chlo_result_;
725 QuicConnectionId connection_id_;
726 const QuicSocketAddress client_address_;
727 ParsedQuicVersion version_;
728 const ParsedQuicVersionVector supported_versions_;
729 const QuicClock* clock_;
730 QuicRandom* rand_;
731 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
732 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
733 const QuicReferenceCountedPointer<Config> requested_config_;
734 const QuicReferenceCountedPointer<Config> primary_config_;
735 std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
736};
737
738void QuicCryptoServerConfig::ProcessClientHello(
739 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
740 validate_chlo_result,
741 bool reject_only,
742 QuicConnectionId connection_id,
743 const QuicSocketAddress& server_address,
744 const QuicSocketAddress& client_address,
745 ParsedQuicVersion version,
746 const ParsedQuicVersionVector& supported_versions,
747 bool use_stateless_rejects,
748 QuicConnectionId server_designated_connection_id,
749 const QuicClock* clock,
750 QuicRandom* rand,
751 QuicCompressedCertsCache* compressed_certs_cache,
752 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
753 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
754 QuicByteCount total_framing_overhead,
755 QuicByteCount chlo_packet_size,
756 std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
757 DCHECK(done_cb);
758
759 ProcessClientHelloHelper helper(&done_cb);
760
761 const CryptoHandshakeMessage& client_hello =
762 validate_chlo_result->client_hello;
763 const ClientHelloInfo& info = validate_chlo_result->info;
764
vasilvvc48c8712019-03-11 13:38:16 -0700765 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500766 QuicErrorCode valid = CryptoUtils::ValidateClientHello(
767 client_hello, version, supported_versions, &error_details);
768 if (valid != QUIC_NO_ERROR) {
769 helper.Fail(valid, error_details);
770 return;
771 }
772
773 QuicStringPiece requested_scid;
774 client_hello.GetStringPiece(kSCID, &requested_scid);
775 const QuicWallTime now(clock->WallNow());
776
777 QuicReferenceCountedPointer<Config> requested_config;
778 QuicReferenceCountedPointer<Config> primary_config;
779 bool no_primary_config = false;
780 {
781 QuicReaderMutexLock locked(&configs_lock_);
782
783 if (!primary_config_) {
784 no_primary_config = true;
785 } else {
786 if (IsNextConfigReady(now)) {
787 configs_lock_.ReaderUnlock();
788 configs_lock_.WriterLock();
789 SelectNewPrimaryConfig(now);
790 DCHECK(primary_config_.get());
791 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
792 primary_config_.get());
793 configs_lock_.WriterUnlock();
794 configs_lock_.ReaderLock();
795 }
796
797 // Use the config that the client requested in order to do key-agreement.
798 // Otherwise give it a copy of |primary_config_| to use.
799 primary_config = signed_config->config;
800 requested_config = GetConfigWithScid(requested_scid);
801 }
802 }
803 if (no_primary_config) {
804 helper.Fail(QUIC_CRYPTO_INTERNAL_ERROR, "No configurations loaded");
805 return;
806 }
807
808 if (validate_chlo_result->error_code != QUIC_NO_ERROR) {
809 helper.Fail(validate_chlo_result->error_code,
810 validate_chlo_result->error_details);
811 return;
812 }
813
814 if (!ClientDemandsX509Proof(client_hello)) {
815 helper.Fail(QUIC_UNSUPPORTED_PROOF_DEMAND, "Missing or invalid PDMD");
816 return;
817 }
818 DCHECK(proof_source_.get());
vasilvvc48c8712019-03-11 13:38:16 -0700819 std::string chlo_hash;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500820 CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash,
821 Perspective::IS_SERVER);
822
823 // No need to get a new proof if one was already generated.
824 if (!signed_config->chain) {
QUICHE teamea5bdef2019-03-13 15:41:27 -0700825 auto cb = QuicMakeUnique<ProcessClientHelloCallback>(
826 this, validate_chlo_result, reject_only, connection_id, client_address,
827 version, supported_versions, use_stateless_rejects,
828 server_designated_connection_id, clock, rand, compressed_certs_cache,
829 params, signed_config, total_framing_overhead, chlo_packet_size,
830 requested_config, primary_config, std::move(done_cb));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500831 proof_source_->GetProof(
vasilvvc48c8712019-03-11 13:38:16 -0700832 server_address, std::string(info.sni), primary_config->serialized,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500833 version.transport_version, chlo_hash, std::move(cb));
834 helper.DetachCallback();
835 return;
836 }
837
838 helper.DetachCallback();
839 ProcessClientHelloAfterGetProof(
840 /* found_error = */ false, /* proof_source_details = */ nullptr,
841 validate_chlo_result, reject_only, connection_id, client_address, version,
842 supported_versions, use_stateless_rejects,
843 server_designated_connection_id, clock, rand, compressed_certs_cache,
844 params, signed_config, total_framing_overhead, chlo_packet_size,
845 requested_config, primary_config, std::move(done_cb));
846}
847
848void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
849 bool found_error,
850 std::unique_ptr<ProofSource::Details> proof_source_details,
851 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
852 validate_chlo_result,
853 bool reject_only,
854 QuicConnectionId connection_id,
855 const QuicSocketAddress& client_address,
856 ParsedQuicVersion version,
857 const ParsedQuicVersionVector& supported_versions,
858 bool use_stateless_rejects,
859 QuicConnectionId server_designated_connection_id,
860 const QuicClock* clock,
861 QuicRandom* rand,
862 QuicCompressedCertsCache* compressed_certs_cache,
863 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
864 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
865 QuicByteCount total_framing_overhead,
866 QuicByteCount chlo_packet_size,
867 const QuicReferenceCountedPointer<Config>& requested_config,
868 const QuicReferenceCountedPointer<Config>& primary_config,
869 std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
870 QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
871 connection_id, version.transport_version))
872 << "ProcessClientHelloAfterGetProof: attempted to use connection ID "
873 << connection_id << " which is invalid with version "
874 << QuicVersionToString(version.transport_version);
875 ProcessClientHelloHelper helper(&done_cb);
876
877 if (found_error) {
878 helper.Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
879 return;
880 }
881
882 const CryptoHandshakeMessage& client_hello =
883 validate_chlo_result->client_hello;
884 const ClientHelloInfo& info = validate_chlo_result->info;
QUICHE teamea5bdef2019-03-13 15:41:27 -0700885 auto out_diversification_nonce = QuicMakeUnique<DiversificationNonce>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500886
887 QuicStringPiece cert_sct;
888 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) &&
889 cert_sct.empty()) {
890 params->sct_supported_by_client = true;
891 }
892
QUICHE teamea5bdef2019-03-13 15:41:27 -0700893 auto out = QuicMakeUnique<CryptoHandshakeMessage>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500894 if (!info.reject_reasons.empty() || !requested_config.get()) {
895 BuildRejection(version.transport_version, clock->WallNow(), *primary_config,
896 client_hello, info,
897 validate_chlo_result->cached_network_params,
898 use_stateless_rejects, server_designated_connection_id, rand,
899 compressed_certs_cache, params, *signed_config,
900 total_framing_overhead, chlo_packet_size, out.get());
901 if (rejection_observer_ != nullptr) {
902 rejection_observer_->OnRejectionBuilt(info.reject_reasons, out.get());
903 }
904 helper.Succeed(std::move(out), std::move(out_diversification_nonce),
905 std::move(proof_source_details));
906 return;
907 }
908
909 if (reject_only) {
910 helper.Succeed(std::move(out), std::move(out_diversification_nonce),
911 std::move(proof_source_details));
912 return;
913 }
914
915 QuicTagVector their_aeads;
916 QuicTagVector their_key_exchanges;
917 if (client_hello.GetTaglist(kAEAD, &their_aeads) != QUIC_NO_ERROR ||
918 client_hello.GetTaglist(kKEXS, &their_key_exchanges) != QUIC_NO_ERROR ||
919 their_aeads.size() != 1 || their_key_exchanges.size() != 1) {
920 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
921 "Missing or invalid AEAD or KEXS");
922 return;
923 }
924
925 size_t key_exchange_index;
926 if (!FindMutualQuicTag(requested_config->aead, their_aeads, &params->aead,
927 nullptr) ||
928 !FindMutualQuicTag(requested_config->kexs, their_key_exchanges,
929 &params->key_exchange, &key_exchange_index)) {
930 helper.Fail(QUIC_CRYPTO_NO_SUPPORT, "Unsupported AEAD or KEXS");
931 return;
932 }
933
934 if (!requested_config->tb_key_params.empty()) {
935 QuicTagVector their_tbkps;
936 switch (client_hello.GetTaglist(kTBKP, &their_tbkps)) {
937 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
938 break;
939 case QUIC_NO_ERROR:
940 if (FindMutualQuicTag(requested_config->tb_key_params, their_tbkps,
941 &params->token_binding_key_param, nullptr)) {
942 break;
943 }
944 QUIC_FALLTHROUGH_INTENDED;
945 default:
946 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
947 "Invalid Token Binding key parameter");
948 return;
949 }
950 }
951
952 QuicStringPiece public_value;
953 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
954 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Missing public value");
955 return;
956 }
957
958 const KeyExchange* key_exchange =
959 requested_config->key_exchanges[key_exchange_index].get();
960 // TODO(rch): Would it be better to implement a move operator and just
961 // std::move(helper) instead of done_cb?
962 helper.DetachCallback();
963 auto cb = QuicMakeUnique<ProcessClientHelloAfterGetProofCallback>(
964 this, std::move(proof_source_details), key_exchange->GetFactory(),
965 std::move(out), public_value, validate_chlo_result, connection_id,
966 client_address, version, supported_versions, clock, rand, params,
967 signed_config, requested_config, primary_config, std::move(done_cb));
968 key_exchange->CalculateSharedKey(
969 public_value, &params->initial_premaster_secret, std::move(cb));
970}
971
972void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
973 bool found_error,
974 std::unique_ptr<ProofSource::Details> proof_source_details,
975 const KeyExchange::Factory& key_exchange_factory,
976 std::unique_ptr<CryptoHandshakeMessage> out,
977 QuicStringPiece public_value,
978 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
979 QuicConnectionId connection_id,
980 const QuicSocketAddress& client_address,
981 ParsedQuicVersion version,
982 const ParsedQuicVersionVector& supported_versions,
983 const QuicClock* clock,
984 QuicRandom* rand,
985 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
986 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
987 const QuicReferenceCountedPointer<Config>& requested_config,
988 const QuicReferenceCountedPointer<Config>& primary_config,
989 std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
990 QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
991 connection_id, version.transport_version))
992 << "ProcessClientHelloAfterCalculateSharedKeys:"
993 " attempted to use connection ID "
994 << connection_id << " which is invalid with version "
995 << QuicVersionToString(version.transport_version);
996 ProcessClientHelloHelper helper(&done_cb);
997
998 if (found_error) {
999 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Invalid public value");
1000 return;
1001 }
1002
1003 const CryptoHandshakeMessage& client_hello =
1004 validate_chlo_result.client_hello;
1005 const ClientHelloInfo& info = validate_chlo_result.info;
1006 auto out_diversification_nonce = QuicMakeUnique<DiversificationNonce>();
1007
1008 if (!info.sni.empty()) {
1009 params->sni = QuicHostnameUtils::NormalizeHostname(info.sni);
1010 }
1011
vasilvvc48c8712019-03-11 13:38:16 -07001012 std::string hkdf_suffix;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001013 const QuicData& client_hello_serialized = client_hello.GetSerialized();
vasilvvc48c8712019-03-11 13:38:16 -07001014 hkdf_suffix.reserve(connection_id.length() +
1015 client_hello_serialized.length() +
1016 requested_config->serialized.size());
1017 hkdf_suffix.append(connection_id.data(), connection_id.length());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001018 hkdf_suffix.append(client_hello_serialized.data(),
1019 client_hello_serialized.length());
1020 hkdf_suffix.append(requested_config->serialized);
1021 DCHECK(proof_source_.get());
1022 if (signed_config->chain->certs.empty()) {
1023 helper.Fail(QUIC_CRYPTO_INTERNAL_ERROR, "Failed to get certs");
1024 return;
1025 }
1026 hkdf_suffix.append(signed_config->chain->certs.at(0));
1027
1028 QuicStringPiece cetv_ciphertext;
1029 if (requested_config->channel_id_enabled &&
1030 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
1031 CryptoHandshakeMessage client_hello_copy(client_hello);
1032 client_hello_copy.Erase(kCETV);
1033 client_hello_copy.Erase(kPAD);
1034
1035 const QuicData& client_hello_copy_serialized =
1036 client_hello_copy.GetSerialized();
vasilvvc48c8712019-03-11 13:38:16 -07001037 std::string hkdf_input;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001038 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
1039 strlen(QuicCryptoConfig::kCETVLabel) + 1);
1040 hkdf_input.append(connection_id.data(), connection_id.length());
1041 hkdf_input.append(client_hello_copy_serialized.data(),
1042 client_hello_copy_serialized.length());
1043 hkdf_input.append(requested_config->serialized);
1044
1045 CrypterPair crypters;
1046 if (!CryptoUtils::DeriveKeys(
1047 params->initial_premaster_secret, params->aead, info.client_nonce,
1048 info.server_nonce, pre_shared_key_, hkdf_input,
1049 Perspective::IS_SERVER, CryptoUtils::Diversification::Never(),
1050 &crypters, nullptr /* subkey secret */)) {
1051 helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
1052 "Symmetric key setup failed");
1053 return;
1054 }
1055
1056 char plaintext[kMaxPacketSize];
1057 size_t plaintext_length = 0;
1058 const bool success = crypters.decrypter->DecryptPacket(
1059 0 /* packet number */, QuicStringPiece() /* associated data */,
1060 cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
1061 if (!success) {
1062 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1063 "CETV decryption failure");
1064 return;
1065 }
1066 std::unique_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
1067 QuicStringPiece(plaintext, plaintext_length)));
1068 if (!cetv.get()) {
1069 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "CETV parse error");
1070 return;
1071 }
1072
1073 QuicStringPiece key, signature;
1074 if (cetv->GetStringPiece(kCIDK, &key) &&
1075 cetv->GetStringPiece(kCIDS, &signature)) {
1076 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
1077 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1078 "ChannelID signature failure");
1079 return;
1080 }
1081
vasilvvc48c8712019-03-11 13:38:16 -07001082 params->channel_id = std::string(key);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001083 }
1084 }
1085
vasilvvc48c8712019-03-11 13:38:16 -07001086 std::string hkdf_input;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001087 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
1088 hkdf_input.reserve(label_len + hkdf_suffix.size());
1089 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
1090 hkdf_input.append(hkdf_suffix);
1091
1092 rand->RandBytes(out_diversification_nonce->data(),
1093 out_diversification_nonce->size());
1094 CryptoUtils::Diversification diversification =
1095 CryptoUtils::Diversification::Now(out_diversification_nonce.get());
1096 if (!CryptoUtils::DeriveKeys(
1097 params->initial_premaster_secret, params->aead, info.client_nonce,
1098 info.server_nonce, pre_shared_key_, hkdf_input,
1099 Perspective::IS_SERVER, diversification, &params->initial_crypters,
1100 &params->initial_subkey_secret)) {
1101 helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
1102 "Symmetric key setup failed");
1103 return;
1104 }
1105
vasilvvc48c8712019-03-11 13:38:16 -07001106 std::string forward_secure_public_value;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001107 std::unique_ptr<KeyExchange> forward_secure_key_exchange =
1108 key_exchange_factory.Create(rand);
1109 forward_secure_public_value =
vasilvvc48c8712019-03-11 13:38:16 -07001110 std::string(forward_secure_key_exchange->public_value());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001111 if (!forward_secure_key_exchange->CalculateSharedKey(
1112 public_value, &params->forward_secure_premaster_secret)) {
1113 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Invalid public value");
1114 return;
1115 }
1116
vasilvvc48c8712019-03-11 13:38:16 -07001117 std::string forward_secure_hkdf_input;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001118 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
1119 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
1120 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
1121 label_len);
1122 forward_secure_hkdf_input.append(hkdf_suffix);
1123
vasilvvc48c8712019-03-11 13:38:16 -07001124 std::string shlo_nonce;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001125 shlo_nonce = NewServerNonce(rand, info.now);
1126 out->SetStringPiece(kServerNonceTag, shlo_nonce);
1127
1128 if (!CryptoUtils::DeriveKeys(
1129 params->forward_secure_premaster_secret, params->aead,
1130 info.client_nonce,
1131 shlo_nonce.empty() ? info.server_nonce : shlo_nonce, pre_shared_key_,
1132 forward_secure_hkdf_input, Perspective::IS_SERVER,
1133 CryptoUtils::Diversification::Never(),
1134 &params->forward_secure_crypters, &params->subkey_secret)) {
1135 helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
1136 "Symmetric key setup failed");
1137 return;
1138 }
1139
1140 out->set_tag(kSHLO);
1141 out->SetVersionVector(kVER, supported_versions);
1142 out->SetStringPiece(
1143 kSourceAddressTokenTag,
1144 NewSourceAddressToken(*requested_config, info.source_address_tokens,
1145 client_address.host(), rand, info.now, nullptr));
1146 QuicSocketAddressCoder address_coder(client_address);
1147 out->SetStringPiece(kCADR, address_coder.Encode());
1148 out->SetStringPiece(kPUBS, forward_secure_public_value);
1149
1150 helper.Succeed(std::move(out), std::move(out_diversification_nonce),
1151 std::move(proof_source_details));
1152}
1153
1154QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1155QuicCryptoServerConfig::GetConfigWithScid(
1156 QuicStringPiece requested_scid) const {
1157 configs_lock_.AssertReaderHeld();
1158
1159 if (!requested_scid.empty()) {
vasilvvc48c8712019-03-11 13:38:16 -07001160 auto it = configs_.find((std::string(requested_scid)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001161 if (it != configs_.end()) {
1162 // We'll use the config that the client requested in order to do
1163 // key-agreement.
1164 return QuicReferenceCountedPointer<Config>(it->second);
1165 }
1166 }
1167
1168 return QuicReferenceCountedPointer<Config>();
1169}
1170
1171// ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
1172// Config's based on their primary_time.
1173// static
1174bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
1175 const QuicReferenceCountedPointer<Config>& a,
1176 const QuicReferenceCountedPointer<Config>& b) {
1177 if (a->primary_time.IsBefore(b->primary_time) ||
1178 b->primary_time.IsBefore(a->primary_time)) {
1179 // Primary times differ.
1180 return a->primary_time.IsBefore(b->primary_time);
1181 } else if (a->priority != b->priority) {
1182 // Primary times are equal, sort backwards by priority.
1183 return a->priority < b->priority;
1184 } else {
1185 // Primary times and priorities are equal, sort by config id.
1186 return a->id < b->id;
1187 }
1188}
1189
1190void QuicCryptoServerConfig::SelectNewPrimaryConfig(
1191 const QuicWallTime now) const {
1192 std::vector<QuicReferenceCountedPointer<Config>> configs;
1193 configs.reserve(configs_.size());
1194
1195 for (auto it = configs_.begin(); it != configs_.end(); ++it) {
1196 // TODO(avd) Exclude expired configs?
1197 configs.push_back(it->second);
1198 }
1199
1200 if (configs.empty()) {
1201 if (primary_config_ != nullptr) {
1202 QUIC_BUG << "No valid QUIC server config. Keeping the current config.";
1203 } else {
1204 QUIC_BUG << "No valid QUIC server config.";
1205 }
1206 return;
1207 }
1208
1209 std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
1210
1211 QuicReferenceCountedPointer<Config> best_candidate = configs[0];
1212
1213 for (size_t i = 0; i < configs.size(); ++i) {
1214 const QuicReferenceCountedPointer<Config> config(configs[i]);
1215 if (!config->primary_time.IsAfter(now)) {
1216 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
1217 best_candidate = config;
1218 }
1219 continue;
1220 }
1221
1222 // This is the first config with a primary_time in the future. Thus the
1223 // previous Config should be the primary and this one should determine the
1224 // next_config_promotion_time_.
1225 QuicReferenceCountedPointer<Config> new_primary = best_candidate;
1226 if (i == 0) {
1227 // We need the primary_time of the next config.
1228 if (configs.size() > 1) {
1229 next_config_promotion_time_ = configs[1]->primary_time;
1230 } else {
1231 next_config_promotion_time_ = QuicWallTime::Zero();
1232 }
1233 } else {
1234 next_config_promotion_time_ = config->primary_time;
1235 }
1236
1237 if (primary_config_) {
1238 primary_config_->is_primary = false;
1239 }
1240 primary_config_ = new_primary;
1241 new_primary->is_primary = true;
1242 QUIC_DLOG(INFO) << "New primary config. orbit: "
1243 << QuicTextUtils::HexEncode(reinterpret_cast<const char*>(
1244 primary_config_->orbit),
1245 kOrbitSize);
1246 if (primary_config_changed_cb_ != nullptr) {
1247 primary_config_changed_cb_->Run(primary_config_->id);
1248 }
1249
1250 return;
1251 }
1252
1253 // All config's primary times are in the past. We should make the most recent
1254 // and highest priority candidate primary.
1255 QuicReferenceCountedPointer<Config> new_primary = best_candidate;
1256 if (primary_config_) {
1257 primary_config_->is_primary = false;
1258 }
1259 primary_config_ = new_primary;
1260 new_primary->is_primary = true;
1261 QUIC_DLOG(INFO) << "New primary config. orbit: "
1262 << QuicTextUtils::HexEncode(
1263 reinterpret_cast<const char*>(primary_config_->orbit),
1264 kOrbitSize)
1265 << " scid: " << QuicTextUtils::HexEncode(primary_config_->id);
1266 next_config_promotion_time_ = QuicWallTime::Zero();
1267 if (primary_config_changed_cb_ != nullptr) {
1268 primary_config_changed_cb_->Run(primary_config_->id);
1269 }
1270}
1271
1272class QuicCryptoServerConfig::EvaluateClientHelloCallback
1273 : public ProofSource::Callback {
1274 public:
1275 EvaluateClientHelloCallback(
1276 const QuicCryptoServerConfig& config,
1277 const QuicIpAddress& server_ip,
1278 QuicTransportVersion version,
1279 QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1280 requested_config,
1281 QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1282 primary_config,
1283 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
1284 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1285 client_hello_state,
1286 std::unique_ptr<ValidateClientHelloResultCallback> done_cb)
1287 : config_(config),
1288 server_ip_(server_ip),
1289 version_(version),
1290 requested_config_(std::move(requested_config)),
1291 primary_config_(std::move(primary_config)),
1292 signed_config_(signed_config),
1293 client_hello_state_(std::move(client_hello_state)),
1294 done_cb_(std::move(done_cb)) {}
1295
1296 void Run(bool ok,
1297 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
1298 const QuicCryptoProof& proof,
1299 std::unique_ptr<ProofSource::Details> details) override {
1300 if (ok) {
1301 signed_config_->chain = chain;
1302 signed_config_->proof = proof;
1303 }
1304 config_.EvaluateClientHelloAfterGetProof(
1305 server_ip_, version_, requested_config_, primary_config_,
1306 signed_config_, std::move(details), !ok, client_hello_state_,
1307 std::move(done_cb_));
1308 }
1309
1310 private:
1311 const QuicCryptoServerConfig& config_;
1312 const QuicIpAddress& server_ip_;
1313 const QuicTransportVersion version_;
1314 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1315 requested_config_;
1316 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1317 primary_config_;
1318 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1319 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1320 client_hello_state_;
1321 std::unique_ptr<ValidateClientHelloResultCallback> done_cb_;
1322};
1323
1324void QuicCryptoServerConfig::EvaluateClientHello(
1325 const QuicSocketAddress& server_address,
1326 QuicTransportVersion version,
1327 QuicReferenceCountedPointer<Config> requested_config,
1328 QuicReferenceCountedPointer<Config> primary_config,
1329 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
1330 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1331 client_hello_state,
1332 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
1333 DCHECK(!signed_config->chain);
1334
1335 ValidateClientHelloHelper helper(client_hello_state, &done_cb);
1336
1337 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
1338 ClientHelloInfo* info = &(client_hello_state->info);
1339
1340 if (validate_chlo_size_ && client_hello.size() < kClientHelloMinimumSize) {
1341 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
1342 "Client hello too small", nullptr);
1343 return;
1344 }
1345
1346 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
1347 !QuicHostnameUtils::IsValidSNI(info->sni)) {
1348 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1349 "Invalid SNI name", nullptr);
1350 return;
1351 }
1352
1353 client_hello.GetStringPiece(kUAID, &info->user_agent_id);
1354
1355 HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
1356 if (validate_source_address_token_) {
1357 QuicStringPiece srct;
1358 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
1359 Config& config =
1360 requested_config != nullptr ? *requested_config : *primary_config;
1361 source_address_token_error =
1362 ParseSourceAddressToken(config, srct, &info->source_address_tokens);
1363
1364 if (source_address_token_error == HANDSHAKE_OK) {
1365 source_address_token_error = ValidateSourceAddressTokens(
1366 info->source_address_tokens, info->client_ip, info->now,
1367 &client_hello_state->cached_network_params);
1368 }
1369 info->valid_source_address_token =
1370 (source_address_token_error == HANDSHAKE_OK);
1371 } else {
1372 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
1373 }
1374 } else {
1375 source_address_token_error = HANDSHAKE_OK;
1376 info->valid_source_address_token = true;
1377 }
1378
1379 if (!requested_config.get()) {
1380 QuicStringPiece requested_scid;
1381 if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
1382 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1383 } else {
1384 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1385 }
1386 // No server config with the requested ID.
1387 helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1388 return;
1389 }
1390
1391 if (!client_hello.GetStringPiece(kNONC, &info->client_nonce)) {
1392 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1393 // Report no client nonce as INCHOATE_HELLO_FAILURE.
1394 helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1395 return;
1396 }
1397
1398 if (source_address_token_error != HANDSHAKE_OK) {
1399 info->reject_reasons.push_back(source_address_token_error);
1400 // No valid source address token.
1401 }
1402
1403 QuicReferenceCountedPointer<ProofSource::Chain> chain =
vasilvvc48c8712019-03-11 13:38:16 -07001404 proof_source_->GetCertChain(server_address, std::string(info->sni));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001405 if (!chain) {
1406 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1407 } else if (!ValidateExpectedLeafCertificate(client_hello, chain->certs)) {
1408 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
1409 }
1410 EvaluateClientHelloAfterGetProof(
1411 server_address.host(), version, requested_config, primary_config,
1412 signed_config, /*proof_source_details=*/nullptr,
1413 /*get_proof_failed=*/false, client_hello_state, std::move(done_cb));
1414 helper.DetachCallback();
1415}
1416
1417void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof(
1418 const QuicIpAddress& server_ip,
1419 QuicTransportVersion version,
1420 QuicReferenceCountedPointer<Config> requested_config,
1421 QuicReferenceCountedPointer<Config> primary_config,
1422 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
1423 std::unique_ptr<ProofSource::Details> proof_source_details,
1424 bool get_proof_failed,
1425 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1426 client_hello_state,
1427 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
1428 ValidateClientHelloHelper helper(client_hello_state, &done_cb);
1429 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
1430 ClientHelloInfo* info = &(client_hello_state->info);
1431
1432 if (info->client_nonce.size() != kNonceSize) {
1433 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
1434 // Invalid client nonce.
1435 QUIC_LOG_FIRST_N(ERROR, 2)
1436 << "Invalid client nonce: " << client_hello.DebugString();
1437 QUIC_DLOG(INFO) << "Invalid client nonce.";
1438 }
1439
1440 // Server nonce is optional, and used for key derivation if present.
1441 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
1442
1443 QUIC_DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
1444 // If the server nonce is empty and we're requiring handshake confirmation
1445 // for DoS reasons then we must reject the CHLO.
1446 if (GetQuicReloadableFlag(quic_require_handshake_confirmation) &&
1447 info->server_nonce.empty()) {
1448 info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
1449 }
1450 helper.ValidationComplete(QUIC_NO_ERROR, "", std::move(proof_source_details));
1451}
1452
1453void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1454 QuicTransportVersion version,
1455 QuicStringPiece chlo_hash,
1456 const SourceAddressTokens& previous_source_address_tokens,
1457 const QuicSocketAddress& server_address,
1458 const QuicIpAddress& client_ip,
1459 const QuicClock* clock,
1460 QuicRandom* rand,
1461 QuicCompressedCertsCache* compressed_certs_cache,
1462 const QuicCryptoNegotiatedParameters& params,
1463 const CachedNetworkParameters* cached_network_params,
1464 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
vasilvvc48c8712019-03-11 13:38:16 -07001465 std::string serialized;
1466 std::string source_address_token;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001467 const CommonCertSets* common_cert_sets;
1468 {
1469 QuicReaderMutexLock locked(&configs_lock_);
1470 serialized = primary_config_->serialized;
1471 common_cert_sets = primary_config_->common_cert_sets;
1472 source_address_token = NewSourceAddressToken(
1473 *primary_config_, previous_source_address_tokens, client_ip, rand,
1474 clock->WallNow(), cached_network_params);
1475 }
1476
1477 CryptoHandshakeMessage message;
1478 message.set_tag(kSCUP);
1479 message.SetStringPiece(kSCFG, serialized);
1480 message.SetStringPiece(kSourceAddressTokenTag, source_address_token);
1481
QUICHE teamea5bdef2019-03-13 15:41:27 -07001482 auto proof_source_cb =
1483 QuicMakeUnique<BuildServerConfigUpdateMessageProofSourceCallback>(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001484 this, version, compressed_certs_cache, common_cert_sets, params,
QUICHE teamea5bdef2019-03-13 15:41:27 -07001485 std::move(message), std::move(cb));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001486
1487 proof_source_->GetProof(server_address, params.sni, serialized, version,
1488 chlo_hash, std::move(proof_source_cb));
1489}
1490
1491QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1492 ~BuildServerConfigUpdateMessageProofSourceCallback() {}
1493
1494QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1495 BuildServerConfigUpdateMessageProofSourceCallback(
1496 const QuicCryptoServerConfig* config,
1497 QuicTransportVersion version,
1498 QuicCompressedCertsCache* compressed_certs_cache,
1499 const CommonCertSets* common_cert_sets,
1500 const QuicCryptoNegotiatedParameters& params,
1501 CryptoHandshakeMessage message,
1502 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
1503 : config_(config),
1504 version_(version),
1505 compressed_certs_cache_(compressed_certs_cache),
1506 common_cert_sets_(common_cert_sets),
1507 client_common_set_hashes_(params.client_common_set_hashes),
1508 client_cached_cert_hashes_(params.client_cached_cert_hashes),
1509 sct_supported_by_client_(params.sct_supported_by_client),
1510 sni_(params.sni),
1511 message_(std::move(message)),
1512 cb_(std::move(cb)) {}
1513
1514void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1515 Run(bool ok,
1516 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
1517 const QuicCryptoProof& proof,
1518 std::unique_ptr<ProofSource::Details> details) {
1519 config_->FinishBuildServerConfigUpdateMessage(
1520 version_, compressed_certs_cache_, common_cert_sets_,
1521 client_common_set_hashes_, client_cached_cert_hashes_,
1522 sct_supported_by_client_, sni_, ok, chain, proof.signature,
1523 proof.leaf_cert_scts, std::move(details), std::move(message_),
1524 std::move(cb_));
1525}
1526
1527void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
1528 QuicTransportVersion version,
1529 QuicCompressedCertsCache* compressed_certs_cache,
1530 const CommonCertSets* common_cert_sets,
vasilvvc48c8712019-03-11 13:38:16 -07001531 const std::string& client_common_set_hashes,
1532 const std::string& client_cached_cert_hashes,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001533 bool sct_supported_by_client,
vasilvvc48c8712019-03-11 13:38:16 -07001534 const std::string& sni,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001535 bool ok,
1536 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
vasilvvc48c8712019-03-11 13:38:16 -07001537 const std::string& signature,
1538 const std::string& leaf_cert_sct,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001539 std::unique_ptr<ProofSource::Details> details,
1540 CryptoHandshakeMessage message,
1541 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
1542 if (!ok) {
1543 cb->Run(false, message);
1544 return;
1545 }
1546
vasilvvc48c8712019-03-11 13:38:16 -07001547 const std::string compressed =
QUICHE teama6ef0a62019-03-07 20:34:33 -05001548 CompressChain(compressed_certs_cache, chain, client_common_set_hashes,
1549 client_cached_cert_hashes, common_cert_sets);
1550
1551 message.SetStringPiece(kCertificateTag, compressed);
1552 message.SetStringPiece(kPROF, signature);
1553 if (sct_supported_by_client && enable_serving_sct_) {
1554 if (leaf_cert_sct.empty()) {
1555 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1556 << "SCT is expected but it is empty. SNI: " << sni;
1557 } else {
1558 message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct);
1559 }
1560 }
1561
1562 cb->Run(true, message);
1563}
1564
1565void QuicCryptoServerConfig::BuildRejection(
1566 QuicTransportVersion version,
1567 QuicWallTime now,
1568 const Config& config,
1569 const CryptoHandshakeMessage& client_hello,
1570 const ClientHelloInfo& info,
1571 const CachedNetworkParameters& cached_network_params,
1572 bool use_stateless_rejects,
1573 QuicConnectionId server_designated_connection_id,
1574 QuicRandom* rand,
1575 QuicCompressedCertsCache* compressed_certs_cache,
1576 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
1577 const QuicSignedServerConfig& signed_config,
1578 QuicByteCount total_framing_overhead,
1579 QuicByteCount chlo_packet_size,
1580 CryptoHandshakeMessage* out) const {
1581 if (GetQuicReloadableFlag(enable_quic_stateless_reject_support) &&
1582 use_stateless_rejects) {
1583 QUIC_DVLOG(1) << "QUIC Crypto server config returning stateless reject "
1584 << "with server-designated connection ID "
1585 << server_designated_connection_id;
1586 out->set_tag(kSREJ);
vasilvvc48c8712019-03-11 13:38:16 -07001587 if (!QuicUtils::IsConnectionIdValidForVersion(
1588 server_designated_connection_id, version)) {
1589 QUIC_BUG << "Tried to send server designated connection ID "
1590 << server_designated_connection_id
1591 << " which is invalid with version "
1592 << QuicVersionToString(version);
1593 return;
1594 }
1595 out->SetStringPiece(
1596 kRCID, QuicStringPiece(server_designated_connection_id.data(),
1597 server_designated_connection_id.length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001598 } else {
1599 out->set_tag(kREJ);
1600 }
1601 out->SetStringPiece(kSCFG, config.serialized);
1602 out->SetStringPiece(
1603 kSourceAddressTokenTag,
1604 NewSourceAddressToken(config, info.source_address_tokens, info.client_ip,
1605 rand, info.now, &cached_network_params));
1606 out->SetValue(kSTTL, config.expiry_time.AbsoluteDifference(now).ToSeconds());
1607 if (replay_protection_) {
1608 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
1609 }
1610
1611 // Send client the reject reason for debugging purposes.
1612 DCHECK_LT(0u, info.reject_reasons.size());
1613 out->SetVector(kRREJ, info.reject_reasons);
1614
1615 // The client may have requested a certificate chain.
1616 if (!ClientDemandsX509Proof(client_hello)) {
1617 QUIC_BUG << "x509 certificates not supported in proof demand";
1618 return;
1619 }
1620
1621 QuicStringPiece client_common_set_hashes;
1622 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
vasilvvc48c8712019-03-11 13:38:16 -07001623 params->client_common_set_hashes = std::string(client_common_set_hashes);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001624 }
1625
1626 QuicStringPiece client_cached_cert_hashes;
1627 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
vasilvvc48c8712019-03-11 13:38:16 -07001628 params->client_cached_cert_hashes = std::string(client_cached_cert_hashes);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001629 } else {
1630 params->client_cached_cert_hashes.clear();
1631 }
1632
vasilvvc48c8712019-03-11 13:38:16 -07001633 const std::string compressed =
QUICHE teama6ef0a62019-03-07 20:34:33 -05001634 CompressChain(compressed_certs_cache, signed_config.chain,
1635 params->client_common_set_hashes,
1636 params->client_cached_cert_hashes, config.common_cert_sets);
1637
1638 DCHECK_GT(chlo_packet_size, client_hello.size());
1639 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1640 // message is taken up by things other than the certificates.
1641 // STK: 56 bytes
1642 // SNO: 56 bytes
1643 // SCFG
1644 // SCID: 16 bytes
1645 // PUBS: 38 bytes
1646 const size_t kREJOverheadBytes = 166;
1647 // max_unverified_size is the number of bytes that the certificate chain,
1648 // signature, and (optionally) signed certificate timestamp can consume before
1649 // we will demand a valid source-address token.
1650 const size_t max_unverified_size =
1651 chlo_multiplier_ * (chlo_packet_size - total_framing_overhead) -
1652 kREJOverheadBytes;
1653 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1654 "overhead calculation may underflow");
1655 bool should_return_sct =
1656 params->sct_supported_by_client && enable_serving_sct_;
vasilvvc48c8712019-03-11 13:38:16 -07001657 const std::string& cert_sct = signed_config.proof.leaf_cert_scts;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001658 const size_t sct_size = should_return_sct ? cert_sct.size() : 0;
1659 const size_t total_size =
1660 signed_config.proof.signature.size() + compressed.size() + sct_size;
1661 if (info.valid_source_address_token || total_size < max_unverified_size) {
1662 out->SetStringPiece(kCertificateTag, compressed);
1663 out->SetStringPiece(kPROF, signed_config.proof.signature);
1664 if (should_return_sct) {
1665 if (cert_sct.empty()) {
1666 if (!GetQuicReloadableFlag(quic_log_cert_name_for_empty_sct)) {
1667 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1668 << "SCT is expected but it is empty. sni :" << params->sni;
1669 } else {
1670 // Log SNI and subject name for the leaf cert if its SCT is empty.
1671 // This is for debugging b/28342827.
vasilvvc48c8712019-03-11 13:38:16 -07001672 const std::vector<std::string>& certs = signed_config.chain->certs;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001673 QuicStringPiece ca_subject;
1674 if (!certs.empty()) {
1675 QuicCertUtils::ExtractSubjectNameFromDERCert(certs[0], &ca_subject);
1676 }
1677 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1678 << "SCT is expected but it is empty. sni: '" << params->sni
1679 << "' cert subject: '" << ca_subject << "'";
1680 }
1681 } else {
1682 out->SetStringPiece(kCertificateSCTTag, cert_sct);
1683 }
1684 }
1685 } else {
1686 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1687 << "Sending inchoate REJ for hostname: " << info.sni
1688 << " signature: " << signed_config.proof.signature.size()
1689 << " cert: " << compressed.size() << " sct:" << sct_size
1690 << " total: " << total_size << " max: " << max_unverified_size;
1691 }
1692}
1693
vasilvvc48c8712019-03-11 13:38:16 -07001694std::string QuicCryptoServerConfig::CompressChain(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001695 QuicCompressedCertsCache* compressed_certs_cache,
1696 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
vasilvvc48c8712019-03-11 13:38:16 -07001697 const std::string& client_common_set_hashes,
1698 const std::string& client_cached_cert_hashes,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001699 const CommonCertSets* common_sets) {
1700 // Check whether the compressed certs is available in the cache.
1701 DCHECK(compressed_certs_cache);
vasilvvc48c8712019-03-11 13:38:16 -07001702 const std::string* cached_value = compressed_certs_cache->GetCompressedCert(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001703 chain, client_common_set_hashes, client_cached_cert_hashes);
1704 if (cached_value) {
1705 return *cached_value;
1706 }
vasilvvc48c8712019-03-11 13:38:16 -07001707 std::string compressed =
QUICHE teama6ef0a62019-03-07 20:34:33 -05001708 CertCompressor::CompressChain(chain->certs, client_common_set_hashes,
1709 client_cached_cert_hashes, common_sets);
1710 // Insert the newly compressed cert to cache.
1711 compressed_certs_cache->Insert(chain, client_common_set_hashes,
1712 client_cached_cert_hashes, compressed);
1713 return compressed;
1714}
1715
1716QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1717QuicCryptoServerConfig::ParseConfigProtobuf(
1718 const std::unique_ptr<QuicServerConfigProtobuf>& protobuf) {
1719 std::unique_ptr<CryptoHandshakeMessage> msg(
1720 CryptoFramer::ParseMessage(protobuf->config()));
1721
1722 if (msg->tag() != kSCFG) {
1723 QUIC_LOG(WARNING) << "Server config message has tag " << msg->tag()
1724 << " expected " << kSCFG;
1725 return nullptr;
1726 }
1727
1728 QuicReferenceCountedPointer<Config> config(new Config);
1729 config->serialized = protobuf->config();
1730 config->source_address_token_boxer = &source_address_token_boxer_;
1731
1732 if (protobuf->has_primary_time()) {
1733 config->primary_time =
1734 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1735 }
1736
1737 config->priority = protobuf->priority();
1738
1739 QuicStringPiece scid;
1740 if (!msg->GetStringPiece(kSCID, &scid)) {
1741 QUIC_LOG(WARNING) << "Server config message is missing SCID";
1742 return nullptr;
1743 }
vasilvvc48c8712019-03-11 13:38:16 -07001744 config->id = std::string(scid);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001745
1746 if (msg->GetTaglist(kAEAD, &config->aead) != QUIC_NO_ERROR) {
1747 QUIC_LOG(WARNING) << "Server config message is missing AEAD";
1748 return nullptr;
1749 }
1750
1751 QuicTagVector kexs_tags;
1752 if (msg->GetTaglist(kKEXS, &kexs_tags) != QUIC_NO_ERROR) {
1753 QUIC_LOG(WARNING) << "Server config message is missing KEXS";
1754 return nullptr;
1755 }
1756
1757 QuicErrorCode err;
1758 if ((err = msg->GetTaglist(kTBKP, &config->tb_key_params)) !=
1759 QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND &&
1760 err != QUIC_NO_ERROR) {
1761 QUIC_LOG(WARNING) << "Server config message is missing or has invalid TBKP";
1762 return nullptr;
1763 }
1764
1765 QuicStringPiece orbit;
1766 if (!msg->GetStringPiece(kORBT, &orbit)) {
1767 QUIC_LOG(WARNING) << "Server config message is missing ORBT";
1768 return nullptr;
1769 }
1770
1771 if (orbit.size() != kOrbitSize) {
1772 QUIC_LOG(WARNING) << "Orbit value in server config is the wrong length."
1773 " Got "
1774 << orbit.size() << " want " << kOrbitSize;
1775 return nullptr;
1776 }
1777 static_assert(sizeof(config->orbit) == kOrbitSize, "incorrect orbit size");
1778 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1779
1780 if (kexs_tags.size() != static_cast<size_t>(protobuf->key_size())) {
1781 QUIC_LOG(WARNING) << "Server config has " << kexs_tags.size()
1782 << " key exchange methods configured, but "
1783 << protobuf->key_size() << " private keys";
1784 return nullptr;
1785 }
1786
1787 QuicTagVector proof_demand_tags;
1788 if (msg->GetTaglist(kPDMD, &proof_demand_tags) == QUIC_NO_ERROR) {
1789 for (QuicTag tag : proof_demand_tags) {
1790 if (tag == kCHID) {
1791 config->channel_id_enabled = true;
1792 break;
1793 }
1794 }
1795 }
1796
1797 for (size_t i = 0; i < kexs_tags.size(); i++) {
1798 const QuicTag tag = kexs_tags[i];
vasilvvc48c8712019-03-11 13:38:16 -07001799 std::string private_key;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001800
1801 config->kexs.push_back(tag);
1802
1803 for (int j = 0; j < protobuf->key_size(); j++) {
1804 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1805 if (key.tag() == tag) {
1806 private_key = key.private_key();
1807 break;
1808 }
1809 }
1810
1811 std::unique_ptr<KeyExchange> ka =
1812 key_exchange_source_->Create(config->id, tag, private_key);
1813 if (!ka) {
1814 return nullptr;
1815 }
1816 for (const auto& key_exchange : config->key_exchanges) {
1817 if (key_exchange->GetFactory().tag() == tag) {
1818 QUIC_LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1819 return nullptr;
1820 }
1821 }
1822
1823 config->key_exchanges.push_back(std::move(ka));
1824 }
1825
1826 uint64_t expiry_seconds;
1827 if (msg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
1828 QUIC_LOG(WARNING) << "Server config message is missing EXPY";
1829 return nullptr;
1830 }
1831 config->expiry_time = QuicWallTime::FromUNIXSeconds(expiry_seconds);
1832
1833 return config;
1834}
1835
1836void QuicCryptoServerConfig::set_replay_protection(bool on) {
1837 replay_protection_ = on;
1838}
1839
1840void QuicCryptoServerConfig::set_chlo_multiplier(size_t multiplier) {
1841 chlo_multiplier_ = multiplier;
1842}
1843
1844void QuicCryptoServerConfig::set_source_address_token_future_secs(
1845 uint32_t future_secs) {
1846 source_address_token_future_secs_ = future_secs;
1847}
1848
1849void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1850 uint32_t lifetime_secs) {
1851 source_address_token_lifetime_secs_ = lifetime_secs;
1852}
1853
1854void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) {
1855 enable_serving_sct_ = enable_serving_sct;
1856}
1857
1858void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1859 std::unique_ptr<PrimaryConfigChangedCallback> cb) {
1860 QuicWriterMutexLock locked(&configs_lock_);
1861 primary_config_changed_cb_ = std::move(cb);
1862}
1863
vasilvvc48c8712019-03-11 13:38:16 -07001864std::string QuicCryptoServerConfig::NewSourceAddressToken(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001865 const Config& config,
1866 const SourceAddressTokens& previous_tokens,
1867 const QuicIpAddress& ip,
1868 QuicRandom* rand,
1869 QuicWallTime now,
1870 const CachedNetworkParameters* cached_network_params) const {
1871 SourceAddressTokens source_address_tokens;
1872 SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
1873 source_address_token->set_ip(ip.DualStacked().ToPackedString());
1874 source_address_token->set_timestamp(now.ToUNIXSeconds());
1875 if (cached_network_params != nullptr) {
1876 *(source_address_token->mutable_cached_network_parameters()) =
1877 *cached_network_params;
1878 }
1879
1880 // Append previous tokens.
1881 for (const SourceAddressToken& token : previous_tokens.tokens()) {
1882 if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
1883 break;
1884 }
1885
1886 if (token.ip() == source_address_token->ip()) {
1887 // It's for the same IP address.
1888 continue;
1889 }
1890
1891 if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
1892 continue;
1893 }
1894
1895 *(source_address_tokens.add_tokens()) = token;
1896 }
1897
1898 return config.source_address_token_boxer->Box(
1899 rand, source_address_tokens.SerializeAsString());
1900}
1901
1902int QuicCryptoServerConfig::NumberOfConfigs() const {
1903 QuicReaderMutexLock locked(&configs_lock_);
1904 return configs_.size();
1905}
1906
1907ProofSource* QuicCryptoServerConfig::proof_source() const {
1908 return proof_source_.get();
1909}
1910
1911SSL_CTX* QuicCryptoServerConfig::ssl_ctx() const {
1912 return ssl_ctx_.get();
1913}
1914
1915HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
1916 const Config& config,
1917 QuicStringPiece token,
1918 SourceAddressTokens* tokens) const {
vasilvvc48c8712019-03-11 13:38:16 -07001919 std::string storage;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001920 QuicStringPiece plaintext;
1921 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1922 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1923 }
1924
1925 if (!tokens->ParseFromArray(plaintext.data(), plaintext.size())) {
1926 // Some clients might still be using the old source token format so
1927 // attempt to parse that format.
1928 // TODO(rch): remove this code once the new format is ubiquitous.
1929 SourceAddressToken token;
1930 if (!token.ParseFromArray(plaintext.data(), plaintext.size())) {
1931 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1932 }
1933 *tokens->add_tokens() = token;
1934 }
1935
1936 return HANDSHAKE_OK;
1937}
1938
1939HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
1940 const SourceAddressTokens& source_address_tokens,
1941 const QuicIpAddress& ip,
1942 QuicWallTime now,
1943 CachedNetworkParameters* cached_network_params) const {
1944 HandshakeFailureReason reason =
1945 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1946 for (const SourceAddressToken& token : source_address_tokens.tokens()) {
1947 reason = ValidateSingleSourceAddressToken(token, ip, now);
1948 if (reason == HANDSHAKE_OK) {
1949 if (token.has_cached_network_parameters()) {
1950 *cached_network_params = token.cached_network_parameters();
1951 }
1952 break;
1953 }
1954 }
1955 return reason;
1956}
1957
1958HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1959 const SourceAddressToken& source_address_token,
1960 const QuicIpAddress& ip,
1961 QuicWallTime now) const {
1962 if (source_address_token.ip() != ip.DualStacked().ToPackedString()) {
1963 // It's for a different IP address.
1964 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1965 }
1966
1967 return ValidateSourceAddressTokenTimestamp(source_address_token, now);
1968}
1969
1970HandshakeFailureReason
1971QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1972 const SourceAddressToken& source_address_token,
1973 QuicWallTime now) const {
1974 const QuicWallTime timestamp(
1975 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1976 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1977
1978 if (now.IsBefore(timestamp) &&
1979 delta.ToSeconds() > source_address_token_future_secs_) {
1980 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1981 }
1982
1983 if (now.IsAfter(timestamp) &&
1984 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1985 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1986 }
1987
1988 return HANDSHAKE_OK;
1989}
1990
1991// kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1992// nonce.
1993static const size_t kServerNoncePlaintextSize =
1994 4 /* timestamp */ + 20 /* random bytes */;
1995
vasilvvc48c8712019-03-11 13:38:16 -07001996std::string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1997 QuicWallTime now) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001998 const uint32_t timestamp = static_cast<uint32_t>(now.ToUNIXSeconds());
1999
2000 uint8_t server_nonce[kServerNoncePlaintextSize];
2001 static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
2002 server_nonce[0] = static_cast<uint8_t>(timestamp >> 24);
2003 server_nonce[1] = static_cast<uint8_t>(timestamp >> 16);
2004 server_nonce[2] = static_cast<uint8_t>(timestamp >> 8);
2005 server_nonce[3] = static_cast<uint8_t>(timestamp);
2006 rand->RandBytes(&server_nonce[sizeof(timestamp)],
2007 sizeof(server_nonce) - sizeof(timestamp));
2008
2009 return server_nonce_boxer_.Box(
2010 rand, QuicStringPiece(reinterpret_cast<char*>(server_nonce),
2011 sizeof(server_nonce)));
2012}
2013
2014bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
2015 const CryptoHandshakeMessage& client_hello,
vasilvvc48c8712019-03-11 13:38:16 -07002016 const std::vector<std::string>& certs) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002017 if (certs.empty()) {
2018 return false;
2019 }
2020
2021 uint64_t hash_from_client;
2022 if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) {
2023 return false;
2024 }
2025 return CryptoUtils::ComputeLeafCertHash(certs.at(0)) == hash_from_client;
2026}
2027
2028bool QuicCryptoServerConfig::ClientDemandsX509Proof(
2029 const CryptoHandshakeMessage& client_hello) const {
2030 QuicTagVector their_proof_demands;
2031
2032 if (client_hello.GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) {
2033 return false;
2034 }
2035
2036 for (const QuicTag tag : their_proof_demands) {
2037 if (tag == kX509) {
2038 return true;
2039 }
2040 }
2041 return false;
2042}
2043
2044bool QuicCryptoServerConfig::IsNextConfigReady(QuicWallTime now) const {
2045 if (GetQuicReloadableFlag(quic_fix_config_rotation)) {
2046 QUIC_RELOADABLE_FLAG_COUNT(quic_fix_config_rotation);
2047 return !next_config_promotion_time_.IsZero() &&
2048 !next_config_promotion_time_.IsAfter(now);
2049 }
2050 return !next_config_promotion_time_.IsZero() &&
2051 next_config_promotion_time_.IsAfter(now);
2052}
2053
2054QuicCryptoServerConfig::Config::Config()
2055 : channel_id_enabled(false),
2056 is_primary(false),
2057 primary_time(QuicWallTime::Zero()),
2058 expiry_time(QuicWallTime::Zero()),
2059 priority(0),
2060 source_address_token_boxer(nullptr) {}
2061
2062QuicCryptoServerConfig::Config::~Config() {}
2063
2064QuicSignedServerConfig::QuicSignedServerConfig() {}
2065QuicSignedServerConfig::~QuicSignedServerConfig() {}
2066
2067} // namespace quic