xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
6 
7 #include <algorithm>
8 #include <cstdlib>
9 #include <memory>
10 #include <optional>
11 #include <string>
12 #include <utility>
13 
14 #include "absl/base/attributes.h"
15 #include "absl/strings/escaping.h"
16 #include "absl/strings/str_format.h"
17 #include "absl/strings/string_view.h"
18 #include "openssl/sha.h"
19 #include "openssl/ssl.h"
20 #include "quiche/quic/core/crypto/aes_128_gcm_12_decrypter.h"
21 #include "quiche/quic/core/crypto/aes_128_gcm_12_encrypter.h"
22 #include "quiche/quic/core/crypto/cert_compressor.h"
23 #include "quiche/quic/core/crypto/certificate_view.h"
24 #include "quiche/quic/core/crypto/chacha20_poly1305_encrypter.h"
25 #include "quiche/quic/core/crypto/channel_id.h"
26 #include "quiche/quic/core/crypto/crypto_framer.h"
27 #include "quiche/quic/core/crypto/crypto_handshake_message.h"
28 #include "quiche/quic/core/crypto/crypto_utils.h"
29 #include "quiche/quic/core/crypto/curve25519_key_exchange.h"
30 #include "quiche/quic/core/crypto/key_exchange.h"
31 #include "quiche/quic/core/crypto/p256_key_exchange.h"
32 #include "quiche/quic/core/crypto/proof_source.h"
33 #include "quiche/quic/core/crypto/quic_decrypter.h"
34 #include "quiche/quic/core/crypto/quic_encrypter.h"
35 #include "quiche/quic/core/crypto/quic_hkdf.h"
36 #include "quiche/quic/core/crypto/quic_random.h"
37 #include "quiche/quic/core/crypto/tls_server_connection.h"
38 #include "quiche/quic/core/proto/crypto_server_config_proto.h"
39 #include "quiche/quic/core/proto/source_address_token_proto.h"
40 #include "quiche/quic/core/quic_clock.h"
41 #include "quiche/quic/core/quic_connection_context.h"
42 #include "quiche/quic/core/quic_packets.h"
43 #include "quiche/quic/core/quic_socket_address_coder.h"
44 #include "quiche/quic/core/quic_types.h"
45 #include "quiche/quic/core/quic_utils.h"
46 #include "quiche/quic/platform/api/quic_bug_tracker.h"
47 #include "quiche/quic/platform/api/quic_flag_utils.h"
48 #include "quiche/quic/platform/api/quic_flags.h"
49 #include "quiche/quic/platform/api/quic_hostname_utils.h"
50 #include "quiche/quic/platform/api/quic_logging.h"
51 #include "quiche/quic/platform/api/quic_socket_address.h"
52 #include "quiche/quic/platform/api/quic_testvalue.h"
53 #include "quiche/common/platform/api/quiche_reference_counted.h"
54 
55 namespace quic {
56 
57 namespace {
58 
59 // kMultiplier is the multiple of the CHLO message size that a REJ message
60 // must stay under when the client doesn't present a valid source-address
61 // token. This is used to protect QUIC from amplification attacks.
62 // TODO(rch): Reduce this to 2 again once b/25933682 is fixed.
63 const size_t kMultiplier = 3;
64 
65 const int kMaxTokenAddresses = 4;
66 
DeriveSourceAddressTokenKey(absl::string_view source_address_token_secret)67 std::string DeriveSourceAddressTokenKey(
68     absl::string_view source_address_token_secret) {
69   QuicHKDF hkdf(source_address_token_secret, absl::string_view() /* no salt */,
70                 "QUIC source address token key",
71                 CryptoSecretBoxer::GetKeySize(), 0 /* no fixed IV needed */,
72                 0 /* no subkey secret */);
73   return std::string(hkdf.server_write_key());
74 }
75 
76 // Default source for creating KeyExchange objects.
77 class DefaultKeyExchangeSource : public KeyExchangeSource {
78  public:
79   DefaultKeyExchangeSource() = default;
80   ~DefaultKeyExchangeSource() override = default;
81 
Create(std::string,bool,QuicTag type,absl::string_view private_key)82   std::unique_ptr<AsynchronousKeyExchange> Create(
83       std::string /*server_config_id*/, bool /* is_fallback */, QuicTag type,
84       absl::string_view private_key) override {
85     if (private_key.empty()) {
86       QUIC_LOG(WARNING) << "Server config contains key exchange method without "
87                            "corresponding private key of type "
88                         << QuicTagToString(type);
89       return nullptr;
90     }
91 
92     std::unique_ptr<SynchronousKeyExchange> ka =
93         CreateLocalSynchronousKeyExchange(type, private_key);
94     if (!ka) {
95       QUIC_LOG(WARNING) << "Failed to create key exchange method of type "
96                         << QuicTagToString(type);
97     }
98     return ka;
99   }
100 };
101 
102 // Returns true if the PDMD field from the client hello demands an X509
103 // certificate.
ClientDemandsX509Proof(const CryptoHandshakeMessage & client_hello)104 bool ClientDemandsX509Proof(const CryptoHandshakeMessage& client_hello) {
105   QuicTagVector their_proof_demands;
106 
107   if (client_hello.GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) {
108     return false;
109   }
110 
111   for (const QuicTag tag : their_proof_demands) {
112     if (tag == kX509) {
113       return true;
114     }
115   }
116   return false;
117 }
118 
FormatCryptoHandshakeMessageForTrace(const CryptoHandshakeMessage * message)119 std::string FormatCryptoHandshakeMessageForTrace(
120     const CryptoHandshakeMessage* message) {
121   if (message == nullptr) {
122     return "<null message>";
123   }
124 
125   std::string s = QuicTagToString(message->tag());
126 
127   // Append the reasons for REJ.
128   if (const auto it = message->tag_value_map().find(kRREJ);
129       it != message->tag_value_map().end()) {
130     const std::string& value = it->second;
131     // The value is a vector of uint32_t(s).
132     if (value.size() % sizeof(uint32_t) == 0) {
133       absl::StrAppend(&s, " RREJ:[");
134       // Append comma-separated list of reasons to |s|.
135       for (size_t j = 0; j < value.size(); j += sizeof(uint32_t)) {
136         uint32_t reason;
137         memcpy(&reason, value.data() + j, sizeof(reason));
138         if (j > 0) {
139           absl::StrAppend(&s, ",");
140         }
141         absl::StrAppend(&s, CryptoUtils::HandshakeFailureReasonToString(
142                                 static_cast<HandshakeFailureReason>(reason)));
143       }
144       absl::StrAppend(&s, "]");
145     } else {
146       absl::StrAppendFormat(&s, " RREJ:[unexpected length:%u]", value.size());
147     }
148   }
149 
150   return s;
151 }
152 
153 }  // namespace
154 
155 // static
Default()156 std::unique_ptr<KeyExchangeSource> KeyExchangeSource::Default() {
157   return std::make_unique<DefaultKeyExchangeSource>();
158 }
159 
160 class ValidateClientHelloHelper {
161  public:
162   // Note: stores a pointer to a unique_ptr, and std::moves the unique_ptr when
163   // ValidationComplete is called.
ValidateClientHelloHelper(quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result,std::unique_ptr<ValidateClientHelloResultCallback> * done_cb)164   ValidateClientHelloHelper(
165       quiche::QuicheReferenceCountedPointer<
166           ValidateClientHelloResultCallback::Result>
167           result,
168       std::unique_ptr<ValidateClientHelloResultCallback>* done_cb)
169       : result_(std::move(result)), done_cb_(done_cb) {}
170   ValidateClientHelloHelper(const ValidateClientHelloHelper&) = delete;
171   ValidateClientHelloHelper& operator=(const ValidateClientHelloHelper&) =
172       delete;
173 
~ValidateClientHelloHelper()174   ~ValidateClientHelloHelper() {
175     QUIC_BUG_IF(quic_bug_12963_1, done_cb_ != nullptr)
176         << "Deleting ValidateClientHelloHelper with a pending callback.";
177   }
178 
ValidationComplete(QuicErrorCode error_code,const char * error_details,std::unique_ptr<ProofSource::Details> proof_source_details)179   void ValidationComplete(
180       QuicErrorCode error_code, const char* error_details,
181       std::unique_ptr<ProofSource::Details> proof_source_details) {
182     result_->error_code = error_code;
183     result_->error_details = error_details;
184     (*done_cb_)->Run(std::move(result_), std::move(proof_source_details));
185     DetachCallback();
186   }
187 
DetachCallback()188   void DetachCallback() {
189     QUIC_BUG_IF(quic_bug_10630_1, done_cb_ == nullptr)
190         << "Callback already detached.";
191     done_cb_ = nullptr;
192   }
193 
194  private:
195   quiche::QuicheReferenceCountedPointer<
196       ValidateClientHelloResultCallback::Result>
197       result_;
198   std::unique_ptr<ValidateClientHelloResultCallback>* done_cb_;
199 };
200 
201 // static
202 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
203 
ClientHelloInfo(const QuicIpAddress & in_client_ip,QuicWallTime in_now)204 ClientHelloInfo::ClientHelloInfo(const QuicIpAddress& in_client_ip,
205                                  QuicWallTime in_now)
206     : client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {}
207 
208 ClientHelloInfo::ClientHelloInfo(const ClientHelloInfo& other) = default;
209 
~ClientHelloInfo()210 ClientHelloInfo::~ClientHelloInfo() {}
211 
PrimaryConfigChangedCallback()212 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {}
213 
~PrimaryConfigChangedCallback()214 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {}
215 
Result(const CryptoHandshakeMessage & in_client_hello,QuicIpAddress in_client_ip,QuicWallTime in_now)216 ValidateClientHelloResultCallback::Result::Result(
217     const CryptoHandshakeMessage& in_client_hello, QuicIpAddress in_client_ip,
218     QuicWallTime in_now)
219     : client_hello(in_client_hello),
220       info(in_client_ip, in_now),
221       error_code(QUIC_NO_ERROR) {}
222 
~Result()223 ValidateClientHelloResultCallback::Result::~Result() {}
224 
ValidateClientHelloResultCallback()225 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {}
226 
~ValidateClientHelloResultCallback()227 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {}
228 
ProcessClientHelloResultCallback()229 ProcessClientHelloResultCallback::ProcessClientHelloResultCallback() {}
230 
~ProcessClientHelloResultCallback()231 ProcessClientHelloResultCallback::~ProcessClientHelloResultCallback() {}
232 
ConfigOptions()233 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
234     : expiry_time(QuicWallTime::Zero()),
235       channel_id_enabled(false),
236       p256(false) {}
237 
238 QuicCryptoServerConfig::ConfigOptions::ConfigOptions(
239     const ConfigOptions& other) = default;
240 
~ConfigOptions()241 QuicCryptoServerConfig::ConfigOptions::~ConfigOptions() {}
242 
243 QuicCryptoServerConfig::ProcessClientHelloContext::
~ProcessClientHelloContext()244     ~ProcessClientHelloContext() {
245   if (done_cb_ != nullptr) {
246     QUIC_LOG(WARNING)
247         << "Deleting ProcessClientHelloContext with a pending callback.";
248   }
249 }
250 
Fail(QuicErrorCode error,const std::string & error_details)251 void QuicCryptoServerConfig::ProcessClientHelloContext::Fail(
252     QuicErrorCode error, const std::string& error_details) {
253   QUIC_TRACEPRINTF("ProcessClientHello failed: error=%s, details=%s",
254                    QuicErrorCodeToString(error), error_details);
255   done_cb_->Run(error, error_details, nullptr, nullptr, nullptr);
256   done_cb_ = nullptr;
257 }
258 
Succeed(std::unique_ptr<CryptoHandshakeMessage> message,std::unique_ptr<DiversificationNonce> diversification_nonce,std::unique_ptr<ProofSource::Details> proof_source_details)259 void QuicCryptoServerConfig::ProcessClientHelloContext::Succeed(
260     std::unique_ptr<CryptoHandshakeMessage> message,
261     std::unique_ptr<DiversificationNonce> diversification_nonce,
262     std::unique_ptr<ProofSource::Details> proof_source_details) {
263   QUIC_TRACEPRINTF("ProcessClientHello succeeded: %s",
264                    FormatCryptoHandshakeMessageForTrace(message.get()));
265 
266   done_cb_->Run(QUIC_NO_ERROR, std::string(), std::move(message),
267                 std::move(diversification_nonce),
268                 std::move(proof_source_details));
269   done_cb_ = nullptr;
270 }
271 
QuicCryptoServerConfig(absl::string_view source_address_token_secret,QuicRandom * server_nonce_entropy,std::unique_ptr<ProofSource> proof_source,std::unique_ptr<KeyExchangeSource> key_exchange_source)272 QuicCryptoServerConfig::QuicCryptoServerConfig(
273     absl::string_view source_address_token_secret,
274     QuicRandom* server_nonce_entropy, std::unique_ptr<ProofSource> proof_source,
275     std::unique_ptr<KeyExchangeSource> key_exchange_source)
276     : replay_protection_(true),
277       chlo_multiplier_(kMultiplier),
278       configs_lock_(),
279       primary_config_(nullptr),
280       next_config_promotion_time_(QuicWallTime::Zero()),
281       proof_source_(std::move(proof_source)),
282       key_exchange_source_(std::move(key_exchange_source)),
283       ssl_ctx_(TlsServerConnection::CreateSslCtx(proof_source_.get())),
284       source_address_token_future_secs_(3600),
285       source_address_token_lifetime_secs_(86400),
286       enable_serving_sct_(false),
287       rejection_observer_(nullptr),
288       pad_rej_(true),
289       pad_shlo_(true),
290       validate_chlo_size_(true),
291       validate_source_address_token_(true) {
292   QUICHE_DCHECK(proof_source_.get());
293   source_address_token_boxer_.SetKeys(
294       {DeriveSourceAddressTokenKey(source_address_token_secret)});
295 
296   // Generate a random key and orbit for server nonces.
297   server_nonce_entropy->RandBytes(server_nonce_orbit_,
298                                   sizeof(server_nonce_orbit_));
299   const size_t key_size = server_nonce_boxer_.GetKeySize();
300   std::unique_ptr<uint8_t[]> key_bytes(new uint8_t[key_size]);
301   server_nonce_entropy->RandBytes(key_bytes.get(), key_size);
302 
303   server_nonce_boxer_.SetKeys(
304       {std::string(reinterpret_cast<char*>(key_bytes.get()), key_size)});
305 }
306 
~QuicCryptoServerConfig()307 QuicCryptoServerConfig::~QuicCryptoServerConfig() {}
308 
309 // static
GenerateConfig(QuicRandom * rand,const QuicClock * clock,const ConfigOptions & options)310 QuicServerConfigProtobuf QuicCryptoServerConfig::GenerateConfig(
311     QuicRandom* rand, const QuicClock* clock, const ConfigOptions& options) {
312   CryptoHandshakeMessage msg;
313 
314   const std::string curve25519_private_key =
315       Curve25519KeyExchange::NewPrivateKey(rand);
316   std::unique_ptr<Curve25519KeyExchange> curve25519 =
317       Curve25519KeyExchange::New(curve25519_private_key);
318   absl::string_view curve25519_public_value = curve25519->public_value();
319 
320   std::string encoded_public_values;
321   // First three bytes encode the length of the public value.
322   QUICHE_DCHECK_LT(curve25519_public_value.size(), (1U << 24));
323   encoded_public_values.push_back(
324       static_cast<char>(curve25519_public_value.size()));
325   encoded_public_values.push_back(
326       static_cast<char>(curve25519_public_value.size() >> 8));
327   encoded_public_values.push_back(
328       static_cast<char>(curve25519_public_value.size() >> 16));
329   encoded_public_values.append(curve25519_public_value.data(),
330                                curve25519_public_value.size());
331 
332   std::string p256_private_key;
333   if (options.p256) {
334     p256_private_key = P256KeyExchange::NewPrivateKey();
335     std::unique_ptr<P256KeyExchange> p256(
336         P256KeyExchange::New(p256_private_key));
337     absl::string_view p256_public_value = p256->public_value();
338 
339     QUICHE_DCHECK_LT(p256_public_value.size(), (1U << 24));
340     encoded_public_values.push_back(
341         static_cast<char>(p256_public_value.size()));
342     encoded_public_values.push_back(
343         static_cast<char>(p256_public_value.size() >> 8));
344     encoded_public_values.push_back(
345         static_cast<char>(p256_public_value.size() >> 16));
346     encoded_public_values.append(p256_public_value.data(),
347                                  p256_public_value.size());
348   }
349 
350   msg.set_tag(kSCFG);
351   if (options.p256) {
352     msg.SetVector(kKEXS, QuicTagVector{kC255, kP256});
353   } else {
354     msg.SetVector(kKEXS, QuicTagVector{kC255});
355   }
356   msg.SetVector(kAEAD, QuicTagVector{kAESG, kCC20});
357   msg.SetStringPiece(kPUBS, encoded_public_values);
358 
359   if (options.expiry_time.IsZero()) {
360     const QuicWallTime now = clock->WallNow();
361     const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
362         60 * 60 * 24 * 180 /* 180 days, ~six months */));
363     const uint64_t expiry_seconds = expiry.ToUNIXSeconds();
364     msg.SetValue(kEXPY, expiry_seconds);
365   } else {
366     msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
367   }
368 
369   char orbit_bytes[kOrbitSize];
370   if (options.orbit.size() == sizeof(orbit_bytes)) {
371     memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
372   } else {
373     QUICHE_DCHECK(options.orbit.empty());
374     rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
375   }
376   msg.SetStringPiece(kORBT,
377                      absl::string_view(orbit_bytes, sizeof(orbit_bytes)));
378 
379   if (options.channel_id_enabled) {
380     msg.SetVector(kPDMD, QuicTagVector{kCHID});
381   }
382 
383   if (options.id.empty()) {
384     // We need to ensure that the SCID changes whenever the server config does
385     // thus we make it a hash of the rest of the server config.
386     std::unique_ptr<QuicData> serialized =
387         CryptoFramer::ConstructHandshakeMessage(msg);
388 
389     uint8_t scid_bytes[SHA256_DIGEST_LENGTH];
390     SHA256(reinterpret_cast<const uint8_t*>(serialized->data()),
391            serialized->length(), scid_bytes);
392     // The SCID is a truncated SHA-256 digest.
393     static_assert(16 <= SHA256_DIGEST_LENGTH, "SCID length too high.");
394     msg.SetStringPiece(
395         kSCID,
396         absl::string_view(reinterpret_cast<const char*>(scid_bytes), 16));
397   } else {
398     msg.SetStringPiece(kSCID, options.id);
399   }
400   // Don't put new tags below this point. The SCID generation should hash over
401   // everything but itself and so extra tags should be added prior to the
402   // preceding if block.
403 
404   std::unique_ptr<QuicData> serialized =
405       CryptoFramer::ConstructHandshakeMessage(msg);
406 
407   QuicServerConfigProtobuf config;
408   config.set_config(std::string(serialized->AsStringPiece()));
409   QuicServerConfigProtobuf::PrivateKey* curve25519_key = config.add_key();
410   curve25519_key->set_tag(kC255);
411   curve25519_key->set_private_key(curve25519_private_key);
412 
413   if (options.p256) {
414     QuicServerConfigProtobuf::PrivateKey* p256_key = config.add_key();
415     p256_key->set_tag(kP256);
416     p256_key->set_private_key(p256_private_key);
417   }
418 
419   return config;
420 }
421 
AddConfig(const QuicServerConfigProtobuf & protobuf,const QuicWallTime now)422 std::unique_ptr<CryptoHandshakeMessage> QuicCryptoServerConfig::AddConfig(
423     const QuicServerConfigProtobuf& protobuf, const QuicWallTime now) {
424   std::unique_ptr<CryptoHandshakeMessage> msg =
425       CryptoFramer::ParseMessage(protobuf.config());
426 
427   if (!msg) {
428     QUIC_LOG(WARNING) << "Failed to parse server config message";
429     return nullptr;
430   }
431 
432   quiche::QuicheReferenceCountedPointer<Config> config =
433       ParseConfigProtobuf(protobuf, /* is_fallback = */ false);
434   if (!config) {
435     QUIC_LOG(WARNING) << "Failed to parse server config message";
436     return nullptr;
437   }
438 
439   {
440     QuicWriterMutexLock locked(&configs_lock_);
441     if (configs_.find(config->id) != configs_.end()) {
442       QUIC_LOG(WARNING) << "Failed to add config because another with the same "
443                            "server config id already exists: "
444                         << absl::BytesToHexString(config->id);
445       return nullptr;
446     }
447 
448     configs_[config->id] = config;
449     SelectNewPrimaryConfig(now);
450     QUICHE_DCHECK(primary_config_.get());
451     QUICHE_DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
452                      primary_config_.get());
453   }
454 
455   return msg;
456 }
457 
458 std::unique_ptr<CryptoHandshakeMessage>
AddDefaultConfig(QuicRandom * rand,const QuicClock * clock,const ConfigOptions & options)459 QuicCryptoServerConfig::AddDefaultConfig(QuicRandom* rand,
460                                          const QuicClock* clock,
461                                          const ConfigOptions& options) {
462   return AddConfig(GenerateConfig(rand, clock, options), clock->WallNow());
463 }
464 
SetConfigs(const std::vector<QuicServerConfigProtobuf> & protobufs,const QuicServerConfigProtobuf * fallback_protobuf,const QuicWallTime now)465 bool QuicCryptoServerConfig::SetConfigs(
466     const std::vector<QuicServerConfigProtobuf>& protobufs,
467     const QuicServerConfigProtobuf* fallback_protobuf, const QuicWallTime now) {
468   std::vector<quiche::QuicheReferenceCountedPointer<Config>> parsed_configs;
469   for (auto& protobuf : protobufs) {
470     quiche::QuicheReferenceCountedPointer<Config> config =
471         ParseConfigProtobuf(protobuf, /* is_fallback = */ false);
472     if (!config) {
473       QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
474       return false;
475     }
476 
477     parsed_configs.push_back(config);
478   }
479 
480   quiche::QuicheReferenceCountedPointer<Config> fallback_config;
481   if (fallback_protobuf != nullptr) {
482     fallback_config =
483         ParseConfigProtobuf(*fallback_protobuf, /* is_fallback = */ true);
484     if (!fallback_config) {
485       QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
486       return false;
487     }
488     QUIC_LOG(INFO) << "Fallback config has scid "
489                    << absl::BytesToHexString(fallback_config->id);
490     parsed_configs.push_back(fallback_config);
491   } else {
492     QUIC_LOG(INFO) << "No fallback config provided";
493   }
494 
495   if (parsed_configs.empty()) {
496     QUIC_LOG(WARNING)
497         << "Rejecting QUIC configs because new config list is empty.";
498     return false;
499   }
500 
501   QUIC_LOG(INFO) << "Updating configs:";
502 
503   QuicWriterMutexLock locked(&configs_lock_);
504   ConfigMap new_configs;
505 
506   for (const quiche::QuicheReferenceCountedPointer<Config>& config :
507        parsed_configs) {
508     auto it = configs_.find(config->id);
509     if (it != configs_.end()) {
510       QUIC_LOG(INFO) << "Keeping scid: " << absl::BytesToHexString(config->id)
511                      << " orbit: "
512                      << absl::BytesToHexString(absl::string_view(
513                             reinterpret_cast<const char*>(config->orbit),
514                             kOrbitSize))
515                      << " new primary_time "
516                      << config->primary_time.ToUNIXSeconds()
517                      << " old primary_time "
518                      << it->second->primary_time.ToUNIXSeconds()
519                      << " new priority " << config->priority << " old priority "
520                      << it->second->priority;
521       // Update primary_time and priority.
522       it->second->primary_time = config->primary_time;
523       it->second->priority = config->priority;
524       new_configs.insert(*it);
525     } else {
526       QUIC_LOG(INFO) << "Adding scid: " << absl::BytesToHexString(config->id)
527                      << " orbit: "
528                      << absl::BytesToHexString(absl::string_view(
529                             reinterpret_cast<const char*>(config->orbit),
530                             kOrbitSize))
531                      << " primary_time " << config->primary_time.ToUNIXSeconds()
532                      << " priority " << config->priority;
533       new_configs.emplace(config->id, config);
534     }
535   }
536 
537   configs_ = std::move(new_configs);
538   fallback_config_ = fallback_config;
539   SelectNewPrimaryConfig(now);
540   QUICHE_DCHECK(primary_config_.get());
541   QUICHE_DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
542                    primary_config_.get());
543 
544   return true;
545 }
546 
SetSourceAddressTokenKeys(const std::vector<std::string> & keys)547 void QuicCryptoServerConfig::SetSourceAddressTokenKeys(
548     const std::vector<std::string>& keys) {
549   // TODO(b/208866709)
550   source_address_token_boxer_.SetKeys(keys);
551 }
552 
GetConfigIds() const553 std::vector<std::string> QuicCryptoServerConfig::GetConfigIds() const {
554   QuicReaderMutexLock locked(&configs_lock_);
555   std::vector<std::string> scids;
556   for (auto it = configs_.begin(); it != configs_.end(); ++it) {
557     scids.push_back(it->first);
558   }
559   return scids;
560 }
561 
ValidateClientHello(const CryptoHandshakeMessage & client_hello,const QuicSocketAddress & client_address,const QuicSocketAddress & server_address,QuicTransportVersion version,const QuicClock * clock,quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const562 void QuicCryptoServerConfig::ValidateClientHello(
563     const CryptoHandshakeMessage& client_hello,
564     const QuicSocketAddress& client_address,
565     const QuicSocketAddress& server_address, QuicTransportVersion version,
566     const QuicClock* clock,
567     quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,
568     std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
569   const QuicWallTime now(clock->WallNow());
570 
571   quiche::QuicheReferenceCountedPointer<
572       ValidateClientHelloResultCallback::Result>
573       result(new ValidateClientHelloResultCallback::Result(
574           client_hello, client_address.host(), now));
575 
576   absl::string_view requested_scid;
577   // We ignore here the return value from GetStringPiece. If there is no SCID
578   // tag, EvaluateClientHello will discover that because GetCurrentConfigs will
579   // not have found the requested config (i.e. because none of the configs will
580   // have an empty string as its id).
581   client_hello.GetStringPiece(kSCID, &requested_scid);
582   Configs configs;
583   if (!GetCurrentConfigs(now, requested_scid,
584                          /* old_primary_config = */ nullptr, &configs)) {
585     result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
586     result->error_details = "No configurations loaded";
587   }
588   signed_config->config = configs.primary;
589 
590   if (result->error_code == QUIC_NO_ERROR) {
591     // QUIC requires a new proof for each CHLO so clear any existing proof.
592     signed_config->chain = nullptr;
593     signed_config->proof.signature = "";
594     signed_config->proof.leaf_cert_scts = "";
595     EvaluateClientHello(server_address, client_address, version, configs,
596                         result, std::move(done_cb));
597   } else {
598     done_cb->Run(result, /* details = */ nullptr);
599   }
600 }
601 
602 class QuicCryptoServerConfig::ProcessClientHelloCallback
603     : public ProofSource::Callback {
604  public:
ProcessClientHelloCallback(const QuicCryptoServerConfig * config,std::unique_ptr<ProcessClientHelloContext> context,const Configs & configs)605   ProcessClientHelloCallback(const QuicCryptoServerConfig* config,
606                              std::unique_ptr<ProcessClientHelloContext> context,
607                              const Configs& configs)
608       : config_(config), context_(std::move(context)), configs_(configs) {}
609 
Run(bool ok,const quiche::QuicheReferenceCountedPointer<ProofSource::Chain> & chain,const QuicCryptoProof & proof,std::unique_ptr<ProofSource::Details> details)610   void Run(
611       bool ok,
612       const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
613       const QuicCryptoProof& proof,
614       std::unique_ptr<ProofSource::Details> details) override {
615     if (ok) {
616       context_->signed_config()->chain = chain;
617       context_->signed_config()->proof = proof;
618     }
619     config_->ProcessClientHelloAfterGetProof(!ok, std::move(details),
620                                              std::move(context_), configs_);
621   }
622 
623  private:
624   const QuicCryptoServerConfig* config_;
625   std::unique_ptr<ProcessClientHelloContext> context_;
626   const Configs configs_;
627 };
628 
629 class QuicCryptoServerConfig::ProcessClientHelloAfterGetProofCallback
630     : public AsynchronousKeyExchange::Callback {
631  public:
ProcessClientHelloAfterGetProofCallback(const QuicCryptoServerConfig * config,std::unique_ptr<ProofSource::Details> proof_source_details,QuicTag key_exchange_type,std::unique_ptr<CryptoHandshakeMessage> out,absl::string_view public_value,std::unique_ptr<ProcessClientHelloContext> context,const Configs & configs)632   ProcessClientHelloAfterGetProofCallback(
633       const QuicCryptoServerConfig* config,
634       std::unique_ptr<ProofSource::Details> proof_source_details,
635       QuicTag key_exchange_type, std::unique_ptr<CryptoHandshakeMessage> out,
636       absl::string_view public_value,
637       std::unique_ptr<ProcessClientHelloContext> context,
638       const Configs& configs)
639       : config_(config),
640         proof_source_details_(std::move(proof_source_details)),
641         key_exchange_type_(key_exchange_type),
642         out_(std::move(out)),
643         public_value_(public_value),
644         context_(std::move(context)),
645         configs_(configs) {}
646 
Run(bool ok)647   void Run(bool ok) override {
648     config_->ProcessClientHelloAfterCalculateSharedKeys(
649         !ok, std::move(proof_source_details_), key_exchange_type_,
650         std::move(out_), public_value_, std::move(context_), configs_);
651   }
652 
653  private:
654   const QuicCryptoServerConfig* config_;
655   std::unique_ptr<ProofSource::Details> proof_source_details_;
656   const QuicTag key_exchange_type_;
657   std::unique_ptr<CryptoHandshakeMessage> out_;
658   const std::string public_value_;
659   std::unique_ptr<ProcessClientHelloContext> context_;
660   const Configs configs_;
661   std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
662 };
663 
664 class QuicCryptoServerConfig::SendRejectWithFallbackConfigCallback
665     : public ProofSource::Callback {
666  public:
SendRejectWithFallbackConfigCallback(const QuicCryptoServerConfig * config,std::unique_ptr<ProcessClientHelloContext> context,quiche::QuicheReferenceCountedPointer<Config> fallback_config)667   SendRejectWithFallbackConfigCallback(
668       const QuicCryptoServerConfig* config,
669       std::unique_ptr<ProcessClientHelloContext> context,
670       quiche::QuicheReferenceCountedPointer<Config> fallback_config)
671       : config_(config),
672         context_(std::move(context)),
673         fallback_config_(fallback_config) {}
674 
675   // Capture |chain| and |proof| into the signed config, and then invoke
676   // SendRejectWithFallbackConfigAfterGetProof.
Run(bool ok,const quiche::QuicheReferenceCountedPointer<ProofSource::Chain> & chain,const QuicCryptoProof & proof,std::unique_ptr<ProofSource::Details> details)677   void Run(
678       bool ok,
679       const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
680       const QuicCryptoProof& proof,
681       std::unique_ptr<ProofSource::Details> details) override {
682     if (ok) {
683       context_->signed_config()->chain = chain;
684       context_->signed_config()->proof = proof;
685     }
686     config_->SendRejectWithFallbackConfigAfterGetProof(
687         !ok, std::move(details), std::move(context_), fallback_config_);
688   }
689 
690  private:
691   const QuicCryptoServerConfig* config_;
692   std::unique_ptr<ProcessClientHelloContext> context_;
693   quiche::QuicheReferenceCountedPointer<Config> fallback_config_;
694 };
695 
ProcessClientHello(quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> validate_chlo_result,bool reject_only,QuicConnectionId connection_id,const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,ParsedQuicVersion version,const ParsedQuicVersionVector & supported_versions,const QuicClock * clock,QuicRandom * rand,QuicCompressedCertsCache * compressed_certs_cache,quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,QuicByteCount total_framing_overhead,QuicByteCount chlo_packet_size,std::shared_ptr<ProcessClientHelloResultCallback> done_cb) const696 void QuicCryptoServerConfig::ProcessClientHello(
697     quiche::QuicheReferenceCountedPointer<
698         ValidateClientHelloResultCallback::Result>
699         validate_chlo_result,
700     bool reject_only, QuicConnectionId connection_id,
701     const QuicSocketAddress& server_address,
702     const QuicSocketAddress& client_address, ParsedQuicVersion version,
703     const ParsedQuicVersionVector& supported_versions, const QuicClock* clock,
704     QuicRandom* rand, QuicCompressedCertsCache* compressed_certs_cache,
705     quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
706         params,
707     quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,
708     QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size,
709     std::shared_ptr<ProcessClientHelloResultCallback> done_cb) const {
710   QUICHE_DCHECK(done_cb);
711   auto context = std::make_unique<ProcessClientHelloContext>(
712       validate_chlo_result, reject_only, connection_id, server_address,
713       client_address, version, supported_versions, clock, rand,
714       compressed_certs_cache, params, signed_config, total_framing_overhead,
715       chlo_packet_size, std::move(done_cb));
716 
717   // Verify that various parts of the CHLO are valid
718   std::string error_details;
719   QuicErrorCode valid = CryptoUtils::ValidateClientHello(
720       context->client_hello(), context->version(),
721       context->supported_versions(), &error_details);
722   if (valid != QUIC_NO_ERROR) {
723     context->Fail(valid, error_details);
724     return;
725   }
726 
727   absl::string_view requested_scid;
728   context->client_hello().GetStringPiece(kSCID, &requested_scid);
729   Configs configs;
730   if (!GetCurrentConfigs(context->clock()->WallNow(), requested_scid,
731                          signed_config->config, &configs)) {
732     context->Fail(QUIC_CRYPTO_INTERNAL_ERROR, "No configurations loaded");
733     return;
734   }
735 
736   if (context->validate_chlo_result()->error_code != QUIC_NO_ERROR) {
737     context->Fail(context->validate_chlo_result()->error_code,
738                   context->validate_chlo_result()->error_details);
739     return;
740   }
741 
742   if (!ClientDemandsX509Proof(context->client_hello())) {
743     context->Fail(QUIC_UNSUPPORTED_PROOF_DEMAND, "Missing or invalid PDMD");
744     return;
745   }
746 
747   // No need to get a new proof if one was already generated.
748   if (!context->signed_config()->chain) {
749     const std::string chlo_hash = CryptoUtils::HashHandshakeMessage(
750         context->client_hello(), Perspective::IS_SERVER);
751     const QuicSocketAddress context_server_address = context->server_address();
752     const std::string sni = std::string(context->info().sni);
753     const QuicTransportVersion transport_version = context->transport_version();
754 
755     auto cb = std::make_unique<ProcessClientHelloCallback>(
756         this, std::move(context), configs);
757 
758     QUICHE_DCHECK(proof_source_.get());
759     proof_source_->GetProof(context_server_address, client_address, sni,
760                             configs.primary->serialized, transport_version,
761                             chlo_hash, std::move(cb));
762     return;
763   }
764 
765   ProcessClientHelloAfterGetProof(
766       /* found_error = */ false, /* proof_source_details = */ nullptr,
767       std::move(context), configs);
768 }
769 
ProcessClientHelloAfterGetProof(bool found_error,std::unique_ptr<ProofSource::Details> proof_source_details,std::unique_ptr<ProcessClientHelloContext> context,const Configs & configs) const770 void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
771     bool found_error,
772     std::unique_ptr<ProofSource::Details> proof_source_details,
773     std::unique_ptr<ProcessClientHelloContext> context,
774     const Configs& configs) const {
775   QUIC_BUG_IF(quic_bug_12963_2,
776               !QuicUtils::IsConnectionIdValidForVersion(
777                   context->connection_id(), context->transport_version()))
778       << "ProcessClientHelloAfterGetProof: attempted to use connection ID "
779       << context->connection_id() << " which is invalid with version "
780       << context->version();
781 
782   if (context->info().reject_reasons.empty()) {
783     if (!context->signed_config() || !context->signed_config()->chain) {
784       // No chain.
785       context->validate_chlo_result()->info.reject_reasons.push_back(
786           SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
787     } else if (!ValidateExpectedLeafCertificate(
788                    context->client_hello(),
789                    context->signed_config()->chain->certs)) {
790       // Has chain but leaf is invalid.
791       context->validate_chlo_result()->info.reject_reasons.push_back(
792           INVALID_EXPECTED_LEAF_CERTIFICATE);
793     }
794   }
795 
796   if (found_error) {
797     context->Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
798     return;
799   }
800 
801   auto out_diversification_nonce = std::make_unique<DiversificationNonce>();
802 
803   absl::string_view cert_sct;
804   if (context->client_hello().GetStringPiece(kCertificateSCTTag, &cert_sct) &&
805       cert_sct.empty()) {
806     context->params()->sct_supported_by_client = true;
807   }
808 
809   auto out = std::make_unique<CryptoHandshakeMessage>();
810   if (!context->info().reject_reasons.empty() || !configs.requested) {
811     BuildRejectionAndRecordStats(*context, *configs.primary,
812                                  context->info().reject_reasons, out.get());
813     context->Succeed(std::move(out), std::move(out_diversification_nonce),
814                      std::move(proof_source_details));
815     return;
816   }
817 
818   if (context->reject_only()) {
819     context->Succeed(std::move(out), std::move(out_diversification_nonce),
820                      std::move(proof_source_details));
821     return;
822   }
823 
824   QuicTagVector their_aeads;
825   QuicTagVector their_key_exchanges;
826   if (context->client_hello().GetTaglist(kAEAD, &their_aeads) !=
827           QUIC_NO_ERROR ||
828       context->client_hello().GetTaglist(kKEXS, &their_key_exchanges) !=
829           QUIC_NO_ERROR ||
830       their_aeads.size() != 1 || their_key_exchanges.size() != 1) {
831     context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
832                   "Missing or invalid AEAD or KEXS");
833     return;
834   }
835 
836   size_t key_exchange_index;
837   if (!FindMutualQuicTag(configs.requested->aead, their_aeads,
838                          &context->params()->aead, nullptr) ||
839       !FindMutualQuicTag(configs.requested->kexs, their_key_exchanges,
840                          &context->params()->key_exchange,
841                          &key_exchange_index)) {
842     context->Fail(QUIC_CRYPTO_NO_SUPPORT, "Unsupported AEAD or KEXS");
843     return;
844   }
845 
846   absl::string_view public_value;
847   if (!context->client_hello().GetStringPiece(kPUBS, &public_value)) {
848     context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
849                   "Missing public value");
850     return;
851   }
852 
853   // Allow testing a specific adversarial case in which a client sends a public
854   // value of incorrect size.
855   AdjustTestValue("quic::QuicCryptoServerConfig::public_value_adjust",
856                   &public_value);
857 
858   const AsynchronousKeyExchange* key_exchange =
859       configs.requested->key_exchanges[key_exchange_index].get();
860   std::string* initial_premaster_secret =
861       &context->params()->initial_premaster_secret;
862   auto cb = std::make_unique<ProcessClientHelloAfterGetProofCallback>(
863       this, std::move(proof_source_details), key_exchange->type(),
864       std::move(out), public_value, std::move(context), configs);
865   key_exchange->CalculateSharedKeyAsync(public_value, initial_premaster_secret,
866                                         std::move(cb));
867 }
868 
ProcessClientHelloAfterCalculateSharedKeys(bool found_error,std::unique_ptr<ProofSource::Details> proof_source_details,QuicTag key_exchange_type,std::unique_ptr<CryptoHandshakeMessage> out,absl::string_view public_value,std::unique_ptr<ProcessClientHelloContext> context,const Configs & configs) const869 void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
870     bool found_error,
871     std::unique_ptr<ProofSource::Details> proof_source_details,
872     QuicTag key_exchange_type, std::unique_ptr<CryptoHandshakeMessage> out,
873     absl::string_view public_value,
874     std::unique_ptr<ProcessClientHelloContext> context,
875     const Configs& configs) const {
876   QUIC_BUG_IF(quic_bug_12963_3,
877               !QuicUtils::IsConnectionIdValidForVersion(
878                   context->connection_id(), context->transport_version()))
879       << "ProcessClientHelloAfterCalculateSharedKeys:"
880          " attempted to use connection ID "
881       << context->connection_id() << " which is invalid with version "
882       << context->version();
883 
884   if (found_error) {
885     // If we are already using the fallback config, or there is no fallback
886     // config to use, just bail out of the handshake.
887     if (configs.fallback == nullptr ||
888         context->signed_config()->config == configs.fallback) {
889       context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
890                     "Failed to calculate shared key");
891     } else {
892       SendRejectWithFallbackConfig(std::move(context), configs.fallback);
893     }
894     return;
895   }
896 
897   if (!context->info().sni.empty()) {
898     context->params()->sni =
899         QuicHostnameUtils::NormalizeHostname(context->info().sni);
900   }
901 
902   std::string hkdf_suffix;
903   const QuicData& client_hello_serialized =
904       context->client_hello().GetSerialized();
905   hkdf_suffix.reserve(context->connection_id().length() +
906                       client_hello_serialized.length() +
907                       configs.requested->serialized.size());
908   hkdf_suffix.append(context->connection_id().data(),
909                      context->connection_id().length());
910   hkdf_suffix.append(client_hello_serialized.data(),
911                      client_hello_serialized.length());
912   hkdf_suffix.append(configs.requested->serialized);
913   QUICHE_DCHECK(proof_source_.get());
914   if (context->signed_config()->chain->certs.empty()) {
915     context->Fail(QUIC_CRYPTO_INTERNAL_ERROR, "Failed to get certs");
916     return;
917   }
918   hkdf_suffix.append(context->signed_config()->chain->certs[0]);
919 
920   absl::string_view cetv_ciphertext;
921   if (configs.requested->channel_id_enabled &&
922       context->client_hello().GetStringPiece(kCETV, &cetv_ciphertext)) {
923     CryptoHandshakeMessage client_hello_copy(context->client_hello());
924     client_hello_copy.Erase(kCETV);
925     client_hello_copy.Erase(kPAD);
926 
927     const QuicData& client_hello_copy_serialized =
928         client_hello_copy.GetSerialized();
929     std::string hkdf_input;
930     hkdf_input.append(QuicCryptoConfig::kCETVLabel,
931                       strlen(QuicCryptoConfig::kCETVLabel) + 1);
932     hkdf_input.append(context->connection_id().data(),
933                       context->connection_id().length());
934     hkdf_input.append(client_hello_copy_serialized.data(),
935                       client_hello_copy_serialized.length());
936     hkdf_input.append(configs.requested->serialized);
937 
938     CrypterPair crypters;
939     if (!CryptoUtils::DeriveKeys(
940             context->version(), context->params()->initial_premaster_secret,
941             context->params()->aead, context->info().client_nonce,
942             context->info().server_nonce, pre_shared_key_, hkdf_input,
943             Perspective::IS_SERVER, CryptoUtils::Diversification::Never(),
944             &crypters, nullptr /* subkey secret */)) {
945       context->Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
946                     "Symmetric key setup failed");
947       return;
948     }
949 
950     char plaintext[kMaxOutgoingPacketSize];
951     size_t plaintext_length = 0;
952     const bool success = crypters.decrypter->DecryptPacket(
953         0 /* packet number */, absl::string_view() /* associated data */,
954         cetv_ciphertext, plaintext, &plaintext_length, kMaxOutgoingPacketSize);
955     if (!success) {
956       context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
957                     "CETV decryption failure");
958       return;
959     }
960     std::unique_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
961         absl::string_view(plaintext, plaintext_length)));
962     if (!cetv) {
963       context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "CETV parse error");
964       return;
965     }
966 
967     absl::string_view key, signature;
968     if (cetv->GetStringPiece(kCIDK, &key) &&
969         cetv->GetStringPiece(kCIDS, &signature)) {
970       if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
971         context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
972                       "ChannelID signature failure");
973         return;
974       }
975 
976       context->params()->channel_id = std::string(key);
977     }
978   }
979 
980   std::string hkdf_input;
981   size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
982   hkdf_input.reserve(label_len + hkdf_suffix.size());
983   hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
984   hkdf_input.append(hkdf_suffix);
985 
986   auto out_diversification_nonce = std::make_unique<DiversificationNonce>();
987   context->rand()->RandBytes(out_diversification_nonce->data(),
988                              out_diversification_nonce->size());
989   CryptoUtils::Diversification diversification =
990       CryptoUtils::Diversification::Now(out_diversification_nonce.get());
991   if (!CryptoUtils::DeriveKeys(
992           context->version(), context->params()->initial_premaster_secret,
993           context->params()->aead, context->info().client_nonce,
994           context->info().server_nonce, pre_shared_key_, hkdf_input,
995           Perspective::IS_SERVER, diversification,
996           &context->params()->initial_crypters,
997           &context->params()->initial_subkey_secret)) {
998     context->Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
999                   "Symmetric key setup failed");
1000     return;
1001   }
1002 
1003   std::string forward_secure_public_value;
1004   std::unique_ptr<SynchronousKeyExchange> forward_secure_key_exchange =
1005       CreateLocalSynchronousKeyExchange(key_exchange_type, context->rand());
1006   if (!forward_secure_key_exchange) {
1007     QUIC_DLOG(WARNING) << "Failed to create keypair";
1008     context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1009                   "Failed to create keypair");
1010     return;
1011   }
1012 
1013   forward_secure_public_value =
1014       std::string(forward_secure_key_exchange->public_value());
1015   if (!forward_secure_key_exchange->CalculateSharedKeySync(
1016           public_value, &context->params()->forward_secure_premaster_secret)) {
1017     context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1018                   "Invalid public value");
1019     return;
1020   }
1021 
1022   std::string forward_secure_hkdf_input;
1023   label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
1024   forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
1025   forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
1026                                    label_len);
1027   forward_secure_hkdf_input.append(hkdf_suffix);
1028 
1029   std::string shlo_nonce;
1030   shlo_nonce = NewServerNonce(context->rand(), context->info().now);
1031   out->SetStringPiece(kServerNonceTag, shlo_nonce);
1032 
1033   if (!CryptoUtils::DeriveKeys(
1034           context->version(),
1035           context->params()->forward_secure_premaster_secret,
1036           context->params()->aead, context->info().client_nonce,
1037           shlo_nonce.empty() ? context->info().server_nonce : shlo_nonce,
1038           pre_shared_key_, forward_secure_hkdf_input, Perspective::IS_SERVER,
1039           CryptoUtils::Diversification::Never(),
1040           &context->params()->forward_secure_crypters,
1041           &context->params()->subkey_secret)) {
1042     context->Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
1043                   "Symmetric key setup failed");
1044     return;
1045   }
1046 
1047   out->set_tag(kSHLO);
1048   out->SetVersionVector(kVER, context->supported_versions());
1049   out->SetStringPiece(
1050       kSourceAddressTokenTag,
1051       NewSourceAddressToken(*configs.requested->source_address_token_boxer,
1052                             context->info().source_address_tokens,
1053                             context->client_address().host(), context->rand(),
1054                             context->info().now, nullptr));
1055   QuicSocketAddressCoder address_coder(context->client_address());
1056   out->SetStringPiece(kCADR, address_coder.Encode());
1057   out->SetStringPiece(kPUBS, forward_secure_public_value);
1058 
1059   context->Succeed(std::move(out), std::move(out_diversification_nonce),
1060                    std::move(proof_source_details));
1061 }
1062 
SendRejectWithFallbackConfig(std::unique_ptr<ProcessClientHelloContext> context,quiche::QuicheReferenceCountedPointer<Config> fallback_config) const1063 void QuicCryptoServerConfig::SendRejectWithFallbackConfig(
1064     std::unique_ptr<ProcessClientHelloContext> context,
1065     quiche::QuicheReferenceCountedPointer<Config> fallback_config) const {
1066   // We failed to calculate a shared initial key, likely because we tried to use
1067   // a remote key-exchange service which could not be reached.  We want to send
1068   // a REJ which tells the client to use a different ServerConfig which
1069   // corresponds to a local keypair.  To generate the REJ we need to request a
1070   // new proof.
1071   const std::string chlo_hash = CryptoUtils::HashHandshakeMessage(
1072       context->client_hello(), Perspective::IS_SERVER);
1073   const QuicSocketAddress server_address = context->server_address();
1074   const std::string sni(context->info().sni);
1075   const QuicTransportVersion transport_version = context->transport_version();
1076 
1077   const QuicSocketAddress& client_address = context->client_address();
1078   auto cb = std::make_unique<SendRejectWithFallbackConfigCallback>(
1079       this, std::move(context), fallback_config);
1080   proof_source_->GetProof(server_address, client_address, sni,
1081                           fallback_config->serialized, transport_version,
1082                           chlo_hash, std::move(cb));
1083 }
1084 
SendRejectWithFallbackConfigAfterGetProof(bool found_error,std::unique_ptr<ProofSource::Details> proof_source_details,std::unique_ptr<ProcessClientHelloContext> context,quiche::QuicheReferenceCountedPointer<Config> fallback_config) const1085 void QuicCryptoServerConfig::SendRejectWithFallbackConfigAfterGetProof(
1086     bool found_error,
1087     std::unique_ptr<ProofSource::Details> proof_source_details,
1088     std::unique_ptr<ProcessClientHelloContext> context,
1089     quiche::QuicheReferenceCountedPointer<Config> fallback_config) const {
1090   if (found_error) {
1091     context->Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
1092     return;
1093   }
1094 
1095   auto out = std::make_unique<CryptoHandshakeMessage>();
1096   BuildRejectionAndRecordStats(*context, *fallback_config,
1097                                {SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE},
1098                                out.get());
1099 
1100   context->Succeed(std::move(out), std::make_unique<DiversificationNonce>(),
1101                    std::move(proof_source_details));
1102 }
1103 
1104 quiche::QuicheReferenceCountedPointer<QuicCryptoServerConfig::Config>
GetConfigWithScid(absl::string_view requested_scid) const1105 QuicCryptoServerConfig::GetConfigWithScid(
1106     absl::string_view requested_scid) const {
1107   configs_lock_.AssertReaderHeld();
1108 
1109   if (!requested_scid.empty()) {
1110     auto it = configs_.find((std::string(requested_scid)));
1111     if (it != configs_.end()) {
1112       // We'll use the config that the client requested in order to do
1113       // key-agreement.
1114       return quiche::QuicheReferenceCountedPointer<Config>(it->second);
1115     }
1116   }
1117 
1118   return quiche::QuicheReferenceCountedPointer<Config>();
1119 }
1120 
GetCurrentConfigs(const QuicWallTime & now,absl::string_view requested_scid,quiche::QuicheReferenceCountedPointer<Config> old_primary_config,Configs * configs) const1121 bool QuicCryptoServerConfig::GetCurrentConfigs(
1122     const QuicWallTime& now, absl::string_view requested_scid,
1123     quiche::QuicheReferenceCountedPointer<Config> old_primary_config,
1124     Configs* configs) const {
1125   QuicReaderMutexLock locked(&configs_lock_);
1126 
1127   if (!primary_config_) {
1128     return false;
1129   }
1130 
1131   if (IsNextConfigReady(now)) {
1132     configs_lock_.ReaderUnlock();
1133     configs_lock_.WriterLock();
1134     SelectNewPrimaryConfig(now);
1135     QUICHE_DCHECK(primary_config_.get());
1136     QUICHE_DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
1137                      primary_config_.get());
1138     configs_lock_.WriterUnlock();
1139     configs_lock_.ReaderLock();
1140   }
1141 
1142   if (old_primary_config != nullptr) {
1143     configs->primary = old_primary_config;
1144   } else {
1145     configs->primary = primary_config_;
1146   }
1147   configs->requested = GetConfigWithScid(requested_scid);
1148   configs->fallback = fallback_config_;
1149 
1150   return true;
1151 }
1152 
1153 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
1154 // Config's based on their primary_time.
1155 // static
ConfigPrimaryTimeLessThan(const quiche::QuicheReferenceCountedPointer<Config> & a,const quiche::QuicheReferenceCountedPointer<Config> & b)1156 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
1157     const quiche::QuicheReferenceCountedPointer<Config>& a,
1158     const quiche::QuicheReferenceCountedPointer<Config>& b) {
1159   if (a->primary_time.IsBefore(b->primary_time) ||
1160       b->primary_time.IsBefore(a->primary_time)) {
1161     // Primary times differ.
1162     return a->primary_time.IsBefore(b->primary_time);
1163   } else if (a->priority != b->priority) {
1164     // Primary times are equal, sort backwards by priority.
1165     return a->priority < b->priority;
1166   } else {
1167     // Primary times and priorities are equal, sort by config id.
1168     return a->id < b->id;
1169   }
1170 }
1171 
SelectNewPrimaryConfig(const QuicWallTime now) const1172 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
1173     const QuicWallTime now) const {
1174   std::vector<quiche::QuicheReferenceCountedPointer<Config>> configs;
1175   configs.reserve(configs_.size());
1176 
1177   for (auto it = configs_.begin(); it != configs_.end(); ++it) {
1178     // TODO(avd) Exclude expired configs?
1179     configs.push_back(it->second);
1180   }
1181 
1182   if (configs.empty()) {
1183     if (primary_config_ != nullptr) {
1184       QUIC_BUG(quic_bug_10630_2)
1185           << "No valid QUIC server config. Keeping the current config.";
1186     } else {
1187       QUIC_BUG(quic_bug_10630_3) << "No valid QUIC server config.";
1188     }
1189     return;
1190   }
1191 
1192   std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
1193 
1194   quiche::QuicheReferenceCountedPointer<Config> best_candidate = configs[0];
1195 
1196   for (size_t i = 0; i < configs.size(); ++i) {
1197     const quiche::QuicheReferenceCountedPointer<Config> config(configs[i]);
1198     if (!config->primary_time.IsAfter(now)) {
1199       if (config->primary_time.IsAfter(best_candidate->primary_time)) {
1200         best_candidate = config;
1201       }
1202       continue;
1203     }
1204 
1205     // This is the first config with a primary_time in the future. Thus the
1206     // previous Config should be the primary and this one should determine the
1207     // next_config_promotion_time_.
1208     quiche::QuicheReferenceCountedPointer<Config> new_primary = best_candidate;
1209     if (i == 0) {
1210       // We need the primary_time of the next config.
1211       if (configs.size() > 1) {
1212         next_config_promotion_time_ = configs[1]->primary_time;
1213       } else {
1214         next_config_promotion_time_ = QuicWallTime::Zero();
1215       }
1216     } else {
1217       next_config_promotion_time_ = config->primary_time;
1218     }
1219 
1220     if (primary_config_) {
1221       primary_config_->is_primary = false;
1222     }
1223     primary_config_ = new_primary;
1224     new_primary->is_primary = true;
1225     QUIC_DLOG(INFO) << "New primary config.  orbit: "
1226                     << absl::BytesToHexString(
1227                            absl::string_view(reinterpret_cast<const char*>(
1228                                                  primary_config_->orbit),
1229                                              kOrbitSize));
1230     if (primary_config_changed_cb_ != nullptr) {
1231       primary_config_changed_cb_->Run(primary_config_->id);
1232     }
1233 
1234     return;
1235   }
1236 
1237   // All config's primary times are in the past. We should make the most recent
1238   // and highest priority candidate primary.
1239   quiche::QuicheReferenceCountedPointer<Config> new_primary = best_candidate;
1240   if (primary_config_) {
1241     primary_config_->is_primary = false;
1242   }
1243   primary_config_ = new_primary;
1244   new_primary->is_primary = true;
1245   QUIC_DLOG(INFO) << "New primary config.  orbit: "
1246                   << absl::BytesToHexString(absl::string_view(
1247                          reinterpret_cast<const char*>(primary_config_->orbit),
1248                          kOrbitSize))
1249                   << " scid: " << absl::BytesToHexString(primary_config_->id);
1250   next_config_promotion_time_ = QuicWallTime::Zero();
1251   if (primary_config_changed_cb_ != nullptr) {
1252     primary_config_changed_cb_->Run(primary_config_->id);
1253   }
1254 }
1255 
EvaluateClientHello(const QuicSocketAddress &,const QuicSocketAddress &,QuicTransportVersion,const Configs & configs,quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> client_hello_state,std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const1256 void QuicCryptoServerConfig::EvaluateClientHello(
1257     const QuicSocketAddress& /*server_address*/,
1258     const QuicSocketAddress& /*client_address*/,
1259     QuicTransportVersion /*version*/, const Configs& configs,
1260     quiche::QuicheReferenceCountedPointer<
1261         ValidateClientHelloResultCallback::Result>
1262         client_hello_state,
1263     std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
1264   ValidateClientHelloHelper helper(client_hello_state, &done_cb);
1265 
1266   const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
1267   ClientHelloInfo* info = &(client_hello_state->info);
1268 
1269   if (client_hello.GetStringPiece(kSNI, &info->sni) &&
1270       !QuicHostnameUtils::IsValidSNI(info->sni)) {
1271     helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1272                               "Invalid SNI name", nullptr);
1273     return;
1274   }
1275 
1276   client_hello.GetStringPiece(kUAID, &info->user_agent_id);
1277 
1278   HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
1279   if (validate_source_address_token_) {
1280     absl::string_view srct;
1281     if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
1282       Config& config =
1283           configs.requested != nullptr ? *configs.requested : *configs.primary;
1284       source_address_token_error =
1285           ParseSourceAddressToken(*config.source_address_token_boxer, srct,
1286                                   info->source_address_tokens);
1287 
1288       if (source_address_token_error == HANDSHAKE_OK) {
1289         source_address_token_error = ValidateSourceAddressTokens(
1290             info->source_address_tokens, info->client_ip, info->now,
1291             &client_hello_state->cached_network_params);
1292       }
1293       info->valid_source_address_token =
1294           (source_address_token_error == HANDSHAKE_OK);
1295     } else {
1296       source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
1297     }
1298   } else {
1299     source_address_token_error = HANDSHAKE_OK;
1300     info->valid_source_address_token = true;
1301   }
1302 
1303   if (!configs.requested) {
1304     absl::string_view requested_scid;
1305     if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
1306       info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1307     } else {
1308       info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1309     }
1310     // No server config with the requested ID.
1311     helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1312     return;
1313   }
1314 
1315   if (!client_hello.GetStringPiece(kNONC, &info->client_nonce)) {
1316     info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1317     // Report no client nonce as INCHOATE_HELLO_FAILURE.
1318     helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1319     return;
1320   }
1321 
1322   if (source_address_token_error != HANDSHAKE_OK) {
1323     info->reject_reasons.push_back(source_address_token_error);
1324     // No valid source address token.
1325   }
1326 
1327   if (info->client_nonce.size() != kNonceSize) {
1328     info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
1329     // Invalid client nonce.
1330     QUIC_LOG_FIRST_N(ERROR, 2)
1331         << "Invalid client nonce: " << client_hello.DebugString();
1332     QUIC_DLOG(INFO) << "Invalid client nonce.";
1333   }
1334 
1335   // Server nonce is optional, and used for key derivation if present.
1336   client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
1337 
1338   // If the server nonce is empty and we're requiring handshake confirmation
1339   // for DoS reasons then we must reject the CHLO.
1340   if (GetQuicReloadableFlag(quic_require_handshake_confirmation) &&
1341       info->server_nonce.empty()) {
1342     QUIC_RELOADABLE_FLAG_COUNT(quic_require_handshake_confirmation);
1343     info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
1344   }
1345   helper.ValidationComplete(QUIC_NO_ERROR, "",
1346                             std::unique_ptr<ProofSource::Details>());
1347 }
1348 
BuildServerConfigUpdateMessage(QuicTransportVersion version,absl::string_view chlo_hash,const SourceAddressTokens & previous_source_address_tokens,const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const QuicClock * clock,QuicRandom * rand,QuicCompressedCertsCache * compressed_certs_cache,const QuicCryptoNegotiatedParameters & params,const CachedNetworkParameters * cached_network_params,std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const1349 void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1350     QuicTransportVersion version, absl::string_view chlo_hash,
1351     const SourceAddressTokens& previous_source_address_tokens,
1352     const QuicSocketAddress& server_address,
1353     const QuicSocketAddress& client_address, const QuicClock* clock,
1354     QuicRandom* rand, QuicCompressedCertsCache* compressed_certs_cache,
1355     const QuicCryptoNegotiatedParameters& params,
1356     const CachedNetworkParameters* cached_network_params,
1357     std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
1358   std::string serialized;
1359   std::string source_address_token;
1360   {
1361     QuicReaderMutexLock locked(&configs_lock_);
1362     serialized = primary_config_->serialized;
1363     source_address_token = NewSourceAddressToken(
1364         *primary_config_->source_address_token_boxer,
1365         previous_source_address_tokens, client_address.host(), rand,
1366         clock->WallNow(), cached_network_params);
1367   }
1368 
1369   CryptoHandshakeMessage message;
1370   message.set_tag(kSCUP);
1371   message.SetStringPiece(kSCFG, serialized);
1372   message.SetStringPiece(kSourceAddressTokenTag, source_address_token);
1373 
1374   auto proof_source_cb =
1375       std::make_unique<BuildServerConfigUpdateMessageProofSourceCallback>(
1376           this, compressed_certs_cache, params, std::move(message),
1377           std::move(cb));
1378 
1379   proof_source_->GetProof(server_address, client_address, params.sni,
1380                           serialized, version, chlo_hash,
1381                           std::move(proof_source_cb));
1382 }
1383 
1384 QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
~BuildServerConfigUpdateMessageProofSourceCallback()1385     ~BuildServerConfigUpdateMessageProofSourceCallback() {}
1386 
1387 QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
BuildServerConfigUpdateMessageProofSourceCallback(const QuicCryptoServerConfig * config,QuicCompressedCertsCache * compressed_certs_cache,const QuicCryptoNegotiatedParameters & params,CryptoHandshakeMessage message,std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)1388     BuildServerConfigUpdateMessageProofSourceCallback(
1389         const QuicCryptoServerConfig* config,
1390         QuicCompressedCertsCache* compressed_certs_cache,
1391         const QuicCryptoNegotiatedParameters& params,
1392         CryptoHandshakeMessage message,
1393         std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
1394     : config_(config),
1395       compressed_certs_cache_(compressed_certs_cache),
1396       client_cached_cert_hashes_(params.client_cached_cert_hashes),
1397       sct_supported_by_client_(params.sct_supported_by_client),
1398       sni_(params.sni),
1399       message_(std::move(message)),
1400       cb_(std::move(cb)) {}
1401 
1402 void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
Run(bool ok,const quiche::QuicheReferenceCountedPointer<ProofSource::Chain> & chain,const QuicCryptoProof & proof,std::unique_ptr<ProofSource::Details> details)1403     Run(bool ok,
1404         const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
1405         const QuicCryptoProof& proof,
1406         std::unique_ptr<ProofSource::Details> details) {
1407   config_->FinishBuildServerConfigUpdateMessage(
1408       compressed_certs_cache_, client_cached_cert_hashes_,
1409       sct_supported_by_client_, sni_, ok, chain, proof.signature,
1410       proof.leaf_cert_scts, std::move(details), std::move(message_),
1411       std::move(cb_));
1412 }
1413 
FinishBuildServerConfigUpdateMessage(QuicCompressedCertsCache * compressed_certs_cache,const std::string & client_cached_cert_hashes,bool sct_supported_by_client,const std::string & sni,bool ok,const quiche::QuicheReferenceCountedPointer<ProofSource::Chain> & chain,const std::string & signature,const std::string & leaf_cert_sct,std::unique_ptr<ProofSource::Details>,CryptoHandshakeMessage message,std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const1414 void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
1415     QuicCompressedCertsCache* compressed_certs_cache,
1416     const std::string& client_cached_cert_hashes, bool sct_supported_by_client,
1417     const std::string& sni, bool ok,
1418     const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
1419     const std::string& signature, const std::string& leaf_cert_sct,
1420     std::unique_ptr<ProofSource::Details> /*details*/,
1421     CryptoHandshakeMessage message,
1422     std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
1423   if (!ok) {
1424     cb->Run(false, message);
1425     return;
1426   }
1427 
1428   const std::string compressed =
1429       CompressChain(compressed_certs_cache, chain, client_cached_cert_hashes);
1430 
1431   message.SetStringPiece(kCertificateTag, compressed);
1432   message.SetStringPiece(kPROF, signature);
1433   if (sct_supported_by_client && enable_serving_sct_) {
1434     if (leaf_cert_sct.empty()) {
1435       QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1436           << "SCT is expected but it is empty. SNI: " << sni;
1437     } else {
1438       message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct);
1439     }
1440   }
1441 
1442   cb->Run(true, message);
1443 }
1444 
BuildRejectionAndRecordStats(const ProcessClientHelloContext & context,const Config & config,const std::vector<uint32_t> & reject_reasons,CryptoHandshakeMessage * out) const1445 void QuicCryptoServerConfig::BuildRejectionAndRecordStats(
1446     const ProcessClientHelloContext& context, const Config& config,
1447     const std::vector<uint32_t>& reject_reasons,
1448     CryptoHandshakeMessage* out) const {
1449   BuildRejection(context, config, reject_reasons, out);
1450   if (rejection_observer_ != nullptr) {
1451     rejection_observer_->OnRejectionBuilt(reject_reasons, out);
1452   }
1453 }
1454 
BuildRejection(const ProcessClientHelloContext & context,const Config & config,const std::vector<uint32_t> & reject_reasons,CryptoHandshakeMessage * out) const1455 void QuicCryptoServerConfig::BuildRejection(
1456     const ProcessClientHelloContext& context, const Config& config,
1457     const std::vector<uint32_t>& reject_reasons,
1458     CryptoHandshakeMessage* out) const {
1459   const QuicWallTime now = context.clock()->WallNow();
1460 
1461   out->set_tag(kREJ);
1462   out->SetStringPiece(kSCFG, config.serialized);
1463   out->SetStringPiece(
1464       kSourceAddressTokenTag,
1465       NewSourceAddressToken(
1466           *config.source_address_token_boxer,
1467           context.info().source_address_tokens, context.info().client_ip,
1468           context.rand(), context.info().now,
1469           &context.validate_chlo_result()->cached_network_params));
1470   out->SetValue(kSTTL, config.expiry_time.AbsoluteDifference(now).ToSeconds());
1471   if (replay_protection_) {
1472     out->SetStringPiece(kServerNonceTag,
1473                         NewServerNonce(context.rand(), context.info().now));
1474   }
1475 
1476   // Send client the reject reason for debugging purposes.
1477   QUICHE_DCHECK_LT(0u, reject_reasons.size());
1478   out->SetVector(kRREJ, reject_reasons);
1479 
1480   // The client may have requested a certificate chain.
1481   if (!ClientDemandsX509Proof(context.client_hello())) {
1482     QUIC_BUG(quic_bug_10630_4)
1483         << "x509 certificates not supported in proof demand";
1484     return;
1485   }
1486 
1487   absl::string_view client_cached_cert_hashes;
1488   if (context.client_hello().GetStringPiece(kCCRT,
1489                                             &client_cached_cert_hashes)) {
1490     context.params()->client_cached_cert_hashes =
1491         std::string(client_cached_cert_hashes);
1492   } else {
1493     context.params()->client_cached_cert_hashes.clear();
1494   }
1495 
1496   const std::string compressed = CompressChain(
1497       context.compressed_certs_cache(), context.signed_config()->chain,
1498       context.params()->client_cached_cert_hashes);
1499 
1500   QUICHE_DCHECK_GT(context.chlo_packet_size(), context.client_hello().size());
1501   // kREJOverheadBytes is a very rough estimate of how much of a REJ
1502   // message is taken up by things other than the certificates.
1503   // STK: 56 bytes
1504   // SNO: 56 bytes
1505   // SCFG
1506   //   SCID: 16 bytes
1507   //   PUBS: 38 bytes
1508   const size_t kREJOverheadBytes = 166;
1509   // max_unverified_size is the number of bytes that the certificate chain,
1510   // signature, and (optionally) signed certificate timestamp can consume before
1511   // we will demand a valid source-address token.
1512   const size_t max_unverified_size =
1513       chlo_multiplier_ *
1514           (context.chlo_packet_size() - context.total_framing_overhead()) -
1515       kREJOverheadBytes;
1516   static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1517                 "overhead calculation may underflow");
1518   bool should_return_sct =
1519       context.params()->sct_supported_by_client && enable_serving_sct_;
1520   const std::string& cert_sct = context.signed_config()->proof.leaf_cert_scts;
1521   const size_t sct_size = should_return_sct ? cert_sct.size() : 0;
1522   const size_t total_size = context.signed_config()->proof.signature.size() +
1523                             compressed.size() + sct_size;
1524   if (context.info().valid_source_address_token ||
1525       total_size < max_unverified_size) {
1526     out->SetStringPiece(kCertificateTag, compressed);
1527     out->SetStringPiece(kPROF, context.signed_config()->proof.signature);
1528     if (should_return_sct) {
1529       if (cert_sct.empty()) {
1530         // Log SNI and subject name for the leaf cert if its SCT is empty.
1531         // This is for debugging b/28342827.
1532         const std::vector<std::string>& certs =
1533             context.signed_config()->chain->certs;
1534         std::string ca_subject;
1535         if (!certs.empty()) {
1536           std::unique_ptr<CertificateView> view =
1537               CertificateView::ParseSingleCertificate(certs[0]);
1538           if (view != nullptr) {
1539             std::optional<std::string> maybe_ca_subject =
1540                 view->GetHumanReadableSubject();
1541             if (maybe_ca_subject.has_value()) {
1542               ca_subject = *maybe_ca_subject;
1543             }
1544           }
1545         }
1546         QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1547             << "SCT is expected but it is empty. sni: '"
1548             << context.params()->sni << "' cert subject: '" << ca_subject
1549             << "'";
1550       } else {
1551         out->SetStringPiece(kCertificateSCTTag, cert_sct);
1552       }
1553     }
1554   } else {
1555     QUIC_LOG_EVERY_N_SEC(WARNING, 60)
1556         << "Sending inchoate REJ for hostname: " << context.info().sni
1557         << " signature: " << context.signed_config()->proof.signature.size()
1558         << " cert: " << compressed.size() << " sct:" << sct_size
1559         << " total: " << total_size << " max: " << max_unverified_size;
1560   }
1561 }
1562 
CompressChain(QuicCompressedCertsCache * compressed_certs_cache,const quiche::QuicheReferenceCountedPointer<ProofSource::Chain> & chain,const std::string & client_cached_cert_hashes)1563 std::string QuicCryptoServerConfig::CompressChain(
1564     QuicCompressedCertsCache* compressed_certs_cache,
1565     const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
1566     const std::string& client_cached_cert_hashes) {
1567   // Check whether the compressed certs is available in the cache.
1568   QUICHE_DCHECK(compressed_certs_cache);
1569   const std::string* cached_value = compressed_certs_cache->GetCompressedCert(
1570       chain, client_cached_cert_hashes);
1571   if (cached_value) {
1572     return *cached_value;
1573   }
1574   std::string compressed =
1575       CertCompressor::CompressChain(chain->certs, client_cached_cert_hashes);
1576   // Insert the newly compressed cert to cache.
1577   compressed_certs_cache->Insert(chain, client_cached_cert_hashes, compressed);
1578   return compressed;
1579 }
1580 
1581 quiche::QuicheReferenceCountedPointer<QuicCryptoServerConfig::Config>
ParseConfigProtobuf(const QuicServerConfigProtobuf & protobuf,bool is_fallback) const1582 QuicCryptoServerConfig::ParseConfigProtobuf(
1583     const QuicServerConfigProtobuf& protobuf, bool is_fallback) const {
1584   std::unique_ptr<CryptoHandshakeMessage> msg =
1585       CryptoFramer::ParseMessage(protobuf.config());
1586 
1587   if (!msg) {
1588     QUIC_LOG(WARNING) << "Failed to parse server config message";
1589     return nullptr;
1590   }
1591 
1592   if (msg->tag() != kSCFG) {
1593     QUIC_LOG(WARNING) << "Server config message has tag " << msg->tag()
1594                       << ", but expected " << kSCFG;
1595     return nullptr;
1596   }
1597 
1598   quiche::QuicheReferenceCountedPointer<Config> config(new Config);
1599   config->serialized = protobuf.config();
1600   config->source_address_token_boxer = &source_address_token_boxer_;
1601 
1602   if (protobuf.has_primary_time()) {
1603     config->primary_time =
1604         QuicWallTime::FromUNIXSeconds(protobuf.primary_time());
1605   }
1606 
1607   config->priority = protobuf.priority();
1608 
1609   absl::string_view scid;
1610   if (!msg->GetStringPiece(kSCID, &scid)) {
1611     QUIC_LOG(WARNING) << "Server config message is missing SCID";
1612     return nullptr;
1613   }
1614   if (scid.empty()) {
1615     QUIC_LOG(WARNING) << "Server config message contains an empty SCID";
1616     return nullptr;
1617   }
1618   config->id = std::string(scid);
1619 
1620   if (msg->GetTaglist(kAEAD, &config->aead) != QUIC_NO_ERROR) {
1621     QUIC_LOG(WARNING) << "Server config message is missing AEAD";
1622     return nullptr;
1623   }
1624 
1625   QuicTagVector kexs_tags;
1626   if (msg->GetTaglist(kKEXS, &kexs_tags) != QUIC_NO_ERROR) {
1627     QUIC_LOG(WARNING) << "Server config message is missing KEXS";
1628     return nullptr;
1629   }
1630 
1631   absl::string_view orbit;
1632   if (!msg->GetStringPiece(kORBT, &orbit)) {
1633     QUIC_LOG(WARNING) << "Server config message is missing ORBT";
1634     return nullptr;
1635   }
1636 
1637   if (orbit.size() != kOrbitSize) {
1638     QUIC_LOG(WARNING) << "Orbit value in server config is the wrong length."
1639                          " Got "
1640                       << orbit.size() << " want " << kOrbitSize;
1641     return nullptr;
1642   }
1643   static_assert(sizeof(config->orbit) == kOrbitSize, "incorrect orbit size");
1644   memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1645 
1646   QuicTagVector proof_demand_tags;
1647   if (msg->GetTaglist(kPDMD, &proof_demand_tags) == QUIC_NO_ERROR) {
1648     for (QuicTag tag : proof_demand_tags) {
1649       if (tag == kCHID) {
1650         config->channel_id_enabled = true;
1651         break;
1652       }
1653     }
1654   }
1655 
1656   for (size_t i = 0; i < kexs_tags.size(); i++) {
1657     const QuicTag tag = kexs_tags[i];
1658     std::string private_key;
1659 
1660     config->kexs.push_back(tag);
1661 
1662     for (int j = 0; j < protobuf.key_size(); j++) {
1663       const QuicServerConfigProtobuf::PrivateKey& key = protobuf.key(i);
1664       if (key.tag() == tag) {
1665         private_key = key.private_key();
1666         break;
1667       }
1668     }
1669 
1670     std::unique_ptr<AsynchronousKeyExchange> ka =
1671         key_exchange_source_->Create(config->id, is_fallback, tag, private_key);
1672     if (!ka) {
1673       return nullptr;
1674     }
1675     for (const auto& key_exchange : config->key_exchanges) {
1676       if (key_exchange->type() == tag) {
1677         QUIC_LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1678         return nullptr;
1679       }
1680     }
1681 
1682     config->key_exchanges.push_back(std::move(ka));
1683   }
1684 
1685   uint64_t expiry_seconds;
1686   if (msg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
1687     QUIC_LOG(WARNING) << "Server config message is missing EXPY";
1688     return nullptr;
1689   }
1690   config->expiry_time = QuicWallTime::FromUNIXSeconds(expiry_seconds);
1691 
1692   return config;
1693 }
1694 
set_replay_protection(bool on)1695 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1696   replay_protection_ = on;
1697 }
1698 
set_chlo_multiplier(size_t multiplier)1699 void QuicCryptoServerConfig::set_chlo_multiplier(size_t multiplier) {
1700   chlo_multiplier_ = multiplier;
1701 }
1702 
set_source_address_token_future_secs(uint32_t future_secs)1703 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1704     uint32_t future_secs) {
1705   source_address_token_future_secs_ = future_secs;
1706 }
1707 
set_source_address_token_lifetime_secs(uint32_t lifetime_secs)1708 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1709     uint32_t lifetime_secs) {
1710   source_address_token_lifetime_secs_ = lifetime_secs;
1711 }
1712 
set_enable_serving_sct(bool enable_serving_sct)1713 void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) {
1714   enable_serving_sct_ = enable_serving_sct;
1715 }
1716 
AcquirePrimaryConfigChangedCb(std::unique_ptr<PrimaryConfigChangedCallback> cb)1717 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1718     std::unique_ptr<PrimaryConfigChangedCallback> cb) {
1719   QuicWriterMutexLock locked(&configs_lock_);
1720   primary_config_changed_cb_ = std::move(cb);
1721 }
1722 
NewSourceAddressToken(const CryptoSecretBoxer & crypto_secret_boxer,const SourceAddressTokens & previous_tokens,const QuicIpAddress & ip,QuicRandom * rand,QuicWallTime now,const CachedNetworkParameters * cached_network_params) const1723 std::string QuicCryptoServerConfig::NewSourceAddressToken(
1724     const CryptoSecretBoxer& crypto_secret_boxer,
1725     const SourceAddressTokens& previous_tokens, const QuicIpAddress& ip,
1726     QuicRandom* rand, QuicWallTime now,
1727     const CachedNetworkParameters* cached_network_params) const {
1728   SourceAddressTokens source_address_tokens;
1729   SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
1730   source_address_token->set_ip(ip.DualStacked().ToPackedString());
1731   source_address_token->set_timestamp(now.ToUNIXSeconds());
1732   if (cached_network_params != nullptr) {
1733     *(source_address_token->mutable_cached_network_parameters()) =
1734         *cached_network_params;
1735   }
1736 
1737   // Append previous tokens.
1738   for (const SourceAddressToken& token : previous_tokens.tokens()) {
1739     if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
1740       break;
1741     }
1742 
1743     if (token.ip() == source_address_token->ip()) {
1744       // It's for the same IP address.
1745       continue;
1746     }
1747 
1748     if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
1749       continue;
1750     }
1751 
1752     *(source_address_tokens.add_tokens()) = token;
1753   }
1754 
1755   return crypto_secret_boxer.Box(rand,
1756                                  source_address_tokens.SerializeAsString());
1757 }
1758 
NumberOfConfigs() const1759 int QuicCryptoServerConfig::NumberOfConfigs() const {
1760   QuicReaderMutexLock locked(&configs_lock_);
1761   return configs_.size();
1762 }
1763 
proof_source() const1764 ProofSource* QuicCryptoServerConfig::proof_source() const {
1765   return proof_source_.get();
1766 }
1767 
ssl_ctx() const1768 SSL_CTX* QuicCryptoServerConfig::ssl_ctx() const { return ssl_ctx_.get(); }
1769 
ParseSourceAddressToken(const CryptoSecretBoxer & crypto_secret_boxer,absl::string_view token,SourceAddressTokens & tokens) const1770 HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
1771     const CryptoSecretBoxer& crypto_secret_boxer, absl::string_view token,
1772     SourceAddressTokens& tokens) const {
1773   std::string storage;
1774   absl::string_view plaintext;
1775   if (!crypto_secret_boxer.Unbox(token, &storage, &plaintext)) {
1776     return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1777   }
1778 
1779   if (!tokens.ParseFromArray(plaintext.data(), plaintext.size())) {
1780     // Some clients might still be using the old source token format so
1781     // attempt to parse that format.
1782     // TODO(rch): remove this code once the new format is ubiquitous.
1783     SourceAddressToken old_source_token;
1784     if (!old_source_token.ParseFromArray(plaintext.data(), plaintext.size())) {
1785       return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1786     }
1787     *tokens.add_tokens() = old_source_token;
1788   }
1789 
1790   return HANDSHAKE_OK;
1791 }
1792 
ValidateSourceAddressTokens(const SourceAddressTokens & source_address_tokens,const QuicIpAddress & ip,QuicWallTime now,CachedNetworkParameters * cached_network_params) const1793 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
1794     const SourceAddressTokens& source_address_tokens, const QuicIpAddress& ip,
1795     QuicWallTime now, CachedNetworkParameters* cached_network_params) const {
1796   HandshakeFailureReason reason =
1797       SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1798   for (const SourceAddressToken& token : source_address_tokens.tokens()) {
1799     reason = ValidateSingleSourceAddressToken(token, ip, now);
1800     if (reason == HANDSHAKE_OK) {
1801       if (cached_network_params != nullptr &&
1802           token.has_cached_network_parameters()) {
1803         *cached_network_params = token.cached_network_parameters();
1804       }
1805       break;
1806     }
1807   }
1808   return reason;
1809 }
1810 
ValidateSingleSourceAddressToken(const SourceAddressToken & source_address_token,const QuicIpAddress & ip,QuicWallTime now) const1811 HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1812     const SourceAddressToken& source_address_token, const QuicIpAddress& ip,
1813     QuicWallTime now) const {
1814   if (source_address_token.ip() != ip.DualStacked().ToPackedString()) {
1815     // It's for a different IP address.
1816     return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1817   }
1818 
1819   return ValidateSourceAddressTokenTimestamp(source_address_token, now);
1820 }
1821 
1822 HandshakeFailureReason
ValidateSourceAddressTokenTimestamp(const SourceAddressToken & source_address_token,QuicWallTime now) const1823 QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1824     const SourceAddressToken& source_address_token, QuicWallTime now) const {
1825   const QuicWallTime timestamp(
1826       QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1827   const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1828 
1829   if (now.IsBefore(timestamp) &&
1830       delta.ToSeconds() > source_address_token_future_secs_) {
1831     return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1832   }
1833 
1834   if (now.IsAfter(timestamp) &&
1835       delta.ToSeconds() > source_address_token_lifetime_secs_) {
1836     return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1837   }
1838 
1839   return HANDSHAKE_OK;
1840 }
1841 
1842 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1843 // nonce.
1844 static const size_t kServerNoncePlaintextSize =
1845     4 /* timestamp */ + 20 /* random bytes */;
1846 
NewServerNonce(QuicRandom * rand,QuicWallTime now) const1847 std::string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1848                                                    QuicWallTime now) const {
1849   const uint32_t timestamp = static_cast<uint32_t>(now.ToUNIXSeconds());
1850 
1851   uint8_t server_nonce[kServerNoncePlaintextSize];
1852   static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
1853   server_nonce[0] = static_cast<uint8_t>(timestamp >> 24);
1854   server_nonce[1] = static_cast<uint8_t>(timestamp >> 16);
1855   server_nonce[2] = static_cast<uint8_t>(timestamp >> 8);
1856   server_nonce[3] = static_cast<uint8_t>(timestamp);
1857   rand->RandBytes(&server_nonce[sizeof(timestamp)],
1858                   sizeof(server_nonce) - sizeof(timestamp));
1859 
1860   return server_nonce_boxer_.Box(
1861       rand, absl::string_view(reinterpret_cast<char*>(server_nonce),
1862                               sizeof(server_nonce)));
1863 }
1864 
ValidateExpectedLeafCertificate(const CryptoHandshakeMessage & client_hello,const std::vector<std::string> & certs) const1865 bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
1866     const CryptoHandshakeMessage& client_hello,
1867     const std::vector<std::string>& certs) const {
1868   if (certs.empty()) {
1869     return false;
1870   }
1871 
1872   uint64_t hash_from_client;
1873   if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) {
1874     return false;
1875   }
1876   return CryptoUtils::ComputeLeafCertHash(certs[0]) == hash_from_client;
1877 }
1878 
IsNextConfigReady(QuicWallTime now) const1879 bool QuicCryptoServerConfig::IsNextConfigReady(QuicWallTime now) const {
1880   return !next_config_promotion_time_.IsZero() &&
1881          !next_config_promotion_time_.IsAfter(now);
1882 }
1883 
Config()1884 QuicCryptoServerConfig::Config::Config()
1885     : channel_id_enabled(false),
1886       is_primary(false),
1887       primary_time(QuicWallTime::Zero()),
1888       expiry_time(QuicWallTime::Zero()),
1889       priority(0),
1890       source_address_token_boxer(nullptr) {}
1891 
~Config()1892 QuicCryptoServerConfig::Config::~Config() {}
1893 
QuicSignedServerConfig()1894 QuicSignedServerConfig::QuicSignedServerConfig() {}
~QuicSignedServerConfig()1895 QuicSignedServerConfig::~QuicSignedServerConfig() {}
1896 
1897 }  // namespace quic
1898