No public description PiperOrigin-RevId: 606821319
diff --git a/quiche/quic/core/crypto/proof_source.h b/quiche/quic/core/crypto/proof_source.h index b963034..b2a9738 100644 --- a/quiche/quic/core/crypto/proof_source.h +++ b/quiche/quic/core/crypto/proof_source.h
@@ -5,17 +5,26 @@ #ifndef QUICHE_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_ #define QUICHE_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_ +#include <cstddef> +#include <cstdint> #include <memory> +#include <optional> #include <string> #include <vector> +#include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "absl/types/variant.h" +#include "openssl/base.h" +#include "openssl/pool.h" #include "openssl/ssl.h" #include "quiche/quic/core/crypto/certificate_view.h" #include "quiche/quic/core/crypto/quic_crypto_proof.h" +#include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_reference_counted.h" namespace quic { @@ -245,27 +254,44 @@ public: virtual ~ProofSourceHandleCallback() = default; + // Configuration to use for configuring the SSL object when handshaking + // locally. + struct LocalSSLConfig { + const ProofSource::Chain* chain; + QuicDelayedSSLConfig delayed_ssl_config; + }; + + // Functor to call to configure the SSL object. This functor must not be + // called more than once. + using ConfigureSSLFunc = + std::function<absl::Status(SSL& ssl, const SSL_PRIVATE_KEY_METHOD& key)>; + + // Configuration to use for configuring the SSL object when using a + // handshake-hints server. + struct HintsSSLConfig { + ConfigureSSLFunc configure_ssl; + QuicDelayedSSLConfig delayed_ssl_config; + }; + + using SSLConfig = absl::variant<LocalSSLConfig, HintsSSLConfig>; + // Called when a ProofSourceHandle::SelectCertificate operation completes. // |ok| indicates whether the operation was successful. // |is_sync| indicates whether the operation completed synchronously, i.e. // whether it is completed before ProofSourceHandle::SelectCertificate // returned. - // |chain| the certificate chain in leaf-first order. - // |handshake_hints| (optional) handshake hints that can be used by - // SSL_set_handshake_hints. + // |ssl_config| configuration used to configure the SSL object. // |ticket_encryption_key| (optional) encryption key to be used for minting // TLS resumption tickets. // |cert_matched_sni| is true if the certificate matched the SNI hostname, // false if a non-matching default cert was used. - // |delayed_ssl_config| contains SSL configs to be applied on the SSL object. // // When called asynchronously(is_sync=false), this method will be responsible // to continue the handshake from where it left off. - virtual void OnSelectCertificateDone( - bool ok, bool is_sync, const ProofSource::Chain* chain, - absl::string_view handshake_hints, - absl::string_view ticket_encryption_key, bool cert_matched_sni, - QuicDelayedSSLConfig delayed_ssl_config) = 0; + virtual void OnSelectCertificateDone(bool ok, bool is_sync, + SSLConfig ssl_config, + absl::string_view ticket_encryption_key, + bool cert_matched_sni) = 0; // Called when a ProofSourceHandle::ComputeSignature operation completes. virtual void OnComputeSignatureDone(
diff --git a/quiche/quic/core/crypto/tls_server_connection.cc b/quiche/quic/core/crypto/tls_server_connection.cc index 51311bc..9bf6dca 100644 --- a/quiche/quic/core/crypto/tls_server_connection.cc +++ b/quiche/quic/core/crypto/tls_server_connection.cc
@@ -4,12 +4,20 @@ #include "quiche/quic/core/crypto/tls_server_connection.h" +#include <cstddef> +#include <cstdint> +#include <utility> +#include <vector> + +#include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "openssl/base.h" #include "openssl/ssl.h" #include "quiche/quic/core/crypto/proof_source.h" +#include "quiche/quic/core/crypto/tls_connection.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_flag_utils.h" -#include "quiche/quic/platform/api/quic_flags.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -59,6 +67,12 @@ return ssl_ctx; } +absl::Status TlsServerConnection::ConfigureSSL( + ProofSourceHandleCallback::ConfigureSSLFunc configure_ssl) { + return std::move(configure_ssl)(*ssl(), // never nullptr + TlsServerConnection::kPrivateKeyMethod); +} + void TlsServerConnection::SetCertChain( const std::vector<CRYPTO_BUFFER*>& cert_chain) { SSL_set_chain_and_key(ssl(), cert_chain.data(), cert_chain.size(), nullptr,
diff --git a/quiche/quic/core/crypto/tls_server_connection.h b/quiche/quic/core/crypto/tls_server_connection.h index bdb58be..9301f2c 100644 --- a/quiche/quic/core/crypto/tls_server_connection.h +++ b/quiche/quic/core/crypto/tls_server_connection.h
@@ -5,9 +5,18 @@ #ifndef QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_ #define QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_ +#include <cstddef> +#include <cstdint> +#include <vector> + +#include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "openssl/base.h" +#include "openssl/ssl.h" #include "quiche/quic/core/crypto/proof_source.h" #include "quiche/quic/core/crypto/tls_connection.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/common/platform/api/quiche_export.h" namespace quic { @@ -120,6 +129,10 @@ // Creates and configures an SSL_CTX that is appropriate for servers to use. static bssl::UniquePtr<SSL_CTX> CreateSslCtx(ProofSource* proof_source); + // Invoke |configure_ssl| to configure the SSL object. + absl::Status ConfigureSSL( + ProofSourceHandleCallback::ConfigureSSLFunc configure_ssl); + void SetCertChain(const std::vector<CRYPTO_BUFFER*>& cert_chain); // Set the client cert mode to be used on this connection. This should be
diff --git a/quiche/quic/core/tls_server_handshaker.cc b/quiche/quic/core/tls_server_handshaker.cc index d819703..bc378fc 100644 --- a/quiche/quic/core/tls_server_handshaker.cc +++ b/quiche/quic/core/tls_server_handshaker.cc
@@ -4,25 +4,56 @@ #include "quiche/quic/core/tls_server_handshaker.h" +#include <cstddef> +#include <cstdint> +#include <cstring> #include <memory> +#include <optional> #include <string> +#include <utility> +#include <variant> +#include <vector> -#include "absl/base/macros.h" +#include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" -#include "openssl/pool.h" +#include "absl/types/span.h" +#include "absl/types/variant.h" +#include "openssl/base.h" +#include "openssl/bytestring.h" #include "openssl/ssl.h" +#include "openssl/tls1.h" +#include "quiche/quic/core/crypto/crypto_handshake.h" +#include "quiche/quic/core/crypto/crypto_message_parser.h" +#include "quiche/quic/core/crypto/crypto_utils.h" +#include "quiche/quic/core/crypto/proof_source.h" +#include "quiche/quic/core/crypto/proof_verifier.h" #include "quiche/quic/core/crypto/quic_crypto_server_config.h" +#include "quiche/quic/core/crypto/quic_decrypter.h" +#include "quiche/quic/core/crypto/quic_encrypter.h" #include "quiche/quic/core/crypto/transport_parameters.h" #include "quiche/quic/core/http/http_encoder.h" #include "quiche/quic/core/http/http_frames.h" +#include "quiche/quic/core/quic_config.h" +#include "quiche/quic/core/quic_connection.h" +#include "quiche/quic/core/quic_connection_context.h" +#include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_connection_stats.h" +#include "quiche/quic/core/quic_crypto_server_stream_base.h" +#include "quiche/quic/core/quic_error_codes.h" +#include "quiche/quic/core/quic_session.h" #include "quiche/quic/core/quic_time.h" +#include "quiche/quic/core/quic_time_accumulator.h" #include "quiche/quic/core/quic_types.h" +#include "quiche/quic/core/quic_versions.h" +#include "quiche/quic/core/tls_handshaker.h" +#include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_flag_utils.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_hostname_utils.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_server_stats.h" +#include "quiche/quic/platform/api/quic_socket_address.h" #define RECORD_LATENCY_IN_US(stat_name, latency, comment) \ do { \ @@ -81,10 +112,10 @@ &cert_matched_sni); handshaker_->OnSelectCertificateDone( - /*ok=*/true, /*is_sync=*/true, chain.get(), - /*handshake_hints=*/absl::string_view(), - /*ticket_encryption_key=*/absl::string_view(), cert_matched_sni, - QuicDelayedSSLConfig()); + /*ok=*/true, /*is_sync=*/true, + ProofSourceHandleCallback::LocalSSLConfig{chain.get(), + QuicDelayedSSLConfig()}, + /*ticket_encryption_key=*/absl::string_view(), cert_matched_sni); if (!handshaker_->select_cert_status().has_value()) { QUIC_BUG(quic_bug_12423_1) << "select_cert_status() has no value after a synchronous select cert"; @@ -1007,13 +1038,10 @@ } void TlsServerHandshaker::OnSelectCertificateDone( - bool ok, bool is_sync, const ProofSource::Chain* chain, - absl::string_view handshake_hints, absl::string_view ticket_encryption_key, - bool cert_matched_sni, QuicDelayedSSLConfig delayed_ssl_config) { + bool ok, bool is_sync, SSLConfig ssl_config, + absl::string_view ticket_encryption_key, bool cert_matched_sni) { QUIC_DVLOG(1) << "OnSelectCertificateDone. ok:" << ok - << ", is_sync:" << is_sync - << ", len(handshake_hints):" << handshake_hints.size() - << ", len(ticket_encryption_key):" + << ", is_sync:" << is_sync << ", len(ticket_encryption_key):" << ticket_encryption_key.size(); std::optional<QuicConnectionContextSwitcher> context_switcher; if (!is_sync) { @@ -1022,14 +1050,17 @@ QUIC_TRACESTRING(absl::StrCat( "TLS select certificate done: ok:", ok, - ", certs_found:", (chain != nullptr && !chain->certs.empty()), - ", len(handshake_hints):", handshake_hints.size(), ", len(ticket_encryption_key):", ticket_encryption_key.size())); ticket_encryption_key_ = std::string(ticket_encryption_key); select_cert_status_ = QUIC_FAILURE; cert_matched_sni_ = cert_matched_sni; + // Extract the delayed SSL config from either LocalSSLConfig or + // HintsSSLConfig. + const QuicDelayedSSLConfig& delayed_ssl_config = absl::visit( + [](const auto& config) { return config.delayed_ssl_config; }, ssl_config); + if (delayed_ssl_config.quic_transport_parameters.has_value()) { // In case of any error the SSL object is still valid. Handshaker may need // to call ComputeSignature but otherwise can proceed. @@ -1053,25 +1084,33 @@ } if (ok) { - if (chain && !chain->certs.empty()) { - tls_connection_.SetCertChain(chain->ToCryptoBuffers().value); - if (!handshake_hints.empty() && - !SSL_set_handshake_hints( - ssl(), reinterpret_cast<const uint8_t*>(handshake_hints.data()), - handshake_hints.size())) { - // If |SSL_set_handshake_hints| fails, the ssl() object will remain - // intact, it is as if we didn't call it. The handshaker will - // continue to compute signature/decrypt ticket as normal. - QUIC_CODE_COUNT(quic_tls_server_set_handshake_hints_failed); - QUIC_DVLOG(1) << "SSL_set_handshake_hints failed"; + if (auto* local_config = std::get_if<LocalSSLConfig>(&ssl_config); + local_config != nullptr) { + if (local_config->chain && !local_config->chain->certs.empty()) { + tls_connection_.SetCertChain( + local_config->chain->ToCryptoBuffers().value); + select_cert_status_ = QUIC_SUCCESS; + } else { + QUIC_DLOG(ERROR) << "No certs provided for host '" + << crypto_negotiated_params_->sni + << "', server_address:" + << session()->connection()->self_address() + << ", client_address:" + << session()->connection()->peer_address(); } - select_cert_status_ = QUIC_SUCCESS; + } else if (auto* hints_config = std::get_if<HintsSSLConfig>(&ssl_config); + hints_config != nullptr) { + if (hints_config->configure_ssl) { + if (const absl::Status status = tls_connection_.ConfigureSSL( + std::move(hints_config->configure_ssl)); + !status.ok()) { + QUIC_CODE_COUNT(quic_tls_server_set_handshake_hints_failed); + QUIC_DVLOG(1) << "SSL_set_handshake_hints failed: " << status; + } + select_cert_status_ = QUIC_SUCCESS; + } } else { - QUIC_DLOG(ERROR) << "No certs provided for host '" - << crypto_negotiated_params_->sni << "', server_address:" - << session()->connection()->self_address() - << ", client_address:" - << session()->connection()->peer_address(); + QUIC_DLOG(FATAL) << "Neither branch hit"; } }
diff --git a/quiche/quic/core/tls_server_handshaker.h b/quiche/quic/core/tls_server_handshaker.h index 5f571ed..2e0351e 100644 --- a/quiche/quic/core/tls_server_handshaker.h +++ b/quiche/quic/core/tls_server_handshaker.h
@@ -5,23 +5,40 @@ #ifndef QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ #define QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ +#include <cstddef> +#include <cstdint> +#include <memory> +#include <optional> #include <string> +#include <utility> +#include <vector> #include "absl/strings/string_view.h" -#include "openssl/pool.h" +#include "absl/types/span.h" +#include "openssl/base.h" #include "openssl/ssl.h" +#include "quiche/quic/core/crypto/crypto_handshake.h" +#include "quiche/quic/core/crypto/crypto_message_parser.h" +#include "quiche/quic/core/crypto/proof_source.h" +#include "quiche/quic/core/crypto/proof_verifier.h" #include "quiche/quic/core/crypto/quic_crypto_server_config.h" +#include "quiche/quic/core/crypto/quic_decrypter.h" +#include "quiche/quic/core/crypto/quic_encrypter.h" +#include "quiche/quic/core/crypto/tls_connection.h" #include "quiche/quic/core/crypto/tls_server_connection.h" -#include "quiche/quic/core/proto/cached_network_parameters_proto.h" +#include "quiche/quic/core/crypto/transport_parameters.h" +#include "quiche/quic/core/quic_config.h" +#include "quiche/quic/core/quic_connection_context.h" #include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_connection_stats.h" #include "quiche/quic/core/quic_crypto_server_stream_base.h" #include "quiche/quic/core/quic_crypto_stream.h" +#include "quiche/quic/core/quic_error_codes.h" +#include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_time_accumulator.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/tls_handshaker.h" -#include "quiche/quic/platform/api/quic_export.h" -#include "quiche/quic/platform/api/quic_flag_utils.h" -#include "quiche/quic/platform/api/quic_flags.h" +#include "quiche/quic/platform/api/quic_socket_address.h" namespace quic { @@ -178,11 +195,9 @@ bool HasValidSignature(size_t max_signature_size) const; // ProofSourceHandleCallback implementation: - void OnSelectCertificateDone( - bool ok, bool is_sync, const ProofSource::Chain* chain, - absl::string_view handshake_hints, - absl::string_view ticket_encryption_key, bool cert_matched_sni, - QuicDelayedSSLConfig delayed_ssl_config) override; + void OnSelectCertificateDone(bool ok, bool is_sync, SSLConfig ssl_config, + absl::string_view ticket_encryption_key, + bool cert_matched_sni) override; void OnComputeSignatureDone( bool ok, bool is_sync, std::string signature,
diff --git a/quiche/quic/test_tools/fake_proof_source_handle.cc b/quiche/quic/test_tools/fake_proof_source_handle.cc index 9ab13ce..0f95d00 100644 --- a/quiche/quic/test_tools/fake_proof_source_handle.cc +++ b/quiche/quic/test_tools/fake_proof_source_handle.cc
@@ -4,9 +4,22 @@ #include "quiche/quic/test_tools/fake_proof_source_handle.h" +#include <cstddef> +#include <cstdint> +#include <memory> +#include <optional> +#include <string> +#include <utility> +#include <vector> + +#include "absl/strings/string_view.h" +#include "quiche/quic/core/crypto/proof_source.h" #include "quiche/quic/core/quic_connection_id.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" +#include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/platform/api/quiche_logging.h" +#include "quiche/common/platform/api/quiche_reference_counted.h" namespace quic { namespace test { @@ -93,9 +106,10 @@ select_cert_action_ == Action::FAIL_SYNC_DO_NOT_CHECK_CLOSED) { callback()->OnSelectCertificateDone( /*ok=*/false, - /*is_sync=*/true, nullptr, /*handshake_hints=*/absl::string_view(), + /*is_sync=*/true, + ProofSourceHandleCallback::LocalSSLConfig{nullptr, delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/false, delayed_ssl_config_); + /*cert_matched_sni=*/false); return QUIC_FAILURE; } @@ -107,10 +121,11 @@ bool ok = chain && !chain->certs.empty(); callback_->OnSelectCertificateDone( - ok, /*is_sync=*/true, chain.get(), - /*handshake_hints=*/absl::string_view(), + ok, /*is_sync=*/true, + ProofSourceHandleCallback::LocalSSLConfig{chain.get(), + delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/cert_matched_sni, delayed_ssl_config_); + /*cert_matched_sni=*/cert_matched_sni); return ok ? QUIC_SUCCESS : QUIC_FAILURE; } @@ -186,10 +201,10 @@ if (action_ == Action::FAIL_ASYNC) { callback_->OnSelectCertificateDone( /*ok=*/false, - /*is_sync=*/false, nullptr, - /*handshake_hints=*/absl::string_view(), + /*is_sync=*/false, + ProofSourceHandleCallback::LocalSSLConfig{nullptr, delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/false, delayed_ssl_config_); + /*cert_matched_sni=*/false); } else if (action_ == Action::DELEGATE_ASYNC) { bool cert_matched_sni; quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain = @@ -197,10 +212,11 @@ args_.hostname, &cert_matched_sni); bool ok = chain && !chain->certs.empty(); callback_->OnSelectCertificateDone( - ok, /*is_sync=*/false, chain.get(), - /*handshake_hints=*/absl::string_view(), + ok, /*is_sync=*/false, + ProofSourceHandleCallback::LocalSSLConfig{chain.get(), + delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/cert_matched_sni, delayed_ssl_config_); + /*cert_matched_sni=*/cert_matched_sni); } else { QUIC_BUG(quic_bug_10139_1) << "Unexpected action: " << static_cast<int>(action_);