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