• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
6 #define QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include "absl/strings/string_view.h"
16 #include "openssl/base.h"
17 #include "quiche/quic/core/crypto/crypto_handshake.h"
18 #include "quiche/quic/core/crypto/crypto_handshake_message.h"
19 #include "quiche/quic/core/crypto/crypto_protocol.h"
20 #include "quiche/quic/core/crypto/crypto_secret_boxer.h"
21 #include "quiche/quic/core/crypto/key_exchange.h"
22 #include "quiche/quic/core/crypto/proof_source.h"
23 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h"
24 #include "quiche/quic/core/crypto/quic_crypto_proof.h"
25 #include "quiche/quic/core/crypto/quic_random.h"
26 #include "quiche/quic/core/proto/cached_network_parameters_proto.h"
27 #include "quiche/quic/core/proto/source_address_token_proto.h"
28 #include "quiche/quic/core/quic_time.h"
29 #include "quiche/quic/platform/api/quic_export.h"
30 #include "quiche/quic/platform/api/quic_mutex.h"
31 #include "quiche/quic/platform/api/quic_socket_address.h"
32 #include "quiche/common/platform/api/quiche_reference_counted.h"
33 
34 namespace quic {
35 
36 class CryptoHandshakeMessage;
37 class ProofSource;
38 class QuicClock;
39 class QuicServerConfigProtobuf;
40 struct QuicSignedServerConfig;
41 
42 // ClientHelloInfo contains information about a client hello message that is
43 // only kept for as long as it's being processed.
44 struct QUIC_EXPORT_PRIVATE ClientHelloInfo {
45   ClientHelloInfo(const QuicIpAddress& in_client_ip, QuicWallTime in_now);
46   ClientHelloInfo(const ClientHelloInfo& other);
47   ~ClientHelloInfo();
48 
49   // Inputs to EvaluateClientHello.
50   const QuicIpAddress client_ip;
51   const QuicWallTime now;
52 
53   // Outputs from EvaluateClientHello.
54   bool valid_source_address_token;
55   absl::string_view sni;
56   absl::string_view client_nonce;
57   absl::string_view server_nonce;
58   absl::string_view user_agent_id;
59   SourceAddressTokens source_address_tokens;
60 
61   // Errors from EvaluateClientHello.
62   std::vector<uint32_t> reject_reasons;
63   static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync");
64 };
65 
66 namespace test {
67 class QuicCryptoServerConfigPeer;
68 }  // namespace test
69 
70 // Hook that allows application code to subscribe to primary config changes.
71 class QUIC_EXPORT_PRIVATE PrimaryConfigChangedCallback {
72  public:
73   PrimaryConfigChangedCallback();
74   PrimaryConfigChangedCallback(const PrimaryConfigChangedCallback&) = delete;
75   PrimaryConfigChangedCallback& operator=(const PrimaryConfigChangedCallback&) =
76       delete;
77   virtual ~PrimaryConfigChangedCallback();
78   virtual void Run(const std::string& scid) = 0;
79 };
80 
81 // Callback used to accept the result of the |client_hello| validation step.
82 class QUIC_EXPORT_PRIVATE ValidateClientHelloResultCallback {
83  public:
84   // Opaque token that holds information about the client_hello and
85   // its validity.  Can be interpreted by calling ProcessClientHello.
86   struct QUIC_EXPORT_PRIVATE Result : public quiche::QuicheReferenceCounted {
87     Result(const CryptoHandshakeMessage& in_client_hello,
88            QuicIpAddress in_client_ip, QuicWallTime in_now);
89 
90     CryptoHandshakeMessage client_hello;
91     ClientHelloInfo info;
92     QuicErrorCode error_code;
93     std::string error_details;
94 
95     // Populated if the CHLO STK contained a CachedNetworkParameters proto.
96     CachedNetworkParameters cached_network_params;
97 
98    protected:
99     ~Result() override;
100   };
101 
102   ValidateClientHelloResultCallback();
103   ValidateClientHelloResultCallback(const ValidateClientHelloResultCallback&) =
104       delete;
105   ValidateClientHelloResultCallback& operator=(
106       const ValidateClientHelloResultCallback&) = delete;
107   virtual ~ValidateClientHelloResultCallback();
108   virtual void Run(quiche::QuicheReferenceCountedPointer<Result> result,
109                    std::unique_ptr<ProofSource::Details> details) = 0;
110 };
111 
112 // Callback used to accept the result of the ProcessClientHello method.
113 class QUIC_EXPORT_PRIVATE ProcessClientHelloResultCallback {
114  public:
115   ProcessClientHelloResultCallback();
116   ProcessClientHelloResultCallback(const ProcessClientHelloResultCallback&) =
117       delete;
118   ProcessClientHelloResultCallback& operator=(
119       const ProcessClientHelloResultCallback&) = delete;
120   virtual ~ProcessClientHelloResultCallback();
121   virtual void Run(QuicErrorCode error, const std::string& error_details,
122                    std::unique_ptr<CryptoHandshakeMessage> message,
123                    std::unique_ptr<DiversificationNonce> diversification_nonce,
124                    std::unique_ptr<ProofSource::Details> details) = 0;
125 };
126 
127 // Callback used to receive the results of a call to
128 // BuildServerConfigUpdateMessage.
129 class QUIC_EXPORT_PRIVATE BuildServerConfigUpdateMessageResultCallback {
130  public:
131   BuildServerConfigUpdateMessageResultCallback() = default;
~BuildServerConfigUpdateMessageResultCallback()132   virtual ~BuildServerConfigUpdateMessageResultCallback() {}
133   BuildServerConfigUpdateMessageResultCallback(
134       const BuildServerConfigUpdateMessageResultCallback&) = delete;
135   BuildServerConfigUpdateMessageResultCallback& operator=(
136       const BuildServerConfigUpdateMessageResultCallback&) = delete;
137   virtual void Run(bool ok, const CryptoHandshakeMessage& message) = 0;
138 };
139 
140 // Object that is interested in built rejections (which include REJ, SREJ and
141 // cheap SREJ).
142 class QUIC_EXPORT_PRIVATE RejectionObserver {
143  public:
144   RejectionObserver() = default;
~RejectionObserver()145   virtual ~RejectionObserver() {}
146   RejectionObserver(const RejectionObserver&) = delete;
147   RejectionObserver& operator=(const RejectionObserver&) = delete;
148   // Called after a rejection is built.
149   virtual void OnRejectionBuilt(const std::vector<uint32_t>& reasons,
150                                 CryptoHandshakeMessage* out) const = 0;
151 };
152 
153 // Factory for creating KeyExchange objects.
154 class QUIC_EXPORT_PRIVATE KeyExchangeSource {
155  public:
156   virtual ~KeyExchangeSource() = default;
157 
158   // Returns the default KeyExchangeSource.
159   static std::unique_ptr<KeyExchangeSource> Default();
160 
161   // Create a new KeyExchange using the curve specified by |type| using the
162   // specified private key.  |private_key| may be empty for key-exchange
163   // mechanisms which do not hold the private key in-process.  If |is_fallback|
164   // is set, |private_key| is required to be set, and a local key-exchange
165   // object should be returned.
166   virtual std::unique_ptr<AsynchronousKeyExchange> Create(
167       std::string server_config_id, bool is_fallback, QuicTag type,
168       absl::string_view private_key) = 0;
169 };
170 
171 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server.
172 // Unlike a client, a QUIC server can have multiple configurations active in
173 // order to support clients resuming with a previous configuration.
174 // TODO(agl): when adding configurations at runtime is added, this object will
175 // need to consider locking.
176 class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
177  public:
178   // ConfigOptions contains options for generating server configs.
179   struct QUIC_EXPORT_PRIVATE ConfigOptions {
180     ConfigOptions();
181     ConfigOptions(const ConfigOptions& other);
182     ~ConfigOptions();
183 
184     // expiry_time is the time, in UNIX seconds, when the server config will
185     // expire. If unset, it defaults to the current time plus six months.
186     QuicWallTime expiry_time;
187     // channel_id_enabled controls whether the server config will indicate
188     // support for ChannelIDs.
189     bool channel_id_enabled;
190     // id contains the server config id for the resulting config. If empty, a
191     // random id is generated.
192     std::string id;
193     // orbit contains the kOrbitSize bytes of the orbit value for the server
194     // config. If |orbit| is empty then a random orbit is generated.
195     std::string orbit;
196     // p256 determines whether a P-256 public key will be included in the
197     // server config. Note that this breaks deterministic server-config
198     // generation since P-256 key generation doesn't use the QuicRandom given
199     // to GenerateConfig().
200     bool p256;
201   };
202 
203   // |source_address_token_secret|: secret key material used for encrypting and
204   //     decrypting source address tokens. It can be of any length as it is fed
205   //     into a KDF before use. In tests, use TESTING.
206   // |server_nonce_entropy|: an entropy source used to generate the orbit and
207   //     key for server nonces, which are always local to a given instance of a
208   //     server. Not owned.
209   // |proof_source|: provides certificate chains and signatures.
210   // |key_exchange_source|: provides key-exchange functionality.
211   QuicCryptoServerConfig(
212       absl::string_view source_address_token_secret,
213       QuicRandom* server_nonce_entropy,
214       std::unique_ptr<ProofSource> proof_source,
215       std::unique_ptr<KeyExchangeSource> key_exchange_source);
216   QuicCryptoServerConfig(const QuicCryptoServerConfig&) = delete;
217   QuicCryptoServerConfig& operator=(const QuicCryptoServerConfig&) = delete;
218   ~QuicCryptoServerConfig();
219 
220   // TESTING is a magic parameter for passing to the constructor in tests.
221   static const char TESTING[];
222 
223   // Generates a QuicServerConfigProtobuf protobuf suitable for
224   // AddConfig and SetConfigs.
225   static QuicServerConfigProtobuf GenerateConfig(QuicRandom* rand,
226                                                  const QuicClock* clock,
227                                                  const ConfigOptions& options);
228 
229   // AddConfig adds a QuicServerConfigProtobuf to the available configurations.
230   // It returns the SCFG message from the config if successful. |now| is used in
231   // conjunction with |protobuf->primary_time()| to determine whether the
232   // config should be made primary.
233   std::unique_ptr<CryptoHandshakeMessage> AddConfig(
234       const QuicServerConfigProtobuf& protobuf, QuicWallTime now);
235 
236   // AddDefaultConfig calls GenerateConfig to create a config and then calls
237   // AddConfig to add it. See the comment for |GenerateConfig| for details of
238   // the arguments.
239   std::unique_ptr<CryptoHandshakeMessage> AddDefaultConfig(
240       QuicRandom* rand, const QuicClock* clock, const ConfigOptions& options);
241 
242   // SetConfigs takes a vector of config protobufs and the current time.
243   // Configs are assumed to be uniquely identified by their server config ID.
244   // Previously unknown configs are added and possibly made the primary config
245   // depending on their |primary_time| and the value of |now|. Configs that are
246   // known, but are missing from the protobufs are deleted, unless they are
247   // currently the primary config. SetConfigs returns false if any errors were
248   // encountered and no changes to the QuicCryptoServerConfig will occur.
249   bool SetConfigs(const std::vector<QuicServerConfigProtobuf>& protobufs,
250                   const QuicServerConfigProtobuf* fallback_protobuf,
251                   QuicWallTime now);
252 
253   // SetSourceAddressTokenKeys sets the keys to be tried, in order, when
254   // decrypting a source address token.  Note that these keys are used *without*
255   // passing them through a KDF, in contradistinction to the
256   // |source_address_token_secret| argument to the constructor.
257   void SetSourceAddressTokenKeys(const std::vector<std::string>& keys);
258 
259   // Get the server config ids for all known configs.
260   std::vector<std::string> GetConfigIds() const;
261 
262   // Checks |client_hello| for gross errors and determines whether it can be
263   // shown to be fresh (i.e. not a replay).  The result of the validation step
264   // must be interpreted by calling QuicCryptoServerConfig::ProcessClientHello
265   // from the done_cb.
266   //
267   // ValidateClientHello may invoke the done_cb before unrolling the
268   // stack if it is able to assess the validity of the client_nonce
269   // without asynchronous operations.
270   //
271   // client_hello: the incoming client hello message.
272   // client_ip: the IP address of the client, which is used to generate and
273   //     validate source-address tokens.
274   // server_address: the IP address and port of the server. The IP address and
275   //     port may be used for certificate selection.
276   // version: protocol version used for this connection.
277   // clock: used to validate client nonces and ephemeral keys.
278   // signed_config: in/out parameter to which will be written the crypto proof
279   //     used in reply to a proof demand.  The pointed-to-object must live until
280   //     the callback is invoked.
281   // done_cb: single-use callback that accepts an opaque
282   //     ValidatedClientHelloMsg token that holds information about
283   //     the client hello.  The callback will always be called exactly
284   //     once, either under the current call stack, or after the
285   //     completion of an asynchronous operation.
286   void ValidateClientHello(
287       const CryptoHandshakeMessage& client_hello,
288       const QuicSocketAddress& client_address,
289       const QuicSocketAddress& server_address, QuicTransportVersion version,
290       const QuicClock* clock,
291       quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
292           signed_config,
293       std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const;
294 
295   // ProcessClientHello processes |client_hello| and decides whether to accept
296   // or reject the connection. If the connection is to be accepted, |done_cb| is
297   // invoked with the contents of the ServerHello and QUIC_NO_ERROR. Otherwise
298   // |done_cb| is called with a REJ or SREJ message and QUIC_NO_ERROR.
299   //
300   // validate_chlo_result: Output from the asynchronous call to
301   //     ValidateClientHello.  Contains the client hello message and
302   //     information about it.
303   // reject_only: Only generate rejections, not server hello messages.
304   // connection_id: the ConnectionId for the connection, which is used in key
305   //     derivation.
306   // server_ip: the IP address of the server. The IP address may be used for
307   //     certificate selection.
308   // client_address: the IP address and port of the client. The IP address is
309   //     used to generate and validate source-address tokens.
310   // version: version of the QUIC protocol in use for this connection
311   // supported_versions: versions of the QUIC protocol that this server
312   //     supports.
313   // clock: used to validate client nonces and ephemeral keys.
314   // rand: an entropy source
315   // compressed_certs_cache: the cache that caches a set of most recently used
316   //     certs. Owned by QuicDispatcher.
317   // params: the state of the handshake. This may be updated with a server
318   //     nonce when we send a rejection.
319   // signed_config: output structure containing the crypto proof used in reply
320   //     to a proof demand.
321   // total_framing_overhead: the total per-packet overhead for a stream frame
322   // chlo_packet_size: the size, in bytes, of the CHLO packet
323   // done_cb: the callback invoked on completion
324   void ProcessClientHello(
325       quiche::QuicheReferenceCountedPointer<
326           ValidateClientHelloResultCallback::Result>
327           validate_chlo_result,
328       bool reject_only, QuicConnectionId connection_id,
329       const QuicSocketAddress& server_address,
330       const QuicSocketAddress& client_address, ParsedQuicVersion version,
331       const ParsedQuicVersionVector& supported_versions, const QuicClock* clock,
332       QuicRandom* rand, QuicCompressedCertsCache* compressed_certs_cache,
333       quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
334           params,
335       quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
336           signed_config,
337       QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size,
338       std::shared_ptr<ProcessClientHelloResultCallback> done_cb) const;
339 
340   // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing
341   // the current primary config, an up to date source-address token, and cert
342   // chain and proof in the case of secure QUIC. Passes true to |cb| if the
343   // message was generated successfully, and false otherwise.  This method
344   // assumes ownership of |cb|.
345   //
346   // |cached_network_params| is optional, and can be nullptr.
347   void BuildServerConfigUpdateMessage(
348       QuicTransportVersion version, absl::string_view chlo_hash,
349       const SourceAddressTokens& previous_source_address_tokens,
350       const QuicSocketAddress& server_address,
351       const QuicSocketAddress& client_address, const QuicClock* clock,
352       QuicRandom* rand, QuicCompressedCertsCache* compressed_certs_cache,
353       const QuicCryptoNegotiatedParameters& params,
354       const CachedNetworkParameters* cached_network_params,
355       std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const;
356 
357   // set_replay_protection controls whether replay protection is enabled. If
358   // replay protection is disabled then no strike registers are needed and
359   // frontends can share an orbit value without a shared strike-register.
360   // However, an attacker can duplicate a handshake and cause a client's
361   // request to be processed twice.
362   void set_replay_protection(bool on);
363 
364   // set_chlo_multiplier specifies the multiple of the CHLO message size
365   // that a REJ message must stay under when the client doesn't present a
366   // valid source-address token.
367   void set_chlo_multiplier(size_t multiplier);
368 
369   // When sender is allowed to not pad client hello (not standards compliant),
370   // we need to disable the client hello check.
set_validate_chlo_size(bool new_value)371   void set_validate_chlo_size(bool new_value) {
372     validate_chlo_size_ = new_value;
373   }
374 
375   // Returns whether the sender is allowed to not pad the client hello.
validate_chlo_size()376   bool validate_chlo_size() const { return validate_chlo_size_; }
377 
378   // When QUIC is tunneled through some other mechanism, source token validation
379   // may be disabled. Do not disable it if you are not providing other
380   // protection. (|true| protects against UDP amplification attack.).
set_validate_source_address_token(bool new_value)381   void set_validate_source_address_token(bool new_value) {
382     validate_source_address_token_ = new_value;
383   }
384 
385   // set_source_address_token_future_secs sets the number of seconds into the
386   // future that source-address tokens will be accepted from. Since
387   // source-address tokens are authenticated, this should only happen if
388   // another, valid server has clock-skew.
389   void set_source_address_token_future_secs(uint32_t future_secs);
390 
391   // set_source_address_token_lifetime_secs sets the number of seconds that a
392   // source-address token will be valid for.
393   void set_source_address_token_lifetime_secs(uint32_t lifetime_secs);
394 
395   // set_enable_serving_sct enables or disables serving signed cert timestamp
396   // (RFC6962) in server hello.
397   void set_enable_serving_sct(bool enable_serving_sct);
398 
399   // Set and take ownership of the callback to invoke on primary config changes.
400   void AcquirePrimaryConfigChangedCb(
401       std::unique_ptr<PrimaryConfigChangedCallback> cb);
402 
403   // Returns the number of configs this object owns.
404   int NumberOfConfigs() const;
405 
406   // NewSourceAddressToken returns a fresh source address token for the given
407   // IP address. |previous_tokens| is the received tokens, and can be empty.
408   // |cached_network_params| is optional, and can be nullptr.
409   std::string NewSourceAddressToken(
410       const CryptoSecretBoxer& crypto_secret_boxer,
411       const SourceAddressTokens& previous_tokens, const QuicIpAddress& ip,
412       QuicRandom* rand, QuicWallTime now,
413       const CachedNetworkParameters* cached_network_params) const;
414 
415   // ParseSourceAddressToken parses the source address tokens contained in
416   // the encrypted |token|, and populates |tokens| with the parsed tokens.
417   // Returns HANDSHAKE_OK if |token| could be parsed, or the reason for the
418   // failure.
419   HandshakeFailureReason ParseSourceAddressToken(
420       const CryptoSecretBoxer& crypto_secret_boxer, absl::string_view token,
421       SourceAddressTokens& tokens) const;
422 
423   // ValidateSourceAddressTokens returns HANDSHAKE_OK if the source address
424   // tokens in |tokens| contain a valid and timely token for the IP address
425   // |ip| given that the current time is |now|. Otherwise it returns the
426   // reason for failure. |cached_network_params| is populated if the valid
427   // token contains a CachedNetworkParameters proto.
428   HandshakeFailureReason ValidateSourceAddressTokens(
429       const SourceAddressTokens& tokens, const QuicIpAddress& ip,
430       QuicWallTime now, CachedNetworkParameters* cached_network_params) const;
431 
432   // Callers retain the ownership of |rejection_observer| which must outlive the
433   // config.
set_rejection_observer(RejectionObserver * rejection_observer)434   void set_rejection_observer(RejectionObserver* rejection_observer) {
435     rejection_observer_ = rejection_observer;
436   }
437 
438   ProofSource* proof_source() const;
439 
440   SSL_CTX* ssl_ctx() const;
441 
442   // Pre-shared key used during the handshake.
pre_shared_key()443   const std::string& pre_shared_key() const { return pre_shared_key_; }
set_pre_shared_key(absl::string_view psk)444   void set_pre_shared_key(absl::string_view psk) {
445     pre_shared_key_ = std::string(psk);
446   }
447 
pad_rej()448   bool pad_rej() const { return pad_rej_; }
set_pad_rej(bool new_value)449   void set_pad_rej(bool new_value) { pad_rej_ = new_value; }
450 
pad_shlo()451   bool pad_shlo() const { return pad_shlo_; }
set_pad_shlo(bool new_value)452   void set_pad_shlo(bool new_value) { pad_shlo_ = new_value; }
453 
source_address_token_boxer()454   const CryptoSecretBoxer& source_address_token_boxer() const {
455     return source_address_token_boxer_;
456   }
457 
458  private:
459   friend class test::QuicCryptoServerConfigPeer;
460   friend struct QuicSignedServerConfig;
461 
462   // Config represents a server config: a collection of preferences and
463   // Diffie-Hellman public values.
464   class QUIC_EXPORT_PRIVATE Config : public QuicCryptoConfig,
465                                      public quiche::QuicheReferenceCounted {
466    public:
467     Config();
468     Config(const Config&) = delete;
469     Config& operator=(const Config&) = delete;
470 
471     // TODO(rtenneti): since this is a class, we should probably do
472     // getters/setters here.
473     // |serialized| contains the bytes of this server config, suitable for
474     // sending on the wire.
475     std::string serialized;
476     // id contains the SCID of this server config.
477     std::string id;
478     // orbit contains the orbit value for this config: an opaque identifier
479     // used to identify clusters of server frontends.
480     unsigned char orbit[kOrbitSize];
481 
482     // key_exchanges contains key exchange objects. The values correspond,
483     // one-to-one, with the tags in |kexs| from the parent class.
484     std::vector<std::unique_ptr<AsynchronousKeyExchange>> key_exchanges;
485 
486     // channel_id_enabled is true if the config in |serialized| specifies that
487     // ChannelIDs are supported.
488     bool channel_id_enabled;
489 
490     // is_primary is true if this config is the one that we'll give out to
491     // clients as the current one.
492     bool is_primary;
493 
494     // primary_time contains the timestamp when this config should become the
495     // primary config. A value of QuicWallTime::Zero() means that this config
496     // will not be promoted at a specific time.
497     QuicWallTime primary_time;
498 
499     // expiry_time contains the timestamp when this config expires.
500     QuicWallTime expiry_time;
501 
502     // Secondary sort key for use when selecting primary configs and
503     // there are multiple configs with the same primary time.
504     // Smaller numbers mean higher priority.
505     uint64_t priority;
506 
507     // source_address_token_boxer_ is used to protect the
508     // source-address tokens that are given to clients.
509     // Points to either source_address_token_boxer_storage or the
510     // default boxer provided by QuicCryptoServerConfig.
511     const CryptoSecretBoxer* source_address_token_boxer;
512 
513     // Holds the override source_address_token_boxer instance if the
514     // Config is not using the default source address token boxer
515     // instance provided by QuicCryptoServerConfig.
516     std::unique_ptr<CryptoSecretBoxer> source_address_token_boxer_storage;
517 
518    private:
519     ~Config() override;
520   };
521 
522   using ConfigMap =
523       std::map<ServerConfigID, quiche::QuicheReferenceCountedPointer<Config>>;
524 
525   // Get a ref to the config with a given server config id.
526   quiche::QuicheReferenceCountedPointer<Config> GetConfigWithScid(
527       absl::string_view requested_scid) const
528       QUIC_SHARED_LOCKS_REQUIRED(configs_lock_);
529 
530   // A snapshot of the configs associated with an in-progress handshake.
531   struct QUIC_EXPORT_PRIVATE Configs {
532     quiche::QuicheReferenceCountedPointer<Config> requested;
533     quiche::QuicheReferenceCountedPointer<Config> primary;
534     quiche::QuicheReferenceCountedPointer<Config> fallback;
535   };
536 
537   // Get a snapshot of the current configs associated with a handshake.  If this
538   // method was called earlier in this handshake |old_primary_config| should be
539   // set to the primary config returned from that invocation, otherwise nullptr.
540   //
541   // Returns true if any configs are loaded.  If false is returned, |configs| is
542   // not modified.
543   bool GetCurrentConfigs(
544       const QuicWallTime& now, absl::string_view requested_scid,
545       quiche::QuicheReferenceCountedPointer<Config> old_primary_config,
546       Configs* configs) const;
547 
548   // ConfigPrimaryTimeLessThan returns true if a->primary_time <
549   // b->primary_time.
550   static bool ConfigPrimaryTimeLessThan(
551       const quiche::QuicheReferenceCountedPointer<Config>& a,
552       const quiche::QuicheReferenceCountedPointer<Config>& b);
553 
554   // SelectNewPrimaryConfig reevaluates the primary config based on the
555   // "primary_time" deadlines contained in each.
556   void SelectNewPrimaryConfig(QuicWallTime now) const
557       QUIC_EXCLUSIVE_LOCKS_REQUIRED(configs_lock_);
558 
559   // EvaluateClientHello checks |client_hello_state->client_hello| for gross
560   // errors and determines whether it is fresh (i.e. not a replay). The results
561   // are written to |client_hello_state->info|.
562   void EvaluateClientHello(
563       const QuicSocketAddress& server_address,
564       const QuicSocketAddress& client_address, QuicTransportVersion version,
565       const Configs& configs,
566       quiche::QuicheReferenceCountedPointer<
567           ValidateClientHelloResultCallback::Result>
568           client_hello_state,
569       std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const;
570 
571   // Convenience class which carries the arguments passed to
572   // |ProcessClientHellp| along.
573   class QUIC_EXPORT_PRIVATE ProcessClientHelloContext {
574    public:
ProcessClientHelloContext(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)575     ProcessClientHelloContext(
576         quiche::QuicheReferenceCountedPointer<
577             ValidateClientHelloResultCallback::Result>
578             validate_chlo_result,
579         bool reject_only, QuicConnectionId connection_id,
580         const QuicSocketAddress& server_address,
581         const QuicSocketAddress& client_address, ParsedQuicVersion version,
582         const ParsedQuicVersionVector& supported_versions,
583         const QuicClock* clock, QuicRandom* rand,
584         QuicCompressedCertsCache* compressed_certs_cache,
585         quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
586             params,
587         quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
588             signed_config,
589         QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size,
590         std::shared_ptr<ProcessClientHelloResultCallback> done_cb)
591         : validate_chlo_result_(validate_chlo_result),
592           reject_only_(reject_only),
593           connection_id_(connection_id),
594           server_address_(server_address),
595           client_address_(client_address),
596           version_(version),
597           supported_versions_(supported_versions),
598           clock_(clock),
599           rand_(rand),
600           compressed_certs_cache_(compressed_certs_cache),
601           params_(params),
602           signed_config_(signed_config),
603           total_framing_overhead_(total_framing_overhead),
604           chlo_packet_size_(chlo_packet_size),
605           done_cb_(std::move(done_cb)) {}
606 
607     ~ProcessClientHelloContext();
608 
609     // Invoke |done_cb_| with an error status
610     void Fail(QuicErrorCode error, const std::string& error_details);
611 
612     // Invoke |done_cb_| with a success status
613     void Succeed(std::unique_ptr<CryptoHandshakeMessage> message,
614                  std::unique_ptr<DiversificationNonce> diversification_nonce,
615                  std::unique_ptr<ProofSource::Details> proof_source_details);
616 
617     // Member accessors
618     quiche::QuicheReferenceCountedPointer<
619         ValidateClientHelloResultCallback::Result>
validate_chlo_result()620     validate_chlo_result() const {
621       return validate_chlo_result_;
622     }
reject_only()623     bool reject_only() const { return reject_only_; }
connection_id()624     QuicConnectionId connection_id() const { return connection_id_; }
server_address()625     QuicSocketAddress server_address() const { return server_address_; }
client_address()626     QuicSocketAddress client_address() const { return client_address_; }
version()627     ParsedQuicVersion version() const { return version_; }
supported_versions()628     ParsedQuicVersionVector supported_versions() const {
629       return supported_versions_;
630     }
clock()631     const QuicClock* clock() const { return clock_; }
rand()632     QuicRandom* rand() const { return rand_; }  // NOLINT
compressed_certs_cache()633     QuicCompressedCertsCache* compressed_certs_cache() const {
634       return compressed_certs_cache_;
635     }
636     quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
params()637     params() const {
638       return params_;
639     }
640     quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
signed_config()641     signed_config() const {
642       return signed_config_;
643     }
total_framing_overhead()644     QuicByteCount total_framing_overhead() const {
645       return total_framing_overhead_;
646     }
chlo_packet_size()647     QuicByteCount chlo_packet_size() const { return chlo_packet_size_; }
648 
649     // Derived value accessors
client_hello()650     const CryptoHandshakeMessage& client_hello() const {
651       return validate_chlo_result()->client_hello;
652     }
info()653     const ClientHelloInfo& info() const { return validate_chlo_result()->info; }
transport_version()654     QuicTransportVersion transport_version() const {
655       return version().transport_version;
656     }
657 
658    private:
659     const quiche::QuicheReferenceCountedPointer<
660         ValidateClientHelloResultCallback::Result>
661         validate_chlo_result_;
662     const bool reject_only_;
663     const QuicConnectionId connection_id_;
664     const QuicSocketAddress server_address_;
665     const QuicSocketAddress client_address_;
666     const ParsedQuicVersion version_;
667     const ParsedQuicVersionVector supported_versions_;
668     const QuicClock* const clock_;
669     QuicRandom* const rand_;
670     QuicCompressedCertsCache* const compressed_certs_cache_;
671     const quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
672         params_;
673     const quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
674         signed_config_;
675     const QuicByteCount total_framing_overhead_;
676     const QuicByteCount chlo_packet_size_;
677     std::shared_ptr<ProcessClientHelloResultCallback> done_cb_;
678   };
679 
680   // Callback class for bridging between ProcessClientHello and
681   // ProcessClientHelloAfterGetProof.
682   class ProcessClientHelloCallback;
683   friend class ProcessClientHelloCallback;
684 
685   // Portion of ProcessClientHello which executes after GetProof.
686   void ProcessClientHelloAfterGetProof(
687       bool found_error,
688       std::unique_ptr<ProofSource::Details> proof_source_details,
689       std::unique_ptr<ProcessClientHelloContext> context,
690       const Configs& configs) const;
691 
692   // Callback class for bridging between ProcessClientHelloAfterGetProof and
693   // ProcessClientHelloAfterCalculateSharedKeys.
694   class ProcessClientHelloAfterGetProofCallback;
695   friend class ProcessClientHelloAfterGetProofCallback;
696 
697   // Portion of ProcessClientHello which executes after CalculateSharedKeys.
698   void ProcessClientHelloAfterCalculateSharedKeys(
699       bool found_error,
700       std::unique_ptr<ProofSource::Details> proof_source_details,
701       QuicTag key_exchange_type, std::unique_ptr<CryptoHandshakeMessage> out,
702       absl::string_view public_value,
703       std::unique_ptr<ProcessClientHelloContext> context,
704       const Configs& configs) const;
705 
706   // Send a REJ which contains a different ServerConfig than the one the client
707   // originally used.  This is necessary in cases where we discover in the
708   // middle of the handshake that the private key for the ServerConfig the
709   // client used is not accessible.
710   void SendRejectWithFallbackConfig(
711       std::unique_ptr<ProcessClientHelloContext> context,
712       quiche::QuicheReferenceCountedPointer<Config> fallback_config) const;
713 
714   // Callback class for bridging between SendRejectWithFallbackConfig and
715   // SendRejectWithFallbackConfigAfterGetProof.
716   class SendRejectWithFallbackConfigCallback;
717   friend class SendRejectWithFallbackConfigCallback;
718 
719   // Portion of ProcessClientHello which executes after GetProof in the case
720   // where we have received a CHLO but need to reject it due to the ServerConfig
721   // private keys being inaccessible.
722   void SendRejectWithFallbackConfigAfterGetProof(
723       bool found_error,
724       std::unique_ptr<ProofSource::Details> proof_source_details,
725       std::unique_ptr<ProcessClientHelloContext> context,
726       quiche::QuicheReferenceCountedPointer<Config> fallback_config) const;
727 
728   // BuildRejectionAndRecordStats calls |BuildRejection| below and also informs
729   // the RejectionObserver.
730   void BuildRejectionAndRecordStats(const ProcessClientHelloContext& context,
731                                     const Config& config,
732                                     const std::vector<uint32_t>& reject_reasons,
733                                     CryptoHandshakeMessage* out) const;
734 
735   // BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
736   void BuildRejection(const ProcessClientHelloContext& context,
737                       const Config& config,
738                       const std::vector<uint32_t>& reject_reasons,
739                       CryptoHandshakeMessage* out) const;
740 
741   // CompressChain compresses the certificates in |chain->certs| and returns a
742   // compressed representation. |client_cached_cert_hashes| contains
743   // 64-bit, FNV-1a hashes of certificates that the peer already possesses.
744   static std::string CompressChain(
745       QuicCompressedCertsCache* compressed_certs_cache,
746       const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
747       const std::string& client_cached_cert_hashes);
748 
749   // ParseConfigProtobuf parses the given config protobuf and returns a
750   // quiche::QuicheReferenceCountedPointer<Config> if successful. The caller
751   // adopts the reference to the Config. On error, ParseConfigProtobuf returns
752   // nullptr.
753   quiche::QuicheReferenceCountedPointer<Config> ParseConfigProtobuf(
754       const QuicServerConfigProtobuf& protobuf, bool is_fallback) const;
755 
756   // ValidateSingleSourceAddressToken returns HANDSHAKE_OK if the source
757   // address token in |token| is a timely token for the IP address |ip|
758   // given that the current time is |now|. Otherwise it returns the reason
759   // for failure.
760   HandshakeFailureReason ValidateSingleSourceAddressToken(
761       const SourceAddressToken& token, const QuicIpAddress& ip,
762       QuicWallTime now) const;
763 
764   // Returns HANDSHAKE_OK if the source address token in |token| is a timely
765   // token given that the current time is |now|. Otherwise it returns the
766   // reason for failure.
767   HandshakeFailureReason ValidateSourceAddressTokenTimestamp(
768       const SourceAddressToken& token, QuicWallTime now) const;
769 
770   // NewServerNonce generates and encrypts a random nonce.
771   std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const;
772 
773   // ValidateExpectedLeafCertificate checks the |client_hello| to see if it has
774   // an XLCT tag, and if so, verifies that its value matches the hash of the
775   // server's leaf certificate. |certs| is used to compare against the XLCT
776   // value.  This method returns true if the XLCT tag is not present, or if the
777   // XLCT tag is present and valid. It returns false otherwise.
778   bool ValidateExpectedLeafCertificate(
779       const CryptoHandshakeMessage& client_hello,
780       const std::vector<std::string>& certs) const;
781 
782   // Callback to receive the results of ProofSource::GetProof.  Note: this
783   // callback has no cancellation support, since the lifetime of the ProofSource
784   // is controlled by this object via unique ownership.  If that ownership
785   // stricture changes, this decision may need to be revisited.
786   class BuildServerConfigUpdateMessageProofSourceCallback
787       : public ProofSource::Callback {
788    public:
789     BuildServerConfigUpdateMessageProofSourceCallback(
790         const BuildServerConfigUpdateMessageProofSourceCallback&) = delete;
791     ~BuildServerConfigUpdateMessageProofSourceCallback() override;
792     void operator=(const BuildServerConfigUpdateMessageProofSourceCallback&) =
793         delete;
794     BuildServerConfigUpdateMessageProofSourceCallback(
795         const QuicCryptoServerConfig* config,
796         QuicCompressedCertsCache* compressed_certs_cache,
797         const QuicCryptoNegotiatedParameters& params,
798         CryptoHandshakeMessage message,
799         std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb);
800 
801     void Run(
802         bool ok,
803         const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
804         const QuicCryptoProof& proof,
805         std::unique_ptr<ProofSource::Details> details) override;
806 
807    private:
808     const QuicCryptoServerConfig* config_;
809     QuicCompressedCertsCache* compressed_certs_cache_;
810     const std::string client_cached_cert_hashes_;
811     const bool sct_supported_by_client_;
812     const std::string sni_;
813     CryptoHandshakeMessage message_;
814     std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb_;
815   };
816 
817   // Invoked by BuildServerConfigUpdateMessageProofSourceCallback::Run once
818   // the proof has been acquired.  Finishes building the server config update
819   // message and invokes |cb|.
820   void FinishBuildServerConfigUpdateMessage(
821       QuicCompressedCertsCache* compressed_certs_cache,
822       const std::string& client_cached_cert_hashes,
823       bool sct_supported_by_client, const std::string& sni, bool ok,
824       const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
825       const std::string& signature, const std::string& leaf_cert_sct,
826       std::unique_ptr<ProofSource::Details> details,
827       CryptoHandshakeMessage message,
828       std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const;
829 
830   // Returns true if the next config promotion should happen now.
831   bool IsNextConfigReady(QuicWallTime now) const
832       QUIC_SHARED_LOCKS_REQUIRED(configs_lock_);
833 
834   // replay_protection_ controls whether the server enforces that handshakes
835   // aren't replays.
836   bool replay_protection_;
837 
838   // The multiple of the CHLO message size that a REJ message must stay under
839   // when the client doesn't present a valid source-address token. This is
840   // used to protect QUIC from amplification attacks.
841   size_t chlo_multiplier_;
842 
843   // configs_ satisfies the following invariants:
844   //   1) configs_.empty() <-> primary_config_ == nullptr
845   //   2) primary_config_ != nullptr -> primary_config_->is_primary
846   //   3) ∀ c∈configs_, c->is_primary <-> c == primary_config_
847   mutable QuicMutex configs_lock_;
848 
849   // configs_ contains all active server configs. It's expected that there are
850   // about half-a-dozen configs active at any one time.
851   ConfigMap configs_ QUIC_GUARDED_BY(configs_lock_);
852 
853   // primary_config_ points to a Config (which is also in |configs_|) which is
854   // the primary config - i.e. the one that we'll give out to new clients.
855   mutable quiche::QuicheReferenceCountedPointer<Config> primary_config_
856       QUIC_GUARDED_BY(configs_lock_);
857 
858   // fallback_config_ points to a Config (which is also in |configs_|) which is
859   // the fallback config, which will be used if the other configs are unuseable
860   // for some reason.
861   //
862   // TODO(b/112548056): This is currently always nullptr.
863   quiche::QuicheReferenceCountedPointer<Config> fallback_config_
864       QUIC_GUARDED_BY(configs_lock_);
865 
866   // next_config_promotion_time_ contains the nearest, future time when an
867   // active config will be promoted to primary.
868   mutable QuicWallTime next_config_promotion_time_
869       QUIC_GUARDED_BY(configs_lock_);
870 
871   // Callback to invoke when the primary config changes.
872   std::unique_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_
873       QUIC_GUARDED_BY(configs_lock_);
874 
875   // Used to protect the source-address tokens that are given to clients.
876   CryptoSecretBoxer source_address_token_boxer_;
877 
878   // server_nonce_boxer_ is used to encrypt and validate suggested server
879   // nonces.
880   CryptoSecretBoxer server_nonce_boxer_;
881 
882   // server_nonce_orbit_ contains the random, per-server orbit values that this
883   // server will use to generate server nonces (the moral equivalent of a SYN
884   // cookies).
885   uint8_t server_nonce_orbit_[8];
886 
887   // proof_source_ contains an object that can provide certificate chains and
888   // signatures.
889   std::unique_ptr<ProofSource> proof_source_;
890 
891   // key_exchange_source_ contains an object that can provide key exchange
892   // objects.
893   std::unique_ptr<KeyExchangeSource> key_exchange_source_;
894 
895   // ssl_ctx_ contains the server configuration for doing TLS handshakes.
896   bssl::UniquePtr<SSL_CTX> ssl_ctx_;
897 
898   // These fields store configuration values. See the comments for their
899   // respective setter functions.
900   uint32_t source_address_token_future_secs_;
901   uint32_t source_address_token_lifetime_secs_;
902 
903   // Enable serving SCT or not.
904   bool enable_serving_sct_;
905 
906   // Does not own this observer.
907   RejectionObserver* rejection_observer_;
908 
909   // If non-empty, the server will operate in the pre-shared key mode by
910   // incorporating |pre_shared_key_| into the key schedule.
911   std::string pre_shared_key_;
912 
913   // Whether REJ message should be padded to max packet size.
914   bool pad_rej_;
915 
916   // Whether SHLO message should be padded to max packet size.
917   bool pad_shlo_;
918 
919   // If client is allowed to send a small client hello (by disabling padding),
920   // server MUST not check for the client hello size.
921   // DO NOT disable this unless you have some other way of validating client.
922   // (e.g. in realtime scenarios, where quic is tunneled through ICE, ICE will
923   // do its own peer validation using STUN pings with ufrag/upass).
924   bool validate_chlo_size_;
925 
926   // When source address is validated by some other means (e.g. when using ICE),
927   // source address token validation may be disabled.
928   bool validate_source_address_token_;
929 };
930 
931 struct QUIC_EXPORT_PRIVATE QuicSignedServerConfig
932     : public quiche::QuicheReferenceCounted {
933   QuicSignedServerConfig();
934 
935   QuicCryptoProof proof;
936   quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain;
937   // The server config that is used for this proof (and the rest of the
938   // request).
939   quiche::QuicheReferenceCountedPointer<QuicCryptoServerConfig::Config> config;
940   std::string primary_scid;
941 
942  protected:
943   ~QuicSignedServerConfig() override;
944 };
945 
946 }  // namespace quic
947 
948 #endif  // QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
949