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