Refactor TlsHandshaker classes
QuicCryptoClientConfig and QuicCryptoServerConfig each own an SSL_CTX,
which is currently created by TlsHandshaker. Those crypto config classes
can't take a dependency on TlsHandshaker (because TlsHandshaker depends on
classes have a dependency in the other direction), resulting in the SSL_CTX
being passed into the crypto config constructors. The SSL_CTX shouldn't be
exposed like this, as it's essentially an implementation detail of the
crypto handshake.
This CL splits TlsHandshaker in two. TlsConnection (and its subclasses) are
in quic/core/crypto, and handle the callbacks from BoringSSL. In turn, it
passes the implementation of those callbacks to a delegate. TlsHandshaker
implements this delegate and owns the TlsConnection.
gfe-relnote: refactor TLS handshake classes in QUIC; not flag protected
PiperOrigin-RevId: 253140899
Change-Id: Ie907a7f61798c29a385be15ea0f53403b86508ab
diff --git a/quic/core/crypto/tls_connection.h b/quic/core/crypto/tls_connection.h
new file mode 100644
index 0000000..15c2b67
--- /dev/null
+++ b/quic/core/crypto/tls_connection.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_CRYPTO_TLS_CONNECTION_H_
+#define QUICHE_QUIC_CORE_CRYPTO_TLS_CONNECTION_H_
+
+#include <vector>
+
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+// TlsConnection wraps BoringSSL's SSL object which represents a single TLS
+// connection. Callbacks set in BoringSSL which are called with an SSL* argument
+// will get dispatched to the TlsConnection object owning that SSL. In turn, the
+// TlsConnection will delegate the implementation of that callback to its
+// Delegate.
+//
+// The owner of the TlsConnection is responsible for driving the TLS handshake
+// (and other interactions with the SSL*). This class only handles mapping
+// callbacks to the correct instance.
+class TlsConnection {
+ public:
+ // A TlsConnection::Delegate implements the methods that are set as callbacks
+ // of TlsConnection.
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ protected:
+ // SetEncryptionSecret provides the encryption secrets to use at a
+ // particular encryption level |level|. The secrets provided here are the
+ // ones from the TLS 1.3 key schedule (RFC 8446 section 7.1), in particular
+ // the handshake traffic secrets and application traffic secrets. For a
+ // given level |level|, |read_secret| is the secret used for reading data,
+ // and |write_secret| is the secret used for writing data.
+ virtual void SetEncryptionSecret(
+ EncryptionLevel level,
+ const std::vector<uint8_t>& read_secret,
+ const std::vector<uint8_t>& write_secret) = 0;
+
+ // WriteMessage is called when there is |data| from the TLS stack ready for
+ // the QUIC stack to write in a crypto frame. The data must be transmitted
+ // at encryption level |level|.
+ virtual void WriteMessage(EncryptionLevel level, QuicStringPiece data) = 0;
+
+ // FlushFlight is called to signal that the current flight of messages have
+ // all been written (via calls to WriteMessage) and can be flushed to the
+ // underlying transport.
+ virtual void FlushFlight() = 0;
+
+ // SendAlert causes this TlsConnection to close the QUIC connection with an
+ // error code corersponding to the TLS alert description |desc| sent at
+ // level |level|.
+ virtual void SendAlert(EncryptionLevel level, uint8_t desc) = 0;
+
+ friend class TlsConnection;
+ };
+
+ TlsConnection(const TlsConnection&) = delete;
+ TlsConnection& operator=(const TlsConnection&) = delete;
+
+ // Functions to convert between BoringSSL's enum ssl_encryption_level_t and
+ // QUIC's EncryptionLevel.
+ static EncryptionLevel QuicEncryptionLevel(enum ssl_encryption_level_t level);
+ static enum ssl_encryption_level_t BoringEncryptionLevel(
+ EncryptionLevel level);
+
+ SSL* ssl() { return ssl_.get(); }
+
+ protected:
+ // TlsConnection does not take ownership of any of its arguments; they must
+ // outlive the TlsConnection object.
+ TlsConnection(SSL_CTX* ssl_ctx, Delegate* delegate);
+
+ // Creates an SSL_CTX and configures it with the options that are appropriate
+ // for both client and server. The caller is responsible for ownership of the
+ // newly created struct.
+ static bssl::UniquePtr<SSL_CTX> CreateSslCtx();
+
+ // From a given SSL* |ssl|, returns a pointer to the TlsConnection that it
+ // belongs to. This helper method allows the callbacks set in BoringSSL to be
+ // dispatched to the correct TlsConnection from the SSL* passed into the
+ // callback.
+ static TlsConnection* ConnectionFromSsl(const SSL* ssl);
+
+ private:
+ // TlsConnection implements SSL_QUIC_METHOD, which provides the interface
+ // between BoringSSL's TLS stack and a QUIC implementation.
+ static const SSL_QUIC_METHOD kSslQuicMethod;
+
+ // The following static functions make up the members of kSslQuicMethod:
+ static int SetEncryptionSecretCallback(SSL* ssl,
+ enum ssl_encryption_level_t level,
+ const uint8_t* read_key,
+ const uint8_t* write_key,
+ size_t key_length);
+ static int WriteMessageCallback(SSL* ssl,
+ enum ssl_encryption_level_t level,
+ const uint8_t* data,
+ size_t len);
+ static int FlushFlightCallback(SSL* ssl);
+ static int SendAlertCallback(SSL* ssl,
+ enum ssl_encryption_level_t level,
+ uint8_t desc);
+
+ Delegate* delegate_;
+ bssl::UniquePtr<SSL> ssl_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_CRYPTO_TLS_CONNECTION_H_