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