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
23namespace net {
24
25class EphemeralKeySource;
26class KeyExchange;
27class ProofSource;
28class QuicClock;
29class QuicDecrypter;
30class QuicEncrypter;
31class QuicRandom;
32class QuicServerConfigProtobuf;
33class StrikeRegister;
34
35struct ClientHelloInfo;
36
37namespace test {
38class 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.
46class 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) â câconfigs_, 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