gfe-relnote: Add SessionCache to TlsClientHandshaker, protected by reloadable flag quic_supports_tls_handshake
PiperOrigin-RevId: 279800830
Change-Id: Ib7b49726c14208f63c5b3a8c552cff36cb5d89bf
diff --git a/quic/core/crypto/quic_crypto_client_config.cc b/quic/core/crypto/quic_crypto_client_config.cc
index 6813f7c..6b00c4c 100644
--- a/quic/core/crypto/quic_crypto_client_config.cc
+++ b/quic/core/crypto/quic_crypto_client_config.cc
@@ -61,7 +61,13 @@
QuicCryptoClientConfig::QuicCryptoClientConfig(
std::unique_ptr<ProofVerifier> proof_verifier)
+ : QuicCryptoClientConfig(std::move(proof_verifier), nullptr) {}
+
+QuicCryptoClientConfig::QuicCryptoClientConfig(
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache)
: proof_verifier_(std::move(proof_verifier)),
+ session_cache_(std::move(session_cache)),
ssl_ctx_(TlsClientConnection::CreateSslCtx()) {
DCHECK(proof_verifier_.get());
SetDefaults();
@@ -850,6 +856,10 @@
return proof_verifier_.get();
}
+SessionCache* QuicCryptoClientConfig::session_cache() const {
+ return session_cache_.get();
+}
+
SSL_CTX* QuicCryptoClientConfig::ssl_ctx() const {
return ssl_ctx_.get();
}
diff --git a/quic/core/crypto/quic_crypto_client_config.h b/quic/core/crypto/quic_crypto_client_config.h
index d3e627d..a3e1bcd 100644
--- a/quic/core/crypto/quic_crypto_client_config.h
+++ b/quic/core/crypto/quic_crypto_client_config.h
@@ -12,8 +12,10 @@
#include <vector>
#include "third_party/boringssl/src/include/openssl/base.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -27,6 +29,53 @@
class ProofVerifyDetails;
class QuicRandom;
+// QuicResumptionState stores the state a client needs for performing connection
+// resumption.
+struct QUIC_EXPORT_PRIVATE QuicResumptionState {
+ // |tls_session| holds the cryptographic state necessary for a resumption. It
+ // includes the ALPN negotiated on the connection where the ticket was
+ // received.
+ bssl::UniquePtr<SSL_SESSION> tls_session;
+
+ // If the application using QUIC doesn't support 0-RTT handshakes or the
+ // client didn't receive a 0-RTT capable session ticket from the server,
+ // |transport_params| will be null. Otherwise, it will contain the transport
+ // parameters received from the server on the original connection.
+ std::unique_ptr<TransportParameters> transport_params;
+
+ // If |transport_params| is null, then |application_state| is ignored and
+ // should be empty. |application_state| contains serialized state that the
+ // client received from the server at the application layer that the client
+ // needs to remember when performing a 0-RTT handshake.
+ std::vector<uint8_t> application_state;
+};
+
+// SessionCache is an interface for managing storing and retrieving
+// QuicResumptionState structs.
+class QUIC_EXPORT_PRIVATE SessionCache {
+ public:
+ virtual ~SessionCache() {}
+
+ // Inserts |state| into the cache, keyed by |server_id|. Insert is called
+ // after a session ticket is received. If the session ticket is valid for
+ // 0-RTT, there may be a delay between its receipt and the call to Insert
+ // while waiting for application state for |state|.
+ //
+ // Insert may be called multiple times per connection. SessionCache
+ // implementations should support storing multiple entries per server ID.
+ virtual void Insert(const QuicServerId& server_id,
+ std::unique_ptr<QuicResumptionState> state) = 0;
+
+ // Lookup is called once at the beginning of each TLS handshake to potentially
+ // provide the saved state both for the TLS handshake and for sending 0-RTT
+ // data (if supported). Lookup may return a nullptr. Implementations should
+ // delete cache entries after returning them in Lookup so that session tickets
+ // are used only once.
+ virtual std::unique_ptr<QuicResumptionState> Lookup(
+ const QuicServerId& server_id,
+ const SSL_CTX* ctx) = 0;
+};
+
// QuicCryptoClientConfig contains crypto-related configuration settings for a
// client. Note that this object isn't thread-safe. It's designed to be used on
// a single thread at a time.
@@ -203,8 +252,11 @@
virtual bool Matches(const QuicServerId& server_id) const = 0;
};
+ // DEPRECATED: Use the constructor below instead.
explicit QuicCryptoClientConfig(
std::unique_ptr<ProofVerifier> proof_verifier);
+ QuicCryptoClientConfig(std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache);
QuicCryptoClientConfig(const QuicCryptoClientConfig&) = delete;
QuicCryptoClientConfig& operator=(const QuicCryptoClientConfig&) = delete;
~QuicCryptoClientConfig();
@@ -309,7 +361,7 @@
std::string* error_details);
ProofVerifier* proof_verifier() const;
-
+ SessionCache* session_cache() const;
SSL_CTX* ssl_ctx() const;
// Initialize the CachedState from |canonical_crypto_config| for the
@@ -388,6 +440,7 @@
std::vector<std::string> canonical_suffixes_;
std::unique_ptr<ProofVerifier> proof_verifier_;
+ std::unique_ptr<SessionCache> session_cache_;
bssl::UniquePtr<SSL_CTX> ssl_ctx_;
// The |user_agent_id_| passed in QUIC's CHLO message.
diff --git a/quic/core/crypto/tls_client_connection.cc b/quic/core/crypto/tls_client_connection.cc
index f28af66..98aa6e7 100644
--- a/quic/core/crypto/tls_client_connection.cc
+++ b/quic/core/crypto/tls_client_connection.cc
@@ -19,6 +19,11 @@
// certificate after the connection is complete. We need to re-verify on
// resumption in case of expiration or revocation/distrust.
SSL_CTX_set_custom_verify(ssl_ctx.get(), SSL_VERIFY_PEER, &VerifyCallback);
+
+ // Configure session caching.
+ SSL_CTX_set_session_cache_mode(
+ ssl_ctx.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
+ SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
return ssl_ctx;
}
@@ -30,4 +35,11 @@
->delegate_->VerifyCert(out_alert);
}
+// static
+int TlsClientConnection::NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
+ static_cast<TlsClientConnection*>(ConnectionFromSsl(ssl))
+ ->delegate_->InsertSession(bssl::UniquePtr<SSL_SESSION>(session));
+ return 1;
+}
+
} // namespace quic
diff --git a/quic/core/crypto/tls_client_connection.h b/quic/core/crypto/tls_client_connection.h
index 6660343..035f420 100644
--- a/quic/core/crypto/tls_client_connection.h
+++ b/quic/core/crypto/tls_client_connection.h
@@ -26,6 +26,9 @@
// or ssl_verify_retry if verification is happening asynchronously.
virtual enum ssl_verify_result_t VerifyCert(uint8_t* out_alert) = 0;
+ // Called when a NewSessionTicket is received from the server.
+ virtual void InsertSession(bssl::UniquePtr<SSL_SESSION> session) = 0;
+
// Provides the delegate for callbacks that are shared between client and
// server.
virtual TlsConnection::Delegate* ConnectionDelegate() = 0;
@@ -43,6 +46,10 @@
// implementation is delegated to Delegate::VerifyCert.
static enum ssl_verify_result_t VerifyCallback(SSL* ssl, uint8_t* out_alert);
+ // Registered as the callback for SSL_CTX_sess_set_new_cb, which calls
+ // Delegate::InsertSession.
+ static int NewSessionCallback(SSL* ssl, SSL_SESSION* session);
+
Delegate* delegate_;
};
diff --git a/quic/core/crypto/tls_server_connection.cc b/quic/core/crypto/tls_server_connection.cc
index 927c75a..f539a08 100644
--- a/quic/core/crypto/tls_server_connection.cc
+++ b/quic/core/crypto/tls_server_connection.cc
@@ -16,6 +16,7 @@
SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(),
&SelectCertificateCallback);
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), &SelectAlpnCallback, nullptr);
+ SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_NO_TICKET);
return ssl_ctx;
}