OLD | NEW |
| (Empty) |
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 <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <map> | |
12 #include <memory> | |
13 #include <string> | |
14 #include <vector> | |
15 | |
16 #include "base/macros.h" | |
17 #include "base/memory/ref_counted.h" | |
18 #include "base/strings/string_piece.h" | |
19 #include "base/synchronization/lock.h" | |
20 #include "net/base/ip_address.h" | |
21 #include "net/base/ip_endpoint.h" | |
22 #include "net/base/net_export.h" | |
23 #include "net/quic/crypto/crypto_handshake.h" | |
24 #include "net/quic/crypto/crypto_handshake_message.h" | |
25 #include "net/quic/crypto/crypto_protocol.h" | |
26 #include "net/quic/crypto/crypto_secret_boxer.h" | |
27 #include "net/quic/crypto/proof_source.h" | |
28 #include "net/quic/crypto/quic_compressed_certs_cache.h" | |
29 #include "net/quic/proto/cached_network_parameters.pb.h" | |
30 #include "net/quic/proto/source_address_token.pb.h" | |
31 #include "net/quic/quic_time.h" | |
32 | |
33 namespace net { | |
34 | |
35 class CryptoHandshakeMessage; | |
36 class EphemeralKeySource; | |
37 class KeyExchange; | |
38 class ProofSource; | |
39 class QuicClock; | |
40 class QuicDecrypter; | |
41 class QuicEncrypter; | |
42 class QuicRandom; | |
43 class QuicServerConfigProtobuf; | |
44 class StrikeRegister; | |
45 class StrikeRegisterClient; | |
46 struct QuicCryptoProof; | |
47 | |
48 // ClientHelloInfo contains information about a client hello message that is | |
49 // only kept for as long as it's being processed. | |
50 struct ClientHelloInfo { | |
51 ClientHelloInfo(const IPAddress& in_client_ip, QuicWallTime in_now); | |
52 ~ClientHelloInfo(); | |
53 | |
54 // Inputs to EvaluateClientHello. | |
55 const IPAddress client_ip; | |
56 const QuicWallTime now; | |
57 | |
58 // Outputs from EvaluateClientHello. | |
59 bool valid_source_address_token; | |
60 base::StringPiece sni; | |
61 base::StringPiece client_nonce; | |
62 base::StringPiece server_nonce; | |
63 base::StringPiece user_agent_id; | |
64 SourceAddressTokens source_address_tokens; | |
65 | |
66 // Errors from EvaluateClientHello. | |
67 std::vector<uint32_t> reject_reasons; | |
68 static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync"); | |
69 }; | |
70 | |
71 namespace test { | |
72 class QuicCryptoServerConfigPeer; | |
73 } // namespace test | |
74 | |
75 // Hook that allows application code to subscribe to primary config changes. | |
76 class PrimaryConfigChangedCallback { | |
77 public: | |
78 PrimaryConfigChangedCallback(); | |
79 virtual ~PrimaryConfigChangedCallback(); | |
80 virtual void Run(const std::string& scid) = 0; | |
81 | |
82 private: | |
83 DISALLOW_COPY_AND_ASSIGN(PrimaryConfigChangedCallback); | |
84 }; | |
85 | |
86 // Callback used to accept the result of the |client_hello| validation step. | |
87 class NET_EXPORT_PRIVATE ValidateClientHelloResultCallback { | |
88 public: | |
89 // Opaque token that holds information about the client_hello and | |
90 // its validity. Can be interpreted by calling ProcessClientHello. | |
91 struct Result { | |
92 Result(const CryptoHandshakeMessage& in_client_hello, | |
93 IPAddress in_client_ip, | |
94 QuicWallTime in_now); | |
95 ~Result(); | |
96 | |
97 CryptoHandshakeMessage client_hello; | |
98 ClientHelloInfo info; | |
99 QuicErrorCode error_code; | |
100 std::string error_details; | |
101 | |
102 // Populated if the CHLO STK contained a CachedNetworkParameters proto. | |
103 CachedNetworkParameters cached_network_params; | |
104 }; | |
105 | |
106 ValidateClientHelloResultCallback(); | |
107 virtual ~ValidateClientHelloResultCallback(); | |
108 void Run(const Result* result, std::unique_ptr<ProofSource::Details> details); | |
109 | |
110 protected: | |
111 virtual void RunImpl(const CryptoHandshakeMessage& client_hello, | |
112 const Result& result, | |
113 std::unique_ptr<ProofSource::Details> details) = 0; | |
114 | |
115 private: | |
116 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback); | |
117 }; | |
118 | |
119 // Callback used to receive the results of a call to | |
120 // BuildServerConfigUpdateMessage. | |
121 class BuildServerConfigUpdateMessageResultCallback { | |
122 public: | |
123 BuildServerConfigUpdateMessageResultCallback() = default; | |
124 virtual ~BuildServerConfigUpdateMessageResultCallback() {} | |
125 virtual void Run(bool ok, const CryptoHandshakeMessage& message) = 0; | |
126 | |
127 private: | |
128 DISALLOW_COPY_AND_ASSIGN(BuildServerConfigUpdateMessageResultCallback); | |
129 }; | |
130 | |
131 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. | |
132 // Unlike a client, a QUIC server can have multiple configurations active in | |
133 // order to support clients resuming with a previous configuration. | |
134 // TODO(agl): when adding configurations at runtime is added, this object will | |
135 // need to consider locking. | |
136 class NET_EXPORT_PRIVATE QuicCryptoServerConfig { | |
137 public: | |
138 // ConfigOptions contains options for generating server configs. | |
139 struct NET_EXPORT_PRIVATE ConfigOptions { | |
140 ConfigOptions(); | |
141 ConfigOptions(const ConfigOptions& other); | |
142 | |
143 // expiry_time is the time, in UNIX seconds, when the server config will | |
144 // expire. If unset, it defaults to the current time plus six months. | |
145 QuicWallTime expiry_time; | |
146 // channel_id_enabled controls whether the server config will indicate | |
147 // support for ChannelIDs. | |
148 bool channel_id_enabled; | |
149 // token_binding_enabled controls whether the server config will indicate | |
150 // support for Token Binding. | |
151 bool token_binding_enabled; | |
152 // id contains the server config id for the resulting config. If empty, a | |
153 // random id is generated. | |
154 std::string id; | |
155 // orbit contains the kOrbitSize bytes of the orbit value for the server | |
156 // config. If |orbit| is empty then a random orbit is generated. | |
157 std::string orbit; | |
158 // p256 determines whether a P-256 public key will be included in the | |
159 // server config. Note that this breaks deterministic server-config | |
160 // generation since P-256 key generation doesn't use the QuicRandom given | |
161 // to DefaultConfig(). | |
162 bool p256; | |
163 }; | |
164 | |
165 // |source_address_token_secret|: secret key material used for encrypting and | |
166 // decrypting source address tokens. It can be of any length as it is fed | |
167 // into a KDF before use. In tests, use TESTING. | |
168 // |server_nonce_entropy|: an entropy source used to generate the orbit and | |
169 // key for server nonces, which are always local to a given instance of a | |
170 // server. Not owned. | |
171 // |proof_source|: provides certificate chains and signatures. This class | |
172 // takes ownership of |proof_source|. | |
173 QuicCryptoServerConfig(base::StringPiece source_address_token_secret, | |
174 QuicRandom* server_nonce_entropy, | |
175 std::unique_ptr<ProofSource> proof_source); | |
176 ~QuicCryptoServerConfig(); | |
177 | |
178 // TESTING is a magic parameter for passing to the constructor in tests. | |
179 static const char TESTING[]; | |
180 | |
181 // Generates a QuicServerConfigProtobuf protobuf suitable for | |
182 // AddConfig and SetConfigs. | |
183 static QuicServerConfigProtobuf* GenerateConfig(QuicRandom* rand, | |
184 const QuicClock* clock, | |
185 const ConfigOptions& options); | |
186 | |
187 // AddConfig adds a QuicServerConfigProtobuf to the availible configurations. | |
188 // It returns the SCFG message from the config if successful. The caller | |
189 // takes ownership of the CryptoHandshakeMessage. |now| is used in | |
190 // conjunction with |protobuf->primary_time()| to determine whether the | |
191 // config should be made primary. | |
192 CryptoHandshakeMessage* AddConfig(QuicServerConfigProtobuf* protobuf, | |
193 QuicWallTime now); | |
194 | |
195 // AddDefaultConfig calls DefaultConfig to create a config and then calls | |
196 // AddConfig to add it. See the comment for |DefaultConfig| for details of | |
197 // the arguments. | |
198 CryptoHandshakeMessage* AddDefaultConfig(QuicRandom* rand, | |
199 const QuicClock* clock, | |
200 const ConfigOptions& options); | |
201 | |
202 // SetConfigs takes a vector of config protobufs and the current time. | |
203 // Configs are assumed to be uniquely identified by their server config ID. | |
204 // Previously unknown configs are added and possibly made the primary config | |
205 // depending on their |primary_time| and the value of |now|. Configs that are | |
206 // known, but are missing from the protobufs are deleted, unless they are | |
207 // currently the primary config. SetConfigs returns false if any errors were | |
208 // encountered and no changes to the QuicCryptoServerConfig will occur. | |
209 bool SetConfigs(const std::vector<QuicServerConfigProtobuf*>& protobufs, | |
210 QuicWallTime now); | |
211 | |
212 // SetDefaultSourceAddressTokenKeys sets the keys to be tried, in order, | |
213 // when decrypting a source address token. This modifies only the default | |
214 // boxer, which is to say, it is a no-op if a key was specified in the Config. | |
215 // Note that these keys are used *without* passing them through a KDF, in | |
216 // contradistinction to the |source_address_token_secret| argument to the | |
217 // constructor. | |
218 void SetDefaultSourceAddressTokenKeys(const std::vector<std::string>& keys); | |
219 | |
220 // Get the server config ids for all known configs. | |
221 void GetConfigIds(std::vector<std::string>* scids) const; | |
222 | |
223 // Checks |client_hello| for gross errors and determines whether it | |
224 // can be shown to be fresh (i.e. not a replay). The result of the | |
225 // validation step must be interpreted by calling | |
226 // QuicCryptoServerConfig::ProcessClientHello from the done_cb. | |
227 // | |
228 // ValidateClientHello may invoke the done_cb before unrolling the | |
229 // stack if it is able to assess the validity of the client_nonce | |
230 // without asynchronous operations. | |
231 // | |
232 // client_hello: the incoming client hello message. | |
233 // client_ip: the IP address of the client, which is used to generate and | |
234 // validate source-address tokens. | |
235 // server_ip: the IP address of the server. The IP address may be used for | |
236 // certificate selection. | |
237 // version: protocol version used for this connection. | |
238 // clock: used to validate client nonces and ephemeral keys. | |
239 // crypto_proof: output structure containing the crypto proof used in reply to | |
240 // a proof demand. | |
241 // done_cb: single-use callback that accepts an opaque | |
242 // ValidatedClientHelloMsg token that holds information about | |
243 // the client hello. The callback will always be called exactly | |
244 // once, either under the current call stack, or after the | |
245 // completion of an asynchronous operation. | |
246 void ValidateClientHello(const CryptoHandshakeMessage& client_hello, | |
247 const IPAddress& client_ip, | |
248 const IPAddress& server_ip, | |
249 QuicVersion version, | |
250 const QuicClock* clock, | |
251 QuicCryptoProof* crypto_proof, | |
252 ValidateClientHelloResultCallback* done_cb) const; | |
253 | |
254 // ProcessClientHello processes |client_hello| and decides whether to accept | |
255 // or reject the connection. If the connection is to be accepted, |out| is | |
256 // set to the contents of the ServerHello, |out_params| is completed and | |
257 // QUIC_NO_ERROR is returned. Otherwise |out| is set to be a REJ or SREJ | |
258 // message and QUIC_NO_ERROR is returned. | |
259 // | |
260 // validate_chlo_result: Output from the asynchronous call to | |
261 // ValidateClientHello. Contains the client hello message and | |
262 // information about it. | |
263 // reject_only: Only generate rejections, not server hello messages. | |
264 // connection_id: the ConnectionId for the connection, which is used in key | |
265 // derivation. | |
266 // server_ip: the IP address of the server. The IP address may be used for | |
267 // certificate selection. | |
268 // client_address: the IP address and port of the client. The IP address is | |
269 // used to generate and validate source-address tokens. | |
270 // version: version of the QUIC protocol in use for this connection | |
271 // supported_versions: versions of the QUIC protocol that this server | |
272 // supports. | |
273 // clock: used to validate client nonces and ephemeral keys. | |
274 // rand: an entropy source | |
275 // compressed_certs_cache: the cache that caches a set of most recently used | |
276 // certs. Owned by QuicDispatcher. | |
277 // params: the state of the handshake. This may be updated with a server | |
278 // nonce when we send a rejection. After a successful handshake, this will | |
279 // contain the state of the connection. | |
280 // crypto_proof: output structure containing the crypto proof used in reply to | |
281 // a proof demand. | |
282 // out: the resulting handshake message (either REJ or SHLO) | |
283 // out_diversification_nonce: If the resulting handshake message is SHLO and | |
284 // the version is greater than QUIC_VERSION_32 then this contains a | |
285 // 32-byte value that should be included in the public header of | |
286 // initially encrypted packets. | |
287 // error_details: used to store a std::string describing any error. | |
288 QuicErrorCode ProcessClientHello( | |
289 const ValidateClientHelloResultCallback::Result& validate_chlo_result, | |
290 bool reject_only, | |
291 QuicConnectionId connection_id, | |
292 const IPAddress& server_ip, | |
293 const IPEndPoint& client_address, | |
294 QuicVersion version, | |
295 const QuicVersionVector& supported_versions, | |
296 bool use_stateless_rejects, | |
297 QuicConnectionId server_designated_connection_id, | |
298 const QuicClock* clock, | |
299 QuicRandom* rand, | |
300 QuicCompressedCertsCache* compressed_certs_cache, | |
301 QuicCryptoNegotiatedParameters* params, | |
302 QuicCryptoProof* crypto_proof, | |
303 CryptoHandshakeMessage* out, | |
304 DiversificationNonce* out_diversification_nonce, | |
305 std::string* error_details) const; | |
306 | |
307 // BuildServerConfigUpdateMessage sets |out| to be a SCUP message containing | |
308 // the current primary config, an up to date source-address token, and cert | |
309 // chain and proof in the case of secure QUIC. Returns true if successfully | |
310 // filled |out|. | |
311 // | |
312 // |cached_network_params| is optional, and can be nullptr. | |
313 // | |
314 // TODO(gredner): remove this when --FLAGS_enable_async_get_proof is removed. | |
315 bool BuildServerConfigUpdateMessage( | |
316 QuicVersion version, | |
317 base::StringPiece chlo_hash, | |
318 const SourceAddressTokens& previous_source_address_tokens, | |
319 const IPAddress& server_ip, | |
320 const IPAddress& client_ip, | |
321 const QuicClock* clock, | |
322 QuicRandom* rand, | |
323 QuicCompressedCertsCache* compressed_certs_cache, | |
324 const QuicCryptoNegotiatedParameters& params, | |
325 const CachedNetworkParameters* cached_network_params, | |
326 CryptoHandshakeMessage* out) const; | |
327 | |
328 // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing | |
329 // the current primary config, an up to date source-address token, and cert | |
330 // chain and proof in the case of secure QUIC. Passes true to |cb| if the | |
331 // message was generated successfully, and false otherwise. This method | |
332 // assumes ownership of |cb|. | |
333 // | |
334 // |cached_network_params| is optional, and can be nullptr. | |
335 // | |
336 // TODO(gredner): This method is an async version of the above. The | |
337 // synchronous version will eventually be removed. | |
338 void BuildServerConfigUpdateMessage( | |
339 QuicVersion version, | |
340 base::StringPiece chlo_hash, | |
341 const SourceAddressTokens& previous_source_address_tokens, | |
342 const IPAddress& server_ip, | |
343 const IPAddress& client_ip, | |
344 const QuicClock* clock, | |
345 QuicRandom* rand, | |
346 QuicCompressedCertsCache* compressed_certs_cache, | |
347 const QuicCryptoNegotiatedParameters& params, | |
348 const CachedNetworkParameters* cached_network_params, | |
349 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; | |
350 | |
351 // SetEphemeralKeySource installs an object that can cache ephemeral keys for | |
352 // a short period of time. This object takes ownership of | |
353 // |ephemeral_key_source|. If not set then ephemeral keys will be generated | |
354 // per-connection. | |
355 void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source); | |
356 | |
357 // Install an externall created StrikeRegisterClient for use to | |
358 // interact with the strike register. This object takes ownership | |
359 // of the |strike_register_client|. | |
360 void SetStrikeRegisterClient(StrikeRegisterClient* strike_register_client); | |
361 | |
362 // set_replay_protection controls whether replay protection is enabled. If | |
363 // replay protection is disabled then no strike registers are needed and | |
364 // frontends can share an orbit value without a shared strike-register. | |
365 // However, an attacker can duplicate a handshake and cause a client's | |
366 // request to be processed twice. | |
367 void set_replay_protection(bool on); | |
368 | |
369 // set_chlo_multiplier specifies the multiple of the CHLO message size | |
370 // that a REJ message must stay under when the client doesn't present a | |
371 // valid source-address token. | |
372 void set_chlo_multiplier(size_t multiplier); | |
373 | |
374 // set_strike_register_no_startup_period configures the strike register to | |
375 // not have a startup period. | |
376 void set_strike_register_no_startup_period(); | |
377 | |
378 // set_strike_register_max_entries sets the maximum number of entries that | |
379 // the internal strike register will hold. If the strike register fills up | |
380 // then the oldest entries (by the client's clock) will be dropped. | |
381 void set_strike_register_max_entries(uint32_t max_entries); | |
382 | |
383 // set_strike_register_window_secs sets the number of seconds around the | |
384 // current time that the strike register will attempt to be authoritative | |
385 // for. Setting a larger value allows for greater client clock-skew, but | |
386 // means that the quiescent startup period must be longer. | |
387 void set_strike_register_window_secs(uint32_t window_secs); | |
388 | |
389 // set_source_address_token_future_secs sets the number of seconds into the | |
390 // future that source-address tokens will be accepted from. Since | |
391 // source-address tokens are authenticated, this should only happen if | |
392 // another, valid server has clock-skew. | |
393 void set_source_address_token_future_secs(uint32_t future_secs); | |
394 | |
395 // set_source_address_token_lifetime_secs sets the number of seconds that a | |
396 // source-address token will be valid for. | |
397 void set_source_address_token_lifetime_secs(uint32_t lifetime_secs); | |
398 | |
399 // set_server_nonce_strike_register_max_entries sets the number of entries in | |
400 // the server-nonce strike-register. This is used to record that server nonce | |
401 // values have been used. If the number of entries is too small then clients | |
402 // which are depending on server nonces may fail to handshake because their | |
403 // nonce has expired in the amount of time it took to go from the server to | |
404 // the client and back. | |
405 void set_server_nonce_strike_register_max_entries(uint32_t max_entries); | |
406 | |
407 // set_server_nonce_strike_register_window_secs sets the number of seconds | |
408 // around the current time that the server-nonce strike-register will accept | |
409 // nonces from. Setting a larger value allows for clients to delay follow-up | |
410 // client hellos for longer and still use server nonces as proofs of | |
411 // uniqueness. | |
412 void set_server_nonce_strike_register_window_secs(uint32_t window_secs); | |
413 | |
414 // set_enable_serving_sct enables or disables serving signed cert timestamp | |
415 // (RFC6962) in server hello. | |
416 void set_enable_serving_sct(bool enable_serving_sct); | |
417 | |
418 // Set and take ownership of the callback to invoke on primary config changes. | |
419 void AcquirePrimaryConfigChangedCb(PrimaryConfigChangedCallback* cb); | |
420 | |
421 // Returns the number of configs this object owns. | |
422 int NumberOfConfigs() const; | |
423 | |
424 private: | |
425 friend class test::QuicCryptoServerConfigPeer; | |
426 friend struct QuicCryptoProof; | |
427 | |
428 // Config represents a server config: a collection of preferences and | |
429 // Diffie-Hellman public values. | |
430 class NET_EXPORT_PRIVATE Config : public QuicCryptoConfig, | |
431 public base::RefCounted<Config> { | |
432 public: | |
433 Config(); | |
434 | |
435 // TODO(rtenneti): since this is a class, we should probably do | |
436 // getters/setters here. | |
437 // |serialized| contains the bytes of this server config, suitable for | |
438 // sending on the wire. | |
439 std::string serialized; | |
440 // id contains the SCID of this server config. | |
441 std::string id; | |
442 // orbit contains the orbit value for this config: an opaque identifier | |
443 // used to identify clusters of server frontends. | |
444 unsigned char orbit[kOrbitSize]; | |
445 | |
446 // key_exchanges contains key exchange objects with the private keys | |
447 // already loaded. The values correspond, one-to-one, with the tags in | |
448 // |kexs| from the parent class. | |
449 std::vector<KeyExchange*> key_exchanges; | |
450 | |
451 // tag_value_map contains the raw key/value pairs for the config. | |
452 QuicTagValueMap tag_value_map; | |
453 | |
454 // channel_id_enabled is true if the config in |serialized| specifies that | |
455 // ChannelIDs are supported. | |
456 bool channel_id_enabled; | |
457 | |
458 // is_primary is true if this config is the one that we'll give out to | |
459 // clients as the current one. | |
460 bool is_primary; | |
461 | |
462 // primary_time contains the timestamp when this config should become the | |
463 // primary config. A value of QuicWallTime::Zero() means that this config | |
464 // will not be promoted at a specific time. | |
465 QuicWallTime primary_time; | |
466 | |
467 // Secondary sort key for use when selecting primary configs and | |
468 // there are multiple configs with the same primary time. | |
469 // Smaller numbers mean higher priority. | |
470 uint64_t priority; | |
471 | |
472 // source_address_token_boxer_ is used to protect the | |
473 // source-address tokens that are given to clients. | |
474 // Points to either source_address_token_boxer_storage or the | |
475 // default boxer provided by QuicCryptoServerConfig. | |
476 const CryptoSecretBoxer* source_address_token_boxer; | |
477 | |
478 // Holds the override source_address_token_boxer instance if the | |
479 // Config is not using the default source address token boxer | |
480 // instance provided by QuicCryptoServerConfig. | |
481 std::unique_ptr<CryptoSecretBoxer> source_address_token_boxer_storage; | |
482 | |
483 private: | |
484 friend class base::RefCounted<Config>; | |
485 | |
486 virtual ~Config(); | |
487 | |
488 DISALLOW_COPY_AND_ASSIGN(Config); | |
489 }; | |
490 | |
491 typedef std::map<ServerConfigID, scoped_refptr<Config>> ConfigMap; | |
492 | |
493 // Get a ref to the config with a given server config id. | |
494 scoped_refptr<Config> GetConfigWithScid( | |
495 base::StringPiece requested_scid) const; | |
496 | |
497 // ConfigPrimaryTimeLessThan returns true if a->primary_time < | |
498 // b->primary_time. | |
499 static bool ConfigPrimaryTimeLessThan(const scoped_refptr<Config>& a, | |
500 const scoped_refptr<Config>& b); | |
501 | |
502 // SelectNewPrimaryConfig reevaluates the primary config based on the | |
503 // "primary_time" deadlines contained in each. | |
504 void SelectNewPrimaryConfig(QuicWallTime now) const; | |
505 | |
506 // EvaluateClientHello checks |client_hello| for gross errors and determines | |
507 // whether it can be shown to be fresh (i.e. not a replay). The results are | |
508 // written to |info|. | |
509 void EvaluateClientHello( | |
510 const IPAddress& server_ip, | |
511 QuicVersion version, | |
512 const uint8_t* primary_orbit, | |
513 scoped_refptr<Config> requested_config, | |
514 scoped_refptr<Config> primary_config, | |
515 QuicCryptoProof* crypto_proof, | |
516 ValidateClientHelloResultCallback::Result* client_hello_state, | |
517 ValidateClientHelloResultCallback* done_cb) const; | |
518 | |
519 // Callback class for bridging between EvaluateClientHello and | |
520 // EvaluateClientHelloAfterGetProof | |
521 friend class EvaluateClientHelloCallback; | |
522 | |
523 // Continuation of EvaluateClientHello after the call to | |
524 // ProofSource::GetProof. |found_error| indicates whether an error was | |
525 // detected in EvaluateClientHello, and |get_proof_failed| indicates whether | |
526 // GetProof failed. If GetProof was not run, then |get_proof_failed| will be | |
527 // set to false. | |
528 void EvaluateClientHelloAfterGetProof( | |
529 bool found_error, | |
530 const IPAddress& server_ip, | |
531 QuicVersion version, | |
532 const uint8_t* primary_orbit, | |
533 scoped_refptr<Config> requested_config, | |
534 scoped_refptr<Config> primary_config, | |
535 QuicCryptoProof* crypto_proof, | |
536 std::unique_ptr<ProofSource::Details> proof_source_details, | |
537 bool get_proof_failed, | |
538 ValidateClientHelloResultCallback::Result* client_hello_state, | |
539 ValidateClientHelloResultCallback* done_cb) const; | |
540 | |
541 // BuildRejection sets |out| to be a REJ message in reply to |client_hello|. | |
542 void BuildRejection(QuicVersion version, | |
543 const Config& config, | |
544 const CryptoHandshakeMessage& client_hello, | |
545 const ClientHelloInfo& info, | |
546 const CachedNetworkParameters& cached_network_params, | |
547 bool use_stateless_rejects, | |
548 QuicConnectionId server_designated_connection_id, | |
549 QuicRandom* rand, | |
550 QuicCompressedCertsCache* compressed_certs_cache, | |
551 QuicCryptoNegotiatedParameters* params, | |
552 const QuicCryptoProof& crypto_proof, | |
553 CryptoHandshakeMessage* out) const; | |
554 | |
555 // CompressChain compresses the certificates in |chain->certs| and returns a | |
556 // compressed representation. |common_sets| contains the common certificate | |
557 // sets known locally and |client_common_set_hashes| contains the hashes of | |
558 // the common sets known to the peer. |client_cached_cert_hashes| contains | |
559 // 64-bit, FNV-1a hashes of certificates that the peer already possesses. | |
560 static std::string CompressChain( | |
561 QuicCompressedCertsCache* compressed_certs_cache, | |
562 const scoped_refptr<ProofSource::Chain>& chain, | |
563 const std::string& client_common_set_hashes, | |
564 const std::string& client_cached_cert_hashes, | |
565 const CommonCertSets* common_sets); | |
566 | |
567 // ParseConfigProtobuf parses the given config protobuf and returns a | |
568 // scoped_refptr<Config> if successful. The caller adopts the reference to the | |
569 // Config. On error, ParseConfigProtobuf returns nullptr. | |
570 scoped_refptr<Config> ParseConfigProtobuf(QuicServerConfigProtobuf* protobuf); | |
571 | |
572 // NewSourceAddressToken returns a fresh source address token for the given | |
573 // IP address. |cached_network_params| is optional, and can be nullptr. | |
574 std::string NewSourceAddressToken( | |
575 const Config& config, | |
576 const SourceAddressTokens& previous_tokens, | |
577 const IPAddress& ip, | |
578 QuicRandom* rand, | |
579 QuicWallTime now, | |
580 const CachedNetworkParameters* cached_network_params) const; | |
581 | |
582 // ParseSourceAddressToken parses the source address tokens contained in | |
583 // the encrypted |token|, and populates |tokens| with the parsed tokens. | |
584 // Returns HANDSHAKE_OK if |token| could be parsed, or the reason for the | |
585 // failure. | |
586 HandshakeFailureReason ParseSourceAddressToken( | |
587 const Config& config, | |
588 base::StringPiece token, | |
589 SourceAddressTokens* tokens) const; | |
590 | |
591 // ValidateSourceAddressTokens returns HANDSHAKE_OK if the source address | |
592 // tokens in |tokens| contain a valid and timely token for the IP address | |
593 // |ip| given that the current time is |now|. Otherwise it returns the | |
594 // reason for failure. |cached_network_params| is populated if the valid | |
595 // token contains a CachedNetworkParameters proto. | |
596 HandshakeFailureReason ValidateSourceAddressTokens( | |
597 const SourceAddressTokens& tokens, | |
598 const IPAddress& ip, | |
599 QuicWallTime now, | |
600 CachedNetworkParameters* cached_network_params) const; | |
601 | |
602 // ValidateSingleSourceAddressToken returns HANDSHAKE_OK if the source | |
603 // address token in |token| is a timely token for the IP address |ip| | |
604 // given that the current time is |now|. Otherwise it returns the reason | |
605 // for failure. | |
606 HandshakeFailureReason ValidateSingleSourceAddressToken( | |
607 const SourceAddressToken& token, | |
608 const IPAddress& ip, | |
609 QuicWallTime now) const; | |
610 | |
611 // Returns HANDSHAKE_OK if the source address token in |token| is a timely | |
612 // token given that the current time is |now|. Otherwise it returns the | |
613 // reason for failure. | |
614 HandshakeFailureReason ValidateSourceAddressTokenTimestamp( | |
615 const SourceAddressToken& token, | |
616 QuicWallTime now) const; | |
617 | |
618 // NewServerNonce generates and encrypts a random nonce. | |
619 std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const; | |
620 | |
621 // ValidateServerNonce decrypts |token| and verifies that it hasn't been | |
622 // previously used and is recent enough that it is plausible that it was part | |
623 // of a very recently provided rejection ("recent" will be on the order of | |
624 // 10-30 seconds). If so, it records that it has been used and returns | |
625 // HANDSHAKE_OK. Otherwise it returns the reason for failure. | |
626 HandshakeFailureReason ValidateServerNonce( | |
627 base::StringPiece echoed_server_nonce, | |
628 QuicWallTime now) const; | |
629 | |
630 // ValidateExpectedLeafCertificate checks the |client_hello| to see if it has | |
631 // an XLCT tag, and if so, verifies that its value matches the hash of the | |
632 // server's leaf certificate. The certs field of |crypto_proof| is used to | |
633 // compare against the XLCT value. This method returns true if the XLCT tag | |
634 // is not present, or if the XLCT tag is present and valid. It returns false | |
635 // otherwise. | |
636 bool ValidateExpectedLeafCertificate( | |
637 const CryptoHandshakeMessage& client_hello, | |
638 const QuicCryptoProof& crypto_proof) const; | |
639 | |
640 // ParseProofDemand reads the PDMD field from the client hello and sets the | |
641 // |x509_ecdsa_supported| and |x509_supported| output parameters. | |
642 void ParseProofDemand(const CryptoHandshakeMessage& client_hello, | |
643 bool* x509_supported, | |
644 bool* x509_ecdsa_supported) const; | |
645 | |
646 // Callback to receive the results of ProofSource::GetProof. Note: this | |
647 // callback has no cancellation support, since the lifetime of the ProofSource | |
648 // is controlled by this object via unique ownership. If that ownership | |
649 // stricture changes, this decision may need to be revisited. | |
650 class BuildServerConfigUpdateMessageProofSourceCallback | |
651 : public ProofSource::Callback { | |
652 public: | |
653 BuildServerConfigUpdateMessageProofSourceCallback( | |
654 const BuildServerConfigUpdateMessageProofSourceCallback&) = delete; | |
655 ~BuildServerConfigUpdateMessageProofSourceCallback() override; | |
656 void operator=(const BuildServerConfigUpdateMessageProofSourceCallback&) = | |
657 delete; | |
658 BuildServerConfigUpdateMessageProofSourceCallback( | |
659 const QuicCryptoServerConfig* config, | |
660 QuicVersion version, | |
661 QuicCompressedCertsCache* compressed_certs_cache, | |
662 const CommonCertSets* common_cert_sets, | |
663 const QuicCryptoNegotiatedParameters& params, | |
664 CryptoHandshakeMessage message, | |
665 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb); | |
666 | |
667 void Run(bool ok, | |
668 const scoped_refptr<ProofSource::Chain>& chain, | |
669 const std::string& signature, | |
670 const std::string& leaf_cert_sct, | |
671 std::unique_ptr<ProofSource::Details> details) override; | |
672 | |
673 private: | |
674 const QuicCryptoServerConfig* config_; | |
675 const QuicVersion version_; | |
676 QuicCompressedCertsCache* compressed_certs_cache_; | |
677 const CommonCertSets* common_cert_sets_; | |
678 const std::string client_common_set_hashes_; | |
679 const std::string client_cached_cert_hashes_; | |
680 const bool sct_supported_by_client_; | |
681 CryptoHandshakeMessage message_; | |
682 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb_; | |
683 }; | |
684 | |
685 // Invoked by BuildServerConfigUpdateMessageProofSourceCallback::RunImpl once | |
686 // the proof has been acquired. Finishes building the server config update | |
687 // message and invokes |cb|. | |
688 void FinishBuildServerConfigUpdateMessage( | |
689 QuicVersion version, | |
690 QuicCompressedCertsCache* compressed_certs_cache, | |
691 const CommonCertSets* common_cert_sets, | |
692 const std::string& client_common_set_hashes, | |
693 const std::string& client_cached_cert_hashes, | |
694 bool sct_supported_by_client, | |
695 bool ok, | |
696 const scoped_refptr<ProofSource::Chain>& chain, | |
697 const std::string& signature, | |
698 const std::string& leaf_cert_sct, | |
699 std::unique_ptr<ProofSource::Details> details, | |
700 CryptoHandshakeMessage message, | |
701 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; | |
702 | |
703 // replay_protection_ controls whether the server enforces that handshakes | |
704 // aren't replays. | |
705 bool replay_protection_; | |
706 | |
707 // The multiple of the CHLO message size that a REJ message must stay under | |
708 // when the client doesn't present a valid source-address token. This is | |
709 // used to protect QUIC from amplification attacks. | |
710 size_t chlo_multiplier_; | |
711 | |
712 // configs_ satisfies the following invariants: | |
713 // 1) configs_.empty() <-> primary_config_ == nullptr | |
714 // 2) primary_config_ != nullptr -> primary_config_->is_primary | |
715 // 3) ∀ c∈configs_, c->is_primary <-> c == primary_config_ | |
716 mutable base::Lock configs_lock_; | |
717 // configs_ contains all active server configs. It's expected that there are | |
718 // about half-a-dozen configs active at any one time. | |
719 ConfigMap configs_; | |
720 // primary_config_ points to a Config (which is also in |configs_|) which is | |
721 // the primary config - i.e. the one that we'll give out to new clients. | |
722 mutable scoped_refptr<Config> primary_config_; | |
723 // next_config_promotion_time_ contains the nearest, future time when an | |
724 // active config will be promoted to primary. | |
725 mutable QuicWallTime next_config_promotion_time_; | |
726 // Callback to invoke when the primary config changes. | |
727 std::unique_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_; | |
728 | |
729 // Protects access to the pointer held by strike_register_client_. | |
730 mutable base::Lock strike_register_client_lock_; | |
731 // strike_register_ contains a data structure that keeps track of previously | |
732 // observed client nonces in order to prevent replay attacks. | |
733 mutable std::unique_ptr<StrikeRegisterClient> strike_register_client_; | |
734 | |
735 // Default source_address_token_boxer_ used to protect the | |
736 // source-address tokens that are given to clients. Individual | |
737 // configs may use boxers with alternate secrets. | |
738 CryptoSecretBoxer default_source_address_token_boxer_; | |
739 | |
740 // server_nonce_boxer_ is used to encrypt and validate suggested server | |
741 // nonces. | |
742 CryptoSecretBoxer server_nonce_boxer_; | |
743 | |
744 // server_nonce_orbit_ contains the random, per-server orbit values that this | |
745 // server will use to generate server nonces (the moral equivalent of a SYN | |
746 // cookies). | |
747 uint8_t server_nonce_orbit_[8]; | |
748 | |
749 mutable base::Lock server_nonce_strike_register_lock_; | |
750 // server_nonce_strike_register_ contains a data structure that keeps track of | |
751 // previously observed server nonces from this server, in order to prevent | |
752 // replay attacks. | |
753 mutable std::unique_ptr<StrikeRegister> server_nonce_strike_register_; | |
754 | |
755 // proof_source_ contains an object that can provide certificate chains and | |
756 // signatures. | |
757 std::unique_ptr<ProofSource> proof_source_; | |
758 | |
759 // ephemeral_key_source_ contains an object that caches ephemeral keys for a | |
760 // short period of time. | |
761 std::unique_ptr<EphemeralKeySource> ephemeral_key_source_; | |
762 | |
763 // These fields store configuration values. See the comments for their | |
764 // respective setter functions. | |
765 bool strike_register_no_startup_period_; | |
766 uint32_t strike_register_max_entries_; | |
767 uint32_t strike_register_window_secs_; | |
768 uint32_t source_address_token_future_secs_; | |
769 uint32_t source_address_token_lifetime_secs_; | |
770 uint32_t server_nonce_strike_register_max_entries_; | |
771 uint32_t server_nonce_strike_register_window_secs_; | |
772 | |
773 // Enable serving SCT or not. | |
774 bool enable_serving_sct_; | |
775 | |
776 DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerConfig); | |
777 }; | |
778 | |
779 struct NET_EXPORT_PRIVATE QuicCryptoProof { | |
780 QuicCryptoProof(); | |
781 ~QuicCryptoProof(); | |
782 | |
783 std::string signature; | |
784 scoped_refptr<ProofSource::Chain> chain; | |
785 std::string cert_sct; | |
786 // The server config that is used for this proof (and the rest of the | |
787 // request). | |
788 scoped_refptr<QuicCryptoServerConfig::Config> config; | |
789 std::string primary_scid; | |
790 }; | |
791 | |
792 } // namespace net | |
793 | |
794 #endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ | |
OLD | NEW |