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