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 <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/strings/string_piece.h" 15 #include "base/synchronization/lock.h" 16 #include "net/base/ip_endpoint.h" 17 #include "net/base/net_export.h" 18 #include "net/quic/crypto/crypto_handshake.h" 19 #include "net/quic/crypto/crypto_handshake_message.h" 20 #include "net/quic/crypto/crypto_protocol.h" 21 #include "net/quic/crypto/crypto_secret_boxer.h" 22 #include "net/quic/crypto/source_address_token.h" 23 #include "net/quic/quic_time.h" 24 25 namespace net { 26 27 class CryptoHandshakeMessage; 28 class EphemeralKeySource; 29 class KeyExchange; 30 class ProofSource; 31 class QuicClock; 32 class QuicDecrypter; 33 class QuicEncrypter; 34 class QuicRandom; 35 class QuicServerConfigProtobuf; 36 class StrikeRegister; 37 class StrikeRegisterClient; 38 39 struct ClientHelloInfo; 40 41 namespace test { 42 class QuicCryptoServerConfigPeer; 43 } // namespace test 44 45 // Hook that allows application code to subscribe to primary config changes. 46 class PrimaryConfigChangedCallback { 47 public: 48 PrimaryConfigChangedCallback(); 49 virtual ~PrimaryConfigChangedCallback(); 50 virtual void Run(const std::string& scid) = 0; 51 52 private: 53 DISALLOW_COPY_AND_ASSIGN(PrimaryConfigChangedCallback); 54 }; 55 56 // Callback used to accept the result of the |client_hello| validation step. 57 class NET_EXPORT_PRIVATE ValidateClientHelloResultCallback { 58 public: 59 // Opaque token that holds information about the client_hello and 60 // its validity. Can be interpreted by calling ProcessClientHello. 61 struct Result; 62 63 ValidateClientHelloResultCallback(); 64 virtual ~ValidateClientHelloResultCallback(); 65 void Run(const Result* result); 66 67 protected: 68 virtual void RunImpl(const CryptoHandshakeMessage& client_hello, 69 const Result& result) = 0; 70 71 private: 72 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback); 73 }; 74 75 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. 76 // Unlike a client, a QUIC server can have multiple configurations active in 77 // order to support clients resuming with a previous configuration. 78 // TODO(agl): when adding configurations at runtime is added, this object will 79 // need to consider locking. 80 class NET_EXPORT_PRIVATE QuicCryptoServerConfig { 81 public: 82 // ConfigOptions contains options for generating server configs. 83 struct NET_EXPORT_PRIVATE ConfigOptions { 84 ConfigOptions(); 85 86 // expiry_time is the time, in UNIX seconds, when the server config will 87 // expire. If unset, it defaults to the current time plus six months. 88 QuicWallTime expiry_time; 89 // channel_id_enabled controls whether the server config will indicate 90 // support for ChannelIDs. 91 bool channel_id_enabled; 92 // id contains the server config id for the resulting config. If empty, a 93 // random id is generated. 94 std::string id; 95 // orbit contains the kOrbitSize bytes of the orbit value for the server 96 // config. If |orbit| is empty then a random orbit is generated. 97 std::string orbit; 98 // p256 determines whether a P-256 public key will be included in the 99 // server config. Note that this breaks deterministic server-config 100 // generation since P-256 key generation doesn't use the QuicRandom given 101 // to DefaultConfig(). 102 bool p256; 103 }; 104 105 // |source_address_token_secret|: secret key material used for encrypting and 106 // decrypting source address tokens. It can be of any length as it is fed 107 // into a KDF before use. In tests, use TESTING. 108 // |server_nonce_entropy|: an entropy source used to generate the orbit and 109 // key for server nonces, which are always local to a given instance of a 110 // server. 111 QuicCryptoServerConfig(base::StringPiece source_address_token_secret, 112 QuicRandom* server_nonce_entropy); 113 ~QuicCryptoServerConfig(); 114 115 // TESTING is a magic parameter for passing to the constructor in tests. 116 static const char TESTING[]; 117 118 // Generates a QuicServerConfigProtobuf protobuf suitable for 119 // AddConfig and SetConfigs. 120 static QuicServerConfigProtobuf* GenerateConfig( 121 QuicRandom* rand, 122 const QuicClock* clock, 123 const ConfigOptions& options); 124 125 // AddConfig adds a QuicServerConfigProtobuf to the availible configurations. 126 // It returns the SCFG message from the config if successful. The caller 127 // takes ownership of the CryptoHandshakeMessage. |now| is used in 128 // conjunction with |protobuf->primary_time()| to determine whether the 129 // config should be made primary. 130 CryptoHandshakeMessage* AddConfig(QuicServerConfigProtobuf* protobuf, 131 QuicWallTime now); 132 133 // AddDefaultConfig calls DefaultConfig to create a config and then calls 134 // AddConfig to add it. See the comment for |DefaultConfig| for details of 135 // the arguments. 136 CryptoHandshakeMessage* AddDefaultConfig( 137 QuicRandom* rand, 138 const QuicClock* clock, 139 const ConfigOptions& options); 140 141 // SetConfigs takes a vector of config protobufs and the current time. 142 // Configs are assumed to be uniquely identified by their server config ID. 143 // Previously unknown configs are added and possibly made the primary config 144 // depending on their |primary_time| and the value of |now|. Configs that are 145 // known, but are missing from the protobufs are deleted, unless they are 146 // currently the primary config. SetConfigs returns false if any errors were 147 // encountered and no changes to the QuicCryptoServerConfig will occur. 148 bool SetConfigs(const std::vector<QuicServerConfigProtobuf*>& protobufs, 149 QuicWallTime now); 150 151 // Get the server config ids for all known configs. 152 void GetConfigIds(std::vector<std::string>* scids) const; 153 154 // Checks |client_hello| for gross errors and determines whether it 155 // can be shown to be fresh (i.e. not a replay). The result of the 156 // validation step must be interpreted by calling 157 // QuicCryptoServerConfig::ProcessClientHello from the done_cb. 158 // 159 // ValidateClientHello may invoke the done_cb before unrolling the 160 // stack if it is able to assess the validity of the client_nonce 161 // without asynchronous operations. 162 // 163 // client_hello: the incoming client hello message. 164 // client_ip: the IP address of the client, which is used to generate and 165 // validate source-address tokens. 166 // clock: used to validate client nonces and ephemeral keys. 167 // done_cb: single-use callback that accepts an opaque 168 // ValidatedClientHelloMsg token that holds information about 169 // the client hello. The callback will always be called exactly 170 // once, either under the current call stack, or after the 171 // completion of an asynchronous operation. 172 void ValidateClientHello( 173 const CryptoHandshakeMessage& client_hello, 174 IPEndPoint client_ip, 175 const QuicClock* clock, 176 ValidateClientHelloResultCallback* done_cb) const; 177 178 // ProcessClientHello processes |client_hello| and decides whether to accept 179 // or reject the connection. If the connection is to be accepted, |out| is 180 // set to the contents of the ServerHello, |out_params| is completed and 181 // QUIC_NO_ERROR is returned. Otherwise |out| is set to be a REJ message and 182 // an error code is returned. 183 // 184 // validate_chlo_result: Output from the asynchronous call to 185 // ValidateClientHello. Contains the client hello message and 186 // information about it. 187 // connection_id: the ConnectionId for the connection, which is used in key 188 // derivation. 189 // client_address: the IP address and port of the client. The IP address is 190 // used to generate and validate source-address tokens. 191 // version: version of the QUIC protocol in use for this connection 192 // supported_versions: versions of the QUIC protocol that this server 193 // supports. 194 // initial_flow_control_window: size of initial flow control window this 195 // server uses for new streams. 196 // clock: used to validate client nonces and ephemeral keys. 197 // rand: an entropy source 198 // params: the state of the handshake. This may be updated with a server 199 // nonce when we send a rejection. After a successful handshake, this will 200 // contain the state of the connection. 201 // out: the resulting handshake message (either REJ or SHLO) 202 // error_details: used to store a string describing any error. 203 QuicErrorCode ProcessClientHello( 204 const ValidateClientHelloResultCallback::Result& validate_chlo_result, 205 QuicConnectionId connection_id, 206 IPEndPoint client_address, 207 QuicVersion version, 208 const QuicVersionVector& supported_versions, 209 const QuicClock* clock, 210 QuicRandom* rand, 211 QuicCryptoNegotiatedParameters* params, 212 CryptoHandshakeMessage* out, 213 std::string* error_details) const; 214 215 // BuildServerConfigUpdateMessage sets |out| to be a SCUP message containing 216 // the current primary config, an up to date source-address token, and cert 217 // chain and proof in the case of secure QUIC. Returns true if successfully 218 // filled |out|. 219 // 220 // |cached_network_params| is optional, and can be NULL. 221 bool BuildServerConfigUpdateMessage( 222 const IPEndPoint& client_ip, 223 const QuicClock* clock, 224 QuicRandom* rand, 225 const QuicCryptoNegotiatedParameters& params, 226 const CachedNetworkParameters* cached_network_params, 227 CryptoHandshakeMessage* out) const; 228 229 // SetProofSource installs |proof_source| as the ProofSource for handshakes. 230 // This object takes ownership of |proof_source|. 231 void SetProofSource(ProofSource* proof_source); 232 233 // SetEphemeralKeySource installs an object that can cache ephemeral keys for 234 // a short period of time. This object takes ownership of 235 // |ephemeral_key_source|. If not set then ephemeral keys will be generated 236 // per-connection. 237 void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source); 238 239 // Install an externall created StrikeRegisterClient for use to 240 // interact with the strike register. This object takes ownership 241 // of the |strike_register_client|. 242 void SetStrikeRegisterClient(StrikeRegisterClient* strike_register_client); 243 244 // set_replay_protection controls whether replay protection is enabled. If 245 // replay protection is disabled then no strike registers are needed and 246 // frontends can share an orbit value without a shared strike-register. 247 // However, an attacker can duplicate a handshake and cause a client's 248 // request to be processed twice. 249 void set_replay_protection(bool on); 250 251 // set_strike_register_no_startup_period configures the strike register to 252 // not have a startup period. 253 void set_strike_register_no_startup_period(); 254 255 // set_strike_register_max_entries sets the maximum number of entries that 256 // the internal strike register will hold. If the strike register fills up 257 // then the oldest entries (by the client's clock) will be dropped. 258 void set_strike_register_max_entries(uint32 max_entries); 259 260 // set_strike_register_window_secs sets the number of seconds around the 261 // current time that the strike register will attempt to be authoritative 262 // for. Setting a larger value allows for greater client clock-skew, but 263 // means that the quiescent startup period must be longer. 264 void set_strike_register_window_secs(uint32 window_secs); 265 266 // set_source_address_token_future_secs sets the number of seconds into the 267 // future that source-address tokens will be accepted from. Since 268 // source-address tokens are authenticated, this should only happen if 269 // another, valid server has clock-skew. 270 void set_source_address_token_future_secs(uint32 future_secs); 271 272 // set_source_address_token_lifetime_secs sets the number of seconds that a 273 // source-address token will be valid for. 274 void set_source_address_token_lifetime_secs(uint32 lifetime_secs); 275 276 // set_server_nonce_strike_register_max_entries sets the number of entries in 277 // the server-nonce strike-register. This is used to record that server nonce 278 // values have been used. If the number of entries is too small then clients 279 // which are depending on server nonces may fail to handshake because their 280 // nonce has expired in the amount of time it took to go from the server to 281 // the client and back. 282 void set_server_nonce_strike_register_max_entries(uint32 max_entries); 283 284 // set_server_nonce_strike_register_window_secs sets the number of seconds 285 // around the current time that the server-nonce strike-register will accept 286 // nonces from. Setting a larger value allows for clients to delay follow-up 287 // client hellos for longer and still use server nonces as proofs of 288 // uniqueness. 289 void set_server_nonce_strike_register_window_secs(uint32 window_secs); 290 291 // Set and take ownership of the callback to invoke on primary config changes. 292 void AcquirePrimaryConfigChangedCb(PrimaryConfigChangedCallback* cb); 293 294 private: 295 friend class test::QuicCryptoServerConfigPeer; 296 297 // Config represents a server config: a collection of preferences and 298 // Diffie-Hellman public values. 299 class NET_EXPORT_PRIVATE Config : public QuicCryptoConfig, 300 public base::RefCounted<Config> { 301 public: 302 Config(); 303 304 // TODO(rtenneti): since this is a class, we should probably do 305 // getters/setters here. 306 // |serialized| contains the bytes of this server config, suitable for 307 // sending on the wire. 308 std::string serialized; 309 // id contains the SCID of this server config. 310 std::string id; 311 // orbit contains the orbit value for this config: an opaque identifier 312 // used to identify clusters of server frontends. 313 unsigned char orbit[kOrbitSize]; 314 315 // key_exchanges contains key exchange objects with the private keys 316 // already loaded. The values correspond, one-to-one, with the tags in 317 // |kexs| from the parent class. 318 std::vector<KeyExchange*> key_exchanges; 319 320 // tag_value_map contains the raw key/value pairs for the config. 321 QuicTagValueMap tag_value_map; 322 323 // channel_id_enabled is true if the config in |serialized| specifies that 324 // ChannelIDs are supported. 325 bool channel_id_enabled; 326 327 // is_primary is true if this config is the one that we'll give out to 328 // clients as the current one. 329 bool is_primary; 330 331 // primary_time contains the timestamp when this config should become the 332 // primary config. A value of QuicWallTime::Zero() means that this config 333 // will not be promoted at a specific time. 334 QuicWallTime primary_time; 335 336 // Secondary sort key for use when selecting primary configs and 337 // there are multiple configs with the same primary time. 338 // Smaller numbers mean higher priority. 339 uint64 priority; 340 341 // source_address_token_boxer_ is used to protect the 342 // source-address tokens that are given to clients. 343 // Points to either source_address_token_boxer_storage or the 344 // default boxer provided by QuicCryptoServerConfig. 345 const CryptoSecretBoxer* source_address_token_boxer; 346 347 // Holds the override source_address_token_boxer instance if the 348 // Config is not using the default source address token boxer 349 // instance provided by QuicCryptoServerConfig. 350 scoped_ptr<CryptoSecretBoxer> source_address_token_boxer_storage; 351 352 private: 353 friend class base::RefCounted<Config>; 354 355 virtual ~Config(); 356 357 DISALLOW_COPY_AND_ASSIGN(Config); 358 }; 359 360 typedef std::map<ServerConfigID, scoped_refptr<Config> > ConfigMap; 361 362 // Get a ref to the config with a given server config id. 363 scoped_refptr<Config> GetConfigWithScid( 364 base::StringPiece requested_scid) const; 365 366 // ConfigPrimaryTimeLessThan returns true if a->primary_time < 367 // b->primary_time. 368 static bool ConfigPrimaryTimeLessThan(const scoped_refptr<Config>& a, 369 const scoped_refptr<Config>& b); 370 371 // SelectNewPrimaryConfig reevaluates the primary config based on the 372 // "primary_time" deadlines contained in each. 373 void SelectNewPrimaryConfig(QuicWallTime now) const; 374 375 // EvaluateClientHello checks |client_hello| for gross errors and determines 376 // whether it can be shown to be fresh (i.e. not a replay). The results are 377 // written to |info|. 378 void EvaluateClientHello( 379 const uint8* primary_orbit, 380 scoped_refptr<Config> requested_config, 381 ValidateClientHelloResultCallback::Result* client_hello_state, 382 ValidateClientHelloResultCallback* done_cb) const; 383 384 // BuildRejection sets |out| to be a REJ message in reply to |client_hello|. 385 void BuildRejection( 386 const Config& config, 387 const CryptoHandshakeMessage& client_hello, 388 const ClientHelloInfo& info, 389 QuicRandom* rand, 390 QuicCryptoNegotiatedParameters *params, 391 CryptoHandshakeMessage* out) const; 392 393 // ParseConfigProtobuf parses the given config protobuf and returns a 394 // scoped_refptr<Config> if successful. The caller adopts the reference to the 395 // Config. On error, ParseConfigProtobuf returns NULL. 396 scoped_refptr<Config> ParseConfigProtobuf(QuicServerConfigProtobuf* protobuf); 397 398 // NewSourceAddressToken returns a fresh source address token for the given 399 // IP address. |cached_network_params| is optional, and can be NULL. 400 std::string NewSourceAddressToken( 401 const Config& config, 402 const IPEndPoint& ip, 403 QuicRandom* rand, 404 QuicWallTime now, 405 const CachedNetworkParameters* cached_network_params) const; 406 407 // ValidateSourceAddressToken returns HANDSHAKE_OK if the source address token 408 // in |token| is a valid and timely token for the IP address |ip| given that 409 // the current time is |now|. Otherwise it returns the reason for failure. 410 HandshakeFailureReason ValidateSourceAddressToken(const Config& config, 411 base::StringPiece token, 412 const IPEndPoint& ip, 413 QuicWallTime now) const; 414 415 // NewServerNonce generates and encrypts a random nonce. 416 std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const; 417 418 // ValidateServerNonce decrypts |token| and verifies that it hasn't been 419 // previously used and is recent enough that it is plausible that it was part 420 // of a very recently provided rejection ("recent" will be on the order of 421 // 10-30 seconds). If so, it records that it has been used and returns 422 // HANDSHAKE_OK. Otherwise it returns the reason for failure. 423 HandshakeFailureReason ValidateServerNonce( 424 base::StringPiece echoed_server_nonce, 425 QuicWallTime now) const; 426 427 // replay_protection_ controls whether the server enforces that handshakes 428 // aren't replays. 429 bool replay_protection_; 430 431 // configs_ satisfies the following invariants: 432 // 1) configs_.empty() <-> primary_config_ == NULL 433 // 2) primary_config_ != NULL -> primary_config_->is_primary 434 // 3) ∀ c∈configs_, c->is_primary <-> c == primary_config_ 435 mutable base::Lock configs_lock_; 436 // configs_ contains all active server configs. It's expected that there are 437 // about half-a-dozen configs active at any one time. 438 ConfigMap configs_; 439 // primary_config_ points to a Config (which is also in |configs_|) which is 440 // the primary config - i.e. the one that we'll give out to new clients. 441 mutable scoped_refptr<Config> primary_config_; 442 // next_config_promotion_time_ contains the nearest, future time when an 443 // active config will be promoted to primary. 444 mutable QuicWallTime next_config_promotion_time_; 445 // Callback to invoke when the primary config changes. 446 scoped_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_; 447 448 // Protects access to the pointer held by strike_register_client_. 449 mutable base::Lock strike_register_client_lock_; 450 // strike_register_ contains a data structure that keeps track of previously 451 // observed client nonces in order to prevent replay attacks. 452 mutable scoped_ptr<StrikeRegisterClient> strike_register_client_; 453 454 // Default source_address_token_boxer_ used to protect the 455 // source-address tokens that are given to clients. Individual 456 // configs may use boxers with alternate secrets. 457 CryptoSecretBoxer default_source_address_token_boxer_; 458 459 // server_nonce_boxer_ is used to encrypt and validate suggested server 460 // nonces. 461 CryptoSecretBoxer server_nonce_boxer_; 462 463 // server_nonce_orbit_ contains the random, per-server orbit values that this 464 // server will use to generate server nonces (the moral equivalent of a SYN 465 // cookies). 466 uint8 server_nonce_orbit_[8]; 467 468 mutable base::Lock server_nonce_strike_register_lock_; 469 // server_nonce_strike_register_ contains a data structure that keeps track of 470 // previously observed server nonces from this server, in order to prevent 471 // replay attacks. 472 mutable scoped_ptr<StrikeRegister> server_nonce_strike_register_; 473 474 // proof_source_ contains an object that can provide certificate chains and 475 // signatures. 476 scoped_ptr<ProofSource> proof_source_; 477 478 // ephemeral_key_source_ contains an object that caches ephemeral keys for a 479 // short period of time. 480 scoped_ptr<EphemeralKeySource> ephemeral_key_source_; 481 482 // These fields store configuration values. See the comments for their 483 // respective setter functions. 484 bool strike_register_no_startup_period_; 485 uint32 strike_register_max_entries_; 486 uint32 strike_register_window_secs_; 487 uint32 source_address_token_future_secs_; 488 uint32 source_address_token_lifetime_secs_; 489 uint32 server_nonce_strike_register_max_entries_; 490 uint32 server_nonce_strike_register_window_secs_; 491 492 DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerConfig); 493 }; 494 495 } // namespace net 496 497 #endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ 498