xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.h (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 #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 QUICHE_EXPORT 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 QUICHE_EXPORT 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 QUICHE_EXPORT 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 QUICHE_EXPORT 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 QUICHE_EXPORT 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 QUICHE_EXPORT 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 QUICHE_EXPORT 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 QUICHE_EXPORT 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 QUICHE_EXPORT QuicCryptoServerConfig {
177  public:
178   // ConfigOptions contains options for generating server configs.
179   struct QUICHE_EXPORT 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   // The groups to use for key exchange in the TLS handshake;
preferred_groups()443   const std::vector<uint16_t>& preferred_groups() const {
444     return preferred_groups_;
445   }
446 
447   // Sets the preferred groups that will be used in the TLS handshake. Values
448   // in the |preferred_groups| vector are NamedGroup enum codepoints from
449   // https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.7.
set_preferred_groups(const std::vector<uint16_t> & preferred_groups)450   void set_preferred_groups(const std::vector<uint16_t>& preferred_groups) {
451     preferred_groups_ = preferred_groups;
452   }
453 
454   // Pre-shared key used during the handshake.
pre_shared_key()455   const std::string& pre_shared_key() const { return pre_shared_key_; }
set_pre_shared_key(absl::string_view psk)456   void set_pre_shared_key(absl::string_view psk) {
457     pre_shared_key_ = std::string(psk);
458   }
459 
pad_rej()460   bool pad_rej() const { return pad_rej_; }
set_pad_rej(bool new_value)461   void set_pad_rej(bool new_value) { pad_rej_ = new_value; }
462 
pad_shlo()463   bool pad_shlo() const { return pad_shlo_; }
set_pad_shlo(bool new_value)464   void set_pad_shlo(bool new_value) { pad_shlo_ = new_value; }
465 
source_address_token_boxer()466   const CryptoSecretBoxer& source_address_token_boxer() const {
467     return source_address_token_boxer_;
468   }
469 
470  private:
471   friend class test::QuicCryptoServerConfigPeer;
472   friend struct QuicSignedServerConfig;
473 
474   // Config represents a server config: a collection of preferences and
475   // Diffie-Hellman public values.
476   class QUICHE_EXPORT Config : public QuicCryptoConfig,
477                                public quiche::QuicheReferenceCounted {
478    public:
479     Config();
480     Config(const Config&) = delete;
481     Config& operator=(const Config&) = delete;
482 
483     // TODO(rtenneti): since this is a class, we should probably do
484     // getters/setters here.
485     // |serialized| contains the bytes of this server config, suitable for
486     // sending on the wire.
487     std::string serialized;
488     // id contains the SCID of this server config.
489     std::string id;
490     // orbit contains the orbit value for this config: an opaque identifier
491     // used to identify clusters of server frontends.
492     unsigned char orbit[kOrbitSize];
493 
494     // key_exchanges contains key exchange objects. The values correspond,
495     // one-to-one, with the tags in |kexs| from the parent class.
496     std::vector<std::unique_ptr<AsynchronousKeyExchange>> key_exchanges;
497 
498     // channel_id_enabled is true if the config in |serialized| specifies that
499     // ChannelIDs are supported.
500     bool channel_id_enabled;
501 
502     // is_primary is true if this config is the one that we'll give out to
503     // clients as the current one.
504     bool is_primary;
505 
506     // primary_time contains the timestamp when this config should become the
507     // primary config. A value of QuicWallTime::Zero() means that this config
508     // will not be promoted at a specific time.
509     QuicWallTime primary_time;
510 
511     // expiry_time contains the timestamp when this config expires.
512     QuicWallTime expiry_time;
513 
514     // Secondary sort key for use when selecting primary configs and
515     // there are multiple configs with the same primary time.
516     // Smaller numbers mean higher priority.
517     uint64_t priority;
518 
519     // source_address_token_boxer_ is used to protect the
520     // source-address tokens that are given to clients.
521     // Points to either source_address_token_boxer_storage or the
522     // default boxer provided by QuicCryptoServerConfig.
523     const CryptoSecretBoxer* source_address_token_boxer;
524 
525     // Holds the override source_address_token_boxer instance if the
526     // Config is not using the default source address token boxer
527     // instance provided by QuicCryptoServerConfig.
528     std::unique_ptr<CryptoSecretBoxer> source_address_token_boxer_storage;
529 
530    private:
531     ~Config() override;
532   };
533 
534   using ConfigMap =
535       std::map<ServerConfigID, quiche::QuicheReferenceCountedPointer<Config>>;
536 
537   // Get a ref to the config with a given server config id.
538   quiche::QuicheReferenceCountedPointer<Config> GetConfigWithScid(
539       absl::string_view requested_scid) const
540       QUIC_SHARED_LOCKS_REQUIRED(configs_lock_);
541 
542   // A snapshot of the configs associated with an in-progress handshake.
543   struct QUICHE_EXPORT Configs {
544     quiche::QuicheReferenceCountedPointer<Config> requested;
545     quiche::QuicheReferenceCountedPointer<Config> primary;
546     quiche::QuicheReferenceCountedPointer<Config> fallback;
547   };
548 
549   // Get a snapshot of the current configs associated with a handshake.  If this
550   // method was called earlier in this handshake |old_primary_config| should be
551   // set to the primary config returned from that invocation, otherwise nullptr.
552   //
553   // Returns true if any configs are loaded.  If false is returned, |configs| is
554   // not modified.
555   bool GetCurrentConfigs(
556       const QuicWallTime& now, absl::string_view requested_scid,
557       quiche::QuicheReferenceCountedPointer<Config> old_primary_config,
558       Configs* configs) const;
559 
560   // ConfigPrimaryTimeLessThan returns true if a->primary_time <
561   // b->primary_time.
562   static bool ConfigPrimaryTimeLessThan(
563       const quiche::QuicheReferenceCountedPointer<Config>& a,
564       const quiche::QuicheReferenceCountedPointer<Config>& b);
565 
566   // SelectNewPrimaryConfig reevaluates the primary config based on the
567   // "primary_time" deadlines contained in each.
568   void SelectNewPrimaryConfig(QuicWallTime now) const
569       QUIC_EXCLUSIVE_LOCKS_REQUIRED(configs_lock_);
570 
571   // EvaluateClientHello checks |client_hello_state->client_hello| for gross
572   // errors and determines whether it is fresh (i.e. not a replay). The results
573   // are written to |client_hello_state->info|.
574   void EvaluateClientHello(
575       const QuicSocketAddress& server_address,
576       const QuicSocketAddress& client_address, QuicTransportVersion version,
577       const Configs& configs,
578       quiche::QuicheReferenceCountedPointer<
579           ValidateClientHelloResultCallback::Result>
580           client_hello_state,
581       std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const;
582 
583   // Convenience class which carries the arguments passed to
584   // |ProcessClientHellp| along.
585   class QUICHE_EXPORT ProcessClientHelloContext {
586    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)587     ProcessClientHelloContext(
588         quiche::QuicheReferenceCountedPointer<
589             ValidateClientHelloResultCallback::Result>
590             validate_chlo_result,
591         bool reject_only, QuicConnectionId connection_id,
592         const QuicSocketAddress& server_address,
593         const QuicSocketAddress& client_address, ParsedQuicVersion version,
594         const ParsedQuicVersionVector& supported_versions,
595         const QuicClock* clock, QuicRandom* rand,
596         QuicCompressedCertsCache* compressed_certs_cache,
597         quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
598             params,
599         quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
600             signed_config,
601         QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size,
602         std::shared_ptr<ProcessClientHelloResultCallback> done_cb)
603         : validate_chlo_result_(validate_chlo_result),
604           reject_only_(reject_only),
605           connection_id_(connection_id),
606           server_address_(server_address),
607           client_address_(client_address),
608           version_(version),
609           supported_versions_(supported_versions),
610           clock_(clock),
611           rand_(rand),
612           compressed_certs_cache_(compressed_certs_cache),
613           params_(params),
614           signed_config_(signed_config),
615           total_framing_overhead_(total_framing_overhead),
616           chlo_packet_size_(chlo_packet_size),
617           done_cb_(std::move(done_cb)) {}
618 
619     ~ProcessClientHelloContext();
620 
621     // Invoke |done_cb_| with an error status
622     void Fail(QuicErrorCode error, const std::string& error_details);
623 
624     // Invoke |done_cb_| with a success status
625     void Succeed(std::unique_ptr<CryptoHandshakeMessage> message,
626                  std::unique_ptr<DiversificationNonce> diversification_nonce,
627                  std::unique_ptr<ProofSource::Details> proof_source_details);
628 
629     // Member accessors
630     quiche::QuicheReferenceCountedPointer<
631         ValidateClientHelloResultCallback::Result>
validate_chlo_result()632     validate_chlo_result() const {
633       return validate_chlo_result_;
634     }
reject_only()635     bool reject_only() const { return reject_only_; }
connection_id()636     QuicConnectionId connection_id() const { return connection_id_; }
server_address()637     QuicSocketAddress server_address() const { return server_address_; }
client_address()638     QuicSocketAddress client_address() const { return client_address_; }
version()639     ParsedQuicVersion version() const { return version_; }
supported_versions()640     ParsedQuicVersionVector supported_versions() const {
641       return supported_versions_;
642     }
clock()643     const QuicClock* clock() const { return clock_; }
rand()644     QuicRandom* rand() const { return rand_; }  // NOLINT
compressed_certs_cache()645     QuicCompressedCertsCache* compressed_certs_cache() const {
646       return compressed_certs_cache_;
647     }
648     quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
params()649     params() const {
650       return params_;
651     }
652     quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
signed_config()653     signed_config() const {
654       return signed_config_;
655     }
total_framing_overhead()656     QuicByteCount total_framing_overhead() const {
657       return total_framing_overhead_;
658     }
chlo_packet_size()659     QuicByteCount chlo_packet_size() const { return chlo_packet_size_; }
660 
661     // Derived value accessors
client_hello()662     const CryptoHandshakeMessage& client_hello() const {
663       return validate_chlo_result()->client_hello;
664     }
info()665     const ClientHelloInfo& info() const { return validate_chlo_result()->info; }
transport_version()666     QuicTransportVersion transport_version() const {
667       return version().transport_version;
668     }
669 
670    private:
671     const quiche::QuicheReferenceCountedPointer<
672         ValidateClientHelloResultCallback::Result>
673         validate_chlo_result_;
674     const bool reject_only_;
675     const QuicConnectionId connection_id_;
676     const QuicSocketAddress server_address_;
677     const QuicSocketAddress client_address_;
678     const ParsedQuicVersion version_;
679     const ParsedQuicVersionVector supported_versions_;
680     const QuicClock* const clock_;
681     QuicRandom* const rand_;
682     QuicCompressedCertsCache* const compressed_certs_cache_;
683     const quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
684         params_;
685     const quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
686         signed_config_;
687     const QuicByteCount total_framing_overhead_;
688     const QuicByteCount chlo_packet_size_;
689     std::shared_ptr<ProcessClientHelloResultCallback> done_cb_;
690   };
691 
692   // Callback class for bridging between ProcessClientHello and
693   // ProcessClientHelloAfterGetProof.
694   class ProcessClientHelloCallback;
695   friend class ProcessClientHelloCallback;
696 
697   // Portion of ProcessClientHello which executes after GetProof.
698   void ProcessClientHelloAfterGetProof(
699       bool found_error,
700       std::unique_ptr<ProofSource::Details> proof_source_details,
701       std::unique_ptr<ProcessClientHelloContext> context,
702       const Configs& configs) const;
703 
704   // Callback class for bridging between ProcessClientHelloAfterGetProof and
705   // ProcessClientHelloAfterCalculateSharedKeys.
706   class ProcessClientHelloAfterGetProofCallback;
707   friend class ProcessClientHelloAfterGetProofCallback;
708 
709   // Portion of ProcessClientHello which executes after CalculateSharedKeys.
710   void ProcessClientHelloAfterCalculateSharedKeys(
711       bool found_error,
712       std::unique_ptr<ProofSource::Details> proof_source_details,
713       QuicTag key_exchange_type, std::unique_ptr<CryptoHandshakeMessage> out,
714       absl::string_view public_value,
715       std::unique_ptr<ProcessClientHelloContext> context,
716       const Configs& configs) const;
717 
718   // Send a REJ which contains a different ServerConfig than the one the client
719   // originally used.  This is necessary in cases where we discover in the
720   // middle of the handshake that the private key for the ServerConfig the
721   // client used is not accessible.
722   void SendRejectWithFallbackConfig(
723       std::unique_ptr<ProcessClientHelloContext> context,
724       quiche::QuicheReferenceCountedPointer<Config> fallback_config) const;
725 
726   // Callback class for bridging between SendRejectWithFallbackConfig and
727   // SendRejectWithFallbackConfigAfterGetProof.
728   class SendRejectWithFallbackConfigCallback;
729   friend class SendRejectWithFallbackConfigCallback;
730 
731   // Portion of ProcessClientHello which executes after GetProof in the case
732   // where we have received a CHLO but need to reject it due to the ServerConfig
733   // private keys being inaccessible.
734   void SendRejectWithFallbackConfigAfterGetProof(
735       bool found_error,
736       std::unique_ptr<ProofSource::Details> proof_source_details,
737       std::unique_ptr<ProcessClientHelloContext> context,
738       quiche::QuicheReferenceCountedPointer<Config> fallback_config) const;
739 
740   // BuildRejectionAndRecordStats calls |BuildRejection| below and also informs
741   // the RejectionObserver.
742   void BuildRejectionAndRecordStats(const ProcessClientHelloContext& context,
743                                     const Config& config,
744                                     const std::vector<uint32_t>& reject_reasons,
745                                     CryptoHandshakeMessage* out) const;
746 
747   // BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
748   void BuildRejection(const ProcessClientHelloContext& context,
749                       const Config& config,
750                       const std::vector<uint32_t>& reject_reasons,
751                       CryptoHandshakeMessage* out) const;
752 
753   // CompressChain compresses the certificates in |chain->certs| and returns a
754   // compressed representation. |client_cached_cert_hashes| contains
755   // 64-bit, FNV-1a hashes of certificates that the peer already possesses.
756   static std::string CompressChain(
757       QuicCompressedCertsCache* compressed_certs_cache,
758       const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
759       const std::string& client_cached_cert_hashes);
760 
761   // ParseConfigProtobuf parses the given config protobuf and returns a
762   // quiche::QuicheReferenceCountedPointer<Config> if successful. The caller
763   // adopts the reference to the Config. On error, ParseConfigProtobuf returns
764   // nullptr.
765   quiche::QuicheReferenceCountedPointer<Config> ParseConfigProtobuf(
766       const QuicServerConfigProtobuf& protobuf, bool is_fallback) const;
767 
768   // ValidateSingleSourceAddressToken returns HANDSHAKE_OK if the source
769   // address token in |token| is a timely token for the IP address |ip|
770   // given that the current time is |now|. Otherwise it returns the reason
771   // for failure.
772   HandshakeFailureReason ValidateSingleSourceAddressToken(
773       const SourceAddressToken& token, const QuicIpAddress& ip,
774       QuicWallTime now) const;
775 
776   // Returns HANDSHAKE_OK if the source address token in |token| is a timely
777   // token given that the current time is |now|. Otherwise it returns the
778   // reason for failure.
779   HandshakeFailureReason ValidateSourceAddressTokenTimestamp(
780       const SourceAddressToken& token, QuicWallTime now) const;
781 
782   // NewServerNonce generates and encrypts a random nonce.
783   std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const;
784 
785   // ValidateExpectedLeafCertificate checks the |client_hello| to see if it has
786   // an XLCT tag, and if so, verifies that its value matches the hash of the
787   // server's leaf certificate. |certs| is used to compare against the XLCT
788   // value.  This method returns true if the XLCT tag is not present, or if the
789   // XLCT tag is present and valid. It returns false otherwise.
790   bool ValidateExpectedLeafCertificate(
791       const CryptoHandshakeMessage& client_hello,
792       const std::vector<std::string>& certs) const;
793 
794   // Callback to receive the results of ProofSource::GetProof.  Note: this
795   // callback has no cancellation support, since the lifetime of the ProofSource
796   // is controlled by this object via unique ownership.  If that ownership
797   // stricture changes, this decision may need to be revisited.
798   class BuildServerConfigUpdateMessageProofSourceCallback
799       : public ProofSource::Callback {
800    public:
801     BuildServerConfigUpdateMessageProofSourceCallback(
802         const BuildServerConfigUpdateMessageProofSourceCallback&) = delete;
803     ~BuildServerConfigUpdateMessageProofSourceCallback() override;
804     void operator=(const BuildServerConfigUpdateMessageProofSourceCallback&) =
805         delete;
806     BuildServerConfigUpdateMessageProofSourceCallback(
807         const QuicCryptoServerConfig* config,
808         QuicCompressedCertsCache* compressed_certs_cache,
809         const QuicCryptoNegotiatedParameters& params,
810         CryptoHandshakeMessage message,
811         std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb);
812 
813     void Run(
814         bool ok,
815         const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
816         const QuicCryptoProof& proof,
817         std::unique_ptr<ProofSource::Details> details) override;
818 
819    private:
820     const QuicCryptoServerConfig* config_;
821     QuicCompressedCertsCache* compressed_certs_cache_;
822     const std::string client_cached_cert_hashes_;
823     const bool sct_supported_by_client_;
824     const std::string sni_;
825     CryptoHandshakeMessage message_;
826     std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb_;
827   };
828 
829   // Invoked by BuildServerConfigUpdateMessageProofSourceCallback::Run once
830   // the proof has been acquired.  Finishes building the server config update
831   // message and invokes |cb|.
832   void FinishBuildServerConfigUpdateMessage(
833       QuicCompressedCertsCache* compressed_certs_cache,
834       const std::string& client_cached_cert_hashes,
835       bool sct_supported_by_client, const std::string& sni, bool ok,
836       const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
837       const std::string& signature, const std::string& leaf_cert_sct,
838       std::unique_ptr<ProofSource::Details> details,
839       CryptoHandshakeMessage message,
840       std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const;
841 
842   // Returns true if the next config promotion should happen now.
843   bool IsNextConfigReady(QuicWallTime now) const
844       QUIC_SHARED_LOCKS_REQUIRED(configs_lock_);
845 
846   // replay_protection_ controls whether the server enforces that handshakes
847   // aren't replays.
848   bool replay_protection_;
849 
850   // The multiple of the CHLO message size that a REJ message must stay under
851   // when the client doesn't present a valid source-address token. This is
852   // used to protect QUIC from amplification attacks.
853   size_t chlo_multiplier_;
854 
855   // configs_ satisfies the following invariants:
856   //   1) configs_.empty() <-> primary_config_ == nullptr
857   //   2) primary_config_ != nullptr -> primary_config_->is_primary
858   //   3) ∀ c∈configs_, c->is_primary <-> c == primary_config_
859   mutable QuicMutex configs_lock_;
860 
861   // configs_ contains all active server configs. It's expected that there are
862   // about half-a-dozen configs active at any one time.
863   ConfigMap configs_ QUIC_GUARDED_BY(configs_lock_);
864 
865   // primary_config_ points to a Config (which is also in |configs_|) which is
866   // the primary config - i.e. the one that we'll give out to new clients.
867   mutable quiche::QuicheReferenceCountedPointer<Config> primary_config_
868       QUIC_GUARDED_BY(configs_lock_);
869 
870   // fallback_config_ points to a Config (which is also in |configs_|) which is
871   // the fallback config, which will be used if the other configs are unuseable
872   // for some reason.
873   //
874   // TODO(b/112548056): This is currently always nullptr.
875   quiche::QuicheReferenceCountedPointer<Config> fallback_config_
876       QUIC_GUARDED_BY(configs_lock_);
877 
878   // next_config_promotion_time_ contains the nearest, future time when an
879   // active config will be promoted to primary.
880   mutable QuicWallTime next_config_promotion_time_
881       QUIC_GUARDED_BY(configs_lock_);
882 
883   // Callback to invoke when the primary config changes.
884   std::unique_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_
885       QUIC_GUARDED_BY(configs_lock_);
886 
887   // Used to protect the source-address tokens that are given to clients.
888   CryptoSecretBoxer source_address_token_boxer_;
889 
890   // server_nonce_boxer_ is used to encrypt and validate suggested server
891   // nonces.
892   CryptoSecretBoxer server_nonce_boxer_;
893 
894   // server_nonce_orbit_ contains the random, per-server orbit values that this
895   // server will use to generate server nonces (the moral equivalent of a SYN
896   // cookies).
897   uint8_t server_nonce_orbit_[8];
898 
899   // proof_source_ contains an object that can provide certificate chains and
900   // signatures.
901   std::unique_ptr<ProofSource> proof_source_;
902 
903   // key_exchange_source_ contains an object that can provide key exchange
904   // objects.
905   std::unique_ptr<KeyExchangeSource> key_exchange_source_;
906 
907   // ssl_ctx_ contains the server configuration for doing TLS handshakes.
908   bssl::UniquePtr<SSL_CTX> ssl_ctx_;
909 
910   // The groups to use for key exchange in the TLS handshake;
911   std::vector<uint16_t> preferred_groups_;
912 
913   // These fields store configuration values. See the comments for their
914   // respective setter functions.
915   uint32_t source_address_token_future_secs_;
916   uint32_t source_address_token_lifetime_secs_;
917 
918   // Enable serving SCT or not.
919   bool enable_serving_sct_;
920 
921   // Does not own this observer.
922   RejectionObserver* rejection_observer_;
923 
924   // If non-empty, the server will operate in the pre-shared key mode by
925   // incorporating |pre_shared_key_| into the key schedule.
926   std::string pre_shared_key_;
927 
928   // Whether REJ message should be padded to max packet size.
929   bool pad_rej_;
930 
931   // Whether SHLO message should be padded to max packet size.
932   bool pad_shlo_;
933 
934   // If client is allowed to send a small client hello (by disabling padding),
935   // server MUST not check for the client hello size.
936   // DO NOT disable this unless you have some other way of validating client.
937   // (e.g. in realtime scenarios, where quic is tunneled through ICE, ICE will
938   // do its own peer validation using STUN pings with ufrag/upass).
939   bool validate_chlo_size_;
940 
941   // When source address is validated by some other means (e.g. when using ICE),
942   // source address token validation may be disabled.
943   bool validate_source_address_token_;
944 };
945 
946 struct QUICHE_EXPORT QuicSignedServerConfig
947     : public quiche::QuicheReferenceCounted {
948   QuicSignedServerConfig();
949 
950   QuicCryptoProof proof;
951   quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain;
952   // The server config that is used for this proof (and the rest of the
953   // request).
954   quiche::QuicheReferenceCountedPointer<QuicCryptoServerConfig::Config> config;
955   std::string primary_scid;
956 
957  protected:
958   ~QuicSignedServerConfig() override;
959 };
960 
961 }  // namespace quic
962 
963 #endif  // QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
964