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