| OLD | NEW |
| (Empty) |
| 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 NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ | |
| 6 #define NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ | |
| 7 | |
| 8 #include <stddef.h> | |
| 9 #include <stdint.h> | |
| 10 | |
| 11 #include <map> | |
| 12 #include <memory> | |
| 13 #include <string> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/macros.h" | |
| 17 #include "base/memory/ref_counted.h" | |
| 18 #include "base/strings/string_piece.h" | |
| 19 #include "base/synchronization/lock.h" | |
| 20 #include "net/base/ip_address.h" | |
| 21 #include "net/base/ip_endpoint.h" | |
| 22 #include "net/base/net_export.h" | |
| 23 #include "net/quic/crypto/crypto_handshake.h" | |
| 24 #include "net/quic/crypto/crypto_handshake_message.h" | |
| 25 #include "net/quic/crypto/crypto_protocol.h" | |
| 26 #include "net/quic/crypto/crypto_secret_boxer.h" | |
| 27 #include "net/quic/crypto/proof_source.h" | |
| 28 #include "net/quic/crypto/quic_compressed_certs_cache.h" | |
| 29 #include "net/quic/proto/cached_network_parameters.pb.h" | |
| 30 #include "net/quic/proto/source_address_token.pb.h" | |
| 31 #include "net/quic/quic_time.h" | |
| 32 | |
| 33 namespace net { | |
| 34 | |
| 35 class CryptoHandshakeMessage; | |
| 36 class EphemeralKeySource; | |
| 37 class KeyExchange; | |
| 38 class ProofSource; | |
| 39 class QuicClock; | |
| 40 class QuicDecrypter; | |
| 41 class QuicEncrypter; | |
| 42 class QuicRandom; | |
| 43 class QuicServerConfigProtobuf; | |
| 44 class StrikeRegister; | |
| 45 class StrikeRegisterClient; | |
| 46 struct QuicCryptoProof; | |
| 47 | |
| 48 // ClientHelloInfo contains information about a client hello message that is | |
| 49 // only kept for as long as it's being processed. | |
| 50 struct ClientHelloInfo { | |
| 51 ClientHelloInfo(const IPAddress& in_client_ip, QuicWallTime in_now); | |
| 52 ~ClientHelloInfo(); | |
| 53 | |
| 54 // Inputs to EvaluateClientHello. | |
| 55 const IPAddress client_ip; | |
| 56 const QuicWallTime now; | |
| 57 | |
| 58 // Outputs from EvaluateClientHello. | |
| 59 bool valid_source_address_token; | |
| 60 base::StringPiece sni; | |
| 61 base::StringPiece client_nonce; | |
| 62 base::StringPiece server_nonce; | |
| 63 base::StringPiece user_agent_id; | |
| 64 SourceAddressTokens source_address_tokens; | |
| 65 | |
| 66 // Errors from EvaluateClientHello. | |
| 67 std::vector<uint32_t> reject_reasons; | |
| 68 static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync"); | |
| 69 }; | |
| 70 | |
| 71 namespace test { | |
| 72 class QuicCryptoServerConfigPeer; | |
| 73 } // namespace test | |
| 74 | |
| 75 // Hook that allows application code to subscribe to primary config changes. | |
| 76 class PrimaryConfigChangedCallback { | |
| 77 public: | |
| 78 PrimaryConfigChangedCallback(); | |
| 79 virtual ~PrimaryConfigChangedCallback(); | |
| 80 virtual void Run(const std::string& scid) = 0; | |
| 81 | |
| 82 private: | |
| 83 DISALLOW_COPY_AND_ASSIGN(PrimaryConfigChangedCallback); | |
| 84 }; | |
| 85 | |
| 86 // Callback used to accept the result of the |client_hello| validation step. | |
| 87 class NET_EXPORT_PRIVATE ValidateClientHelloResultCallback { | |
| 88 public: | |
| 89 // Opaque token that holds information about the client_hello and | |
| 90 // its validity. Can be interpreted by calling ProcessClientHello. | |
| 91 struct Result { | |
| 92 Result(const CryptoHandshakeMessage& in_client_hello, | |
| 93 IPAddress in_client_ip, | |
| 94 QuicWallTime in_now); | |
| 95 ~Result(); | |
| 96 | |
| 97 CryptoHandshakeMessage client_hello; | |
| 98 ClientHelloInfo info; | |
| 99 QuicErrorCode error_code; | |
| 100 std::string error_details; | |
| 101 | |
| 102 // Populated if the CHLO STK contained a CachedNetworkParameters proto. | |
| 103 CachedNetworkParameters cached_network_params; | |
| 104 }; | |
| 105 | |
| 106 ValidateClientHelloResultCallback(); | |
| 107 virtual ~ValidateClientHelloResultCallback(); | |
| 108 void Run(const Result* result, std::unique_ptr<ProofSource::Details> details); | |
| 109 | |
| 110 protected: | |
| 111 virtual void RunImpl(const CryptoHandshakeMessage& client_hello, | |
| 112 const Result& result, | |
| 113 std::unique_ptr<ProofSource::Details> details) = 0; | |
| 114 | |
| 115 private: | |
| 116 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback); | |
| 117 }; | |
| 118 | |
| 119 // Callback used to receive the results of a call to | |
| 120 // BuildServerConfigUpdateMessage. | |
| 121 class BuildServerConfigUpdateMessageResultCallback { | |
| 122 public: | |
| 123 BuildServerConfigUpdateMessageResultCallback() = default; | |
| 124 virtual ~BuildServerConfigUpdateMessageResultCallback() {} | |
| 125 virtual void Run(bool ok, const CryptoHandshakeMessage& message) = 0; | |
| 126 | |
| 127 private: | |
| 128 DISALLOW_COPY_AND_ASSIGN(BuildServerConfigUpdateMessageResultCallback); | |
| 129 }; | |
| 130 | |
| 131 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. | |
| 132 // Unlike a client, a QUIC server can have multiple configurations active in | |
| 133 // order to support clients resuming with a previous configuration. | |
| 134 // TODO(agl): when adding configurations at runtime is added, this object will | |
| 135 // need to consider locking. | |
| 136 class NET_EXPORT_PRIVATE QuicCryptoServerConfig { | |
| 137 public: | |
| 138 // ConfigOptions contains options for generating server configs. | |
| 139 struct NET_EXPORT_PRIVATE ConfigOptions { | |
| 140 ConfigOptions(); | |
| 141 ConfigOptions(const ConfigOptions& other); | |
| 142 | |
| 143 // expiry_time is the time, in UNIX seconds, when the server config will | |
| 144 // expire. If unset, it defaults to the current time plus six months. | |
| 145 QuicWallTime expiry_time; | |
| 146 // channel_id_enabled controls whether the server config will indicate | |
| 147 // support for ChannelIDs. | |
| 148 bool channel_id_enabled; | |
| 149 // token_binding_enabled controls whether the server config will indicate | |
| 150 // support for Token Binding. | |
| 151 bool token_binding_enabled; | |
| 152 // id contains the server config id for the resulting config. If empty, a | |
| 153 // random id is generated. | |
| 154 std::string id; | |
| 155 // orbit contains the kOrbitSize bytes of the orbit value for the server | |
| 156 // config. If |orbit| is empty then a random orbit is generated. | |
| 157 std::string orbit; | |
| 158 // p256 determines whether a P-256 public key will be included in the | |
| 159 // server config. Note that this breaks deterministic server-config | |
| 160 // generation since P-256 key generation doesn't use the QuicRandom given | |
| 161 // to DefaultConfig(). | |
| 162 bool p256; | |
| 163 }; | |
| 164 | |
| 165 // |source_address_token_secret|: secret key material used for encrypting and | |
| 166 // decrypting source address tokens. It can be of any length as it is fed | |
| 167 // into a KDF before use. In tests, use TESTING. | |
| 168 // |server_nonce_entropy|: an entropy source used to generate the orbit and | |
| 169 // key for server nonces, which are always local to a given instance of a | |
| 170 // server. Not owned. | |
| 171 // |proof_source|: provides certificate chains and signatures. This class | |
| 172 // takes ownership of |proof_source|. | |
| 173 QuicCryptoServerConfig(base::StringPiece source_address_token_secret, | |
| 174 QuicRandom* server_nonce_entropy, | |
| 175 std::unique_ptr<ProofSource> proof_source); | |
| 176 ~QuicCryptoServerConfig(); | |
| 177 | |
| 178 // TESTING is a magic parameter for passing to the constructor in tests. | |
| 179 static const char TESTING[]; | |
| 180 | |
| 181 // Generates a QuicServerConfigProtobuf protobuf suitable for | |
| 182 // AddConfig and SetConfigs. | |
| 183 static QuicServerConfigProtobuf* GenerateConfig(QuicRandom* rand, | |
| 184 const QuicClock* clock, | |
| 185 const ConfigOptions& options); | |
| 186 | |
| 187 // AddConfig adds a QuicServerConfigProtobuf to the availible configurations. | |
| 188 // It returns the SCFG message from the config if successful. The caller | |
| 189 // takes ownership of the CryptoHandshakeMessage. |now| is used in | |
| 190 // conjunction with |protobuf->primary_time()| to determine whether the | |
| 191 // config should be made primary. | |
| 192 CryptoHandshakeMessage* AddConfig(QuicServerConfigProtobuf* protobuf, | |
| 193 QuicWallTime now); | |
| 194 | |
| 195 // AddDefaultConfig calls DefaultConfig to create a config and then calls | |
| 196 // AddConfig to add it. See the comment for |DefaultConfig| for details of | |
| 197 // the arguments. | |
| 198 CryptoHandshakeMessage* AddDefaultConfig(QuicRandom* rand, | |
| 199 const QuicClock* clock, | |
| 200 const ConfigOptions& options); | |
| 201 | |
| 202 // SetConfigs takes a vector of config protobufs and the current time. | |
| 203 // Configs are assumed to be uniquely identified by their server config ID. | |
| 204 // Previously unknown configs are added and possibly made the primary config | |
| 205 // depending on their |primary_time| and the value of |now|. Configs that are | |
| 206 // known, but are missing from the protobufs are deleted, unless they are | |
| 207 // currently the primary config. SetConfigs returns false if any errors were | |
| 208 // encountered and no changes to the QuicCryptoServerConfig will occur. | |
| 209 bool SetConfigs(const std::vector<QuicServerConfigProtobuf*>& protobufs, | |
| 210 QuicWallTime now); | |
| 211 | |
| 212 // SetDefaultSourceAddressTokenKeys sets the keys to be tried, in order, | |
| 213 // when decrypting a source address token. This modifies only the default | |
| 214 // boxer, which is to say, it is a no-op if a key was specified in the Config. | |
| 215 // Note that these keys are used *without* passing them through a KDF, in | |
| 216 // contradistinction to the |source_address_token_secret| argument to the | |
| 217 // constructor. | |
| 218 void SetDefaultSourceAddressTokenKeys(const std::vector<std::string>& keys); | |
| 219 | |
| 220 // Get the server config ids for all known configs. | |
| 221 void GetConfigIds(std::vector<std::string>* scids) const; | |
| 222 | |
| 223 // Checks |client_hello| for gross errors and determines whether it | |
| 224 // can be shown to be fresh (i.e. not a replay). The result of the | |
| 225 // validation step must be interpreted by calling | |
| 226 // QuicCryptoServerConfig::ProcessClientHello from the done_cb. | |
| 227 // | |
| 228 // ValidateClientHello may invoke the done_cb before unrolling the | |
| 229 // stack if it is able to assess the validity of the client_nonce | |
| 230 // without asynchronous operations. | |
| 231 // | |
| 232 // client_hello: the incoming client hello message. | |
| 233 // client_ip: the IP address of the client, which is used to generate and | |
| 234 // validate source-address tokens. | |
| 235 // server_ip: the IP address of the server. The IP address may be used for | |
| 236 // certificate selection. | |
| 237 // version: protocol version used for this connection. | |
| 238 // clock: used to validate client nonces and ephemeral keys. | |
| 239 // crypto_proof: output structure containing the crypto proof used in reply to | |
| 240 // a proof demand. | |
| 241 // done_cb: single-use callback that accepts an opaque | |
| 242 // ValidatedClientHelloMsg token that holds information about | |
| 243 // the client hello. The callback will always be called exactly | |
| 244 // once, either under the current call stack, or after the | |
| 245 // completion of an asynchronous operation. | |
| 246 void ValidateClientHello(const CryptoHandshakeMessage& client_hello, | |
| 247 const IPAddress& client_ip, | |
| 248 const IPAddress& server_ip, | |
| 249 QuicVersion version, | |
| 250 const QuicClock* clock, | |
| 251 QuicCryptoProof* crypto_proof, | |
| 252 ValidateClientHelloResultCallback* done_cb) const; | |
| 253 | |
| 254 // ProcessClientHello processes |client_hello| and decides whether to accept | |
| 255 // or reject the connection. If the connection is to be accepted, |out| is | |
| 256 // set to the contents of the ServerHello, |out_params| is completed and | |
| 257 // QUIC_NO_ERROR is returned. Otherwise |out| is set to be a REJ or SREJ | |
| 258 // message and QUIC_NO_ERROR is returned. | |
| 259 // | |
| 260 // validate_chlo_result: Output from the asynchronous call to | |
| 261 // ValidateClientHello. Contains the client hello message and | |
| 262 // information about it. | |
| 263 // reject_only: Only generate rejections, not server hello messages. | |
| 264 // connection_id: the ConnectionId for the connection, which is used in key | |
| 265 // derivation. | |
| 266 // server_ip: the IP address of the server. The IP address may be used for | |
| 267 // certificate selection. | |
| 268 // client_address: the IP address and port of the client. The IP address is | |
| 269 // used to generate and validate source-address tokens. | |
| 270 // version: version of the QUIC protocol in use for this connection | |
| 271 // supported_versions: versions of the QUIC protocol that this server | |
| 272 // supports. | |
| 273 // clock: used to validate client nonces and ephemeral keys. | |
| 274 // rand: an entropy source | |
| 275 // compressed_certs_cache: the cache that caches a set of most recently used | |
| 276 // certs. Owned by QuicDispatcher. | |
| 277 // params: the state of the handshake. This may be updated with a server | |
| 278 // nonce when we send a rejection. After a successful handshake, this will | |
| 279 // contain the state of the connection. | |
| 280 // crypto_proof: output structure containing the crypto proof used in reply to | |
| 281 // a proof demand. | |
| 282 // out: the resulting handshake message (either REJ or SHLO) | |
| 283 // out_diversification_nonce: If the resulting handshake message is SHLO and | |
| 284 // the version is greater than QUIC_VERSION_32 then this contains a | |
| 285 // 32-byte value that should be included in the public header of | |
| 286 // initially encrypted packets. | |
| 287 // error_details: used to store a std::string describing any error. | |
| 288 QuicErrorCode ProcessClientHello( | |
| 289 const ValidateClientHelloResultCallback::Result& validate_chlo_result, | |
| 290 bool reject_only, | |
| 291 QuicConnectionId connection_id, | |
| 292 const IPAddress& server_ip, | |
| 293 const IPEndPoint& client_address, | |
| 294 QuicVersion version, | |
| 295 const QuicVersionVector& supported_versions, | |
| 296 bool use_stateless_rejects, | |
| 297 QuicConnectionId server_designated_connection_id, | |
| 298 const QuicClock* clock, | |
| 299 QuicRandom* rand, | |
| 300 QuicCompressedCertsCache* compressed_certs_cache, | |
| 301 QuicCryptoNegotiatedParameters* params, | |
| 302 QuicCryptoProof* crypto_proof, | |
| 303 CryptoHandshakeMessage* out, | |
| 304 DiversificationNonce* out_diversification_nonce, | |
| 305 std::string* error_details) const; | |
| 306 | |
| 307 // BuildServerConfigUpdateMessage sets |out| to be a SCUP message containing | |
| 308 // the current primary config, an up to date source-address token, and cert | |
| 309 // chain and proof in the case of secure QUIC. Returns true if successfully | |
| 310 // filled |out|. | |
| 311 // | |
| 312 // |cached_network_params| is optional, and can be nullptr. | |
| 313 // | |
| 314 // TODO(gredner): remove this when --FLAGS_enable_async_get_proof is removed. | |
| 315 bool BuildServerConfigUpdateMessage( | |
| 316 QuicVersion version, | |
| 317 base::StringPiece chlo_hash, | |
| 318 const SourceAddressTokens& previous_source_address_tokens, | |
| 319 const IPAddress& server_ip, | |
| 320 const IPAddress& client_ip, | |
| 321 const QuicClock* clock, | |
| 322 QuicRandom* rand, | |
| 323 QuicCompressedCertsCache* compressed_certs_cache, | |
| 324 const QuicCryptoNegotiatedParameters& params, | |
| 325 const CachedNetworkParameters* cached_network_params, | |
| 326 CryptoHandshakeMessage* out) const; | |
| 327 | |
| 328 // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing | |
| 329 // the current primary config, an up to date source-address token, and cert | |
| 330 // chain and proof in the case of secure QUIC. Passes true to |cb| if the | |
| 331 // message was generated successfully, and false otherwise. This method | |
| 332 // assumes ownership of |cb|. | |
| 333 // | |
| 334 // |cached_network_params| is optional, and can be nullptr. | |
| 335 // | |
| 336 // TODO(gredner): This method is an async version of the above. The | |
| 337 // synchronous version will eventually be removed. | |
| 338 void BuildServerConfigUpdateMessage( | |
| 339 QuicVersion version, | |
| 340 base::StringPiece chlo_hash, | |
| 341 const SourceAddressTokens& previous_source_address_tokens, | |
| 342 const IPAddress& server_ip, | |
| 343 const IPAddress& client_ip, | |
| 344 const QuicClock* clock, | |
| 345 QuicRandom* rand, | |
| 346 QuicCompressedCertsCache* compressed_certs_cache, | |
| 347 const QuicCryptoNegotiatedParameters& params, | |
| 348 const CachedNetworkParameters* cached_network_params, | |
| 349 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; | |
| 350 | |
| 351 // SetEphemeralKeySource installs an object that can cache ephemeral keys for | |
| 352 // a short period of time. This object takes ownership of | |
| 353 // |ephemeral_key_source|. If not set then ephemeral keys will be generated | |
| 354 // per-connection. | |
| 355 void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source); | |
| 356 | |
| 357 // Install an externall created StrikeRegisterClient for use to | |
| 358 // interact with the strike register. This object takes ownership | |
| 359 // of the |strike_register_client|. | |
| 360 void SetStrikeRegisterClient(StrikeRegisterClient* strike_register_client); | |
| 361 | |
| 362 // set_replay_protection controls whether replay protection is enabled. If | |
| 363 // replay protection is disabled then no strike registers are needed and | |
| 364 // frontends can share an orbit value without a shared strike-register. | |
| 365 // However, an attacker can duplicate a handshake and cause a client's | |
| 366 // request to be processed twice. | |
| 367 void set_replay_protection(bool on); | |
| 368 | |
| 369 // set_chlo_multiplier specifies the multiple of the CHLO message size | |
| 370 // that a REJ message must stay under when the client doesn't present a | |
| 371 // valid source-address token. | |
| 372 void set_chlo_multiplier(size_t multiplier); | |
| 373 | |
| 374 // set_strike_register_no_startup_period configures the strike register to | |
| 375 // not have a startup period. | |
| 376 void set_strike_register_no_startup_period(); | |
| 377 | |
| 378 // set_strike_register_max_entries sets the maximum number of entries that | |
| 379 // the internal strike register will hold. If the strike register fills up | |
| 380 // then the oldest entries (by the client's clock) will be dropped. | |
| 381 void set_strike_register_max_entries(uint32_t max_entries); | |
| 382 | |
| 383 // set_strike_register_window_secs sets the number of seconds around the | |
| 384 // current time that the strike register will attempt to be authoritative | |
| 385 // for. Setting a larger value allows for greater client clock-skew, but | |
| 386 // means that the quiescent startup period must be longer. | |
| 387 void set_strike_register_window_secs(uint32_t window_secs); | |
| 388 | |
| 389 // set_source_address_token_future_secs sets the number of seconds into the | |
| 390 // future that source-address tokens will be accepted from. Since | |
| 391 // source-address tokens are authenticated, this should only happen if | |
| 392 // another, valid server has clock-skew. | |
| 393 void set_source_address_token_future_secs(uint32_t future_secs); | |
| 394 | |
| 395 // set_source_address_token_lifetime_secs sets the number of seconds that a | |
| 396 // source-address token will be valid for. | |
| 397 void set_source_address_token_lifetime_secs(uint32_t lifetime_secs); | |
| 398 | |
| 399 // set_server_nonce_strike_register_max_entries sets the number of entries in | |
| 400 // the server-nonce strike-register. This is used to record that server nonce | |
| 401 // values have been used. If the number of entries is too small then clients | |
| 402 // which are depending on server nonces may fail to handshake because their | |
| 403 // nonce has expired in the amount of time it took to go from the server to | |
| 404 // the client and back. | |
| 405 void set_server_nonce_strike_register_max_entries(uint32_t max_entries); | |
| 406 | |
| 407 // set_server_nonce_strike_register_window_secs sets the number of seconds | |
| 408 // around the current time that the server-nonce strike-register will accept | |
| 409 // nonces from. Setting a larger value allows for clients to delay follow-up | |
| 410 // client hellos for longer and still use server nonces as proofs of | |
| 411 // uniqueness. | |
| 412 void set_server_nonce_strike_register_window_secs(uint32_t window_secs); | |
| 413 | |
| 414 // set_enable_serving_sct enables or disables serving signed cert timestamp | |
| 415 // (RFC6962) in server hello. | |
| 416 void set_enable_serving_sct(bool enable_serving_sct); | |
| 417 | |
| 418 // Set and take ownership of the callback to invoke on primary config changes. | |
| 419 void AcquirePrimaryConfigChangedCb(PrimaryConfigChangedCallback* cb); | |
| 420 | |
| 421 // Returns the number of configs this object owns. | |
| 422 int NumberOfConfigs() const; | |
| 423 | |
| 424 private: | |
| 425 friend class test::QuicCryptoServerConfigPeer; | |
| 426 friend struct QuicCryptoProof; | |
| 427 | |
| 428 // Config represents a server config: a collection of preferences and | |
| 429 // Diffie-Hellman public values. | |
| 430 class NET_EXPORT_PRIVATE Config : public QuicCryptoConfig, | |
| 431 public base::RefCounted<Config> { | |
| 432 public: | |
| 433 Config(); | |
| 434 | |
| 435 // TODO(rtenneti): since this is a class, we should probably do | |
| 436 // getters/setters here. | |
| 437 // |serialized| contains the bytes of this server config, suitable for | |
| 438 // sending on the wire. | |
| 439 std::string serialized; | |
| 440 // id contains the SCID of this server config. | |
| 441 std::string id; | |
| 442 // orbit contains the orbit value for this config: an opaque identifier | |
| 443 // used to identify clusters of server frontends. | |
| 444 unsigned char orbit[kOrbitSize]; | |
| 445 | |
| 446 // key_exchanges contains key exchange objects with the private keys | |
| 447 // already loaded. The values correspond, one-to-one, with the tags in | |
| 448 // |kexs| from the parent class. | |
| 449 std::vector<KeyExchange*> key_exchanges; | |
| 450 | |
| 451 // tag_value_map contains the raw key/value pairs for the config. | |
| 452 QuicTagValueMap tag_value_map; | |
| 453 | |
| 454 // channel_id_enabled is true if the config in |serialized| specifies that | |
| 455 // ChannelIDs are supported. | |
| 456 bool channel_id_enabled; | |
| 457 | |
| 458 // is_primary is true if this config is the one that we'll give out to | |
| 459 // clients as the current one. | |
| 460 bool is_primary; | |
| 461 | |
| 462 // primary_time contains the timestamp when this config should become the | |
| 463 // primary config. A value of QuicWallTime::Zero() means that this config | |
| 464 // will not be promoted at a specific time. | |
| 465 QuicWallTime primary_time; | |
| 466 | |
| 467 // Secondary sort key for use when selecting primary configs and | |
| 468 // there are multiple configs with the same primary time. | |
| 469 // Smaller numbers mean higher priority. | |
| 470 uint64_t priority; | |
| 471 | |
| 472 // source_address_token_boxer_ is used to protect the | |
| 473 // source-address tokens that are given to clients. | |
| 474 // Points to either source_address_token_boxer_storage or the | |
| 475 // default boxer provided by QuicCryptoServerConfig. | |
| 476 const CryptoSecretBoxer* source_address_token_boxer; | |
| 477 | |
| 478 // Holds the override source_address_token_boxer instance if the | |
| 479 // Config is not using the default source address token boxer | |
| 480 // instance provided by QuicCryptoServerConfig. | |
| 481 std::unique_ptr<CryptoSecretBoxer> source_address_token_boxer_storage; | |
| 482 | |
| 483 private: | |
| 484 friend class base::RefCounted<Config>; | |
| 485 | |
| 486 virtual ~Config(); | |
| 487 | |
| 488 DISALLOW_COPY_AND_ASSIGN(Config); | |
| 489 }; | |
| 490 | |
| 491 typedef std::map<ServerConfigID, scoped_refptr<Config>> ConfigMap; | |
| 492 | |
| 493 // Get a ref to the config with a given server config id. | |
| 494 scoped_refptr<Config> GetConfigWithScid( | |
| 495 base::StringPiece requested_scid) const; | |
| 496 | |
| 497 // ConfigPrimaryTimeLessThan returns true if a->primary_time < | |
| 498 // b->primary_time. | |
| 499 static bool ConfigPrimaryTimeLessThan(const scoped_refptr<Config>& a, | |
| 500 const scoped_refptr<Config>& b); | |
| 501 | |
| 502 // SelectNewPrimaryConfig reevaluates the primary config based on the | |
| 503 // "primary_time" deadlines contained in each. | |
| 504 void SelectNewPrimaryConfig(QuicWallTime now) const; | |
| 505 | |
| 506 // EvaluateClientHello checks |client_hello| for gross errors and determines | |
| 507 // whether it can be shown to be fresh (i.e. not a replay). The results are | |
| 508 // written to |info|. | |
| 509 void EvaluateClientHello( | |
| 510 const IPAddress& server_ip, | |
| 511 QuicVersion version, | |
| 512 const uint8_t* primary_orbit, | |
| 513 scoped_refptr<Config> requested_config, | |
| 514 scoped_refptr<Config> primary_config, | |
| 515 QuicCryptoProof* crypto_proof, | |
| 516 ValidateClientHelloResultCallback::Result* client_hello_state, | |
| 517 ValidateClientHelloResultCallback* done_cb) const; | |
| 518 | |
| 519 // Callback class for bridging between EvaluateClientHello and | |
| 520 // EvaluateClientHelloAfterGetProof | |
| 521 friend class EvaluateClientHelloCallback; | |
| 522 | |
| 523 // Continuation of EvaluateClientHello after the call to | |
| 524 // ProofSource::GetProof. |found_error| indicates whether an error was | |
| 525 // detected in EvaluateClientHello, and |get_proof_failed| indicates whether | |
| 526 // GetProof failed. If GetProof was not run, then |get_proof_failed| will be | |
| 527 // set to false. | |
| 528 void EvaluateClientHelloAfterGetProof( | |
| 529 bool found_error, | |
| 530 const IPAddress& server_ip, | |
| 531 QuicVersion version, | |
| 532 const uint8_t* primary_orbit, | |
| 533 scoped_refptr<Config> requested_config, | |
| 534 scoped_refptr<Config> primary_config, | |
| 535 QuicCryptoProof* crypto_proof, | |
| 536 std::unique_ptr<ProofSource::Details> proof_source_details, | |
| 537 bool get_proof_failed, | |
| 538 ValidateClientHelloResultCallback::Result* client_hello_state, | |
| 539 ValidateClientHelloResultCallback* done_cb) const; | |
| 540 | |
| 541 // BuildRejection sets |out| to be a REJ message in reply to |client_hello|. | |
| 542 void BuildRejection(QuicVersion version, | |
| 543 const Config& config, | |
| 544 const CryptoHandshakeMessage& client_hello, | |
| 545 const ClientHelloInfo& info, | |
| 546 const CachedNetworkParameters& cached_network_params, | |
| 547 bool use_stateless_rejects, | |
| 548 QuicConnectionId server_designated_connection_id, | |
| 549 QuicRandom* rand, | |
| 550 QuicCompressedCertsCache* compressed_certs_cache, | |
| 551 QuicCryptoNegotiatedParameters* params, | |
| 552 const QuicCryptoProof& crypto_proof, | |
| 553 CryptoHandshakeMessage* out) const; | |
| 554 | |
| 555 // CompressChain compresses the certificates in |chain->certs| and returns a | |
| 556 // compressed representation. |common_sets| contains the common certificate | |
| 557 // sets known locally and |client_common_set_hashes| contains the hashes of | |
| 558 // the common sets known to the peer. |client_cached_cert_hashes| contains | |
| 559 // 64-bit, FNV-1a hashes of certificates that the peer already possesses. | |
| 560 static std::string CompressChain( | |
| 561 QuicCompressedCertsCache* compressed_certs_cache, | |
| 562 const scoped_refptr<ProofSource::Chain>& chain, | |
| 563 const std::string& client_common_set_hashes, | |
| 564 const std::string& client_cached_cert_hashes, | |
| 565 const CommonCertSets* common_sets); | |
| 566 | |
| 567 // ParseConfigProtobuf parses the given config protobuf and returns a | |
| 568 // scoped_refptr<Config> if successful. The caller adopts the reference to the | |
| 569 // Config. On error, ParseConfigProtobuf returns nullptr. | |
| 570 scoped_refptr<Config> ParseConfigProtobuf(QuicServerConfigProtobuf* protobuf); | |
| 571 | |
| 572 // NewSourceAddressToken returns a fresh source address token for the given | |
| 573 // IP address. |cached_network_params| is optional, and can be nullptr. | |
| 574 std::string NewSourceAddressToken( | |
| 575 const Config& config, | |
| 576 const SourceAddressTokens& previous_tokens, | |
| 577 const IPAddress& ip, | |
| 578 QuicRandom* rand, | |
| 579 QuicWallTime now, | |
| 580 const CachedNetworkParameters* cached_network_params) const; | |
| 581 | |
| 582 // ParseSourceAddressToken parses the source address tokens contained in | |
| 583 // the encrypted |token|, and populates |tokens| with the parsed tokens. | |
| 584 // Returns HANDSHAKE_OK if |token| could be parsed, or the reason for the | |
| 585 // failure. | |
| 586 HandshakeFailureReason ParseSourceAddressToken( | |
| 587 const Config& config, | |
| 588 base::StringPiece token, | |
| 589 SourceAddressTokens* tokens) const; | |
| 590 | |
| 591 // ValidateSourceAddressTokens returns HANDSHAKE_OK if the source address | |
| 592 // tokens in |tokens| contain a valid and timely token for the IP address | |
| 593 // |ip| given that the current time is |now|. Otherwise it returns the | |
| 594 // reason for failure. |cached_network_params| is populated if the valid | |
| 595 // token contains a CachedNetworkParameters proto. | |
| 596 HandshakeFailureReason ValidateSourceAddressTokens( | |
| 597 const SourceAddressTokens& tokens, | |
| 598 const IPAddress& ip, | |
| 599 QuicWallTime now, | |
| 600 CachedNetworkParameters* cached_network_params) const; | |
| 601 | |
| 602 // ValidateSingleSourceAddressToken returns HANDSHAKE_OK if the source | |
| 603 // address token in |token| is a timely token for the IP address |ip| | |
| 604 // given that the current time is |now|. Otherwise it returns the reason | |
| 605 // for failure. | |
| 606 HandshakeFailureReason ValidateSingleSourceAddressToken( | |
| 607 const SourceAddressToken& token, | |
| 608 const IPAddress& ip, | |
| 609 QuicWallTime now) const; | |
| 610 | |
| 611 // Returns HANDSHAKE_OK if the source address token in |token| is a timely | |
| 612 // token given that the current time is |now|. Otherwise it returns the | |
| 613 // reason for failure. | |
| 614 HandshakeFailureReason ValidateSourceAddressTokenTimestamp( | |
| 615 const SourceAddressToken& token, | |
| 616 QuicWallTime now) const; | |
| 617 | |
| 618 // NewServerNonce generates and encrypts a random nonce. | |
| 619 std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const; | |
| 620 | |
| 621 // ValidateServerNonce decrypts |token| and verifies that it hasn't been | |
| 622 // previously used and is recent enough that it is plausible that it was part | |
| 623 // of a very recently provided rejection ("recent" will be on the order of | |
| 624 // 10-30 seconds). If so, it records that it has been used and returns | |
| 625 // HANDSHAKE_OK. Otherwise it returns the reason for failure. | |
| 626 HandshakeFailureReason ValidateServerNonce( | |
| 627 base::StringPiece echoed_server_nonce, | |
| 628 QuicWallTime now) const; | |
| 629 | |
| 630 // ValidateExpectedLeafCertificate checks the |client_hello| to see if it has | |
| 631 // an XLCT tag, and if so, verifies that its value matches the hash of the | |
| 632 // server's leaf certificate. The certs field of |crypto_proof| is used to | |
| 633 // compare against the XLCT value. This method returns true if the XLCT tag | |
| 634 // is not present, or if the XLCT tag is present and valid. It returns false | |
| 635 // otherwise. | |
| 636 bool ValidateExpectedLeafCertificate( | |
| 637 const CryptoHandshakeMessage& client_hello, | |
| 638 const QuicCryptoProof& crypto_proof) const; | |
| 639 | |
| 640 // ParseProofDemand reads the PDMD field from the client hello and sets the | |
| 641 // |x509_ecdsa_supported| and |x509_supported| output parameters. | |
| 642 void ParseProofDemand(const CryptoHandshakeMessage& client_hello, | |
| 643 bool* x509_supported, | |
| 644 bool* x509_ecdsa_supported) const; | |
| 645 | |
| 646 // Callback to receive the results of ProofSource::GetProof. Note: this | |
| 647 // callback has no cancellation support, since the lifetime of the ProofSource | |
| 648 // is controlled by this object via unique ownership. If that ownership | |
| 649 // stricture changes, this decision may need to be revisited. | |
| 650 class BuildServerConfigUpdateMessageProofSourceCallback | |
| 651 : public ProofSource::Callback { | |
| 652 public: | |
| 653 BuildServerConfigUpdateMessageProofSourceCallback( | |
| 654 const BuildServerConfigUpdateMessageProofSourceCallback&) = delete; | |
| 655 ~BuildServerConfigUpdateMessageProofSourceCallback() override; | |
| 656 void operator=(const BuildServerConfigUpdateMessageProofSourceCallback&) = | |
| 657 delete; | |
| 658 BuildServerConfigUpdateMessageProofSourceCallback( | |
| 659 const QuicCryptoServerConfig* config, | |
| 660 QuicVersion version, | |
| 661 QuicCompressedCertsCache* compressed_certs_cache, | |
| 662 const CommonCertSets* common_cert_sets, | |
| 663 const QuicCryptoNegotiatedParameters& params, | |
| 664 CryptoHandshakeMessage message, | |
| 665 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb); | |
| 666 | |
| 667 void Run(bool ok, | |
| 668 const scoped_refptr<ProofSource::Chain>& chain, | |
| 669 const std::string& signature, | |
| 670 const std::string& leaf_cert_sct, | |
| 671 std::unique_ptr<ProofSource::Details> details) override; | |
| 672 | |
| 673 private: | |
| 674 const QuicCryptoServerConfig* config_; | |
| 675 const QuicVersion version_; | |
| 676 QuicCompressedCertsCache* compressed_certs_cache_; | |
| 677 const CommonCertSets* common_cert_sets_; | |
| 678 const std::string client_common_set_hashes_; | |
| 679 const std::string client_cached_cert_hashes_; | |
| 680 const bool sct_supported_by_client_; | |
| 681 CryptoHandshakeMessage message_; | |
| 682 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb_; | |
| 683 }; | |
| 684 | |
| 685 // Invoked by BuildServerConfigUpdateMessageProofSourceCallback::RunImpl once | |
| 686 // the proof has been acquired. Finishes building the server config update | |
| 687 // message and invokes |cb|. | |
| 688 void FinishBuildServerConfigUpdateMessage( | |
| 689 QuicVersion version, | |
| 690 QuicCompressedCertsCache* compressed_certs_cache, | |
| 691 const CommonCertSets* common_cert_sets, | |
| 692 const std::string& client_common_set_hashes, | |
| 693 const std::string& client_cached_cert_hashes, | |
| 694 bool sct_supported_by_client, | |
| 695 bool ok, | |
| 696 const scoped_refptr<ProofSource::Chain>& chain, | |
| 697 const std::string& signature, | |
| 698 const std::string& leaf_cert_sct, | |
| 699 std::unique_ptr<ProofSource::Details> details, | |
| 700 CryptoHandshakeMessage message, | |
| 701 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; | |
| 702 | |
| 703 // replay_protection_ controls whether the server enforces that handshakes | |
| 704 // aren't replays. | |
| 705 bool replay_protection_; | |
| 706 | |
| 707 // The multiple of the CHLO message size that a REJ message must stay under | |
| 708 // when the client doesn't present a valid source-address token. This is | |
| 709 // used to protect QUIC from amplification attacks. | |
| 710 size_t chlo_multiplier_; | |
| 711 | |
| 712 // configs_ satisfies the following invariants: | |
| 713 // 1) configs_.empty() <-> primary_config_ == nullptr | |
| 714 // 2) primary_config_ != nullptr -> primary_config_->is_primary | |
| 715 // 3) ∀ c∈configs_, c->is_primary <-> c == primary_config_ | |
| 716 mutable base::Lock configs_lock_; | |
| 717 // configs_ contains all active server configs. It's expected that there are | |
| 718 // about half-a-dozen configs active at any one time. | |
| 719 ConfigMap configs_; | |
| 720 // primary_config_ points to a Config (which is also in |configs_|) which is | |
| 721 // the primary config - i.e. the one that we'll give out to new clients. | |
| 722 mutable scoped_refptr<Config> primary_config_; | |
| 723 // next_config_promotion_time_ contains the nearest, future time when an | |
| 724 // active config will be promoted to primary. | |
| 725 mutable QuicWallTime next_config_promotion_time_; | |
| 726 // Callback to invoke when the primary config changes. | |
| 727 std::unique_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_; | |
| 728 | |
| 729 // Protects access to the pointer held by strike_register_client_. | |
| 730 mutable base::Lock strike_register_client_lock_; | |
| 731 // strike_register_ contains a data structure that keeps track of previously | |
| 732 // observed client nonces in order to prevent replay attacks. | |
| 733 mutable std::unique_ptr<StrikeRegisterClient> strike_register_client_; | |
| 734 | |
| 735 // Default source_address_token_boxer_ used to protect the | |
| 736 // source-address tokens that are given to clients. Individual | |
| 737 // configs may use boxers with alternate secrets. | |
| 738 CryptoSecretBoxer default_source_address_token_boxer_; | |
| 739 | |
| 740 // server_nonce_boxer_ is used to encrypt and validate suggested server | |
| 741 // nonces. | |
| 742 CryptoSecretBoxer server_nonce_boxer_; | |
| 743 | |
| 744 // server_nonce_orbit_ contains the random, per-server orbit values that this | |
| 745 // server will use to generate server nonces (the moral equivalent of a SYN | |
| 746 // cookies). | |
| 747 uint8_t server_nonce_orbit_[8]; | |
| 748 | |
| 749 mutable base::Lock server_nonce_strike_register_lock_; | |
| 750 // server_nonce_strike_register_ contains a data structure that keeps track of | |
| 751 // previously observed server nonces from this server, in order to prevent | |
| 752 // replay attacks. | |
| 753 mutable std::unique_ptr<StrikeRegister> server_nonce_strike_register_; | |
| 754 | |
| 755 // proof_source_ contains an object that can provide certificate chains and | |
| 756 // signatures. | |
| 757 std::unique_ptr<ProofSource> proof_source_; | |
| 758 | |
| 759 // ephemeral_key_source_ contains an object that caches ephemeral keys for a | |
| 760 // short period of time. | |
| 761 std::unique_ptr<EphemeralKeySource> ephemeral_key_source_; | |
| 762 | |
| 763 // These fields store configuration values. See the comments for their | |
| 764 // respective setter functions. | |
| 765 bool strike_register_no_startup_period_; | |
| 766 uint32_t strike_register_max_entries_; | |
| 767 uint32_t strike_register_window_secs_; | |
| 768 uint32_t source_address_token_future_secs_; | |
| 769 uint32_t source_address_token_lifetime_secs_; | |
| 770 uint32_t server_nonce_strike_register_max_entries_; | |
| 771 uint32_t server_nonce_strike_register_window_secs_; | |
| 772 | |
| 773 // Enable serving SCT or not. | |
| 774 bool enable_serving_sct_; | |
| 775 | |
| 776 DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerConfig); | |
| 777 }; | |
| 778 | |
| 779 struct NET_EXPORT_PRIVATE QuicCryptoProof { | |
| 780 QuicCryptoProof(); | |
| 781 ~QuicCryptoProof(); | |
| 782 | |
| 783 std::string signature; | |
| 784 scoped_refptr<ProofSource::Chain> chain; | |
| 785 std::string cert_sct; | |
| 786 // The server config that is used for this proof (and the rest of the | |
| 787 // request). | |
| 788 scoped_refptr<QuicCryptoServerConfig::Config> config; | |
| 789 std::string primary_scid; | |
| 790 }; | |
| 791 | |
| 792 } // namespace net | |
| 793 | |
| 794 #endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ | |
| OLD | NEW |