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