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 QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ 6 #define QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ 7 8 #include <cstddef> 9 #include <cstdint> 10 #include <map> 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 #include "absl/strings/string_view.h" 16 #include "openssl/base.h" 17 #include "quiche/quic/core/crypto/crypto_handshake.h" 18 #include "quiche/quic/core/crypto/crypto_handshake_message.h" 19 #include "quiche/quic/core/crypto/crypto_protocol.h" 20 #include "quiche/quic/core/crypto/crypto_secret_boxer.h" 21 #include "quiche/quic/core/crypto/key_exchange.h" 22 #include "quiche/quic/core/crypto/proof_source.h" 23 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h" 24 #include "quiche/quic/core/crypto/quic_crypto_proof.h" 25 #include "quiche/quic/core/crypto/quic_random.h" 26 #include "quiche/quic/core/proto/cached_network_parameters_proto.h" 27 #include "quiche/quic/core/proto/source_address_token_proto.h" 28 #include "quiche/quic/core/quic_time.h" 29 #include "quiche/quic/platform/api/quic_export.h" 30 #include "quiche/quic/platform/api/quic_mutex.h" 31 #include "quiche/quic/platform/api/quic_socket_address.h" 32 #include "quiche/common/platform/api/quiche_reference_counted.h" 33 34 namespace quic { 35 36 class CryptoHandshakeMessage; 37 class ProofSource; 38 class QuicClock; 39 class QuicServerConfigProtobuf; 40 struct QuicSignedServerConfig; 41 42 // ClientHelloInfo contains information about a client hello message that is 43 // only kept for as long as it's being processed. 44 struct QUIC_EXPORT_PRIVATE ClientHelloInfo { 45 ClientHelloInfo(const QuicIpAddress& in_client_ip, QuicWallTime in_now); 46 ClientHelloInfo(const ClientHelloInfo& other); 47 ~ClientHelloInfo(); 48 49 // Inputs to EvaluateClientHello. 50 const QuicIpAddress client_ip; 51 const QuicWallTime now; 52 53 // Outputs from EvaluateClientHello. 54 bool valid_source_address_token; 55 absl::string_view sni; 56 absl::string_view client_nonce; 57 absl::string_view server_nonce; 58 absl::string_view user_agent_id; 59 SourceAddressTokens source_address_tokens; 60 61 // Errors from EvaluateClientHello. 62 std::vector<uint32_t> reject_reasons; 63 static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync"); 64 }; 65 66 namespace test { 67 class QuicCryptoServerConfigPeer; 68 } // namespace test 69 70 // Hook that allows application code to subscribe to primary config changes. 71 class QUIC_EXPORT_PRIVATE PrimaryConfigChangedCallback { 72 public: 73 PrimaryConfigChangedCallback(); 74 PrimaryConfigChangedCallback(const PrimaryConfigChangedCallback&) = delete; 75 PrimaryConfigChangedCallback& operator=(const PrimaryConfigChangedCallback&) = 76 delete; 77 virtual ~PrimaryConfigChangedCallback(); 78 virtual void Run(const std::string& scid) = 0; 79 }; 80 81 // Callback used to accept the result of the |client_hello| validation step. 82 class QUIC_EXPORT_PRIVATE ValidateClientHelloResultCallback { 83 public: 84 // Opaque token that holds information about the client_hello and 85 // its validity. Can be interpreted by calling ProcessClientHello. 86 struct QUIC_EXPORT_PRIVATE Result : public quiche::QuicheReferenceCounted { 87 Result(const CryptoHandshakeMessage& in_client_hello, 88 QuicIpAddress in_client_ip, QuicWallTime in_now); 89 90 CryptoHandshakeMessage client_hello; 91 ClientHelloInfo info; 92 QuicErrorCode error_code; 93 std::string error_details; 94 95 // Populated if the CHLO STK contained a CachedNetworkParameters proto. 96 CachedNetworkParameters cached_network_params; 97 98 protected: 99 ~Result() override; 100 }; 101 102 ValidateClientHelloResultCallback(); 103 ValidateClientHelloResultCallback(const ValidateClientHelloResultCallback&) = 104 delete; 105 ValidateClientHelloResultCallback& operator=( 106 const ValidateClientHelloResultCallback&) = delete; 107 virtual ~ValidateClientHelloResultCallback(); 108 virtual void Run(quiche::QuicheReferenceCountedPointer<Result> result, 109 std::unique_ptr<ProofSource::Details> details) = 0; 110 }; 111 112 // Callback used to accept the result of the ProcessClientHello method. 113 class QUIC_EXPORT_PRIVATE ProcessClientHelloResultCallback { 114 public: 115 ProcessClientHelloResultCallback(); 116 ProcessClientHelloResultCallback(const ProcessClientHelloResultCallback&) = 117 delete; 118 ProcessClientHelloResultCallback& operator=( 119 const ProcessClientHelloResultCallback&) = delete; 120 virtual ~ProcessClientHelloResultCallback(); 121 virtual void Run(QuicErrorCode error, const std::string& error_details, 122 std::unique_ptr<CryptoHandshakeMessage> message, 123 std::unique_ptr<DiversificationNonce> diversification_nonce, 124 std::unique_ptr<ProofSource::Details> details) = 0; 125 }; 126 127 // Callback used to receive the results of a call to 128 // BuildServerConfigUpdateMessage. 129 class QUIC_EXPORT_PRIVATE BuildServerConfigUpdateMessageResultCallback { 130 public: 131 BuildServerConfigUpdateMessageResultCallback() = default; ~BuildServerConfigUpdateMessageResultCallback()132 virtual ~BuildServerConfigUpdateMessageResultCallback() {} 133 BuildServerConfigUpdateMessageResultCallback( 134 const BuildServerConfigUpdateMessageResultCallback&) = delete; 135 BuildServerConfigUpdateMessageResultCallback& operator=( 136 const BuildServerConfigUpdateMessageResultCallback&) = delete; 137 virtual void Run(bool ok, const CryptoHandshakeMessage& message) = 0; 138 }; 139 140 // Object that is interested in built rejections (which include REJ, SREJ and 141 // cheap SREJ). 142 class QUIC_EXPORT_PRIVATE RejectionObserver { 143 public: 144 RejectionObserver() = default; ~RejectionObserver()145 virtual ~RejectionObserver() {} 146 RejectionObserver(const RejectionObserver&) = delete; 147 RejectionObserver& operator=(const RejectionObserver&) = delete; 148 // Called after a rejection is built. 149 virtual void OnRejectionBuilt(const std::vector<uint32_t>& reasons, 150 CryptoHandshakeMessage* out) const = 0; 151 }; 152 153 // Factory for creating KeyExchange objects. 154 class QUIC_EXPORT_PRIVATE KeyExchangeSource { 155 public: 156 virtual ~KeyExchangeSource() = default; 157 158 // Returns the default KeyExchangeSource. 159 static std::unique_ptr<KeyExchangeSource> Default(); 160 161 // Create a new KeyExchange using the curve specified by |type| using the 162 // specified private key. |private_key| may be empty for key-exchange 163 // mechanisms which do not hold the private key in-process. If |is_fallback| 164 // is set, |private_key| is required to be set, and a local key-exchange 165 // object should be returned. 166 virtual std::unique_ptr<AsynchronousKeyExchange> Create( 167 std::string server_config_id, bool is_fallback, QuicTag type, 168 absl::string_view private_key) = 0; 169 }; 170 171 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. 172 // Unlike a client, a QUIC server can have multiple configurations active in 173 // order to support clients resuming with a previous configuration. 174 // TODO(agl): when adding configurations at runtime is added, this object will 175 // need to consider locking. 176 class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { 177 public: 178 // ConfigOptions contains options for generating server configs. 179 struct QUIC_EXPORT_PRIVATE ConfigOptions { 180 ConfigOptions(); 181 ConfigOptions(const ConfigOptions& other); 182 ~ConfigOptions(); 183 184 // expiry_time is the time, in UNIX seconds, when the server config will 185 // expire. If unset, it defaults to the current time plus six months. 186 QuicWallTime expiry_time; 187 // channel_id_enabled controls whether the server config will indicate 188 // support for ChannelIDs. 189 bool channel_id_enabled; 190 // id contains the server config id for the resulting config. If empty, a 191 // random id is generated. 192 std::string id; 193 // orbit contains the kOrbitSize bytes of the orbit value for the server 194 // config. If |orbit| is empty then a random orbit is generated. 195 std::string orbit; 196 // p256 determines whether a P-256 public key will be included in the 197 // server config. Note that this breaks deterministic server-config 198 // generation since P-256 key generation doesn't use the QuicRandom given 199 // to GenerateConfig(). 200 bool p256; 201 }; 202 203 // |source_address_token_secret|: secret key material used for encrypting and 204 // decrypting source address tokens. It can be of any length as it is fed 205 // into a KDF before use. In tests, use TESTING. 206 // |server_nonce_entropy|: an entropy source used to generate the orbit and 207 // key for server nonces, which are always local to a given instance of a 208 // server. Not owned. 209 // |proof_source|: provides certificate chains and signatures. 210 // |key_exchange_source|: provides key-exchange functionality. 211 QuicCryptoServerConfig( 212 absl::string_view source_address_token_secret, 213 QuicRandom* server_nonce_entropy, 214 std::unique_ptr<ProofSource> proof_source, 215 std::unique_ptr<KeyExchangeSource> key_exchange_source); 216 QuicCryptoServerConfig(const QuicCryptoServerConfig&) = delete; 217 QuicCryptoServerConfig& operator=(const QuicCryptoServerConfig&) = delete; 218 ~QuicCryptoServerConfig(); 219 220 // TESTING is a magic parameter for passing to the constructor in tests. 221 static const char TESTING[]; 222 223 // Generates a QuicServerConfigProtobuf protobuf suitable for 224 // AddConfig and SetConfigs. 225 static QuicServerConfigProtobuf GenerateConfig(QuicRandom* rand, 226 const QuicClock* clock, 227 const ConfigOptions& options); 228 229 // AddConfig adds a QuicServerConfigProtobuf to the available configurations. 230 // It returns the SCFG message from the config if successful. |now| is used in 231 // conjunction with |protobuf->primary_time()| to determine whether the 232 // config should be made primary. 233 std::unique_ptr<CryptoHandshakeMessage> AddConfig( 234 const QuicServerConfigProtobuf& protobuf, QuicWallTime now); 235 236 // AddDefaultConfig calls GenerateConfig to create a config and then calls 237 // AddConfig to add it. See the comment for |GenerateConfig| for details of 238 // the arguments. 239 std::unique_ptr<CryptoHandshakeMessage> AddDefaultConfig( 240 QuicRandom* rand, const QuicClock* clock, const ConfigOptions& options); 241 242 // SetConfigs takes a vector of config protobufs and the current time. 243 // Configs are assumed to be uniquely identified by their server config ID. 244 // Previously unknown configs are added and possibly made the primary config 245 // depending on their |primary_time| and the value of |now|. Configs that are 246 // known, but are missing from the protobufs are deleted, unless they are 247 // currently the primary config. SetConfigs returns false if any errors were 248 // encountered and no changes to the QuicCryptoServerConfig will occur. 249 bool SetConfigs(const std::vector<QuicServerConfigProtobuf>& protobufs, 250 const QuicServerConfigProtobuf* fallback_protobuf, 251 QuicWallTime now); 252 253 // SetSourceAddressTokenKeys sets the keys to be tried, in order, when 254 // decrypting a source address token. Note that these keys are used *without* 255 // passing them through a KDF, in contradistinction to the 256 // |source_address_token_secret| argument to the constructor. 257 void SetSourceAddressTokenKeys(const std::vector<std::string>& keys); 258 259 // Get the server config ids for all known configs. 260 std::vector<std::string> GetConfigIds() const; 261 262 // Checks |client_hello| for gross errors and determines whether it can be 263 // shown to be fresh (i.e. not a replay). The result of the validation step 264 // must be interpreted by calling QuicCryptoServerConfig::ProcessClientHello 265 // from the done_cb. 266 // 267 // ValidateClientHello may invoke the done_cb before unrolling the 268 // stack if it is able to assess the validity of the client_nonce 269 // without asynchronous operations. 270 // 271 // client_hello: the incoming client hello message. 272 // client_ip: the IP address of the client, which is used to generate and 273 // validate source-address tokens. 274 // server_address: the IP address and port of the server. The IP address and 275 // port may be used for certificate selection. 276 // version: protocol version used for this connection. 277 // clock: used to validate client nonces and ephemeral keys. 278 // signed_config: in/out parameter to which will be written the crypto proof 279 // used in reply to a proof demand. The pointed-to-object must live until 280 // the callback is invoked. 281 // done_cb: single-use callback that accepts an opaque 282 // ValidatedClientHelloMsg token that holds information about 283 // the client hello. The callback will always be called exactly 284 // once, either under the current call stack, or after the 285 // completion of an asynchronous operation. 286 void ValidateClientHello( 287 const CryptoHandshakeMessage& client_hello, 288 const QuicSocketAddress& client_address, 289 const QuicSocketAddress& server_address, QuicTransportVersion version, 290 const QuicClock* clock, 291 quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> 292 signed_config, 293 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const; 294 295 // ProcessClientHello processes |client_hello| and decides whether to accept 296 // or reject the connection. If the connection is to be accepted, |done_cb| is 297 // invoked with the contents of the ServerHello and QUIC_NO_ERROR. Otherwise 298 // |done_cb| is called with a REJ or SREJ message and QUIC_NO_ERROR. 299 // 300 // validate_chlo_result: Output from the asynchronous call to 301 // ValidateClientHello. Contains the client hello message and 302 // information about it. 303 // reject_only: Only generate rejections, not server hello messages. 304 // connection_id: the ConnectionId for the connection, which is used in key 305 // derivation. 306 // server_ip: the IP address of the server. The IP address may be used for 307 // certificate selection. 308 // client_address: the IP address and port of the client. The IP address is 309 // used to generate and validate source-address tokens. 310 // version: version of the QUIC protocol in use for this connection 311 // supported_versions: versions of the QUIC protocol that this server 312 // supports. 313 // clock: used to validate client nonces and ephemeral keys. 314 // rand: an entropy source 315 // compressed_certs_cache: the cache that caches a set of most recently used 316 // certs. Owned by QuicDispatcher. 317 // params: the state of the handshake. This may be updated with a server 318 // nonce when we send a rejection. 319 // signed_config: output structure containing the crypto proof used in reply 320 // to a proof demand. 321 // total_framing_overhead: the total per-packet overhead for a stream frame 322 // chlo_packet_size: the size, in bytes, of the CHLO packet 323 // done_cb: the callback invoked on completion 324 void ProcessClientHello( 325 quiche::QuicheReferenceCountedPointer< 326 ValidateClientHelloResultCallback::Result> 327 validate_chlo_result, 328 bool reject_only, QuicConnectionId connection_id, 329 const QuicSocketAddress& server_address, 330 const QuicSocketAddress& client_address, ParsedQuicVersion version, 331 const ParsedQuicVersionVector& supported_versions, const QuicClock* clock, 332 QuicRandom* rand, QuicCompressedCertsCache* compressed_certs_cache, 333 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> 334 params, 335 quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> 336 signed_config, 337 QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size, 338 std::shared_ptr<ProcessClientHelloResultCallback> done_cb) const; 339 340 // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing 341 // the current primary config, an up to date source-address token, and cert 342 // chain and proof in the case of secure QUIC. Passes true to |cb| if the 343 // message was generated successfully, and false otherwise. This method 344 // assumes ownership of |cb|. 345 // 346 // |cached_network_params| is optional, and can be nullptr. 347 void BuildServerConfigUpdateMessage( 348 QuicTransportVersion version, absl::string_view chlo_hash, 349 const SourceAddressTokens& previous_source_address_tokens, 350 const QuicSocketAddress& server_address, 351 const QuicSocketAddress& client_address, const QuicClock* clock, 352 QuicRandom* rand, QuicCompressedCertsCache* compressed_certs_cache, 353 const QuicCryptoNegotiatedParameters& params, 354 const CachedNetworkParameters* cached_network_params, 355 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; 356 357 // set_replay_protection controls whether replay protection is enabled. If 358 // replay protection is disabled then no strike registers are needed and 359 // frontends can share an orbit value without a shared strike-register. 360 // However, an attacker can duplicate a handshake and cause a client's 361 // request to be processed twice. 362 void set_replay_protection(bool on); 363 364 // set_chlo_multiplier specifies the multiple of the CHLO message size 365 // that a REJ message must stay under when the client doesn't present a 366 // valid source-address token. 367 void set_chlo_multiplier(size_t multiplier); 368 369 // When sender is allowed to not pad client hello (not standards compliant), 370 // we need to disable the client hello check. set_validate_chlo_size(bool new_value)371 void set_validate_chlo_size(bool new_value) { 372 validate_chlo_size_ = new_value; 373 } 374 375 // Returns whether the sender is allowed to not pad the client hello. validate_chlo_size()376 bool validate_chlo_size() const { return validate_chlo_size_; } 377 378 // When QUIC is tunneled through some other mechanism, source token validation 379 // may be disabled. Do not disable it if you are not providing other 380 // protection. (|true| protects against UDP amplification attack.). set_validate_source_address_token(bool new_value)381 void set_validate_source_address_token(bool new_value) { 382 validate_source_address_token_ = new_value; 383 } 384 385 // set_source_address_token_future_secs sets the number of seconds into the 386 // future that source-address tokens will be accepted from. Since 387 // source-address tokens are authenticated, this should only happen if 388 // another, valid server has clock-skew. 389 void set_source_address_token_future_secs(uint32_t future_secs); 390 391 // set_source_address_token_lifetime_secs sets the number of seconds that a 392 // source-address token will be valid for. 393 void set_source_address_token_lifetime_secs(uint32_t lifetime_secs); 394 395 // set_enable_serving_sct enables or disables serving signed cert timestamp 396 // (RFC6962) in server hello. 397 void set_enable_serving_sct(bool enable_serving_sct); 398 399 // Set and take ownership of the callback to invoke on primary config changes. 400 void AcquirePrimaryConfigChangedCb( 401 std::unique_ptr<PrimaryConfigChangedCallback> cb); 402 403 // Returns the number of configs this object owns. 404 int NumberOfConfigs() const; 405 406 // NewSourceAddressToken returns a fresh source address token for the given 407 // IP address. |previous_tokens| is the received tokens, and can be empty. 408 // |cached_network_params| is optional, and can be nullptr. 409 std::string NewSourceAddressToken( 410 const CryptoSecretBoxer& crypto_secret_boxer, 411 const SourceAddressTokens& previous_tokens, const QuicIpAddress& ip, 412 QuicRandom* rand, QuicWallTime now, 413 const CachedNetworkParameters* cached_network_params) const; 414 415 // ParseSourceAddressToken parses the source address tokens contained in 416 // the encrypted |token|, and populates |tokens| with the parsed tokens. 417 // Returns HANDSHAKE_OK if |token| could be parsed, or the reason for the 418 // failure. 419 HandshakeFailureReason ParseSourceAddressToken( 420 const CryptoSecretBoxer& crypto_secret_boxer, absl::string_view token, 421 SourceAddressTokens& tokens) const; 422 423 // ValidateSourceAddressTokens returns HANDSHAKE_OK if the source address 424 // tokens in |tokens| contain a valid and timely token for the IP address 425 // |ip| given that the current time is |now|. Otherwise it returns the 426 // reason for failure. |cached_network_params| is populated if the valid 427 // token contains a CachedNetworkParameters proto. 428 HandshakeFailureReason ValidateSourceAddressTokens( 429 const SourceAddressTokens& tokens, const QuicIpAddress& ip, 430 QuicWallTime now, CachedNetworkParameters* cached_network_params) const; 431 432 // Callers retain the ownership of |rejection_observer| which must outlive the 433 // config. set_rejection_observer(RejectionObserver * rejection_observer)434 void set_rejection_observer(RejectionObserver* rejection_observer) { 435 rejection_observer_ = rejection_observer; 436 } 437 438 ProofSource* proof_source() const; 439 440 SSL_CTX* ssl_ctx() const; 441 442 // Pre-shared key used during the handshake. pre_shared_key()443 const std::string& pre_shared_key() const { return pre_shared_key_; } set_pre_shared_key(absl::string_view psk)444 void set_pre_shared_key(absl::string_view psk) { 445 pre_shared_key_ = std::string(psk); 446 } 447 pad_rej()448 bool pad_rej() const { return pad_rej_; } set_pad_rej(bool new_value)449 void set_pad_rej(bool new_value) { pad_rej_ = new_value; } 450 pad_shlo()451 bool pad_shlo() const { return pad_shlo_; } set_pad_shlo(bool new_value)452 void set_pad_shlo(bool new_value) { pad_shlo_ = new_value; } 453 source_address_token_boxer()454 const CryptoSecretBoxer& source_address_token_boxer() const { 455 return source_address_token_boxer_; 456 } 457 458 private: 459 friend class test::QuicCryptoServerConfigPeer; 460 friend struct QuicSignedServerConfig; 461 462 // Config represents a server config: a collection of preferences and 463 // Diffie-Hellman public values. 464 class QUIC_EXPORT_PRIVATE Config : public QuicCryptoConfig, 465 public quiche::QuicheReferenceCounted { 466 public: 467 Config(); 468 Config(const Config&) = delete; 469 Config& operator=(const Config&) = delete; 470 471 // TODO(rtenneti): since this is a class, we should probably do 472 // getters/setters here. 473 // |serialized| contains the bytes of this server config, suitable for 474 // sending on the wire. 475 std::string serialized; 476 // id contains the SCID of this server config. 477 std::string id; 478 // orbit contains the orbit value for this config: an opaque identifier 479 // used to identify clusters of server frontends. 480 unsigned char orbit[kOrbitSize]; 481 482 // key_exchanges contains key exchange objects. The values correspond, 483 // one-to-one, with the tags in |kexs| from the parent class. 484 std::vector<std::unique_ptr<AsynchronousKeyExchange>> key_exchanges; 485 486 // channel_id_enabled is true if the config in |serialized| specifies that 487 // ChannelIDs are supported. 488 bool channel_id_enabled; 489 490 // is_primary is true if this config is the one that we'll give out to 491 // clients as the current one. 492 bool is_primary; 493 494 // primary_time contains the timestamp when this config should become the 495 // primary config. A value of QuicWallTime::Zero() means that this config 496 // will not be promoted at a specific time. 497 QuicWallTime primary_time; 498 499 // expiry_time contains the timestamp when this config expires. 500 QuicWallTime expiry_time; 501 502 // Secondary sort key for use when selecting primary configs and 503 // there are multiple configs with the same primary time. 504 // Smaller numbers mean higher priority. 505 uint64_t priority; 506 507 // source_address_token_boxer_ is used to protect the 508 // source-address tokens that are given to clients. 509 // Points to either source_address_token_boxer_storage or the 510 // default boxer provided by QuicCryptoServerConfig. 511 const CryptoSecretBoxer* source_address_token_boxer; 512 513 // Holds the override source_address_token_boxer instance if the 514 // Config is not using the default source address token boxer 515 // instance provided by QuicCryptoServerConfig. 516 std::unique_ptr<CryptoSecretBoxer> source_address_token_boxer_storage; 517 518 private: 519 ~Config() override; 520 }; 521 522 using ConfigMap = 523 std::map<ServerConfigID, quiche::QuicheReferenceCountedPointer<Config>>; 524 525 // Get a ref to the config with a given server config id. 526 quiche::QuicheReferenceCountedPointer<Config> GetConfigWithScid( 527 absl::string_view requested_scid) const 528 QUIC_SHARED_LOCKS_REQUIRED(configs_lock_); 529 530 // A snapshot of the configs associated with an in-progress handshake. 531 struct QUIC_EXPORT_PRIVATE Configs { 532 quiche::QuicheReferenceCountedPointer<Config> requested; 533 quiche::QuicheReferenceCountedPointer<Config> primary; 534 quiche::QuicheReferenceCountedPointer<Config> fallback; 535 }; 536 537 // Get a snapshot of the current configs associated with a handshake. If this 538 // method was called earlier in this handshake |old_primary_config| should be 539 // set to the primary config returned from that invocation, otherwise nullptr. 540 // 541 // Returns true if any configs are loaded. If false is returned, |configs| is 542 // not modified. 543 bool GetCurrentConfigs( 544 const QuicWallTime& now, absl::string_view requested_scid, 545 quiche::QuicheReferenceCountedPointer<Config> old_primary_config, 546 Configs* configs) const; 547 548 // ConfigPrimaryTimeLessThan returns true if a->primary_time < 549 // b->primary_time. 550 static bool ConfigPrimaryTimeLessThan( 551 const quiche::QuicheReferenceCountedPointer<Config>& a, 552 const quiche::QuicheReferenceCountedPointer<Config>& b); 553 554 // SelectNewPrimaryConfig reevaluates the primary config based on the 555 // "primary_time" deadlines contained in each. 556 void SelectNewPrimaryConfig(QuicWallTime now) const 557 QUIC_EXCLUSIVE_LOCKS_REQUIRED(configs_lock_); 558 559 // EvaluateClientHello checks |client_hello_state->client_hello| for gross 560 // errors and determines whether it is fresh (i.e. not a replay). The results 561 // are written to |client_hello_state->info|. 562 void EvaluateClientHello( 563 const QuicSocketAddress& server_address, 564 const QuicSocketAddress& client_address, QuicTransportVersion version, 565 const Configs& configs, 566 quiche::QuicheReferenceCountedPointer< 567 ValidateClientHelloResultCallback::Result> 568 client_hello_state, 569 std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const; 570 571 // Convenience class which carries the arguments passed to 572 // |ProcessClientHellp| along. 573 class QUIC_EXPORT_PRIVATE ProcessClientHelloContext { 574 public: ProcessClientHelloContext(quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> validate_chlo_result,bool reject_only,QuicConnectionId connection_id,const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,ParsedQuicVersion version,const ParsedQuicVersionVector & supported_versions,const QuicClock * clock,QuicRandom * rand,QuicCompressedCertsCache * compressed_certs_cache,quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,QuicByteCount total_framing_overhead,QuicByteCount chlo_packet_size,std::shared_ptr<ProcessClientHelloResultCallback> done_cb)575 ProcessClientHelloContext( 576 quiche::QuicheReferenceCountedPointer< 577 ValidateClientHelloResultCallback::Result> 578 validate_chlo_result, 579 bool reject_only, QuicConnectionId connection_id, 580 const QuicSocketAddress& server_address, 581 const QuicSocketAddress& client_address, ParsedQuicVersion version, 582 const ParsedQuicVersionVector& supported_versions, 583 const QuicClock* clock, QuicRandom* rand, 584 QuicCompressedCertsCache* compressed_certs_cache, 585 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> 586 params, 587 quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> 588 signed_config, 589 QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size, 590 std::shared_ptr<ProcessClientHelloResultCallback> done_cb) 591 : validate_chlo_result_(validate_chlo_result), 592 reject_only_(reject_only), 593 connection_id_(connection_id), 594 server_address_(server_address), 595 client_address_(client_address), 596 version_(version), 597 supported_versions_(supported_versions), 598 clock_(clock), 599 rand_(rand), 600 compressed_certs_cache_(compressed_certs_cache), 601 params_(params), 602 signed_config_(signed_config), 603 total_framing_overhead_(total_framing_overhead), 604 chlo_packet_size_(chlo_packet_size), 605 done_cb_(std::move(done_cb)) {} 606 607 ~ProcessClientHelloContext(); 608 609 // Invoke |done_cb_| with an error status 610 void Fail(QuicErrorCode error, const std::string& error_details); 611 612 // Invoke |done_cb_| with a success status 613 void Succeed(std::unique_ptr<CryptoHandshakeMessage> message, 614 std::unique_ptr<DiversificationNonce> diversification_nonce, 615 std::unique_ptr<ProofSource::Details> proof_source_details); 616 617 // Member accessors 618 quiche::QuicheReferenceCountedPointer< 619 ValidateClientHelloResultCallback::Result> validate_chlo_result()620 validate_chlo_result() const { 621 return validate_chlo_result_; 622 } reject_only()623 bool reject_only() const { return reject_only_; } connection_id()624 QuicConnectionId connection_id() const { return connection_id_; } server_address()625 QuicSocketAddress server_address() const { return server_address_; } client_address()626 QuicSocketAddress client_address() const { return client_address_; } version()627 ParsedQuicVersion version() const { return version_; } supported_versions()628 ParsedQuicVersionVector supported_versions() const { 629 return supported_versions_; 630 } clock()631 const QuicClock* clock() const { return clock_; } rand()632 QuicRandom* rand() const { return rand_; } // NOLINT compressed_certs_cache()633 QuicCompressedCertsCache* compressed_certs_cache() const { 634 return compressed_certs_cache_; 635 } 636 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params()637 params() const { 638 return params_; 639 } 640 quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config()641 signed_config() const { 642 return signed_config_; 643 } total_framing_overhead()644 QuicByteCount total_framing_overhead() const { 645 return total_framing_overhead_; 646 } chlo_packet_size()647 QuicByteCount chlo_packet_size() const { return chlo_packet_size_; } 648 649 // Derived value accessors client_hello()650 const CryptoHandshakeMessage& client_hello() const { 651 return validate_chlo_result()->client_hello; 652 } info()653 const ClientHelloInfo& info() const { return validate_chlo_result()->info; } transport_version()654 QuicTransportVersion transport_version() const { 655 return version().transport_version; 656 } 657 658 private: 659 const quiche::QuicheReferenceCountedPointer< 660 ValidateClientHelloResultCallback::Result> 661 validate_chlo_result_; 662 const bool reject_only_; 663 const QuicConnectionId connection_id_; 664 const QuicSocketAddress server_address_; 665 const QuicSocketAddress client_address_; 666 const ParsedQuicVersion version_; 667 const ParsedQuicVersionVector supported_versions_; 668 const QuicClock* const clock_; 669 QuicRandom* const rand_; 670 QuicCompressedCertsCache* const compressed_certs_cache_; 671 const quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> 672 params_; 673 const quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> 674 signed_config_; 675 const QuicByteCount total_framing_overhead_; 676 const QuicByteCount chlo_packet_size_; 677 std::shared_ptr<ProcessClientHelloResultCallback> done_cb_; 678 }; 679 680 // Callback class for bridging between ProcessClientHello and 681 // ProcessClientHelloAfterGetProof. 682 class ProcessClientHelloCallback; 683 friend class ProcessClientHelloCallback; 684 685 // Portion of ProcessClientHello which executes after GetProof. 686 void ProcessClientHelloAfterGetProof( 687 bool found_error, 688 std::unique_ptr<ProofSource::Details> proof_source_details, 689 std::unique_ptr<ProcessClientHelloContext> context, 690 const Configs& configs) const; 691 692 // Callback class for bridging between ProcessClientHelloAfterGetProof and 693 // ProcessClientHelloAfterCalculateSharedKeys. 694 class ProcessClientHelloAfterGetProofCallback; 695 friend class ProcessClientHelloAfterGetProofCallback; 696 697 // Portion of ProcessClientHello which executes after CalculateSharedKeys. 698 void ProcessClientHelloAfterCalculateSharedKeys( 699 bool found_error, 700 std::unique_ptr<ProofSource::Details> proof_source_details, 701 QuicTag key_exchange_type, std::unique_ptr<CryptoHandshakeMessage> out, 702 absl::string_view public_value, 703 std::unique_ptr<ProcessClientHelloContext> context, 704 const Configs& configs) const; 705 706 // Send a REJ which contains a different ServerConfig than the one the client 707 // originally used. This is necessary in cases where we discover in the 708 // middle of the handshake that the private key for the ServerConfig the 709 // client used is not accessible. 710 void SendRejectWithFallbackConfig( 711 std::unique_ptr<ProcessClientHelloContext> context, 712 quiche::QuicheReferenceCountedPointer<Config> fallback_config) const; 713 714 // Callback class for bridging between SendRejectWithFallbackConfig and 715 // SendRejectWithFallbackConfigAfterGetProof. 716 class SendRejectWithFallbackConfigCallback; 717 friend class SendRejectWithFallbackConfigCallback; 718 719 // Portion of ProcessClientHello which executes after GetProof in the case 720 // where we have received a CHLO but need to reject it due to the ServerConfig 721 // private keys being inaccessible. 722 void SendRejectWithFallbackConfigAfterGetProof( 723 bool found_error, 724 std::unique_ptr<ProofSource::Details> proof_source_details, 725 std::unique_ptr<ProcessClientHelloContext> context, 726 quiche::QuicheReferenceCountedPointer<Config> fallback_config) const; 727 728 // BuildRejectionAndRecordStats calls |BuildRejection| below and also informs 729 // the RejectionObserver. 730 void BuildRejectionAndRecordStats(const ProcessClientHelloContext& context, 731 const Config& config, 732 const std::vector<uint32_t>& reject_reasons, 733 CryptoHandshakeMessage* out) const; 734 735 // BuildRejection sets |out| to be a REJ message in reply to |client_hello|. 736 void BuildRejection(const ProcessClientHelloContext& context, 737 const Config& config, 738 const std::vector<uint32_t>& reject_reasons, 739 CryptoHandshakeMessage* out) const; 740 741 // CompressChain compresses the certificates in |chain->certs| and returns a 742 // compressed representation. |client_cached_cert_hashes| contains 743 // 64-bit, FNV-1a hashes of certificates that the peer already possesses. 744 static std::string CompressChain( 745 QuicCompressedCertsCache* compressed_certs_cache, 746 const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain, 747 const std::string& client_cached_cert_hashes); 748 749 // ParseConfigProtobuf parses the given config protobuf and returns a 750 // quiche::QuicheReferenceCountedPointer<Config> if successful. The caller 751 // adopts the reference to the Config. On error, ParseConfigProtobuf returns 752 // nullptr. 753 quiche::QuicheReferenceCountedPointer<Config> ParseConfigProtobuf( 754 const QuicServerConfigProtobuf& protobuf, bool is_fallback) const; 755 756 // ValidateSingleSourceAddressToken returns HANDSHAKE_OK if the source 757 // address token in |token| is a timely token for the IP address |ip| 758 // given that the current time is |now|. Otherwise it returns the reason 759 // for failure. 760 HandshakeFailureReason ValidateSingleSourceAddressToken( 761 const SourceAddressToken& token, const QuicIpAddress& ip, 762 QuicWallTime now) const; 763 764 // Returns HANDSHAKE_OK if the source address token in |token| is a timely 765 // token given that the current time is |now|. Otherwise it returns the 766 // reason for failure. 767 HandshakeFailureReason ValidateSourceAddressTokenTimestamp( 768 const SourceAddressToken& token, QuicWallTime now) const; 769 770 // NewServerNonce generates and encrypts a random nonce. 771 std::string NewServerNonce(QuicRandom* rand, QuicWallTime now) const; 772 773 // ValidateExpectedLeafCertificate checks the |client_hello| to see if it has 774 // an XLCT tag, and if so, verifies that its value matches the hash of the 775 // server's leaf certificate. |certs| is used to compare against the XLCT 776 // value. This method returns true if the XLCT tag is not present, or if the 777 // XLCT tag is present and valid. It returns false otherwise. 778 bool ValidateExpectedLeafCertificate( 779 const CryptoHandshakeMessage& client_hello, 780 const std::vector<std::string>& certs) const; 781 782 // Callback to receive the results of ProofSource::GetProof. Note: this 783 // callback has no cancellation support, since the lifetime of the ProofSource 784 // is controlled by this object via unique ownership. If that ownership 785 // stricture changes, this decision may need to be revisited. 786 class BuildServerConfigUpdateMessageProofSourceCallback 787 : public ProofSource::Callback { 788 public: 789 BuildServerConfigUpdateMessageProofSourceCallback( 790 const BuildServerConfigUpdateMessageProofSourceCallback&) = delete; 791 ~BuildServerConfigUpdateMessageProofSourceCallback() override; 792 void operator=(const BuildServerConfigUpdateMessageProofSourceCallback&) = 793 delete; 794 BuildServerConfigUpdateMessageProofSourceCallback( 795 const QuicCryptoServerConfig* config, 796 QuicCompressedCertsCache* compressed_certs_cache, 797 const QuicCryptoNegotiatedParameters& params, 798 CryptoHandshakeMessage message, 799 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb); 800 801 void Run( 802 bool ok, 803 const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain, 804 const QuicCryptoProof& proof, 805 std::unique_ptr<ProofSource::Details> details) override; 806 807 private: 808 const QuicCryptoServerConfig* config_; 809 QuicCompressedCertsCache* compressed_certs_cache_; 810 const std::string client_cached_cert_hashes_; 811 const bool sct_supported_by_client_; 812 const std::string sni_; 813 CryptoHandshakeMessage message_; 814 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb_; 815 }; 816 817 // Invoked by BuildServerConfigUpdateMessageProofSourceCallback::Run once 818 // the proof has been acquired. Finishes building the server config update 819 // message and invokes |cb|. 820 void FinishBuildServerConfigUpdateMessage( 821 QuicCompressedCertsCache* compressed_certs_cache, 822 const std::string& client_cached_cert_hashes, 823 bool sct_supported_by_client, const std::string& sni, bool ok, 824 const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain, 825 const std::string& signature, const std::string& leaf_cert_sct, 826 std::unique_ptr<ProofSource::Details> details, 827 CryptoHandshakeMessage message, 828 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; 829 830 // Returns true if the next config promotion should happen now. 831 bool IsNextConfigReady(QuicWallTime now) const 832 QUIC_SHARED_LOCKS_REQUIRED(configs_lock_); 833 834 // replay_protection_ controls whether the server enforces that handshakes 835 // aren't replays. 836 bool replay_protection_; 837 838 // The multiple of the CHLO message size that a REJ message must stay under 839 // when the client doesn't present a valid source-address token. This is 840 // used to protect QUIC from amplification attacks. 841 size_t chlo_multiplier_; 842 843 // configs_ satisfies the following invariants: 844 // 1) configs_.empty() <-> primary_config_ == nullptr 845 // 2) primary_config_ != nullptr -> primary_config_->is_primary 846 // 3) ∀ c∈configs_, c->is_primary <-> c == primary_config_ 847 mutable QuicMutex configs_lock_; 848 849 // configs_ contains all active server configs. It's expected that there are 850 // about half-a-dozen configs active at any one time. 851 ConfigMap configs_ QUIC_GUARDED_BY(configs_lock_); 852 853 // primary_config_ points to a Config (which is also in |configs_|) which is 854 // the primary config - i.e. the one that we'll give out to new clients. 855 mutable quiche::QuicheReferenceCountedPointer<Config> primary_config_ 856 QUIC_GUARDED_BY(configs_lock_); 857 858 // fallback_config_ points to a Config (which is also in |configs_|) which is 859 // the fallback config, which will be used if the other configs are unuseable 860 // for some reason. 861 // 862 // TODO(b/112548056): This is currently always nullptr. 863 quiche::QuicheReferenceCountedPointer<Config> fallback_config_ 864 QUIC_GUARDED_BY(configs_lock_); 865 866 // next_config_promotion_time_ contains the nearest, future time when an 867 // active config will be promoted to primary. 868 mutable QuicWallTime next_config_promotion_time_ 869 QUIC_GUARDED_BY(configs_lock_); 870 871 // Callback to invoke when the primary config changes. 872 std::unique_ptr<PrimaryConfigChangedCallback> primary_config_changed_cb_ 873 QUIC_GUARDED_BY(configs_lock_); 874 875 // Used to protect the source-address tokens that are given to clients. 876 CryptoSecretBoxer source_address_token_boxer_; 877 878 // server_nonce_boxer_ is used to encrypt and validate suggested server 879 // nonces. 880 CryptoSecretBoxer server_nonce_boxer_; 881 882 // server_nonce_orbit_ contains the random, per-server orbit values that this 883 // server will use to generate server nonces (the moral equivalent of a SYN 884 // cookies). 885 uint8_t server_nonce_orbit_[8]; 886 887 // proof_source_ contains an object that can provide certificate chains and 888 // signatures. 889 std::unique_ptr<ProofSource> proof_source_; 890 891 // key_exchange_source_ contains an object that can provide key exchange 892 // objects. 893 std::unique_ptr<KeyExchangeSource> key_exchange_source_; 894 895 // ssl_ctx_ contains the server configuration for doing TLS handshakes. 896 bssl::UniquePtr<SSL_CTX> ssl_ctx_; 897 898 // These fields store configuration values. See the comments for their 899 // respective setter functions. 900 uint32_t source_address_token_future_secs_; 901 uint32_t source_address_token_lifetime_secs_; 902 903 // Enable serving SCT or not. 904 bool enable_serving_sct_; 905 906 // Does not own this observer. 907 RejectionObserver* rejection_observer_; 908 909 // If non-empty, the server will operate in the pre-shared key mode by 910 // incorporating |pre_shared_key_| into the key schedule. 911 std::string pre_shared_key_; 912 913 // Whether REJ message should be padded to max packet size. 914 bool pad_rej_; 915 916 // Whether SHLO message should be padded to max packet size. 917 bool pad_shlo_; 918 919 // If client is allowed to send a small client hello (by disabling padding), 920 // server MUST not check for the client hello size. 921 // DO NOT disable this unless you have some other way of validating client. 922 // (e.g. in realtime scenarios, where quic is tunneled through ICE, ICE will 923 // do its own peer validation using STUN pings with ufrag/upass). 924 bool validate_chlo_size_; 925 926 // When source address is validated by some other means (e.g. when using ICE), 927 // source address token validation may be disabled. 928 bool validate_source_address_token_; 929 }; 930 931 struct QUIC_EXPORT_PRIVATE QuicSignedServerConfig 932 : public quiche::QuicheReferenceCounted { 933 QuicSignedServerConfig(); 934 935 QuicCryptoProof proof; 936 quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain; 937 // The server config that is used for this proof (and the rest of the 938 // request). 939 quiche::QuicheReferenceCountedPointer<QuicCryptoServerConfig::Config> config; 940 std::string primary_scid; 941 942 protected: 943 ~QuicSignedServerConfig() override; 944 }; 945 946 } // namespace quic 947 948 #endif // QUICHE_QUIC_CORE_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_ 949