QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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> |
vasilvv | 872e7a3 | 2019-03-12 16:42:44 -0700 | [diff] [blame] | 12 | #include <string> |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 13 | #include <vector> |
| 14 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 15 | #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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 31 | #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" |
| 32 | |
| 33 | namespace quic { |
| 34 | |
| 35 | class CryptoHandshakeMessage; |
| 36 | class ProofSource; |
| 37 | class QuicClock; |
| 38 | class QuicRandom; |
| 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 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 | |
| 66 | namespace test { |
| 67 | class QuicCryptoServerConfigPeer; |
| 68 | } // namespace test |
| 69 | |
| 70 | // Hook that allows application code to subscribe to primary config changes. |
| 71 | class PrimaryConfigChangedCallback { |
| 72 | public: |
| 73 | PrimaryConfigChangedCallback(); |
| 74 | PrimaryConfigChangedCallback(const PrimaryConfigChangedCallback&) = delete; |
| 75 | PrimaryConfigChangedCallback& operator=(const PrimaryConfigChangedCallback&) = |
| 76 | delete; |
| 77 | virtual ~PrimaryConfigChangedCallback(); |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 78 | virtual void Run(const std::string& scid) = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 79 | }; |
| 80 | |
| 81 | // Callback used to accept the result of the |client_hello| validation step. |
| 82 | class QUIC_EXPORT_PRIVATE ValidateClientHelloResultCallback { |
| 83 | public: |
| 84 | // Opaque token that holds information about the client_hello and |
| 85 | // its validity. Can be interpreted by calling ProcessClientHello. |
| 86 | struct QUIC_EXPORT_PRIVATE Result : public 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; |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 94 | std::string error_details; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 95 | |
| 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. |
| 114 | class 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, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 123 | const std::string& error_details, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 124 | 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. |
| 131 | class 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). |
| 144 | class 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. |
| 156 | class 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 team | fe1aca6 | 2019-03-14 13:39:01 -0700 | [diff] [blame] | 165 | virtual std::unique_ptr<AsynchronousKeyExchange> Create( |
| 166 | std::string server_config_id, |
| 167 | QuicTag type, |
| 168 | QuicStringPiece private_key) = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 169 | }; |
| 170 | |
| 171 | // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. |
| 172 | // Unlike a client, a QUIC server can have multiple configurations active in |
| 173 | // order to support clients resuming with a previous configuration. |
| 174 | // TODO(agl): when adding configurations at runtime is added, this object will |
| 175 | // need to consider locking. |
| 176 | class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { |
| 177 | public: |
| 178 | // ConfigOptions contains options for generating server configs. |
| 179 | struct QUIC_EXPORT_PRIVATE ConfigOptions { |
| 180 | ConfigOptions(); |
| 181 | ConfigOptions(const ConfigOptions& other); |
| 182 | ~ConfigOptions(); |
| 183 | |
| 184 | // expiry_time is the time, in UNIX seconds, when the server config will |
| 185 | // expire. If unset, it defaults to the current time plus six months. |
| 186 | QuicWallTime expiry_time; |
| 187 | // channel_id_enabled controls whether the server config will indicate |
| 188 | // support for ChannelIDs. |
| 189 | bool channel_id_enabled; |
| 190 | // 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 195 | std::string id; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 196 | // orbit contains the kOrbitSize bytes of the orbit value for the server |
| 197 | // config. If |orbit| is empty then a random orbit is generated. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 198 | std::string orbit; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 199 | // 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 team | d5af58a | 2019-03-14 20:35:50 -0700 | [diff] [blame] | 212 | // |proof_source|: provides certificate chains and signatures. |
| 213 | // |key_exchange_source|: provides key-exchange functionality. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 214 | // |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 team | d5af58a | 2019-03-14 20:35:50 -0700 | [diff] [blame] | 235 | // It returns the SCFG message from the config if successful. |now| is used in |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 236 | // conjunction with |protobuf->primary_time()| to determine whether the |
| 237 | // config should be made primary. |
QUICHE team | d5af58a | 2019-03-14 20:35:50 -0700 | [diff] [blame] | 238 | std::unique_ptr<CryptoHandshakeMessage> AddConfig( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 239 | 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 team | d5af58a | 2019-03-14 20:35:50 -0700 | [diff] [blame] | 245 | std::unique_ptr<CryptoHandshakeMessage> AddDefaultConfig( |
| 246 | QuicRandom* rand, |
| 247 | const QuicClock* clock, |
| 248 | const ConfigOptions& options); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 249 | |
| 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 265 | void SetSourceAddressTokenKeys(const std::vector<std::string>& keys); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 266 | |
| 267 | // Get the server config ids for all known configs. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 268 | void GetConfigIds(std::vector<std::string>* scids) const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 269 | |
| 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) { |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 432 | pre_shared_key_ = std::string(psk); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 433 | } |
| 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 458 | std::string serialized; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 459 | // id contains the SCID of this server config. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 460 | std::string id; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 461 | // 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 team | fe1aca6 | 2019-03-14 13:39:01 -0700 | [diff] [blame] | 465 | // 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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 468 | |
| 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 team | 79fb9e2 | 2019-03-15 07:49:56 -0700 | [diff] [blame] | 527 | // 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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 530 | void EvaluateClientHello( |
| 531 | const QuicSocketAddress& server_address, |
| 532 | QuicTransportVersion version, |
| 533 | QuicReferenceCountedPointer<Config> requested_config, |
| 534 | QuicReferenceCountedPointer<Config> primary_config, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 535 | QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> |
| 536 | client_hello_state, |
| 537 | std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const; |
| 538 | |
QUICHE team | 4dae841 | 2019-03-18 13:11:00 -0700 | [diff] [blame] | 539 | // 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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 653 | // 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 team | 4dae841 | 2019-03-18 13:11:00 -0700 | [diff] [blame] | 662 | std::unique_ptr<ProcessClientHelloContext> context, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 663 | const QuicReferenceCountedPointer<Config>& requested_config, |
QUICHE team | 4dae841 | 2019-03-18 13:11:00 -0700 | [diff] [blame] | 664 | const QuicReferenceCountedPointer<Config>& primary_config) const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 665 | |
| 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 team | fe1aca6 | 2019-03-14 13:39:01 -0700 | [diff] [blame] | 675 | QuicTag key_exchange_type, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 676 | std::unique_ptr<CryptoHandshakeMessage> out, |
| 677 | QuicStringPiece public_value, |
QUICHE team | 4dae841 | 2019-03-18 13:11:00 -0700 | [diff] [blame] | 678 | std::unique_ptr<ProcessClientHelloContext> context, |
| 679 | const QuicReferenceCountedPointer<Config>& requested_config) const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 680 | |
| 681 | // BuildRejection sets |out| to be a REJ message in reply to |client_hello|. |
QUICHE team | 4dae841 | 2019-03-18 13:11:00 -0700 | [diff] [blame] | 682 | void BuildRejection(const ProcessClientHelloContext& context, |
| 683 | const Config& config, |
QUICHE team | e6dcf32 | 2019-03-19 12:23:47 -0700 | [diff] [blame^] | 684 | const std::vector<uint32_t>& reject_reasons, |
QUICHE team | 4dae841 | 2019-03-18 13:11:00 -0700 | [diff] [blame] | 685 | CryptoHandshakeMessage* out) const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 686 | |
| 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 692 | static std::string CompressChain( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 693 | QuicCompressedCertsCache* compressed_certs_cache, |
| 694 | const QuicReferenceCountedPointer<ProofSource::Chain>& chain, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 695 | const std::string& client_common_set_hashes, |
| 696 | const std::string& client_cached_cert_hashes, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 697 | 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 707 | std::string NewSourceAddressToken( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 708 | 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 752 | std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 753 | |
| 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, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 761 | const std::vector<std::string>& certs) const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 762 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 763 | // 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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 777 | 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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 790 | QuicCompressedCertsCache* compressed_certs_cache_; |
| 791 | const CommonCertSets* common_cert_sets_; |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 792 | const std::string client_common_set_hashes_; |
| 793 | const std::string client_cached_cert_hashes_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 794 | const bool sct_supported_by_client_; |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 795 | const std::string sni_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 796 | 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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 804 | QuicCompressedCertsCache* compressed_certs_cache, |
| 805 | const CommonCertSets* common_cert_sets, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 806 | const std::string& client_common_set_hashes, |
| 807 | const std::string& client_cached_cert_hashes, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 808 | bool sct_supported_by_client, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 809 | const std::string& sni, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 810 | bool ok, |
| 811 | const QuicReferenceCountedPointer<ProofSource::Chain>& chain, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 812 | const std::string& signature, |
| 813 | const std::string& leaf_cert_sct, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 814 | 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 886 | std::string pre_shared_key_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 887 | |
| 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 | |
| 906 | struct 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; |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 915 | std::string primary_scid; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 916 | |
| 917 | protected: |
| 918 | ~QuicSignedServerConfig() override; |
| 919 | }; |
| 920 | |
| 921 | } // namespace quic |
| 922 | |
| 923 | #endif // QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ |