OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ | 5 #ifndef NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ |
6 #define NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ | 6 #define NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ |
7 | 7 |
8 #include <map> | 8 #include <map> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/strings/string_piece.h" | 13 #include "base/strings/string_piece.h" |
| 14 #include "base/synchronization/lock.h" |
14 #include "net/base/ip_endpoint.h" | 15 #include "net/base/ip_endpoint.h" |
15 #include "net/base/net_export.h" | 16 #include "net/base/net_export.h" |
16 #include "net/quic/crypto/crypto_protocol.h" | 17 #include "net/quic/crypto/crypto_protocol.h" |
17 #include "net/quic/quic_time.h" | 18 #include "net/quic/quic_time.h" |
18 | 19 |
19 namespace net { | 20 namespace net { |
20 | 21 |
21 class KeyExchange; | 22 class KeyExchange; |
22 class QuicClock; | 23 class QuicClock; |
23 class QuicDecrypter; | 24 class QuicDecrypter; |
24 class QuicEncrypter; | 25 class QuicEncrypter; |
25 class QuicRandom; | 26 class QuicRandom; |
26 class QuicServerConfigProtobuf; | 27 class QuicServerConfigProtobuf; |
| 28 class StrikeRegister; |
27 | 29 |
28 namespace test { | 30 namespace test { |
29 class QuicCryptoServerConfigPeer; | 31 class QuicCryptoServerConfigPeer; |
30 } // namespace test | 32 } // namespace test |
31 | 33 |
32 // An intermediate format of a handshake message that's convenient for a | 34 // An intermediate format of a handshake message that's convenient for a |
33 // CryptoFramer to serialize from or parse into. | 35 // CryptoFramer to serialize from or parse into. |
34 class NET_EXPORT_PRIVATE CryptoHandshakeMessage { | 36 class NET_EXPORT_PRIVATE CryptoHandshakeMessage { |
35 public: | 37 public: |
36 CryptoHandshakeMessage(); | 38 CryptoHandshakeMessage(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 QuicCryptoNegotiatedParameters(); | 216 QuicCryptoNegotiatedParameters(); |
215 ~QuicCryptoNegotiatedParameters(); | 217 ~QuicCryptoNegotiatedParameters(); |
216 | 218 |
217 uint16 version; | 219 uint16 version; |
218 CryptoTag key_exchange; | 220 CryptoTag key_exchange; |
219 CryptoTag aead; | 221 CryptoTag aead; |
220 std::string premaster_secret; | 222 std::string premaster_secret; |
221 scoped_ptr<QuicEncrypter> encrypter; | 223 scoped_ptr<QuicEncrypter> encrypter; |
222 scoped_ptr<QuicDecrypter> decrypter; | 224 scoped_ptr<QuicDecrypter> decrypter; |
223 std::string server_config_id; | 225 std::string server_config_id; |
| 226 std::string server_nonce; |
224 }; | 227 }; |
225 | 228 |
226 // QuicCryptoConfig contains common configuration between clients and servers. | 229 // QuicCryptoConfig contains common configuration between clients and servers. |
227 class NET_EXPORT_PRIVATE QuicCryptoConfig { | 230 class NET_EXPORT_PRIVATE QuicCryptoConfig { |
228 public: | 231 public: |
229 QuicCryptoConfig(); | 232 QuicCryptoConfig(); |
230 ~QuicCryptoConfig(); | 233 ~QuicCryptoConfig(); |
231 | 234 |
232 // Protocol version | 235 // Protocol version |
233 uint16 version; | 236 uint16 version; |
234 // Key exchange methods. The following two members' values correspond by | 237 // Key exchange methods. The following two members' values correspond by |
235 // index. | 238 // index. |
236 CryptoTagVector kexs; | 239 CryptoTagVector kexs; |
237 // Authenticated encryption with associated data (AEAD) algorithms. | 240 // Authenticated encryption with associated data (AEAD) algorithms. |
238 CryptoTagVector aead; | 241 CryptoTagVector aead; |
239 | 242 |
240 private: | 243 private: |
241 DISALLOW_COPY_AND_ASSIGN(QuicCryptoConfig); | 244 DISALLOW_COPY_AND_ASSIGN(QuicCryptoConfig); |
242 }; | 245 }; |
243 | 246 |
244 // QuicCryptoClientConfig contains crypto-related configuration settings for a | 247 // QuicCryptoClientConfig contains crypto-related configuration settings for a |
245 // client. | 248 // client. Note that this object isn't thread-safe. It's designed to be used on |
| 249 // a single thread at a time. |
246 class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig { | 250 class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig { |
247 public: | 251 public: |
248 // A CachedState contains the information that the client needs in order to | 252 // A CachedState contains the information that the client needs in order to |
249 // perform a 0-RTT handshake with a server. This information can be reused | 253 // perform a 0-RTT handshake with a server. This information can be reused |
250 // over several connections to the same server. | 254 // over several connections to the same server. |
251 class CachedState { | 255 class CachedState { |
252 public: | 256 public: |
253 CachedState(); | 257 CachedState(); |
254 ~CachedState(); | 258 ~CachedState(); |
255 | 259 |
256 // is_complete returns true if this object contains enough information to | 260 // is_complete returns true if this object contains enough information to |
257 // perform a handshake with the server. | 261 // perform a handshake with the server. |
258 bool is_complete() const; | 262 bool is_complete() const; |
259 | 263 |
260 // GetServerConfig returns the parsed contents of |server_config|, or NULL | 264 // GetServerConfig returns the parsed contents of |server_config|, or NULL |
261 // if |server_config| is empty. The return value is owned by this object | 265 // if |server_config| is empty. The return value is owned by this object |
262 // and is destroyed when this object is. | 266 // and is destroyed when this object is. |
263 const CryptoHandshakeMessage* GetServerConfig() const; | 267 const CryptoHandshakeMessage* GetServerConfig() const; |
264 | 268 |
265 // SetServerConfig checks that |scfg| parses correctly and stores it in | 269 // SetServerConfig checks that |scfg| parses correctly and stores it in |
266 // |server_config|. It returns true if the parsing succeeds and false | 270 // |server_config|. It returns true if the parsing succeeds and false |
267 // otherwise. | 271 // otherwise. |
268 bool SetServerConfig(base::StringPiece scfg); | 272 bool SetServerConfig(base::StringPiece scfg); |
269 | 273 |
270 const std::string& server_config() const; | 274 const std::string& server_config() const; |
271 const std::string& source_address_token() const; | 275 const std::string& source_address_token() const; |
272 const std::string& orbit() const; | |
273 | 276 |
274 void set_source_address_token(base::StringPiece token); | 277 void set_source_address_token(base::StringPiece token); |
275 | 278 |
276 private: | 279 private: |
277 std::string server_config_id_; // An opaque id from the server. | 280 std::string server_config_id_; // An opaque id from the server. |
278 std::string server_config_; // A serialized handshake message. | 281 std::string server_config_; // A serialized handshake message. |
279 std::string source_address_token_; // An opaque proof of IP ownership. | 282 std::string source_address_token_; // An opaque proof of IP ownership. |
280 std::string orbit_; // An opaque server-id used in nonce generation. | |
281 | 283 |
282 // scfg contains the cached, parsed value of |server_config|. | 284 // scfg contains the cached, parsed value of |server_config|. |
283 mutable scoped_ptr<CryptoHandshakeMessage> scfg_; | 285 mutable scoped_ptr<CryptoHandshakeMessage> scfg_; |
284 }; | 286 }; |
285 | 287 |
286 QuicCryptoClientConfig(); | 288 QuicCryptoClientConfig(); |
287 ~QuicCryptoClientConfig(); | 289 ~QuicCryptoClientConfig(); |
288 | 290 |
289 // Sets the members to reasonable, default values. | 291 // Sets the members to reasonable, default values. |
290 void SetDefaults(); | 292 void SetDefaults(); |
291 | 293 |
292 // Lookup returns a CachedState for the given hostname, or NULL if no | 294 // Lookup returns a CachedState for the given hostname, or NULL if no |
293 // information is known. | 295 // information is known. |
294 const CachedState* Lookup(const std::string& server_hostname); | 296 const CachedState* Lookup(const std::string& server_hostname) const; |
295 | 297 |
296 // FillInchoateClientHello sets |out| to be a CHLO message that elicits a | 298 // FillInchoateClientHello sets |out| to be a CHLO message that elicits a |
297 // source-address token or SCFG from a server. If |cached| is non-NULL, the | 299 // source-address token or SCFG from a server. If |cached| is non-NULL, the |
298 // source-address token will be taken from it. | 300 // source-address token will be taken from it. |
299 void FillInchoateClientHello(const std::string& server_hostname, | 301 void FillInchoateClientHello(const std::string& server_hostname, |
300 const CachedState* cached, | 302 const CachedState* cached, |
301 CryptoHandshakeMessage* out); | 303 CryptoHandshakeMessage* out) const; |
302 | 304 |
303 // FillClientHello sets |out| to be a CHLO message based on the configuration | 305 // FillClientHello sets |out| to be a CHLO message based on the configuration |
304 // of this object. This object must have cached enough information about | 306 // of this object. This object must have cached enough information about |
305 // |server_hostname| in order to perform a handshake. This can be checked | 307 // |server_hostname| in order to perform a handshake. This can be checked |
306 // with the |is_complete| member of |CachedState|. | 308 // with the |is_complete| member of |CachedState|. |
307 // | 309 // |
308 // |clock| and |rand| are used to generate the nonce and |out_params| is | 310 // |clock| and |rand| are used to generate the nonce and |out_params| is |
309 // filled with the results of the handshake that the server is expected to | 311 // filled with the results of the handshake that the server is expected to |
310 // accept. | 312 // accept. |
311 QuicErrorCode FillClientHello(const std::string& server_hostname, | 313 QuicErrorCode FillClientHello(const std::string& server_hostname, |
312 QuicGuid guid, | 314 QuicGuid guid, |
313 const CachedState* cached, | 315 const CachedState* cached, |
314 const QuicClock* clock, | 316 const QuicClock* clock, |
315 QuicRandom* rand, | 317 QuicRandom* rand, |
316 QuicCryptoNegotiatedParameters* out_params, | 318 QuicCryptoNegotiatedParameters* out_params, |
317 CryptoHandshakeMessage* out, | 319 CryptoHandshakeMessage* out, |
318 std::string* error_details); | 320 std::string* error_details) const; |
319 | 321 |
320 // ProcessRejection processes a REJ message from a server and updates the | 322 // ProcessRejection processes a REJ message from a server and updates the |
321 // cached information about that server. After this, |is_complete| may return | 323 // cached information about that server. After this, |is_complete| may return |
322 // true for that server's CachedState. | 324 // true for that server's CachedState. If the rejection message contains |
| 325 // state about a future handshake (i.e. an nonce value from the server), then |
| 326 // it will be saved in |out_params|. |
323 QuicErrorCode ProcessRejection(const std::string& server_hostname, | 327 QuicErrorCode ProcessRejection(const std::string& server_hostname, |
324 const CryptoHandshakeMessage& rej, | 328 const CryptoHandshakeMessage& rej, |
| 329 QuicCryptoNegotiatedParameters* out_params, |
325 std::string* error_details); | 330 std::string* error_details); |
326 | 331 |
327 // ProcessServerHello processes the message in |server_hello|, writes the | 332 // ProcessServerHello processes the message in |server_hello|, writes the |
328 // negotiated parameters to |out_params| and returns QUIC_NO_ERROR. If | 333 // negotiated parameters to |out_params| and returns QUIC_NO_ERROR. If |
329 // |server_hello| is unacceptable then it puts an error message in | 334 // |server_hello| is unacceptable then it puts an error message in |
330 // |error_details| and returns an error code. | 335 // |error_details| and returns an error code. |
331 QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello, | 336 QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello, |
332 const std::string& nonce, | 337 const std::string& nonce, |
333 QuicCryptoNegotiatedParameters* out_params, | 338 QuicCryptoNegotiatedParameters* out_params, |
334 std::string* error_details); | 339 std::string* error_details); |
335 | 340 |
336 private: | 341 private: |
337 // cached_states_ maps from the server hostname to the cached information | 342 // cached_states_ maps from the server hostname to the cached information |
338 // about that server. | 343 // about that server. |
339 std::map<std::string, CachedState*> cached_states_; | 344 std::map<std::string, CachedState*> cached_states_; |
340 }; | 345 }; |
341 | 346 |
342 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. | 347 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. |
343 // Unlike a client, a QUIC server can have multiple configurations active in | 348 // Unlike a client, a QUIC server can have multiple configurations active in |
344 // order to support clients resuming with a previous configuration. | 349 // order to support clients resuming with a previous configuration. |
345 // TODO(agl): when adding configurations at runtime is added, this object will | 350 // TODO(agl): when adding configurations at runtime is added, this object will |
346 // need to consider locking. | 351 // need to consider locking. |
347 class NET_EXPORT_PRIVATE QuicCryptoServerConfig { | 352 class NET_EXPORT_PRIVATE QuicCryptoServerConfig { |
348 public: | 353 public: |
349 // |source_address_token_secret|: secret key material used for encrypting and | 354 // |source_address_token_secret|: secret key material used for encrypting and |
350 // decrypting source address tokens. It can be of any length as it is fed | 355 // decrypting source address tokens. It can be of any length as it is fed |
351 // into a KDF before use. | 356 // into a KDF before use. In tests, use TESTING. |
352 explicit QuicCryptoServerConfig( | 357 explicit QuicCryptoServerConfig( |
353 base::StringPiece source_address_token_secret); | 358 base::StringPiece source_address_token_secret); |
354 ~QuicCryptoServerConfig(); | 359 ~QuicCryptoServerConfig(); |
355 | 360 |
356 // TESTING is a magic parameter for passing to the constructor in tests. | 361 // TESTING is a magic parameter for passing to the constructor in tests. |
357 static const char TESTING[]; | 362 static const char TESTING[]; |
358 | 363 |
359 // ConfigForTesting generates a QuicServerConfigProtobuf protobuf suitable | 364 // DefaultConfig generates a QuicServerConfigProtobuf protobuf suitable |
360 // for using in tests. |extra_tags| contains additional key/value pairs that | 365 // for using in tests. |extra_tags| contains additional key/value pairs that |
361 // will be inserted into the config. | 366 // will be inserted into the config. |
362 static QuicServerConfigProtobuf* ConfigForTesting( | 367 static QuicServerConfigProtobuf* DefaultConfig( |
363 QuicRandom* rand, | 368 QuicRandom* rand, |
364 const QuicClock* clock, | 369 const QuicClock* clock, |
365 const CryptoHandshakeMessage& extra_tags); | 370 const CryptoHandshakeMessage& extra_tags); |
366 | 371 |
367 // AddConfig adds a QuicServerConfigProtobuf to the availible configurations. | 372 // AddConfig adds a QuicServerConfigProtobuf to the availible configurations. |
368 // It returns the SCFG message from the config if successful. The caller | 373 // It returns the SCFG message from the config if successful. The caller |
369 // takes ownership of the CryptoHandshakeMessage. | 374 // takes ownership of the CryptoHandshakeMessage. |
370 CryptoHandshakeMessage* AddConfig(QuicServerConfigProtobuf* protobuf); | 375 CryptoHandshakeMessage* AddConfig(QuicServerConfigProtobuf* protobuf); |
371 | 376 |
372 // AddTestingConfig creates a test config and then calls AddConfig to add it. | 377 // AddDefaultConfig creates a config and then calls AddConfig to |
373 // Any tags in |extra_tags| will be copied into the config. | 378 // add it. Any tags in |extra_tags| will be copied into the config. |
374 CryptoHandshakeMessage* AddTestingConfig( | 379 CryptoHandshakeMessage* AddDefaultConfig( |
375 QuicRandom* rand, | 380 QuicRandom* rand, |
376 const QuicClock* clock, | 381 const QuicClock* clock, |
377 const CryptoHandshakeMessage& extra_tags); | 382 const CryptoHandshakeMessage& extra_tags); |
378 | 383 |
379 // ProcessClientHello processes |client_hello| and decides whether to accept | 384 // ProcessClientHello processes |client_hello| and decides whether to accept |
380 // or reject the connection. If the connection is to be accepted, |out| is | 385 // or reject the connection. If the connection is to be accepted, |out| is |
381 // set to the contents of the ServerHello, |out_params| is completed and | 386 // set to the contents of the ServerHello, |out_params| is completed and |
382 // QUIC_NO_ERROR is returned. Otherwise |out| is set to be a REJ message and | 387 // QUIC_NO_ERROR is returned. Otherwise |out| is set to be a REJ message and |
383 // an error code is returned. | 388 // an error code is returned. |
384 // | 389 // |
385 // client_hello: the incoming client hello message. | 390 // client_hello: the incoming client hello message. |
386 // guid: the GUID for the connection, which is used in key derivation. | 391 // guid: the GUID for the connection, which is used in key derivation. |
387 // client_ip: the IP address of the client, which is used to generate and | 392 // client_ip: the IP address of the client, which is used to generate and |
388 // validate source-address tokens. | 393 // validate source-address tokens. |
389 // now_since_epoch: the current time, as a delta since the unix epoch, | 394 // now_since_epoch: the current time, as a delta since the unix epoch, |
390 // which is used to validate client nonces. | 395 // which is used to validate client nonces. |
391 // rand: an entropy source | 396 // rand: an entropy source |
| 397 // params: the state of the handshake. This may be updated with a server |
| 398 // nonce when we send a rejection. After a successful handshake, this will |
| 399 // contain the state of the connection. |
392 // out: the resulting handshake message (either REJ or SHLO) | 400 // out: the resulting handshake message (either REJ or SHLO) |
393 // out_params: the state of the handshake | |
394 // error_details: used to store a string describing any error. | 401 // error_details: used to store a string describing any error. |
395 QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello, | 402 QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello, |
396 QuicGuid guid, | 403 QuicGuid guid, |
397 const IPEndPoint& client_ip, | 404 const IPEndPoint& client_ip, |
398 QuicTime::Delta now_since_epoch, | 405 QuicTime::Delta now_since_epoch, |
399 QuicRandom* rand, | 406 QuicRandom* rand, |
| 407 QuicCryptoNegotiatedParameters* params, |
400 CryptoHandshakeMessage* out, | 408 CryptoHandshakeMessage* out, |
401 QuicCryptoNegotiatedParameters* out_params, | 409 std::string* error_details) const; |
402 std::string* error_details); | |
403 | 410 |
404 private: | 411 private: |
405 friend class test::QuicCryptoServerConfigPeer; | 412 friend class test::QuicCryptoServerConfigPeer; |
406 | 413 |
407 // Config represents a server config: a collection of preferences and | 414 // Config represents a server config: a collection of preferences and |
408 // Diffie-Hellman public values. | 415 // Diffie-Hellman public values. |
409 struct Config : public QuicCryptoConfig { | 416 struct Config : public QuicCryptoConfig { |
410 Config(); | 417 Config(); |
411 ~Config(); | 418 ~Config(); |
412 | 419 |
413 // serialized contains the bytes of this server config, suitable for sending | 420 // serialized contains the bytes of this server config, suitable for sending |
414 // on the wire. | 421 // on the wire. |
415 std::string serialized; | 422 std::string serialized; |
416 // id contains the SCID of this server config. | 423 // id contains the SCID of this server config. |
417 std::string id; | 424 std::string id; |
| 425 // orbit contains the orbit value for this config: an opaque identifier |
| 426 // used to identify clusters of server frontends. |
| 427 unsigned char orbit[kOrbitSize]; |
418 | 428 |
419 // key_exchanges contains key exchange objects with the private keys | 429 // key_exchanges contains key exchange objects with the private keys |
420 // already loaded. The values correspond, one-to-one, with the tags in | 430 // already loaded. The values correspond, one-to-one, with the tags in |
421 // |kexs| from the parent class. | 431 // |kexs| from the parent class. |
422 std::vector<KeyExchange*> key_exchanges; | 432 std::vector<KeyExchange*> key_exchanges; |
423 | 433 |
424 // tag_value_map contains the raw key/value pairs for the config. | 434 // tag_value_map contains the raw key/value pairs for the config. |
425 CryptoTagValueMap tag_value_map; | 435 CryptoTagValueMap tag_value_map; |
426 | 436 |
427 private: | 437 private: |
428 DISALLOW_COPY_AND_ASSIGN(Config); | 438 DISALLOW_COPY_AND_ASSIGN(Config); |
429 }; | 439 }; |
430 | 440 |
431 // NewSourceAddressToken returns a fresh source address token for the given | 441 // NewSourceAddressToken returns a fresh source address token for the given |
432 // IP address. | 442 // IP address. |
433 std::string NewSourceAddressToken(const IPEndPoint& ip, | 443 std::string NewSourceAddressToken(const IPEndPoint& ip, |
434 QuicRandom* rand, | 444 QuicRandom* rand, |
435 QuicTime::Delta now_since_epoch); | 445 QuicTime::Delta now_since_epoch) const; |
436 | 446 |
437 // ValidateSourceAddressToken returns true if the source address token in | 447 // ValidateSourceAddressToken returns true if the source address token in |
438 // |token| is a valid and timely token for the IP address |ip| given that the | 448 // |token| is a valid and timely token for the IP address |ip| given that the |
439 // current time is |now|. | 449 // current time is |now|. |
440 bool ValidateSourceAddressToken(base::StringPiece token, | 450 bool ValidateSourceAddressToken(base::StringPiece token, |
441 const IPEndPoint& ip, | 451 const IPEndPoint& ip, |
442 QuicTime::Delta now_since_epoch); | 452 QuicTime::Delta now_since_epoch) const; |
443 | 453 |
444 std::map<ServerConfigID, Config*> configs_; | 454 std::map<ServerConfigID, Config*> configs_; |
445 | 455 |
446 ServerConfigID active_config_; | 456 ServerConfigID active_config_; |
447 | 457 |
| 458 mutable base::Lock strike_register_lock_; |
| 459 // strike_register_ contains a data structure that keeps track of previously |
| 460 // observed client nonces in order to prevent replay attacks. |
| 461 mutable scoped_ptr<StrikeRegister> strike_register_; |
| 462 |
448 // These members are used to encrypt and decrypt the source address tokens | 463 // These members are used to encrypt and decrypt the source address tokens |
449 // that we receive from and send to clients. | 464 // that we receive from and send to clients. |
450 scoped_ptr<QuicEncrypter> source_address_token_encrypter_; | 465 scoped_ptr<QuicEncrypter> source_address_token_encrypter_; |
451 scoped_ptr<QuicDecrypter> source_address_token_decrypter_; | 466 scoped_ptr<QuicDecrypter> source_address_token_decrypter_; |
452 }; | 467 }; |
453 | 468 |
454 } // namespace net | 469 } // namespace net |
455 | 470 |
456 #endif // NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ | 471 #endif // NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ |
OLD | NEW |