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_);