blob: 1a991362bd13cdd803c79753e57498133b95374b [file] [log] [blame]
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001// 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
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01008#include <map>
9#include <string>
10#include <vector>
11
12#include "base/memory/ref_counted.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010013#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"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010020#include "net/quic/crypto/crypto_secret_boxer.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010021#include "net/quic/quic_time.h"
22
23namespace net {
24
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010025class EphemeralKeySource;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010026class KeyExchange;
27class ProofSource;
28class QuicClock;
29class QuicDecrypter;
30class QuicEncrypter;
31class QuicRandom;
32class QuicServerConfigProtobuf;
33class StrikeRegister;
34
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010035struct ClientHelloInfo;
36
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010037namespace 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:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010048 // 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;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010058 // id contains the server config id for the resulting config. If empty, a
59 // random id is generated.
60 std::string id;
Ben Murdoch558790d2013-07-30 15:19:42 +010061 // 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;
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010064 };
65
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010066 // |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.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010069 // |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);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010074 ~QuicCryptoServerConfig();
75
76 // TESTING is a magic parameter for passing to the constructor in tests.
77 static const char TESTING[];
78
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010079 // DefaultConfig generates a QuicServerConfigProtobuf protobuf suitable for
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010080 // using in tests.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010081 static QuicServerConfigProtobuf* DefaultConfig(
82 QuicRandom* rand,
83 const QuicClock* clock,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010084 const ConfigOptions& options);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010085
86 // AddConfig adds a QuicServerConfigProtobuf to the availible configurations.
87 // It returns the SCFG message from the config if successful. The caller
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010088 // 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);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010093
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010094 // 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010097 CryptoHandshakeMessage* AddDefaultConfig(
98 QuicRandom* rand,
99 const QuicClock* clock,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100100 const ConfigOptions& options);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100101
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100102 // 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
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100112 // 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 // guid: the GUID for the connection, which is used in key derivation.
120 // client_ip: the IP address of the client, which is used to generate and
121 // validate source-address tokens.
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100122 // clock: used to validate client nonces and ephemeral keys.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100123 // rand: an entropy source
124 // params: the state of the handshake. This may be updated with a server
125 // nonce when we send a rejection. After a successful handshake, this will
126 // contain the state of the connection.
127 // out: the resulting handshake message (either REJ or SHLO)
128 // error_details: used to store a string describing any error.
129 QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
130 QuicGuid guid,
131 const IPEndPoint& client_ip,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100132 const QuicClock* clock,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100133 QuicRandom* rand,
134 QuicCryptoNegotiatedParameters* params,
135 CryptoHandshakeMessage* out,
136 std::string* error_details) const;
137
138 // SetProofSource installs |proof_source| as the ProofSource for handshakes.
139 // This object takes ownership of |proof_source|.
140 void SetProofSource(ProofSource* proof_source);
141
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100142 // SetEphemeralKeySource installs an object that can cache ephemeral keys for
143 // a short period of time. This object takes ownership of
144 // |ephemeral_key_source|. If not set then ephemeral keys will be generated
145 // per-connection.
146 void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source);
147
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100148 // set_replay_protection controls whether replay protection is enabled. If
149 // replay protection is disabled then no strike registers are needed and
150 // frontends can share an orbit value without a shared strike-register.
151 // However, an attacker can duplicate a handshake and cause a client's
152 // request to be processed twice.
153 void set_replay_protection(bool on);
154
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100155 // set_strike_register_max_entries sets the maximum number of entries that
156 // the internal strike register will hold. If the strike register fills up
157 // then the oldest entries (by the client's clock) will be dropped.
158 void set_strike_register_max_entries(uint32 max_entries);
159
160 // set_strike_register_window_secs sets the number of seconds around the
161 // current time that the strike register will attempt to be authoritative
162 // for. Setting a larger value allows for greater client clock-skew, but
163 // means that the quiescent startup period must be longer.
164 void set_strike_register_window_secs(uint32 window_secs);
165
166 // set_source_address_token_future_secs sets the number of seconds into the
167 // future that source-address tokens will be accepted from. Since
168 // source-address tokens are authenticated, this should only happen if
169 // another, valid server has clock-skew.
170 void set_source_address_token_future_secs(uint32 future_secs);
171
172 // set_source_address_token_lifetime_secs sets the number of seconds that a
173 // source-address token will be valid for.
174 void set_source_address_token_lifetime_secs(uint32 lifetime_secs);
175
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100176 // set_server_nonce_strike_register_max_entries sets the number of entries in
177 // the server-nonce strike-register. This is used to record that server nonce
178 // values have been used. If the number of entries is too small then clients
179 // which are depending on server nonces may fail to handshake because their
180 // nonce has expired in the amount of time it took to go from the server to
181 // the client and back.
182 void set_server_nonce_strike_register_max_entries(uint32 max_entries);
183
184 // set_server_nonce_strike_register_window_secs sets the number of seconds
185 // around the current time that the server-nonce strike-register will accept
186 // nonces from. Setting a larger value allows for clients to delay follow-up
187 // client hellos for longer and still use server nonces as proofs of
188 // uniqueness.
189 void set_server_nonce_strike_register_window_secs(uint32 window_secs);
190
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100191 private:
192 friend class test::QuicCryptoServerConfigPeer;
193
194 // Config represents a server config: a collection of preferences and
195 // Diffie-Hellman public values.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100196 class NET_EXPORT_PRIVATE Config : public QuicCryptoConfig,
197 public base::RefCounted<Config> {
198 public:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100199 Config();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100200
Ben Murdochbb1529c2013-08-08 10:24:53 +0100201 // TODO(rtenneti): since this is a class, we should probably do
202 // getters/setters here.
203 // |serialized| contains the bytes of this server config, suitable for
204 // sending on the wire.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100205 std::string serialized;
206 // id contains the SCID of this server config.
207 std::string id;
208 // orbit contains the orbit value for this config: an opaque identifier
209 // used to identify clusters of server frontends.
210 unsigned char orbit[kOrbitSize];
211
212 // key_exchanges contains key exchange objects with the private keys
213 // already loaded. The values correspond, one-to-one, with the tags in
214 // |kexs| from the parent class.
215 std::vector<KeyExchange*> key_exchanges;
216
217 // tag_value_map contains the raw key/value pairs for the config.
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100218 QuicTagValueMap tag_value_map;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100219
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100220 // channel_id_enabled is true if the config in |serialized| specifies that
221 // ChannelIDs are supported.
222 bool channel_id_enabled;
223
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100224 // is_primary is true if this config is the one that we'll give out to
225 // clients as the current one.
226 bool is_primary;
227
228 // primary_time contains the timestamp when this config should become the
229 // primary config. A value of QuicWallTime::Zero() means that this config
230 // will not be promoted at a specific time.
231 QuicWallTime primary_time;
232
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100233 private:
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100234 friend class base::RefCounted<Config>;
235 virtual ~Config();
236
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100237 DISALLOW_COPY_AND_ASSIGN(Config);
238 };
239
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100240 typedef std::map<ServerConfigID, scoped_refptr<Config> > ConfigMap;
241
242 // ConfigPrimaryTimeLessThan returns true if a->primary_time <
243 // b->primary_time.
244 static bool ConfigPrimaryTimeLessThan(const scoped_refptr<Config>& a,
245 const scoped_refptr<Config>& b);
246
247 // SelectNewPrimaryConfig reevaluates the primary config based on the
248 // "primary_time" deadlines contained in each.
249 void SelectNewPrimaryConfig(QuicWallTime now) const;
250
251 // EvaluateClientHello checks |client_hello| for gross errors and determines
252 // whether it can be shown to be fresh (i.e. not a replay). The results are
253 // written to |info|.
254 QuicErrorCode EvaluateClientHello(
255 const CryptoHandshakeMessage& client_hello,
256 const uint8* orbit,
257 ClientHelloInfo* info,
258 std::string* error_details) const;
259
260 // BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
261 void BuildRejection(
262 const scoped_refptr<Config>& config,
263 const CryptoHandshakeMessage& client_hello,
264 const ClientHelloInfo& info,
265 QuicRandom* rand,
266 CryptoHandshakeMessage* out) const;
267
268 // ParseConfigProtobuf parses the given config protobuf and returns a
269 // scoped_refptr<Config> if successful. The caller adopts the reference to the
270 // Config. On error, ParseConfigProtobuf returns NULL.
271 scoped_refptr<Config> ParseConfigProtobuf(QuicServerConfigProtobuf* protobuf);
272
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100273 // NewSourceAddressToken returns a fresh source address token for the given
274 // IP address.
275 std::string NewSourceAddressToken(const IPEndPoint& ip,
276 QuicRandom* rand,
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100277 QuicWallTime now) const;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100278
279 // ValidateSourceAddressToken returns true if the source address token in
280 // |token| is a valid and timely token for the IP address |ip| given that the
281 // current time is |now|.
282 bool ValidateSourceAddressToken(base::StringPiece token,
283 const IPEndPoint& ip,
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100284 QuicWallTime now) const;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100285
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100286 // NewServerNonce generates and encrypts a random nonce.
287 std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const;
288
289 // ValidateServerNonce decrypts |token| and verifies that it hasn't been
290 // previously used and is recent enough that it is plausible that it was part
291 // of a very recently provided rejection ("recent" will be on the order of
292 // 10-30 seconds). If so, it records that it has been used and returns true.
293 // Otherwise it returns false.
294 bool ValidateServerNonce(base::StringPiece echoed_server_nonce,
295 QuicWallTime now) const;
296
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100297 // replay_protection_ controls whether the server enforces that handshakes
298 // aren't replays.
299 bool replay_protection_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100300
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100301 // configs_ satisfies the following invariants:
302 // 1) configs_.empty() <-> primary_config_ == NULL
303 // 2) primary_config_ != NULL -> primary_config_->is_primary
304 // 3) ∀ c∈configs_, c->is_primary <-> c == primary_config_
305 mutable base::Lock configs_lock_;
306 // configs_ contains all active server configs. It's expected that there are
307 // about half-a-dozen configs active at any one time.
308 ConfigMap configs_;
309 // primary_config_ points to a Config (which is also in |configs_|) which is
310 // the primary config - i.e. the one that we'll give out to new clients.
311 mutable scoped_refptr<Config> primary_config_;
312 // next_config_promotion_time_ contains the nearest, future time when an
313 // active config will be promoted to primary.
314 mutable QuicWallTime next_config_promotion_time_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100315
316 mutable base::Lock strike_register_lock_;
317 // strike_register_ contains a data structure that keeps track of previously
318 // observed client nonces in order to prevent replay attacks.
319 mutable scoped_ptr<StrikeRegister> strike_register_;
320
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100321 // source_address_token_boxer_ is used to protect the source-address tokens
322 // that are given to clients.
323 CryptoSecretBoxer source_address_token_boxer_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100324
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100325 // server_nonce_boxer_ is used to encrypt and validate suggested server
326 // nonces.
327 CryptoSecretBoxer server_nonce_boxer_;
328
329 // server_nonce_orbit_ contains the random, per-server orbit values that this
330 // server will use to generate server nonces (the moral equivalent of a SYN
331 // cookies).
332 uint8 server_nonce_orbit_[8];
333
334 mutable base::Lock server_nonce_strike_register_lock_;
335 // server_nonce_strike_register_ contains a data structure that keeps track of
336 // previously observed server nonces from this server, in order to prevent
337 // replay attacks.
338 mutable scoped_ptr<StrikeRegister> server_nonce_strike_register_;
339
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100340 // proof_source_ contains an object that can provide certificate chains and
341 // signatures.
342 scoped_ptr<ProofSource> proof_source_;
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100343
344 // ephemeral_key_source_ contains an object that caches ephemeral keys for a
345 // short period of time.
346 scoped_ptr<EphemeralKeySource> ephemeral_key_source_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100347
348 // These fields store configuration values. See the comments for their
349 // respective setter functions.
350 uint32 strike_register_max_entries_;
351 uint32 strike_register_window_secs_;
352 uint32 source_address_token_future_secs_;
353 uint32 source_address_token_lifetime_secs_;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100354 uint32 server_nonce_strike_register_max_entries_;
355 uint32 server_nonce_strike_register_window_secs_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100356};
357
358} // namespace net
359
360#endif // NET_QUIC_CRYPTO_CRYPTO_SERVER_CONFIG_H_