blob: aa45e33f1516a8ba94f6ef3048c70ad33da06f2b [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
QUICHE teamfe1aca62019-03-14 13:39:01 -070077 std::unique_ptr<AsynchronousKeyExchange> Create(
78 std::string server_config_id,
79 QuicTag type,
80 QuicStringPiece private_key) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 if (private_key.empty()) {
82 QUIC_LOG(WARNING) << "Server config contains key exchange method without "
QUICHE teamfe1aca62019-03-14 13:39:01 -070083 "corresponding private key of type "
84 << QuicTagToString(type);
QUICHE teama6ef0a62019-03-07 20:34:33 -050085 return nullptr;
86 }
87
QUICHE teamfe1aca62019-03-14 13:39:01 -070088 std::unique_ptr<SynchronousKeyExchange> ka =
89 CreateLocalSynchronousKeyExchange(type, private_key);
90 if (!ka) {
91 QUIC_LOG(WARNING) << "Failed to create key exchange method of type "
92 << QuicTagToString(type);
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 }
94 return ka;
95 }
96};
97
98} // namespace
99
100// static
101std::unique_ptr<KeyExchangeSource> KeyExchangeSource::Default() {
102 return QuicMakeUnique<DefaultKeyExchangeSource>();
103}
104
105class ValidateClientHelloHelper {
106 public:
107 // Note: stores a pointer to a unique_ptr, and std::moves the unique_ptr when
108 // ValidationComplete is called.
109 ValidateClientHelloHelper(
110 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
111 result,
112 std::unique_ptr<ValidateClientHelloResultCallback>* done_cb)
113 : result_(std::move(result)), done_cb_(done_cb) {}
114 ValidateClientHelloHelper(const ValidateClientHelloHelper&) = delete;
115 ValidateClientHelloHelper& operator=(const ValidateClientHelloHelper&) =
116 delete;
117
118 ~ValidateClientHelloHelper() {
119 QUIC_BUG_IF(done_cb_ != nullptr)
120 << "Deleting ValidateClientHelloHelper with a pending callback.";
121 }
122
123 void ValidationComplete(
124 QuicErrorCode error_code,
125 const char* error_details,
126 std::unique_ptr<ProofSource::Details> proof_source_details) {
127 result_->error_code = error_code;
128 result_->error_details = error_details;
129 (*done_cb_)->Run(std::move(result_), std::move(proof_source_details));
130 DetachCallback();
131 }
132
133 void DetachCallback() {
134 QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
135 done_cb_ = nullptr;
136 }
137
138 private:
139 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
140 result_;
141 std::unique_ptr<ValidateClientHelloResultCallback>* done_cb_;
142};
143
144// static
145const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
146
147ClientHelloInfo::ClientHelloInfo(const QuicIpAddress& in_client_ip,
148 QuicWallTime in_now)
149 : client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {}
150
151ClientHelloInfo::ClientHelloInfo(const ClientHelloInfo& other) = default;
152
153ClientHelloInfo::~ClientHelloInfo() {}
154
155PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {}
156
157PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {}
158
159ValidateClientHelloResultCallback::Result::Result(
160 const CryptoHandshakeMessage& in_client_hello,
161 QuicIpAddress in_client_ip,
162 QuicWallTime in_now)
163 : client_hello(in_client_hello),
164 info(in_client_ip, in_now),
165 error_code(QUIC_NO_ERROR) {}
166
167ValidateClientHelloResultCallback::Result::~Result() {}
168
169ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {}
170
171ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {}
172
173ProcessClientHelloResultCallback::ProcessClientHelloResultCallback() {}
174
175ProcessClientHelloResultCallback::~ProcessClientHelloResultCallback() {}
176
177QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
178 : expiry_time(QuicWallTime::Zero()),
179 channel_id_enabled(false),
180 p256(false) {}
181
182QuicCryptoServerConfig::ConfigOptions::ConfigOptions(
183 const ConfigOptions& other) = default;
184
185QuicCryptoServerConfig::ConfigOptions::~ConfigOptions() {}
186
187QuicCryptoServerConfig::QuicCryptoServerConfig(
188 QuicStringPiece source_address_token_secret,
189 QuicRandom* server_nonce_entropy,
190 std::unique_ptr<ProofSource> proof_source,
191 std::unique_ptr<KeyExchangeSource> key_exchange_source,
192 bssl::UniquePtr<SSL_CTX> ssl_ctx)
193 : replay_protection_(true),
194 chlo_multiplier_(kMultiplier),
195 configs_lock_(),
196 primary_config_(nullptr),
197 next_config_promotion_time_(QuicWallTime::Zero()),
198 proof_source_(std::move(proof_source)),
199 key_exchange_source_(std::move(key_exchange_source)),
200 ssl_ctx_(std::move(ssl_ctx)),
201 source_address_token_future_secs_(3600),
202 source_address_token_lifetime_secs_(86400),
203 enable_serving_sct_(false),
204 rejection_observer_(nullptr),
205 pad_rej_(true),
206 pad_shlo_(true),
207 validate_chlo_size_(true),
208 validate_source_address_token_(true) {
209 DCHECK(proof_source_.get());
210 source_address_token_boxer_.SetKeys(
211 {DeriveSourceAddressTokenKey(source_address_token_secret)});
212
213 // Generate a random key and orbit for server nonces.
214 server_nonce_entropy->RandBytes(server_nonce_orbit_,
215 sizeof(server_nonce_orbit_));
216 const size_t key_size = server_nonce_boxer_.GetKeySize();
217 std::unique_ptr<uint8_t[]> key_bytes(new uint8_t[key_size]);
218 server_nonce_entropy->RandBytes(key_bytes.get(), key_size);
219
220 server_nonce_boxer_.SetKeys(
vasilvvc48c8712019-03-11 13:38:16 -0700221 {std::string(reinterpret_cast<char*>(key_bytes.get()), key_size)});
QUICHE teama6ef0a62019-03-07 20:34:33 -0500222}
223
224QuicCryptoServerConfig::~QuicCryptoServerConfig() {}
225
226// static
227std::unique_ptr<QuicServerConfigProtobuf>
228QuicCryptoServerConfig::GenerateConfig(QuicRandom* rand,
229 const QuicClock* clock,
230 const ConfigOptions& options) {
231 CryptoHandshakeMessage msg;
232
vasilvvc48c8712019-03-11 13:38:16 -0700233 const std::string curve25519_private_key =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500234 Curve25519KeyExchange::NewPrivateKey(rand);
QUICHE teamfe1aca62019-03-14 13:39:01 -0700235 std::unique_ptr<Curve25519KeyExchange> curve25519 =
236 Curve25519KeyExchange::New(curve25519_private_key);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500237 QuicStringPiece curve25519_public_value = curve25519->public_value();
238
vasilvvc48c8712019-03-11 13:38:16 -0700239 std::string encoded_public_values;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 // First three bytes encode the length of the public value.
241 DCHECK_LT(curve25519_public_value.size(), (1U << 24));
242 encoded_public_values.push_back(
243 static_cast<char>(curve25519_public_value.size()));
244 encoded_public_values.push_back(
245 static_cast<char>(curve25519_public_value.size() >> 8));
246 encoded_public_values.push_back(
247 static_cast<char>(curve25519_public_value.size() >> 16));
248 encoded_public_values.append(curve25519_public_value.data(),
249 curve25519_public_value.size());
250
vasilvvc48c8712019-03-11 13:38:16 -0700251 std::string p256_private_key;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 if (options.p256) {
253 p256_private_key = P256KeyExchange::NewPrivateKey();
254 std::unique_ptr<P256KeyExchange> p256(
255 P256KeyExchange::New(p256_private_key));
256 QuicStringPiece p256_public_value = p256->public_value();
257
258 DCHECK_LT(p256_public_value.size(), (1U << 24));
259 encoded_public_values.push_back(
260 static_cast<char>(p256_public_value.size()));
261 encoded_public_values.push_back(
262 static_cast<char>(p256_public_value.size() >> 8));
263 encoded_public_values.push_back(
264 static_cast<char>(p256_public_value.size() >> 16));
265 encoded_public_values.append(p256_public_value.data(),
266 p256_public_value.size());
267 }
268
269 msg.set_tag(kSCFG);
270 if (options.p256) {
271 msg.SetVector(kKEXS, QuicTagVector{kC255, kP256});
272 } else {
273 msg.SetVector(kKEXS, QuicTagVector{kC255});
274 }
275 msg.SetVector(kAEAD, QuicTagVector{kAESG, kCC20});
276 msg.SetStringPiece(kPUBS, encoded_public_values);
277
278 if (options.expiry_time.IsZero()) {
279 const QuicWallTime now = clock->WallNow();
280 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
281 60 * 60 * 24 * 180 /* 180 days, ~six months */));
282 const uint64_t expiry_seconds = expiry.ToUNIXSeconds();
283 msg.SetValue(kEXPY, expiry_seconds);
284 } else {
285 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
286 }
287
288 char orbit_bytes[kOrbitSize];
289 if (options.orbit.size() == sizeof(orbit_bytes)) {
290 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
291 } else {
292 DCHECK(options.orbit.empty());
293 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
294 }
295 msg.SetStringPiece(kORBT, QuicStringPiece(orbit_bytes, sizeof(orbit_bytes)));
296
297 if (options.channel_id_enabled) {
298 msg.SetVector(kPDMD, QuicTagVector{kCHID});
299 }
300
301 if (!options.token_binding_params.empty()) {
302 msg.SetVector(kTBKP, options.token_binding_params);
303 }
304
305 if (options.id.empty()) {
306 // We need to ensure that the SCID changes whenever the server config does
307 // thus we make it a hash of the rest of the server config.
QUICHE team3fe6a8b2019-03-14 09:10:38 -0700308 std::unique_ptr<QuicData> serialized =
309 CryptoFramer::ConstructHandshakeMessage(msg);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500310
311 uint8_t scid_bytes[SHA256_DIGEST_LENGTH];
312 SHA256(reinterpret_cast<const uint8_t*>(serialized->data()),
313 serialized->length(), scid_bytes);
314 // The SCID is a truncated SHA-256 digest.
315 static_assert(16 <= SHA256_DIGEST_LENGTH, "SCID length too high.");
316 msg.SetStringPiece(
317 kSCID, QuicStringPiece(reinterpret_cast<const char*>(scid_bytes), 16));
318 } else {
319 msg.SetStringPiece(kSCID, options.id);
320 }
321 // Don't put new tags below this point. The SCID generation should hash over
322 // everything but itself and so extra tags should be added prior to the
323 // preceding if block.
324
QUICHE team3fe6a8b2019-03-14 09:10:38 -0700325 std::unique_ptr<QuicData> serialized =
326 CryptoFramer::ConstructHandshakeMessage(msg);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327
QUICHE teamea5bdef2019-03-13 15:41:27 -0700328 auto config = QuicMakeUnique<QuicServerConfigProtobuf>();
vasilvvc48c8712019-03-11 13:38:16 -0700329 config->set_config(std::string(serialized->AsStringPiece()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500330 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
331 curve25519_key->set_tag(kC255);
332 curve25519_key->set_private_key(curve25519_private_key);
333
334 if (options.p256) {
335 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
336 p256_key->set_tag(kP256);
337 p256_key->set_private_key(p256_private_key);
338 }
339
340 return config;
341}
342
QUICHE teamd5af58a2019-03-14 20:35:50 -0700343std::unique_ptr<CryptoHandshakeMessage> QuicCryptoServerConfig::AddConfig(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500344 std::unique_ptr<QuicServerConfigProtobuf> protobuf,
345 const QuicWallTime now) {
QUICHE teamd5af58a2019-03-14 20:35:50 -0700346 std::unique_ptr<CryptoHandshakeMessage> msg =
347 CryptoFramer::ParseMessage(protobuf->config());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500348
349 if (!msg.get()) {
350 QUIC_LOG(WARNING) << "Failed to parse server config message";
351 return nullptr;
352 }
353
354 QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
355 if (!config.get()) {
356 QUIC_LOG(WARNING) << "Failed to parse server config message";
357 return nullptr;
358 }
359
360 {
361 QuicWriterMutexLock locked(&configs_lock_);
362 if (configs_.find(config->id) != configs_.end()) {
363 QUIC_LOG(WARNING) << "Failed to add config because another with the same "
364 "server config id already exists: "
365 << QuicTextUtils::HexEncode(config->id);
366 return nullptr;
367 }
368
369 configs_[config->id] = config;
370 SelectNewPrimaryConfig(now);
371 DCHECK(primary_config_.get());
372 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
373 primary_config_.get());
374 }
375
QUICHE teamd5af58a2019-03-14 20:35:50 -0700376 return msg;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500377}
378
QUICHE teamd5af58a2019-03-14 20:35:50 -0700379std::unique_ptr<CryptoHandshakeMessage>
380QuicCryptoServerConfig::AddDefaultConfig(QuicRandom* rand,
381 const QuicClock* clock,
382 const ConfigOptions& options) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500383 return AddConfig(GenerateConfig(rand, clock, options), clock->WallNow());
384}
385
386bool QuicCryptoServerConfig::SetConfigs(
387 const std::vector<std::unique_ptr<QuicServerConfigProtobuf>>& protobufs,
388 const QuicWallTime now) {
389 std::vector<QuicReferenceCountedPointer<Config>> parsed_configs;
390 bool ok = true;
391
392 for (auto& protobuf : protobufs) {
393 QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
394 if (!config) {
395 ok = false;
396 break;
397 }
398
399 parsed_configs.push_back(config);
400 }
401
402 if (parsed_configs.empty()) {
403 QUIC_LOG(WARNING) << "New config list is empty.";
404 ok = false;
405 }
406
407 if (!ok) {
408 QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
409 } else {
410 QUIC_LOG(INFO) << "Updating configs:";
411
412 QuicWriterMutexLock locked(&configs_lock_);
413 ConfigMap new_configs;
414
415 for (std::vector<QuicReferenceCountedPointer<Config>>::const_iterator i =
416 parsed_configs.begin();
417 i != parsed_configs.end(); ++i) {
418 QuicReferenceCountedPointer<Config> config = *i;
419
420 auto it = configs_.find(config->id);
421 if (it != configs_.end()) {
422 QUIC_LOG(INFO) << "Keeping scid: "
423 << QuicTextUtils::HexEncode(config->id) << " orbit: "
424 << QuicTextUtils::HexEncode(
425 reinterpret_cast<const char*>(config->orbit),
426 kOrbitSize)
427 << " new primary_time "
428 << config->primary_time.ToUNIXSeconds()
429 << " old primary_time "
430 << it->second->primary_time.ToUNIXSeconds()
431 << " new priority " << config->priority
432 << " old priority " << it->second->priority;
433 // Update primary_time and priority.
434 it->second->primary_time = config->primary_time;
435 it->second->priority = config->priority;
436 new_configs.insert(*it);
437 } else {
438 QUIC_LOG(INFO) << "Adding scid: "
439 << QuicTextUtils::HexEncode(config->id) << " orbit: "
440 << QuicTextUtils::HexEncode(
441 reinterpret_cast<const char*>(config->orbit),
442 kOrbitSize)
443 << " primary_time "
444 << config->primary_time.ToUNIXSeconds() << " priority "
445 << config->priority;
446 new_configs.insert(std::make_pair(config->id, config));
447 }
448 }
449
450 configs_.swap(new_configs);
451 SelectNewPrimaryConfig(now);
452 DCHECK(primary_config_.get());
453 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
454 primary_config_.get());
455 }
456
457 return ok;
458}
459
460void QuicCryptoServerConfig::SetSourceAddressTokenKeys(
vasilvvc48c8712019-03-11 13:38:16 -0700461 const std::vector<std::string>& keys) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462 source_address_token_boxer_.SetKeys(keys);
463}
464
465void QuicCryptoServerConfig::GetConfigIds(
vasilvvc48c8712019-03-11 13:38:16 -0700466 std::vector<std::string>* scids) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500467 QuicReaderMutexLock locked(&configs_lock_);
468 for (auto it = configs_.begin(); it != configs_.end(); ++it) {
469 scids->push_back(it->first);
470 }
471}
472
473void QuicCryptoServerConfig::ValidateClientHello(
474 const CryptoHandshakeMessage& client_hello,
475 const QuicIpAddress& client_ip,
476 const QuicSocketAddress& server_address,
477 QuicTransportVersion version,
478 const QuicClock* clock,
479 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
480 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
481 const QuicWallTime now(clock->WallNow());
482
483 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result(
484 new ValidateClientHelloResultCallback::Result(client_hello, client_ip,
485 now));
486
487 QuicStringPiece requested_scid;
488 client_hello.GetStringPiece(kSCID, &requested_scid);
489
490 QuicReferenceCountedPointer<Config> requested_config;
491 QuicReferenceCountedPointer<Config> primary_config;
492 {
493 QuicReaderMutexLock locked(&configs_lock_);
494 if (!primary_config_.get()) {
495 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
496 result->error_details = "No configurations loaded";
497 } else {
498 if (IsNextConfigReady(now)) {
499 configs_lock_.ReaderUnlock();
500 configs_lock_.WriterLock();
501 SelectNewPrimaryConfig(now);
502 DCHECK(primary_config_.get());
503 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
504 primary_config_.get());
505 configs_lock_.WriterUnlock();
506 configs_lock_.ReaderLock();
507 }
508 }
509
510 requested_config = GetConfigWithScid(requested_scid);
511 primary_config = primary_config_;
512 signed_config->config = primary_config_;
513 }
514
515 if (result->error_code == QUIC_NO_ERROR) {
516 // QUIC requires a new proof for each CHLO so clear any existing proof.
517 signed_config->chain = nullptr;
518 signed_config->proof.signature = "";
519 signed_config->proof.leaf_cert_scts = "";
520 EvaluateClientHello(server_address, version, requested_config,
521 primary_config, signed_config, result,
522 std::move(done_cb));
523 } else {
524 done_cb->Run(result, /* details = */ nullptr);
525 }
526}
527
528class ProcessClientHelloHelper {
529 public:
530 explicit ProcessClientHelloHelper(
531 std::unique_ptr<ProcessClientHelloResultCallback>* done_cb)
532 : done_cb_(done_cb) {}
533
534 ~ProcessClientHelloHelper() {
535 QUIC_BUG_IF(done_cb_ != nullptr)
536 << "Deleting ProcessClientHelloHelper with a pending callback.";
537 }
538
vasilvvc48c8712019-03-11 13:38:16 -0700539 void Fail(QuicErrorCode error, const std::string& error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500540 (*done_cb_)->Run(error, error_details, nullptr, nullptr, nullptr);
541 DetachCallback();
542 }
543
544 void Succeed(std::unique_ptr<CryptoHandshakeMessage> message,
545 std::unique_ptr<DiversificationNonce> diversification_nonce,
546 std::unique_ptr<ProofSource::Details> proof_source_details) {
vasilvvc48c8712019-03-11 13:38:16 -0700547 (*done_cb_)->Run(QUIC_NO_ERROR, std::string(), std::move(message),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500548 std::move(diversification_nonce),
549 std::move(proof_source_details));
550 DetachCallback();
551 }
552
553 void DetachCallback() {
554 QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
555 done_cb_ = nullptr;
556 }
557
558 private:
559 std::unique_ptr<ProcessClientHelloResultCallback>* done_cb_;
560};
561
562class QuicCryptoServerConfig::ProcessClientHelloCallback
563 : public ProofSource::Callback {
564 public:
565 ProcessClientHelloCallback(
566 const QuicCryptoServerConfig* config,
567 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
568 validate_chlo_result,
569 bool reject_only,
570 QuicConnectionId connection_id,
571 const QuicSocketAddress& client_address,
572 ParsedQuicVersion version,
573 const ParsedQuicVersionVector& supported_versions,
574 bool use_stateless_rejects,
575 QuicConnectionId server_designated_connection_id,
576 const QuicClock* clock,
577 QuicRandom* rand,
578 QuicCompressedCertsCache* compressed_certs_cache,
579 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
580 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
581 QuicByteCount total_framing_overhead,
582 QuicByteCount chlo_packet_size,
583 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
584 requested_config,
585 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
586 primary_config,
587 std::unique_ptr<ProcessClientHelloResultCallback> done_cb)
588 : config_(config),
589 validate_chlo_result_(std::move(validate_chlo_result)),
590 reject_only_(reject_only),
591 connection_id_(connection_id),
592 client_address_(client_address),
593 version_(version),
594 supported_versions_(supported_versions),
595 use_stateless_rejects_(use_stateless_rejects),
596 server_designated_connection_id_(server_designated_connection_id),
597 clock_(clock),
598 rand_(rand),
599 compressed_certs_cache_(compressed_certs_cache),
600 params_(params),
601 signed_config_(signed_config),
602 total_framing_overhead_(total_framing_overhead),
603 chlo_packet_size_(chlo_packet_size),
604 requested_config_(requested_config),
605 primary_config_(primary_config),
606 done_cb_(std::move(done_cb)) {}
607
608 void Run(bool ok,
609 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
610 const QuicCryptoProof& proof,
611 std::unique_ptr<ProofSource::Details> details) override {
612 if (ok) {
613 signed_config_->chain = chain;
614 signed_config_->proof = proof;
615 }
616 config_->ProcessClientHelloAfterGetProof(
617 !ok, std::move(details), validate_chlo_result_, reject_only_,
618 connection_id_, client_address_, version_, supported_versions_,
619 use_stateless_rejects_, server_designated_connection_id_, clock_, rand_,
620 compressed_certs_cache_, params_, signed_config_,
621 total_framing_overhead_, chlo_packet_size_, requested_config_,
622 primary_config_, std::move(done_cb_));
623 }
624
625 private:
626 const QuicCryptoServerConfig* config_;
627 const QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
628 validate_chlo_result_;
629 const bool reject_only_;
630 const QuicConnectionId connection_id_;
631 const QuicSocketAddress client_address_;
632 const ParsedQuicVersion version_;
633 const ParsedQuicVersionVector supported_versions_;
634 const bool use_stateless_rejects_;
635 const QuicConnectionId server_designated_connection_id_;
636 const QuicClock* const clock_;
637 QuicRandom* const rand_;
638 QuicCompressedCertsCache* compressed_certs_cache_;
639 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
640 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
641 const QuicByteCount total_framing_overhead_;
642 const QuicByteCount chlo_packet_size_;
643 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
644 requested_config_;
645 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
646 primary_config_;
647 std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
648};
649
650class QuicCryptoServerConfig::ProcessClientHelloAfterGetProofCallback
QUICHE teamfe1aca62019-03-14 13:39:01 -0700651 : public AsynchronousKeyExchange::Callback {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500652 public:
653 ProcessClientHelloAfterGetProofCallback(
654 const QuicCryptoServerConfig* config,
655 std::unique_ptr<ProofSource::Details> proof_source_details,
QUICHE teamfe1aca62019-03-14 13:39:01 -0700656 QuicTag key_exchange_type,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500657 std::unique_ptr<CryptoHandshakeMessage> out,
658 QuicStringPiece public_value,
659 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
660 validate_chlo_result,
661 QuicConnectionId connection_id,
662 const QuicSocketAddress& client_address,
663 ParsedQuicVersion version,
664 const ParsedQuicVersionVector& supported_versions,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500665 QuicRandom* rand,
666 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
667 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
668 const QuicReferenceCountedPointer<Config>& requested_config,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500669 std::unique_ptr<ProcessClientHelloResultCallback> done_cb)
670 : config_(config),
671 proof_source_details_(std::move(proof_source_details)),
QUICHE teamfe1aca62019-03-14 13:39:01 -0700672 key_exchange_type_(key_exchange_type),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500673 out_(std::move(out)),
674 public_value_(public_value),
675 validate_chlo_result_(std::move(validate_chlo_result)),
676 connection_id_(connection_id),
677 client_address_(client_address),
678 version_(version),
679 supported_versions_(supported_versions),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500680 rand_(rand),
681 params_(params),
682 signed_config_(signed_config),
683 requested_config_(requested_config),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500684 done_cb_(std::move(done_cb)) {}
685
686 void Run(bool ok) override {
687 config_->ProcessClientHelloAfterCalculateSharedKeys(
QUICHE teamfe1aca62019-03-14 13:39:01 -0700688 !ok, std::move(proof_source_details_), key_exchange_type_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500689 std::move(out_), public_value_, *validate_chlo_result_, connection_id_,
QUICHE team45c889c2019-03-14 16:37:01 -0700690 client_address_, version_, supported_versions_, rand_, params_,
691 signed_config_, requested_config_, std::move(done_cb_));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500692 }
693
694 private:
695 const QuicCryptoServerConfig* config_;
696 std::unique_ptr<ProofSource::Details> proof_source_details_;
QUICHE teamfe1aca62019-03-14 13:39:01 -0700697 QuicTag key_exchange_type_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500698 std::unique_ptr<CryptoHandshakeMessage> out_;
vasilvvc48c8712019-03-11 13:38:16 -0700699 std::string public_value_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500700 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
701 validate_chlo_result_;
702 QuicConnectionId connection_id_;
703 const QuicSocketAddress client_address_;
704 ParsedQuicVersion version_;
705 const ParsedQuicVersionVector supported_versions_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500706 QuicRandom* rand_;
707 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
708 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
709 const QuicReferenceCountedPointer<Config> requested_config_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500710 std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
711};
712
713void QuicCryptoServerConfig::ProcessClientHello(
714 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
715 validate_chlo_result,
716 bool reject_only,
717 QuicConnectionId connection_id,
718 const QuicSocketAddress& server_address,
719 const QuicSocketAddress& client_address,
720 ParsedQuicVersion version,
721 const ParsedQuicVersionVector& supported_versions,
722 bool use_stateless_rejects,
723 QuicConnectionId server_designated_connection_id,
724 const QuicClock* clock,
725 QuicRandom* rand,
726 QuicCompressedCertsCache* compressed_certs_cache,
727 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
728 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
729 QuicByteCount total_framing_overhead,
730 QuicByteCount chlo_packet_size,
731 std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
732 DCHECK(done_cb);
733
734 ProcessClientHelloHelper helper(&done_cb);
735
736 const CryptoHandshakeMessage& client_hello =
737 validate_chlo_result->client_hello;
738 const ClientHelloInfo& info = validate_chlo_result->info;
739
vasilvvc48c8712019-03-11 13:38:16 -0700740 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500741 QuicErrorCode valid = CryptoUtils::ValidateClientHello(
742 client_hello, version, supported_versions, &error_details);
743 if (valid != QUIC_NO_ERROR) {
744 helper.Fail(valid, error_details);
745 return;
746 }
747
748 QuicStringPiece requested_scid;
749 client_hello.GetStringPiece(kSCID, &requested_scid);
750 const QuicWallTime now(clock->WallNow());
751
752 QuicReferenceCountedPointer<Config> requested_config;
753 QuicReferenceCountedPointer<Config> primary_config;
754 bool no_primary_config = false;
755 {
756 QuicReaderMutexLock locked(&configs_lock_);
757
758 if (!primary_config_) {
759 no_primary_config = true;
760 } else {
761 if (IsNextConfigReady(now)) {
762 configs_lock_.ReaderUnlock();
763 configs_lock_.WriterLock();
764 SelectNewPrimaryConfig(now);
765 DCHECK(primary_config_.get());
766 DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
767 primary_config_.get());
768 configs_lock_.WriterUnlock();
769 configs_lock_.ReaderLock();
770 }
771
772 // Use the config that the client requested in order to do key-agreement.
773 // Otherwise give it a copy of |primary_config_| to use.
774 primary_config = signed_config->config;
775 requested_config = GetConfigWithScid(requested_scid);
776 }
777 }
778 if (no_primary_config) {
779 helper.Fail(QUIC_CRYPTO_INTERNAL_ERROR, "No configurations loaded");
780 return;
781 }
782
783 if (validate_chlo_result->error_code != QUIC_NO_ERROR) {
784 helper.Fail(validate_chlo_result->error_code,
785 validate_chlo_result->error_details);
786 return;
787 }
788
789 if (!ClientDemandsX509Proof(client_hello)) {
790 helper.Fail(QUIC_UNSUPPORTED_PROOF_DEMAND, "Missing or invalid PDMD");
791 return;
792 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500793
794 // No need to get a new proof if one was already generated.
795 if (!signed_config->chain) {
QUICHE teamea5bdef2019-03-13 15:41:27 -0700796 auto cb = QuicMakeUnique<ProcessClientHelloCallback>(
797 this, validate_chlo_result, reject_only, connection_id, client_address,
798 version, supported_versions, use_stateless_rejects,
799 server_designated_connection_id, clock, rand, compressed_certs_cache,
800 params, signed_config, total_framing_overhead, chlo_packet_size,
801 requested_config, primary_config, std::move(done_cb));
QUICHE team84910bd2019-03-15 07:03:40 -0700802 const std::string chlo_hash =
803 CryptoUtils::HashHandshakeMessage(client_hello, Perspective::IS_SERVER);
804
805 DCHECK(proof_source_.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500806 proof_source_->GetProof(
vasilvvc48c8712019-03-11 13:38:16 -0700807 server_address, std::string(info.sni), primary_config->serialized,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500808 version.transport_version, chlo_hash, std::move(cb));
809 helper.DetachCallback();
810 return;
811 }
812
813 helper.DetachCallback();
814 ProcessClientHelloAfterGetProof(
815 /* found_error = */ false, /* proof_source_details = */ nullptr,
816 validate_chlo_result, reject_only, connection_id, client_address, version,
817 supported_versions, use_stateless_rejects,
818 server_designated_connection_id, clock, rand, compressed_certs_cache,
819 params, signed_config, total_framing_overhead, chlo_packet_size,
820 requested_config, primary_config, std::move(done_cb));
821}
822
823void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
824 bool found_error,
825 std::unique_ptr<ProofSource::Details> proof_source_details,
826 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
827 validate_chlo_result,
828 bool reject_only,
829 QuicConnectionId connection_id,
830 const QuicSocketAddress& client_address,
831 ParsedQuicVersion version,
832 const ParsedQuicVersionVector& supported_versions,
833 bool use_stateless_rejects,
834 QuicConnectionId server_designated_connection_id,
835 const QuicClock* clock,
836 QuicRandom* rand,
837 QuicCompressedCertsCache* compressed_certs_cache,
838 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
839 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
840 QuicByteCount total_framing_overhead,
841 QuicByteCount chlo_packet_size,
842 const QuicReferenceCountedPointer<Config>& requested_config,
843 const QuicReferenceCountedPointer<Config>& primary_config,
844 std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
845 QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
846 connection_id, version.transport_version))
847 << "ProcessClientHelloAfterGetProof: attempted to use connection ID "
848 << connection_id << " which is invalid with version "
849 << QuicVersionToString(version.transport_version);
850 ProcessClientHelloHelper helper(&done_cb);
851
852 if (found_error) {
853 helper.Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
854 return;
855 }
856
857 const CryptoHandshakeMessage& client_hello =
858 validate_chlo_result->client_hello;
859 const ClientHelloInfo& info = validate_chlo_result->info;
QUICHE teamea5bdef2019-03-13 15:41:27 -0700860 auto out_diversification_nonce = QuicMakeUnique<DiversificationNonce>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500861
862 QuicStringPiece cert_sct;
863 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) &&
864 cert_sct.empty()) {
865 params->sct_supported_by_client = true;
866 }
867
QUICHE teamea5bdef2019-03-13 15:41:27 -0700868 auto out = QuicMakeUnique<CryptoHandshakeMessage>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500869 if (!info.reject_reasons.empty() || !requested_config.get()) {
870 BuildRejection(version.transport_version, clock->WallNow(), *primary_config,
871 client_hello, info,
872 validate_chlo_result->cached_network_params,
873 use_stateless_rejects, server_designated_connection_id, rand,
874 compressed_certs_cache, params, *signed_config,
875 total_framing_overhead, chlo_packet_size, out.get());
876 if (rejection_observer_ != nullptr) {
877 rejection_observer_->OnRejectionBuilt(info.reject_reasons, out.get());
878 }
879 helper.Succeed(std::move(out), std::move(out_diversification_nonce),
880 std::move(proof_source_details));
881 return;
882 }
883
884 if (reject_only) {
885 helper.Succeed(std::move(out), std::move(out_diversification_nonce),
886 std::move(proof_source_details));
887 return;
888 }
889
890 QuicTagVector their_aeads;
891 QuicTagVector their_key_exchanges;
892 if (client_hello.GetTaglist(kAEAD, &their_aeads) != QUIC_NO_ERROR ||
893 client_hello.GetTaglist(kKEXS, &their_key_exchanges) != QUIC_NO_ERROR ||
894 their_aeads.size() != 1 || their_key_exchanges.size() != 1) {
895 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
896 "Missing or invalid AEAD or KEXS");
897 return;
898 }
899
900 size_t key_exchange_index;
901 if (!FindMutualQuicTag(requested_config->aead, their_aeads, &params->aead,
902 nullptr) ||
903 !FindMutualQuicTag(requested_config->kexs, their_key_exchanges,
904 &params->key_exchange, &key_exchange_index)) {
905 helper.Fail(QUIC_CRYPTO_NO_SUPPORT, "Unsupported AEAD or KEXS");
906 return;
907 }
908
909 if (!requested_config->tb_key_params.empty()) {
910 QuicTagVector their_tbkps;
911 switch (client_hello.GetTaglist(kTBKP, &their_tbkps)) {
912 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
913 break;
914 case QUIC_NO_ERROR:
915 if (FindMutualQuicTag(requested_config->tb_key_params, their_tbkps,
916 &params->token_binding_key_param, nullptr)) {
917 break;
918 }
919 QUIC_FALLTHROUGH_INTENDED;
920 default:
921 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
922 "Invalid Token Binding key parameter");
923 return;
924 }
925 }
926
927 QuicStringPiece public_value;
928 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
929 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Missing public value");
930 return;
931 }
932
QUICHE teamfe1aca62019-03-14 13:39:01 -0700933 const AsynchronousKeyExchange* key_exchange =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500934 requested_config->key_exchanges[key_exchange_index].get();
935 // TODO(rch): Would it be better to implement a move operator and just
936 // std::move(helper) instead of done_cb?
937 helper.DetachCallback();
938 auto cb = QuicMakeUnique<ProcessClientHelloAfterGetProofCallback>(
QUICHE teamfe1aca62019-03-14 13:39:01 -0700939 this, std::move(proof_source_details), key_exchange->type(),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500940 std::move(out), public_value, validate_chlo_result, connection_id,
QUICHE team45c889c2019-03-14 16:37:01 -0700941 client_address, version, supported_versions, rand, params, signed_config,
942 requested_config, std::move(done_cb));
QUICHE teamfe1aca62019-03-14 13:39:01 -0700943 key_exchange->CalculateSharedKeyAsync(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500944 public_value, &params->initial_premaster_secret, std::move(cb));
945}
946
947void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
948 bool found_error,
949 std::unique_ptr<ProofSource::Details> proof_source_details,
QUICHE teamfe1aca62019-03-14 13:39:01 -0700950 QuicTag key_exchange_type,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500951 std::unique_ptr<CryptoHandshakeMessage> out,
952 QuicStringPiece public_value,
953 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
954 QuicConnectionId connection_id,
955 const QuicSocketAddress& client_address,
956 ParsedQuicVersion version,
957 const ParsedQuicVersionVector& supported_versions,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500958 QuicRandom* rand,
959 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
960 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
961 const QuicReferenceCountedPointer<Config>& requested_config,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500962 std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
963 QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
964 connection_id, version.transport_version))
965 << "ProcessClientHelloAfterCalculateSharedKeys:"
966 " attempted to use connection ID "
967 << connection_id << " which is invalid with version "
968 << QuicVersionToString(version.transport_version);
969 ProcessClientHelloHelper helper(&done_cb);
970
971 if (found_error) {
QUICHE teamfe1aca62019-03-14 13:39:01 -0700972 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
973 "Failed to calculate shared key");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500974 return;
975 }
976
977 const CryptoHandshakeMessage& client_hello =
978 validate_chlo_result.client_hello;
979 const ClientHelloInfo& info = validate_chlo_result.info;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500980
981 if (!info.sni.empty()) {
982 params->sni = QuicHostnameUtils::NormalizeHostname(info.sni);
983 }
984
vasilvvc48c8712019-03-11 13:38:16 -0700985 std::string hkdf_suffix;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500986 const QuicData& client_hello_serialized = client_hello.GetSerialized();
vasilvvc48c8712019-03-11 13:38:16 -0700987 hkdf_suffix.reserve(connection_id.length() +
988 client_hello_serialized.length() +
989 requested_config->serialized.size());
990 hkdf_suffix.append(connection_id.data(), connection_id.length());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500991 hkdf_suffix.append(client_hello_serialized.data(),
992 client_hello_serialized.length());
993 hkdf_suffix.append(requested_config->serialized);
994 DCHECK(proof_source_.get());
995 if (signed_config->chain->certs.empty()) {
996 helper.Fail(QUIC_CRYPTO_INTERNAL_ERROR, "Failed to get certs");
997 return;
998 }
999 hkdf_suffix.append(signed_config->chain->certs.at(0));
1000
1001 QuicStringPiece cetv_ciphertext;
1002 if (requested_config->channel_id_enabled &&
1003 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
1004 CryptoHandshakeMessage client_hello_copy(client_hello);
1005 client_hello_copy.Erase(kCETV);
1006 client_hello_copy.Erase(kPAD);
1007
1008 const QuicData& client_hello_copy_serialized =
1009 client_hello_copy.GetSerialized();
vasilvvc48c8712019-03-11 13:38:16 -07001010 std::string hkdf_input;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001011 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
1012 strlen(QuicCryptoConfig::kCETVLabel) + 1);
1013 hkdf_input.append(connection_id.data(), connection_id.length());
1014 hkdf_input.append(client_hello_copy_serialized.data(),
1015 client_hello_copy_serialized.length());
1016 hkdf_input.append(requested_config->serialized);
1017
1018 CrypterPair crypters;
1019 if (!CryptoUtils::DeriveKeys(
1020 params->initial_premaster_secret, params->aead, info.client_nonce,
1021 info.server_nonce, pre_shared_key_, hkdf_input,
1022 Perspective::IS_SERVER, CryptoUtils::Diversification::Never(),
1023 &crypters, nullptr /* subkey secret */)) {
1024 helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
1025 "Symmetric key setup failed");
1026 return;
1027 }
1028
1029 char plaintext[kMaxPacketSize];
1030 size_t plaintext_length = 0;
1031 const bool success = crypters.decrypter->DecryptPacket(
1032 0 /* packet number */, QuicStringPiece() /* associated data */,
1033 cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
1034 if (!success) {
1035 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1036 "CETV decryption failure");
1037 return;
1038 }
1039 std::unique_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
1040 QuicStringPiece(plaintext, plaintext_length)));
1041 if (!cetv.get()) {
1042 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "CETV parse error");
1043 return;
1044 }
1045
1046 QuicStringPiece key, signature;
1047 if (cetv->GetStringPiece(kCIDK, &key) &&
1048 cetv->GetStringPiece(kCIDS, &signature)) {
1049 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
1050 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1051 "ChannelID signature failure");
1052 return;
1053 }
1054
vasilvvc48c8712019-03-11 13:38:16 -07001055 params->channel_id = std::string(key);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001056 }
1057 }
1058
vasilvvc48c8712019-03-11 13:38:16 -07001059 std::string hkdf_input;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001060 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
1061 hkdf_input.reserve(label_len + hkdf_suffix.size());
1062 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
1063 hkdf_input.append(hkdf_suffix);
1064
QUICHE team45c889c2019-03-14 16:37:01 -07001065 auto out_diversification_nonce = QuicMakeUnique<DiversificationNonce>();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001066 rand->RandBytes(out_diversification_nonce->data(),
1067 out_diversification_nonce->size());
1068 CryptoUtils::Diversification diversification =
1069 CryptoUtils::Diversification::Now(out_diversification_nonce.get());
1070 if (!CryptoUtils::DeriveKeys(
1071 params->initial_premaster_secret, params->aead, info.client_nonce,
1072 info.server_nonce, pre_shared_key_, hkdf_input,
1073 Perspective::IS_SERVER, diversification, &params->initial_crypters,
1074 &params->initial_subkey_secret)) {
1075 helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
1076 "Symmetric key setup failed");
1077 return;
1078 }
1079
vasilvvc48c8712019-03-11 13:38:16 -07001080 std::string forward_secure_public_value;
QUICHE teamfe1aca62019-03-14 13:39:01 -07001081 std::unique_ptr<SynchronousKeyExchange> forward_secure_key_exchange =
1082 CreateLocalSynchronousKeyExchange(key_exchange_type, rand);
1083 if (!forward_secure_key_exchange) {
1084 QUIC_DLOG(WARNING) << "Failed to create keypair";
1085 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1086 "Failed to create keypair");
1087 return;
1088 }
1089
QUICHE teama6ef0a62019-03-07 20:34:33 -05001090 forward_secure_public_value =
vasilvvc48c8712019-03-11 13:38:16 -07001091 std::string(forward_secure_key_exchange->public_value());
QUICHE teamfe1aca62019-03-14 13:39:01 -07001092 if (!forward_secure_key_exchange->CalculateSharedKeySync(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001093 public_value, &params->forward_secure_premaster_secret)) {
1094 helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Invalid public value");
1095 return;
1096 }
1097
vasilvvc48c8712019-03-11 13:38:16 -07001098 std::string forward_secure_hkdf_input;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001099 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
1100 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
1101 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
1102 label_len);
1103 forward_secure_hkdf_input.append(hkdf_suffix);
1104
vasilvvc48c8712019-03-11 13:38:16 -07001105 std::string shlo_nonce;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001106 shlo_nonce = NewServerNonce(rand, info.now);
1107 out->SetStringPiece(kServerNonceTag, shlo_nonce);
1108
1109 if (!CryptoUtils::DeriveKeys(
1110 params->forward_secure_premaster_secret, params->aead,
1111 info.client_nonce,
1112 shlo_nonce.empty() ? info.server_nonce : shlo_nonce, pre_shared_key_,
1113 forward_secure_hkdf_input, Perspective::IS_SERVER,
1114 CryptoUtils::Diversification::Never(),
1115 &params->forward_secure_crypters, &params->subkey_secret)) {
1116 helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
1117 "Symmetric key setup failed");
1118 return;
1119 }
1120
1121 out->set_tag(kSHLO);
1122 out->SetVersionVector(kVER, supported_versions);
1123 out->SetStringPiece(
1124 kSourceAddressTokenTag,
1125 NewSourceAddressToken(*requested_config, info.source_address_tokens,
1126 client_address.host(), rand, info.now, nullptr));
1127 QuicSocketAddressCoder address_coder(client_address);
1128 out->SetStringPiece(kCADR, address_coder.Encode());
1129 out->SetStringPiece(kPUBS, forward_secure_public_value);
1130
1131 helper.Succeed(std::move(out), std::move(out_diversification_nonce),
1132 std::move(proof_source_details));
1133}
1134
1135QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1136QuicCryptoServerConfig::GetConfigWithScid(
1137 QuicStringPiece requested_scid) const {
1138 configs_lock_.AssertReaderHeld();
1139
1140 if (!requested_scid.empty()) {
vasilvvc48c8712019-03-11 13:38:16 -07001141 auto it = configs_.find((std::string(requested_scid)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001142 if (it != configs_.end()) {
1143 // We'll use the config that the client requested in order to do
1144 // key-agreement.
1145 return QuicReferenceCountedPointer<Config>(it->second);
1146 }
1147 }
1148
1149 return QuicReferenceCountedPointer<Config>();
1150}
1151
1152// ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
1153// Config's based on their primary_time.
1154// static
1155bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
1156 const QuicReferenceCountedPointer<Config>& a,
1157 const QuicReferenceCountedPointer<Config>& b) {
1158 if (a->primary_time.IsBefore(b->primary_time) ||
1159 b->primary_time.IsBefore(a->primary_time)) {
1160 // Primary times differ.
1161 return a->primary_time.IsBefore(b->primary_time);
1162 } else if (a->priority != b->priority) {
1163 // Primary times are equal, sort backwards by priority.
1164 return a->priority < b->priority;
1165 } else {
1166 // Primary times and priorities are equal, sort by config id.
1167 return a->id < b->id;
1168 }
1169}
1170
1171void QuicCryptoServerConfig::SelectNewPrimaryConfig(
1172 const QuicWallTime now) const {
1173 std::vector<QuicReferenceCountedPointer<Config>> configs;
1174 configs.reserve(configs_.size());
1175
1176 for (auto it = configs_.begin(); it != configs_.end(); ++it) {
1177 // TODO(avd) Exclude expired configs?
1178 configs.push_back(it->second);
1179 }
1180
1181 if (configs.empty()) {
1182 if (primary_config_ != nullptr) {
1183 QUIC_BUG << "No valid QUIC server config. Keeping the current config.";
1184 } else {
1185 QUIC_BUG << "No valid QUIC server config.";
1186 }
1187 return;
1188 }
1189
1190 std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
1191
1192 QuicReferenceCountedPointer<Config> best_candidate = configs[0];
1193
1194 for (size_t i = 0; i < configs.size(); ++i) {
1195 const QuicReferenceCountedPointer<Config> config(configs[i]);
1196 if (!config->primary_time.IsAfter(now)) {
1197 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
1198 best_candidate = config;
1199 }
1200 continue;
1201 }
1202
1203 // This is the first config with a primary_time in the future. Thus the
1204 // previous Config should be the primary and this one should determine the
1205 // next_config_promotion_time_.
1206 QuicReferenceCountedPointer<Config> new_primary = best_candidate;
1207 if (i == 0) {
1208 // We need the primary_time of the next config.
1209 if (configs.size() > 1) {
1210 next_config_promotion_time_ = configs[1]->primary_time;
1211 } else {
1212 next_config_promotion_time_ = QuicWallTime::Zero();
1213 }
1214 } else {
1215 next_config_promotion_time_ = config->primary_time;
1216 }
1217
1218 if (primary_config_) {
1219 primary_config_->is_primary = false;
1220 }
1221 primary_config_ = new_primary;
1222 new_primary->is_primary = true;
1223 QUIC_DLOG(INFO) << "New primary config. orbit: "
1224 << QuicTextUtils::HexEncode(reinterpret_cast<const char*>(
1225 primary_config_->orbit),
1226 kOrbitSize);
1227 if (primary_config_changed_cb_ != nullptr) {
1228 primary_config_changed_cb_->Run(primary_config_->id);
1229 }
1230
1231 return;
1232 }
1233
1234 // All config's primary times are in the past. We should make the most recent
1235 // and highest priority candidate primary.
1236 QuicReferenceCountedPointer<Config> new_primary = best_candidate;
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(
1244 reinterpret_cast<const char*>(primary_config_->orbit),
1245 kOrbitSize)
1246 << " scid: " << QuicTextUtils::HexEncode(primary_config_->id);
1247 next_config_promotion_time_ = QuicWallTime::Zero();
1248 if (primary_config_changed_cb_ != nullptr) {
1249 primary_config_changed_cb_->Run(primary_config_->id);
1250 }
1251}
1252
1253class QuicCryptoServerConfig::EvaluateClientHelloCallback
1254 : public ProofSource::Callback {
1255 public:
1256 EvaluateClientHelloCallback(
1257 const QuicCryptoServerConfig& config,
1258 const QuicIpAddress& server_ip,
1259 QuicTransportVersion version,
1260 QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1261 requested_config,
1262 QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1263 primary_config,
1264 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
1265 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1266 client_hello_state,
1267 std::unique_ptr<ValidateClientHelloResultCallback> done_cb)
1268 : config_(config),
1269 server_ip_(server_ip),
1270 version_(version),
1271 requested_config_(std::move(requested_config)),
1272 primary_config_(std::move(primary_config)),
1273 signed_config_(signed_config),
1274 client_hello_state_(std::move(client_hello_state)),
1275 done_cb_(std::move(done_cb)) {}
1276
1277 void Run(bool ok,
1278 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
1279 const QuicCryptoProof& proof,
1280 std::unique_ptr<ProofSource::Details> details) override {
1281 if (ok) {
1282 signed_config_->chain = chain;
1283 signed_config_->proof = proof;
1284 }
1285 config_.EvaluateClientHelloAfterGetProof(
1286 server_ip_, version_, requested_config_, primary_config_,
1287 signed_config_, std::move(details), !ok, client_hello_state_,
1288 std::move(done_cb_));
1289 }
1290
1291 private:
1292 const QuicCryptoServerConfig& config_;
1293 const QuicIpAddress& server_ip_;
1294 const QuicTransportVersion version_;
1295 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1296 requested_config_;
1297 const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1298 primary_config_;
1299 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1300 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1301 client_hello_state_;
1302 std::unique_ptr<ValidateClientHelloResultCallback> done_cb_;
1303};
1304
1305void QuicCryptoServerConfig::EvaluateClientHello(
1306 const QuicSocketAddress& server_address,
1307 QuicTransportVersion version,
1308 QuicReferenceCountedPointer<Config> requested_config,
1309 QuicReferenceCountedPointer<Config> primary_config,
1310 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
1311 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1312 client_hello_state,
1313 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
1314 DCHECK(!signed_config->chain);
1315
1316 ValidateClientHelloHelper helper(client_hello_state, &done_cb);
1317
1318 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
1319 ClientHelloInfo* info = &(client_hello_state->info);
1320
1321 if (validate_chlo_size_ && client_hello.size() < kClientHelloMinimumSize) {
1322 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
1323 "Client hello too small", nullptr);
1324 return;
1325 }
1326
1327 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
1328 !QuicHostnameUtils::IsValidSNI(info->sni)) {
1329 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1330 "Invalid SNI name", nullptr);
1331 return;
1332 }
1333
1334 client_hello.GetStringPiece(kUAID, &info->user_agent_id);
1335
1336 HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
1337 if (validate_source_address_token_) {
1338 QuicStringPiece srct;
1339 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
1340 Config& config =
1341 requested_config != nullptr ? *requested_config : *primary_config;
1342 source_address_token_error =
1343 ParseSourceAddressToken(config, srct, &info->source_address_tokens);
1344
1345 if (source_address_token_error == HANDSHAKE_OK) {
1346 source_address_token_error = ValidateSourceAddressTokens(
1347 info->source_address_tokens, info->client_ip, info->now,
1348 &client_hello_state->cached_network_params);
1349 }
1350 info->valid_source_address_token =
1351 (source_address_token_error == HANDSHAKE_OK);
1352 } else {
1353 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
1354 }
1355 } else {
1356 source_address_token_error = HANDSHAKE_OK;
1357 info->valid_source_address_token = true;
1358 }
1359
1360 if (!requested_config.get()) {
1361 QuicStringPiece requested_scid;
1362 if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
1363 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1364 } else {
1365 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1366 }
1367 // No server config with the requested ID.
1368 helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1369 return;
1370 }
1371
1372 if (!client_hello.GetStringPiece(kNONC, &info->client_nonce)) {
1373 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1374 // Report no client nonce as INCHOATE_HELLO_FAILURE.
1375 helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1376 return;
1377 }
1378
1379 if (source_address_token_error != HANDSHAKE_OK) {
1380 info->reject_reasons.push_back(source_address_token_error);
1381 // No valid source address token.
1382 }
1383
1384 QuicReferenceCountedPointer<ProofSource::Chain> chain =
vasilvvc48c8712019-03-11 13:38:16 -07001385 proof_source_->GetCertChain(server_address, std::string(info->sni));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001386 if (!chain) {
1387 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1388 } else if (!ValidateExpectedLeafCertificate(client_hello, chain->certs)) {
1389 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
1390 }
1391 EvaluateClientHelloAfterGetProof(
1392 server_address.host(), version, requested_config, primary_config,
1393 signed_config, /*proof_source_details=*/nullptr,
1394 /*get_proof_failed=*/false, client_hello_state, std::move(done_cb));
1395 helper.DetachCallback();
1396}
1397
1398void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof(
1399 const QuicIpAddress& server_ip,
1400 QuicTransportVersion version,
1401 QuicReferenceCountedPointer<Config> requested_config,
1402 QuicReferenceCountedPointer<Config> primary_config,
1403 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
1404 std::unique_ptr<ProofSource::Details> proof_source_details,
1405 bool get_proof_failed,
1406 QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
1407 client_hello_state,
1408 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
1409 ValidateClientHelloHelper helper(client_hello_state, &done_cb);
1410 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
1411 ClientHelloInfo* info = &(client_hello_state->info);
1412
1413 if (info->client_nonce.size() != kNonceSize) {
1414 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
1415 // Invalid client nonce.
1416 QUIC_LOG_FIRST_N(ERROR, 2)
1417 << "Invalid client nonce: " << client_hello.DebugString();
1418 QUIC_DLOG(INFO) << "Invalid client nonce.";
1419 }
1420
1421 // Server nonce is optional, and used for key derivation if present.
1422 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
1423
1424 QUIC_DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
1425 // If the server nonce is empty and we're requiring handshake confirmation
1426 // for DoS reasons then we must reject the CHLO.
1427 if (GetQuicReloadableFlag(quic_require_handshake_confirmation) &&
1428 info->server_nonce.empty()) {
1429 info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
1430 }
1431 helper.ValidationComplete(QUIC_NO_ERROR, "", std::move(proof_source_details));
1432}
1433
1434void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1435 QuicTransportVersion version,
1436 QuicStringPiece chlo_hash,
1437 const SourceAddressTokens& previous_source_address_tokens,
1438 const QuicSocketAddress& server_address,
1439 const QuicIpAddress& client_ip,
1440 const QuicClock* clock,
1441 QuicRandom* rand,
1442 QuicCompressedCertsCache* compressed_certs_cache,
1443 const QuicCryptoNegotiatedParameters& params,
1444 const CachedNetworkParameters* cached_network_params,
1445 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
vasilvvc48c8712019-03-11 13:38:16 -07001446 std::string serialized;
1447 std::string source_address_token;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001448 const CommonCertSets* common_cert_sets;
1449 {
1450 QuicReaderMutexLock locked(&configs_lock_);
1451 serialized = primary_config_->serialized;
1452 common_cert_sets = primary_config_->common_cert_sets;
1453 source_address_token = NewSourceAddressToken(
1454 *primary_config_, previous_source_address_tokens, client_ip, rand,
1455 clock->WallNow(), cached_network_params);
1456 }
1457
1458 CryptoHandshakeMessage message;
1459 message.set_tag(kSCUP);
1460 message.SetStringPiece(kSCFG, serialized);
1461 message.SetStringPiece(kSourceAddressTokenTag, source_address_token);
1462
QUICHE teamea5bdef2019-03-13 15:41:27 -07001463 auto proof_source_cb =
1464 QuicMakeUnique<BuildServerConfigUpdateMessageProofSourceCallback>(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001465 this, version, compressed_certs_cache, common_cert_sets, params,
QUICHE teamea5bdef2019-03-13 15:41:27 -07001466 std::move(message), std::move(cb));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001467
1468 proof_source_->GetProof(server_address, params.sni, serialized, version,
1469 chlo_hash, std::move(proof_source_cb));
1470}
1471
1472QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1473 ~BuildServerConfigUpdateMessageProofSourceCallback() {}
1474
1475QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1476 BuildServerConfigUpdateMessageProofSourceCallback(
1477 const QuicCryptoServerConfig* config,
1478 QuicTransportVersion version,
1479 QuicCompressedCertsCache* compressed_certs_cache,
1480 const CommonCertSets* common_cert_sets,
1481 const QuicCryptoNegotiatedParameters& params,
1482 CryptoHandshakeMessage message,
1483 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
1484 : config_(config),
1485 version_(version),
1486 compressed_certs_cache_(compressed_certs_cache),
1487 common_cert_sets_(common_cert_sets),
1488 client_common_set_hashes_(params.client_common_set_hashes),
1489 client_cached_cert_hashes_(params.client_cached_cert_hashes),
1490 sct_supported_by_client_(params.sct_supported_by_client),
1491 sni_(params.sni),
1492 message_(std::move(message)),
1493 cb_(std::move(cb)) {}
1494
1495void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1496 Run(bool ok,
1497 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
1498 const QuicCryptoProof& proof,
1499 std::unique_ptr<ProofSource::Details> details) {
1500 config_->FinishBuildServerConfigUpdateMessage(
1501 version_, compressed_certs_cache_, common_cert_sets_,
1502 client_common_set_hashes_, client_cached_cert_hashes_,
1503 sct_supported_by_client_, sni_, ok, chain, proof.signature,
1504 proof.leaf_cert_scts, std::move(details), std::move(message_),
1505 std::move(cb_));
1506}
1507
1508void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
1509 QuicTransportVersion version,
1510 QuicCompressedCertsCache* compressed_certs_cache,
1511 const CommonCertSets* common_cert_sets,
vasilvvc48c8712019-03-11 13:38:16 -07001512 const std::string& client_common_set_hashes,
1513 const std::string& client_cached_cert_hashes,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001514 bool sct_supported_by_client,
vasilvvc48c8712019-03-11 13:38:16 -07001515 const std::string& sni,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001516 bool ok,
1517 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
vasilvvc48c8712019-03-11 13:38:16 -07001518 const std::string& signature,
1519 const std::string& leaf_cert_sct,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001520 std::unique_ptr<ProofSource::Details> details,
1521 CryptoHandshakeMessage message,
1522 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
1523 if (!ok) {
1524 cb->Run(false, message);
1525 return;
1526 }
1527
vasilvvc48c8712019-03-11 13:38:16 -07001528 const std::string compressed =
QUICHE teama6ef0a62019-03-07 20:34:33 -05001529 CompressChain(compressed_certs_cache, chain, client_common_set_hashes,
1530 client_cached_cert_hashes, common_cert_sets);
1531
1532 message.SetStringPiece(kCertificateTag, compressed);
1533 message.SetStringPiece(kPROF, signature);
1534 if (sct_supported_by_client && enable_serving_sct_) {
1535 if (leaf_cert_sct.empty()) {
1536 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1537 << "SCT is expected but it is empty. SNI: " << sni;
1538 } else {
1539 message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct);
1540 }
1541 }
1542
1543 cb->Run(true, message);
1544}
1545
1546void QuicCryptoServerConfig::BuildRejection(
1547 QuicTransportVersion version,
1548 QuicWallTime now,
1549 const Config& config,
1550 const CryptoHandshakeMessage& client_hello,
1551 const ClientHelloInfo& info,
1552 const CachedNetworkParameters& cached_network_params,
1553 bool use_stateless_rejects,
1554 QuicConnectionId server_designated_connection_id,
1555 QuicRandom* rand,
1556 QuicCompressedCertsCache* compressed_certs_cache,
1557 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
1558 const QuicSignedServerConfig& signed_config,
1559 QuicByteCount total_framing_overhead,
1560 QuicByteCount chlo_packet_size,
1561 CryptoHandshakeMessage* out) const {
1562 if (GetQuicReloadableFlag(enable_quic_stateless_reject_support) &&
1563 use_stateless_rejects) {
1564 QUIC_DVLOG(1) << "QUIC Crypto server config returning stateless reject "
1565 << "with server-designated connection ID "
1566 << server_designated_connection_id;
1567 out->set_tag(kSREJ);
vasilvvc48c8712019-03-11 13:38:16 -07001568 if (!QuicUtils::IsConnectionIdValidForVersion(
1569 server_designated_connection_id, version)) {
1570 QUIC_BUG << "Tried to send server designated connection ID "
1571 << server_designated_connection_id
1572 << " which is invalid with version "
1573 << QuicVersionToString(version);
1574 return;
1575 }
1576 out->SetStringPiece(
1577 kRCID, QuicStringPiece(server_designated_connection_id.data(),
1578 server_designated_connection_id.length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001579 } else {
1580 out->set_tag(kREJ);
1581 }
1582 out->SetStringPiece(kSCFG, config.serialized);
1583 out->SetStringPiece(
1584 kSourceAddressTokenTag,
1585 NewSourceAddressToken(config, info.source_address_tokens, info.client_ip,
1586 rand, info.now, &cached_network_params));
1587 out->SetValue(kSTTL, config.expiry_time.AbsoluteDifference(now).ToSeconds());
1588 if (replay_protection_) {
1589 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
1590 }
1591
1592 // Send client the reject reason for debugging purposes.
1593 DCHECK_LT(0u, info.reject_reasons.size());
1594 out->SetVector(kRREJ, info.reject_reasons);
1595
1596 // The client may have requested a certificate chain.
1597 if (!ClientDemandsX509Proof(client_hello)) {
1598 QUIC_BUG << "x509 certificates not supported in proof demand";
1599 return;
1600 }
1601
1602 QuicStringPiece client_common_set_hashes;
1603 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
vasilvvc48c8712019-03-11 13:38:16 -07001604 params->client_common_set_hashes = std::string(client_common_set_hashes);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001605 }
1606
1607 QuicStringPiece client_cached_cert_hashes;
1608 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
vasilvvc48c8712019-03-11 13:38:16 -07001609 params->client_cached_cert_hashes = std::string(client_cached_cert_hashes);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001610 } else {
1611 params->client_cached_cert_hashes.clear();
1612 }
1613
vasilvvc48c8712019-03-11 13:38:16 -07001614 const std::string compressed =
QUICHE teama6ef0a62019-03-07 20:34:33 -05001615 CompressChain(compressed_certs_cache, signed_config.chain,
1616 params->client_common_set_hashes,
1617 params->client_cached_cert_hashes, config.common_cert_sets);
1618
1619 DCHECK_GT(chlo_packet_size, client_hello.size());
1620 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1621 // message is taken up by things other than the certificates.
1622 // STK: 56 bytes
1623 // SNO: 56 bytes
1624 // SCFG
1625 // SCID: 16 bytes
1626 // PUBS: 38 bytes
1627 const size_t kREJOverheadBytes = 166;
1628 // max_unverified_size is the number of bytes that the certificate chain,
1629 // signature, and (optionally) signed certificate timestamp can consume before
1630 // we will demand a valid source-address token.
1631 const size_t max_unverified_size =
1632 chlo_multiplier_ * (chlo_packet_size - total_framing_overhead) -
1633 kREJOverheadBytes;
1634 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1635 "overhead calculation may underflow");
1636 bool should_return_sct =
1637 params->sct_supported_by_client && enable_serving_sct_;
vasilvvc48c8712019-03-11 13:38:16 -07001638 const std::string& cert_sct = signed_config.proof.leaf_cert_scts;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001639 const size_t sct_size = should_return_sct ? cert_sct.size() : 0;
1640 const size_t total_size =
1641 signed_config.proof.signature.size() + compressed.size() + sct_size;
1642 if (info.valid_source_address_token || total_size < max_unverified_size) {
1643 out->SetStringPiece(kCertificateTag, compressed);
1644 out->SetStringPiece(kPROF, signed_config.proof.signature);
1645 if (should_return_sct) {
1646 if (cert_sct.empty()) {
1647 if (!GetQuicReloadableFlag(quic_log_cert_name_for_empty_sct)) {
1648 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1649 << "SCT is expected but it is empty. sni :" << params->sni;
1650 } else {
1651 // Log SNI and subject name for the leaf cert if its SCT is empty.
1652 // This is for debugging b/28342827.
vasilvvc48c8712019-03-11 13:38:16 -07001653 const std::vector<std::string>& certs = signed_config.chain->certs;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001654 QuicStringPiece ca_subject;
1655 if (!certs.empty()) {
1656 QuicCertUtils::ExtractSubjectNameFromDERCert(certs[0], &ca_subject);
1657 }
1658 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1659 << "SCT is expected but it is empty. sni: '" << params->sni
1660 << "' cert subject: '" << ca_subject << "'";
1661 }
1662 } else {
1663 out->SetStringPiece(kCertificateSCTTag, cert_sct);
1664 }
1665 }
1666 } else {
1667 QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1668 << "Sending inchoate REJ for hostname: " << info.sni
1669 << " signature: " << signed_config.proof.signature.size()
1670 << " cert: " << compressed.size() << " sct:" << sct_size
1671 << " total: " << total_size << " max: " << max_unverified_size;
1672 }
1673}
1674
vasilvvc48c8712019-03-11 13:38:16 -07001675std::string QuicCryptoServerConfig::CompressChain(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001676 QuicCompressedCertsCache* compressed_certs_cache,
1677 const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
vasilvvc48c8712019-03-11 13:38:16 -07001678 const std::string& client_common_set_hashes,
1679 const std::string& client_cached_cert_hashes,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001680 const CommonCertSets* common_sets) {
1681 // Check whether the compressed certs is available in the cache.
1682 DCHECK(compressed_certs_cache);
vasilvvc48c8712019-03-11 13:38:16 -07001683 const std::string* cached_value = compressed_certs_cache->GetCompressedCert(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001684 chain, client_common_set_hashes, client_cached_cert_hashes);
1685 if (cached_value) {
1686 return *cached_value;
1687 }
vasilvvc48c8712019-03-11 13:38:16 -07001688 std::string compressed =
QUICHE teama6ef0a62019-03-07 20:34:33 -05001689 CertCompressor::CompressChain(chain->certs, client_common_set_hashes,
1690 client_cached_cert_hashes, common_sets);
1691 // Insert the newly compressed cert to cache.
1692 compressed_certs_cache->Insert(chain, client_common_set_hashes,
1693 client_cached_cert_hashes, compressed);
1694 return compressed;
1695}
1696
1697QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
1698QuicCryptoServerConfig::ParseConfigProtobuf(
1699 const std::unique_ptr<QuicServerConfigProtobuf>& protobuf) {
QUICHE teamfe1aca62019-03-14 13:39:01 -07001700 std::unique_ptr<CryptoHandshakeMessage> msg =
1701 CryptoFramer::ParseMessage(protobuf->config());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001702
1703 if (msg->tag() != kSCFG) {
1704 QUIC_LOG(WARNING) << "Server config message has tag " << msg->tag()
1705 << " expected " << kSCFG;
1706 return nullptr;
1707 }
1708
1709 QuicReferenceCountedPointer<Config> config(new Config);
1710 config->serialized = protobuf->config();
1711 config->source_address_token_boxer = &source_address_token_boxer_;
1712
1713 if (protobuf->has_primary_time()) {
1714 config->primary_time =
1715 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1716 }
1717
1718 config->priority = protobuf->priority();
1719
1720 QuicStringPiece scid;
1721 if (!msg->GetStringPiece(kSCID, &scid)) {
1722 QUIC_LOG(WARNING) << "Server config message is missing SCID";
1723 return nullptr;
1724 }
vasilvvc48c8712019-03-11 13:38:16 -07001725 config->id = std::string(scid);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001726
1727 if (msg->GetTaglist(kAEAD, &config->aead) != QUIC_NO_ERROR) {
1728 QUIC_LOG(WARNING) << "Server config message is missing AEAD";
1729 return nullptr;
1730 }
1731
1732 QuicTagVector kexs_tags;
1733 if (msg->GetTaglist(kKEXS, &kexs_tags) != QUIC_NO_ERROR) {
1734 QUIC_LOG(WARNING) << "Server config message is missing KEXS";
1735 return nullptr;
1736 }
1737
1738 QuicErrorCode err;
1739 if ((err = msg->GetTaglist(kTBKP, &config->tb_key_params)) !=
1740 QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND &&
1741 err != QUIC_NO_ERROR) {
1742 QUIC_LOG(WARNING) << "Server config message is missing or has invalid TBKP";
1743 return nullptr;
1744 }
1745
1746 QuicStringPiece orbit;
1747 if (!msg->GetStringPiece(kORBT, &orbit)) {
1748 QUIC_LOG(WARNING) << "Server config message is missing ORBT";
1749 return nullptr;
1750 }
1751
1752 if (orbit.size() != kOrbitSize) {
1753 QUIC_LOG(WARNING) << "Orbit value in server config is the wrong length."
1754 " Got "
1755 << orbit.size() << " want " << kOrbitSize;
1756 return nullptr;
1757 }
1758 static_assert(sizeof(config->orbit) == kOrbitSize, "incorrect orbit size");
1759 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1760
1761 if (kexs_tags.size() != static_cast<size_t>(protobuf->key_size())) {
1762 QUIC_LOG(WARNING) << "Server config has " << kexs_tags.size()
1763 << " key exchange methods configured, but "
1764 << protobuf->key_size() << " private keys";
1765 return nullptr;
1766 }
1767
1768 QuicTagVector proof_demand_tags;
1769 if (msg->GetTaglist(kPDMD, &proof_demand_tags) == QUIC_NO_ERROR) {
1770 for (QuicTag tag : proof_demand_tags) {
1771 if (tag == kCHID) {
1772 config->channel_id_enabled = true;
1773 break;
1774 }
1775 }
1776 }
1777
1778 for (size_t i = 0; i < kexs_tags.size(); i++) {
1779 const QuicTag tag = kexs_tags[i];
vasilvvc48c8712019-03-11 13:38:16 -07001780 std::string private_key;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001781
1782 config->kexs.push_back(tag);
1783
1784 for (int j = 0; j < protobuf->key_size(); j++) {
1785 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1786 if (key.tag() == tag) {
1787 private_key = key.private_key();
1788 break;
1789 }
1790 }
1791
QUICHE teamfe1aca62019-03-14 13:39:01 -07001792 std::unique_ptr<AsynchronousKeyExchange> ka =
QUICHE teama6ef0a62019-03-07 20:34:33 -05001793 key_exchange_source_->Create(config->id, tag, private_key);
1794 if (!ka) {
1795 return nullptr;
1796 }
1797 for (const auto& key_exchange : config->key_exchanges) {
QUICHE teamfe1aca62019-03-14 13:39:01 -07001798 if (key_exchange->type() == tag) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001799 QUIC_LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1800 return nullptr;
1801 }
1802 }
1803
1804 config->key_exchanges.push_back(std::move(ka));
1805 }
1806
1807 uint64_t expiry_seconds;
1808 if (msg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
1809 QUIC_LOG(WARNING) << "Server config message is missing EXPY";
1810 return nullptr;
1811 }
1812 config->expiry_time = QuicWallTime::FromUNIXSeconds(expiry_seconds);
1813
1814 return config;
1815}
1816
1817void QuicCryptoServerConfig::set_replay_protection(bool on) {
1818 replay_protection_ = on;
1819}
1820
1821void QuicCryptoServerConfig::set_chlo_multiplier(size_t multiplier) {
1822 chlo_multiplier_ = multiplier;
1823}
1824
1825void QuicCryptoServerConfig::set_source_address_token_future_secs(
1826 uint32_t future_secs) {
1827 source_address_token_future_secs_ = future_secs;
1828}
1829
1830void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1831 uint32_t lifetime_secs) {
1832 source_address_token_lifetime_secs_ = lifetime_secs;
1833}
1834
1835void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) {
1836 enable_serving_sct_ = enable_serving_sct;
1837}
1838
1839void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1840 std::unique_ptr<PrimaryConfigChangedCallback> cb) {
1841 QuicWriterMutexLock locked(&configs_lock_);
1842 primary_config_changed_cb_ = std::move(cb);
1843}
1844
vasilvvc48c8712019-03-11 13:38:16 -07001845std::string QuicCryptoServerConfig::NewSourceAddressToken(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001846 const Config& config,
1847 const SourceAddressTokens& previous_tokens,
1848 const QuicIpAddress& ip,
1849 QuicRandom* rand,
1850 QuicWallTime now,
1851 const CachedNetworkParameters* cached_network_params) const {
1852 SourceAddressTokens source_address_tokens;
1853 SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
1854 source_address_token->set_ip(ip.DualStacked().ToPackedString());
1855 source_address_token->set_timestamp(now.ToUNIXSeconds());
1856 if (cached_network_params != nullptr) {
1857 *(source_address_token->mutable_cached_network_parameters()) =
1858 *cached_network_params;
1859 }
1860
1861 // Append previous tokens.
1862 for (const SourceAddressToken& token : previous_tokens.tokens()) {
1863 if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
1864 break;
1865 }
1866
1867 if (token.ip() == source_address_token->ip()) {
1868 // It's for the same IP address.
1869 continue;
1870 }
1871
1872 if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
1873 continue;
1874 }
1875
1876 *(source_address_tokens.add_tokens()) = token;
1877 }
1878
1879 return config.source_address_token_boxer->Box(
1880 rand, source_address_tokens.SerializeAsString());
1881}
1882
1883int QuicCryptoServerConfig::NumberOfConfigs() const {
1884 QuicReaderMutexLock locked(&configs_lock_);
1885 return configs_.size();
1886}
1887
1888ProofSource* QuicCryptoServerConfig::proof_source() const {
1889 return proof_source_.get();
1890}
1891
1892SSL_CTX* QuicCryptoServerConfig::ssl_ctx() const {
1893 return ssl_ctx_.get();
1894}
1895
1896HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
1897 const Config& config,
1898 QuicStringPiece token,
1899 SourceAddressTokens* tokens) const {
vasilvvc48c8712019-03-11 13:38:16 -07001900 std::string storage;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001901 QuicStringPiece plaintext;
1902 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1903 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1904 }
1905
1906 if (!tokens->ParseFromArray(plaintext.data(), plaintext.size())) {
1907 // Some clients might still be using the old source token format so
1908 // attempt to parse that format.
1909 // TODO(rch): remove this code once the new format is ubiquitous.
1910 SourceAddressToken token;
1911 if (!token.ParseFromArray(plaintext.data(), plaintext.size())) {
1912 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1913 }
1914 *tokens->add_tokens() = token;
1915 }
1916
1917 return HANDSHAKE_OK;
1918}
1919
1920HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
1921 const SourceAddressTokens& source_address_tokens,
1922 const QuicIpAddress& ip,
1923 QuicWallTime now,
1924 CachedNetworkParameters* cached_network_params) const {
1925 HandshakeFailureReason reason =
1926 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1927 for (const SourceAddressToken& token : source_address_tokens.tokens()) {
1928 reason = ValidateSingleSourceAddressToken(token, ip, now);
1929 if (reason == HANDSHAKE_OK) {
1930 if (token.has_cached_network_parameters()) {
1931 *cached_network_params = token.cached_network_parameters();
1932 }
1933 break;
1934 }
1935 }
1936 return reason;
1937}
1938
1939HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1940 const SourceAddressToken& source_address_token,
1941 const QuicIpAddress& ip,
1942 QuicWallTime now) const {
1943 if (source_address_token.ip() != ip.DualStacked().ToPackedString()) {
1944 // It's for a different IP address.
1945 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1946 }
1947
1948 return ValidateSourceAddressTokenTimestamp(source_address_token, now);
1949}
1950
1951HandshakeFailureReason
1952QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1953 const SourceAddressToken& source_address_token,
1954 QuicWallTime now) const {
1955 const QuicWallTime timestamp(
1956 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1957 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1958
1959 if (now.IsBefore(timestamp) &&
1960 delta.ToSeconds() > source_address_token_future_secs_) {
1961 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1962 }
1963
1964 if (now.IsAfter(timestamp) &&
1965 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1966 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1967 }
1968
1969 return HANDSHAKE_OK;
1970}
1971
1972// kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1973// nonce.
1974static const size_t kServerNoncePlaintextSize =
1975 4 /* timestamp */ + 20 /* random bytes */;
1976
vasilvvc48c8712019-03-11 13:38:16 -07001977std::string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1978 QuicWallTime now) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001979 const uint32_t timestamp = static_cast<uint32_t>(now.ToUNIXSeconds());
1980
1981 uint8_t server_nonce[kServerNoncePlaintextSize];
1982 static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
1983 server_nonce[0] = static_cast<uint8_t>(timestamp >> 24);
1984 server_nonce[1] = static_cast<uint8_t>(timestamp >> 16);
1985 server_nonce[2] = static_cast<uint8_t>(timestamp >> 8);
1986 server_nonce[3] = static_cast<uint8_t>(timestamp);
1987 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1988 sizeof(server_nonce) - sizeof(timestamp));
1989
1990 return server_nonce_boxer_.Box(
1991 rand, QuicStringPiece(reinterpret_cast<char*>(server_nonce),
1992 sizeof(server_nonce)));
1993}
1994
1995bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
1996 const CryptoHandshakeMessage& client_hello,
vasilvvc48c8712019-03-11 13:38:16 -07001997 const std::vector<std::string>& certs) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001998 if (certs.empty()) {
1999 return false;
2000 }
2001
2002 uint64_t hash_from_client;
2003 if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) {
2004 return false;
2005 }
2006 return CryptoUtils::ComputeLeafCertHash(certs.at(0)) == hash_from_client;
2007}
2008
2009bool QuicCryptoServerConfig::ClientDemandsX509Proof(
2010 const CryptoHandshakeMessage& client_hello) const {
2011 QuicTagVector their_proof_demands;
2012
2013 if (client_hello.GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) {
2014 return false;
2015 }
2016
2017 for (const QuicTag tag : their_proof_demands) {
2018 if (tag == kX509) {
2019 return true;
2020 }
2021 }
2022 return false;
2023}
2024
2025bool QuicCryptoServerConfig::IsNextConfigReady(QuicWallTime now) const {
2026 if (GetQuicReloadableFlag(quic_fix_config_rotation)) {
2027 QUIC_RELOADABLE_FLAG_COUNT(quic_fix_config_rotation);
2028 return !next_config_promotion_time_.IsZero() &&
2029 !next_config_promotion_time_.IsAfter(now);
2030 }
2031 return !next_config_promotion_time_.IsZero() &&
2032 next_config_promotion_time_.IsAfter(now);
2033}
2034
2035QuicCryptoServerConfig::Config::Config()
2036 : channel_id_enabled(false),
2037 is_primary(false),
2038 primary_time(QuicWallTime::Zero()),
2039 expiry_time(QuicWallTime::Zero()),
2040 priority(0),
2041 source_address_token_boxer(nullptr) {}
2042
2043QuicCryptoServerConfig::Config::~Config() {}
2044
2045QuicSignedServerConfig::QuicSignedServerConfig() {}
2046QuicSignedServerConfig::~QuicSignedServerConfig() {}
2047
2048} // namespace quic