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/crypto_server_test.cc b/quic/core/crypto/crypto_server_test.cc index 8663832..92f774c 100644 --- a/quic/core/crypto/crypto_server_test.cc +++ b/quic/core/crypto/crypto_server_test.cc
@@ -20,7 +20,6 @@ #include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.pb.h" #include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" #include "net/third_party/quiche/src/quic/platform/api/quic_endian.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" @@ -93,8 +92,7 @@ config_(QuicCryptoServerConfig::TESTING, rand_, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), peer_(&config_), compressed_certs_cache_( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), @@ -972,12 +970,10 @@ QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); std::unique_ptr<CryptoHandshakeMessage> scfg_a( a.AddDefaultConfig(&rand_a, &clock, options)); std::unique_ptr<CryptoHandshakeMessage> scfg_b( @@ -996,13 +992,11 @@ QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); rand_b.ChangeValue(); QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); std::unique_ptr<CryptoHandshakeMessage> scfg_a( a.AddDefaultConfig(&rand_a, &clock, options)); std::unique_ptr<CryptoHandshakeMessage> scfg_b( @@ -1022,8 +1016,7 @@ QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); std::unique_ptr<CryptoHandshakeMessage> scfg( a.AddDefaultConfig(&rand_a, &clock, options));
diff --git a/quic/core/crypto/quic_crypto_client_config.cc b/quic/core/crypto/quic_crypto_client_config.cc index c967b17..14f1347 100644 --- a/quic/core/crypto/quic_crypto_client_config.cc +++ b/quic/core/crypto/quic_crypto_client_config.cc
@@ -21,6 +21,7 @@ #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" +#include "net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h" #include "net/third_party/quiche/src/quic/core/quic_connection_id.h" #include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" @@ -59,6 +60,11 @@ } // namespace QuicCryptoClientConfig::QuicCryptoClientConfig( + std::unique_ptr<ProofVerifier> proof_verifier) + : QuicCryptoClientConfig(std::move(proof_verifier), + TlsClientConnection::CreateSslCtx()) {} + +QuicCryptoClientConfig::QuicCryptoClientConfig( std::unique_ptr<ProofVerifier> proof_verifier, bssl::UniquePtr<SSL_CTX> ssl_ctx) : proof_verifier_(std::move(proof_verifier)), ssl_ctx_(std::move(ssl_ctx)) {
diff --git a/quic/core/crypto/quic_crypto_client_config.h b/quic/core/crypto/quic_crypto_client_config.h index 2918a23..2d95103 100644 --- a/quic/core/crypto/quic_crypto_client_config.h +++ b/quic/core/crypto/quic_crypto_client_config.h
@@ -203,6 +203,9 @@ virtual bool Matches(const QuicServerId& server_id) const = 0; }; + explicit QuicCryptoClientConfig( + std::unique_ptr<ProofVerifier> proof_verifier); + // Deprecated. Use the single-arg constructor instead. QuicCryptoClientConfig(std::unique_ptr<ProofVerifier> proof_verifier, bssl::UniquePtr<SSL_CTX> ssl_ctx); QuicCryptoClientConfig(const QuicCryptoClientConfig&) = delete;
diff --git a/quic/core/crypto/quic_crypto_client_config_test.cc b/quic/core/crypto/quic_crypto_client_config_test.cc index 563c7f1..7b473de 100644 --- a/quic/core/crypto/quic_crypto_client_config_test.cc +++ b/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -10,7 +10,6 @@ #include "net/third_party/quiche/src/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_endian.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" @@ -178,8 +177,7 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChlo) { QuicCryptoClientConfig::CachedState state; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); config.set_user_agent_id("quic-tester"); config.set_alpn("hq"); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( @@ -208,8 +206,7 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChloIsNotPadded) { QuicCryptoClientConfig::CachedState state; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); config.set_pad_inchoate_hello(false); config.set_user_agent_id("quic-tester"); config.set_alpn("hq"); @@ -227,8 +224,7 @@ // Make sure AES-GCM is the preferred encryption algorithm if it has hardware // acceleration. TEST_F(QuicCryptoClientConfigTest, PreferAesGcm) { - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); if (EVP_has_aes_hardware() == 1) { EXPECT_EQ(kAESG, config.aead[0]); } else { @@ -238,8 +234,7 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChloSecure) { QuicCryptoClientConfig::CachedState state; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( new QuicCryptoNegotiatedParameters); CryptoHandshakeMessage msg; @@ -268,8 +263,7 @@ state.SetServerConfig(scfg.GetSerialized().AsStringPiece(), now, expiry, &details); - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( new QuicCryptoNegotiatedParameters); CryptoHandshakeMessage msg; @@ -295,8 +289,7 @@ QuicWallTime::FromUNIXSeconds(1), QuicWallTime::FromUNIXSeconds(0), &details); - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( new QuicCryptoNegotiatedParameters); CryptoHandshakeMessage msg; @@ -312,8 +305,7 @@ TEST_F(QuicCryptoClientConfigTest, FillClientHello) { QuicCryptoClientConfig::CachedState state; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( new QuicCryptoNegotiatedParameters); QuicConnectionId kConnectionId = TestConnectionId(1234); @@ -333,8 +325,7 @@ TEST_F(QuicCryptoClientConfigTest, FillClientHelloNoPadding) { QuicCryptoClientConfig::CachedState state; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); config.set_pad_full_hello(false); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( new QuicCryptoNegotiatedParameters); @@ -374,8 +365,7 @@ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params( new QuicCryptoNegotiatedParameters); std::string error; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); EXPECT_EQ(QUIC_VERSION_NEGOTIATION_MISMATCH, config.ProcessServerHello( msg, EmptyQuicConnectionId(), supported_versions.front(), @@ -384,8 +374,7 @@ } TEST_F(QuicCryptoClientConfigTest, InitializeFrom) { - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicServerId canonical_server_id("www.google.com", 443, false); QuicCryptoClientConfig::CachedState* state = config.LookupOrCreate(canonical_server_id); @@ -405,8 +394,7 @@ } TEST_F(QuicCryptoClientConfigTest, Canonical) { - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); config.AddCanonicalSuffix(".google.com"); QuicServerId canonical_id1("www.google.com", 443, false); QuicServerId canonical_id2("mail.google.com", 443, false); @@ -430,8 +418,7 @@ } TEST_F(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) { - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); config.AddCanonicalSuffix(".google.com"); QuicServerId canonical_id1("www.google.com", 443, false); QuicServerId canonical_id2("mail.google.com", 443, false); @@ -446,8 +433,7 @@ } TEST_F(QuicCryptoClientConfigTest, ClearCachedStates) { - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); // Create two states on different origins. struct TestCase { @@ -542,8 +528,7 @@ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params( new QuicCryptoNegotiatedParameters); std::string error; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); EXPECT_EQ(QUIC_NO_ERROR, config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0), AllSupportedTransportVersions().front(), "", @@ -564,8 +549,7 @@ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params( new QuicCryptoNegotiatedParameters); std::string error; - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); EXPECT_EQ(QUIC_NO_ERROR, config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0), AllSupportedTransportVersions().front(), "", @@ -588,8 +572,7 @@ supported_versions.push_back(version); msg.SetVersionVector(kVER, supported_versions); - QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicCryptoClientConfig::CachedState cached; QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params( new QuicCryptoNegotiatedParameters);
diff --git a/quic/core/crypto/quic_crypto_server_config.cc b/quic/core/crypto/quic_crypto_server_config.cc index 9d70641..24d0500 100644 --- a/quic/core/crypto/quic_crypto_server_config.cc +++ b/quic/core/crypto/quic_crypto_server_config.cc
@@ -27,6 +27,7 @@ #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" +#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h" #include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.pb.h" #include "net/third_party/quiche/src/quic/core/proto/source_address_token.pb.h" #include "net/third_party/quiche/src/quic/core/quic_packets.h" @@ -231,6 +232,17 @@ QuicStringPiece source_address_token_secret, QuicRandom* server_nonce_entropy, std::unique_ptr<ProofSource> proof_source, + std::unique_ptr<KeyExchangeSource> key_exchange_source) + : QuicCryptoServerConfig(source_address_token_secret, + server_nonce_entropy, + std::move(proof_source), + std::move(key_exchange_source), + TlsServerConnection::CreateSslCtx()) {} + +QuicCryptoServerConfig::QuicCryptoServerConfig( + QuicStringPiece source_address_token_secret, + QuicRandom* server_nonce_entropy, + std::unique_ptr<ProofSource> proof_source, std::unique_ptr<KeyExchangeSource> key_exchange_source, bssl::UniquePtr<SSL_CTX> ssl_ctx) : replay_protection_(true),
diff --git a/quic/core/crypto/quic_crypto_server_config.h b/quic/core/crypto/quic_crypto_server_config.h index 503b377..85edc0e 100644 --- a/quic/core/crypto/quic_crypto_server_config.h +++ b/quic/core/crypto/quic_crypto_server_config.h
@@ -218,6 +218,11 @@ std::unique_ptr<ProofSource> proof_source, std::unique_ptr<KeyExchangeSource> key_exchange_source, bssl::UniquePtr<SSL_CTX> ssl_ctx); + QuicCryptoServerConfig( + QuicStringPiece source_address_token_secret, + QuicRandom* server_nonce_entropy, + std::unique_ptr<ProofSource> proof_source, + std::unique_ptr<KeyExchangeSource> key_exchange_source); QuicCryptoServerConfig(const QuicCryptoServerConfig&) = delete; QuicCryptoServerConfig& operator=(const QuicCryptoServerConfig&) = delete; ~QuicCryptoServerConfig();
diff --git a/quic/core/crypto/quic_crypto_server_config_test.cc b/quic/core/crypto/quic_crypto_server_config_test.cc index b3f8f77..90da3cd 100644 --- a/quic/core/crypto/quic_crypto_server_config_test.cc +++ b/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -16,7 +16,6 @@ #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" #include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.pb.h" #include "net/third_party/quiche/src/quic/core/quic_time.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" @@ -43,8 +42,7 @@ QuicRandom* rand = QuicRandom::GetInstance(); QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); MockClock clock; std::unique_ptr<CryptoHandshakeMessage> message(server.AddDefaultConfig( @@ -65,8 +63,7 @@ QuicRandom* rand = QuicRandom::GetInstance(); QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); QuicCryptoServerConfigPeer peer(&server); std::vector<std::string> certs = {"testcert"}; @@ -86,8 +83,7 @@ QuicRandom* rand = QuicRandom::GetInstance(); QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); QuicCryptoServerConfigPeer peer(&server); // Compress the certs for the first time. @@ -117,8 +113,7 @@ QuicRandom* rand = QuicRandom::GetInstance(); QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + KeyExchangeSource::Default()); QuicCryptoServerConfigPeer peer(&server); std::vector<std::string> certs = {"testcert"}; @@ -162,8 +157,7 @@ server_(QuicCryptoServerConfig::TESTING, rand_, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), peer_(&server_) { // Advance the clock to some non-zero time. clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000000)); @@ -305,8 +299,7 @@ config_(QuicCryptoServerConfig::TESTING, rand_, crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), test_peer_(&config_) {} void SetUp() override {
diff --git a/quic/core/crypto/tls_client_connection.cc b/quic/core/crypto/tls_client_connection.cc new file mode 100644 index 0000000..f28af66 --- /dev/null +++ b/quic/core/crypto/tls_client_connection.cc
@@ -0,0 +1,33 @@ +// 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. + +#include "net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h" + +namespace quic { + +TlsClientConnection::TlsClientConnection(SSL_CTX* ssl_ctx, Delegate* delegate) + : TlsConnection(ssl_ctx, delegate->ConnectionDelegate()), + delegate_(delegate) {} + +// static +bssl::UniquePtr<SSL_CTX> TlsClientConnection::CreateSslCtx() { + bssl::UniquePtr<SSL_CTX> ssl_ctx = TlsConnection::CreateSslCtx(); + // Configure certificate verification. + // TODO(nharper): This only verifies certs on initial connection, not on + // resumption. Chromium has this callback be a no-op and verifies the + // 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); + return ssl_ctx; +} + +// static +enum ssl_verify_result_t TlsClientConnection::VerifyCallback( + SSL* ssl, + uint8_t* out_alert) { + return static_cast<TlsClientConnection*>(ConnectionFromSsl(ssl)) + ->delegate_->VerifyCert(out_alert); +} + +} // namespace quic
diff --git a/quic/core/crypto/tls_client_connection.h b/quic/core/crypto/tls_client_connection.h new file mode 100644 index 0000000..c741389 --- /dev/null +++ b/quic/core/crypto/tls_client_connection.h
@@ -0,0 +1,51 @@ +// 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_CLIENT_CONNECTION_H_ +#define QUICHE_QUIC_CORE_CRYPTO_TLS_CLIENT_CONNECTION_H_ + +#include "net/third_party/quiche/src/quic/core/crypto/tls_connection.h" + +namespace quic { + +// TlsClientConnection receives calls for client-specific BoringSSL callbacks +// and calls its Delegate for the implementation of those callbacks. +class TlsClientConnection : public TlsConnection { + public: + // A TlsClientConnection::Delegate implements the client-specific methods that + // are set as callbacks for an SSL object. + class Delegate { + public: + virtual ~Delegate() {} + + protected: + // Verifies the peer's certificate chain. It may use + // SSL_get0_peer_certificates to get the cert chain. This method returns + // ssl_verify_ok if the cert is valid, ssl_verify_invalid if it is invalid, + // or ssl_verify_retry if verification is happening asynchronously. + virtual enum ssl_verify_result_t VerifyCert(uint8_t* out_alert) = 0; + + // Provides the delegate for callbacks that are shared between client and + // server. + virtual TlsConnection::Delegate* ConnectionDelegate() = 0; + + friend class TlsClientConnection; + }; + + TlsClientConnection(SSL_CTX* ssl_ctx, Delegate* delegate); + + // Creates and configures an SSL_CTX that is appropriate for clients to use. + static bssl::UniquePtr<SSL_CTX> CreateSslCtx(); + + private: + // Registered as the callback for SSL_CTX_set_custom_verify. The + // implementation is delegated to Delegate::VerifyCert. + static enum ssl_verify_result_t VerifyCallback(SSL* ssl, uint8_t* out_alert); + + Delegate* delegate_; +}; + +} // namespace quic + +#endif // QUICHE_QUIC_CORE_CRYPTO_TLS_CLIENT_CONNECTION_H_
diff --git a/quic/core/crypto/tls_connection.cc b/quic/core/crypto/tls_connection.cc new file mode 100644 index 0000000..d28db22 --- /dev/null +++ b/quic/core/crypto/tls_connection.cc
@@ -0,0 +1,158 @@ +// 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. + +#include "net/third_party/quiche/src/quic/core/crypto/tls_connection.h" + +#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" + +namespace quic { + +namespace { + +// BoringSSL allows storing extra data off of some of its data structures, +// including the SSL struct. To allow for multiple callers to store data, each +// caller can use a different index for setting and getting data. These indices +// are globals handed out by calling SSL_get_ex_new_index. +// +// SslIndexSingleton calls SSL_get_ex_new_index on its construction, and then +// provides this index to be used in calls to SSL_get_ex_data/SSL_set_ex_data. +// This is used to store in the SSL struct a pointer to the TlsConnection which +// owns it. +class SslIndexSingleton { + public: + static SslIndexSingleton* GetInstance() { + static SslIndexSingleton* instance = new SslIndexSingleton(); + return instance; + } + + int ssl_ex_data_index_connection() const { + return ssl_ex_data_index_connection_; + } + + private: + SslIndexSingleton() { + CRYPTO_library_init(); + ssl_ex_data_index_connection_ = + SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr); + CHECK_LE(0, ssl_ex_data_index_connection_); + } + + SslIndexSingleton(const SslIndexSingleton&) = delete; + SslIndexSingleton& operator=(const SslIndexSingleton&) = delete; + + // The index to supply to SSL_get_ex_data/SSL_set_ex_data for getting/setting + // the TlsConnection pointer. + int ssl_ex_data_index_connection_; +}; + +} // namespace + +// static +EncryptionLevel TlsConnection::QuicEncryptionLevel( + enum ssl_encryption_level_t level) { + switch (level) { + case ssl_encryption_initial: + return ENCRYPTION_INITIAL; + case ssl_encryption_early_data: + return ENCRYPTION_ZERO_RTT; + case ssl_encryption_handshake: + return ENCRYPTION_HANDSHAKE; + case ssl_encryption_application: + return ENCRYPTION_FORWARD_SECURE; + default: + QUIC_BUG << "Invalid ssl_encryption_level_t " << static_cast<int>(level); + return ENCRYPTION_INITIAL; + } +} + +// static +enum ssl_encryption_level_t TlsConnection::BoringEncryptionLevel( + EncryptionLevel level) { + switch (level) { + case ENCRYPTION_INITIAL: + return ssl_encryption_initial; + case ENCRYPTION_HANDSHAKE: + return ssl_encryption_handshake; + case ENCRYPTION_ZERO_RTT: + return ssl_encryption_early_data; + case ENCRYPTION_FORWARD_SECURE: + return ssl_encryption_application; + default: + QUIC_BUG << "Invalid encryption level " << static_cast<int>(level); + return ssl_encryption_initial; + } +} + +TlsConnection::TlsConnection(SSL_CTX* ssl_ctx, + TlsConnection::Delegate* delegate) + : delegate_(delegate), ssl_(SSL_new(ssl_ctx)) { + SSL_set_ex_data( + ssl(), SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection(), + this); +} +// static +bssl::UniquePtr<SSL_CTX> TlsConnection::CreateSslCtx() { + CRYPTO_library_init(); + bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_with_buffers_method())); + SSL_CTX_set_min_proto_version(ssl_ctx.get(), TLS1_3_VERSION); + SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION); + SSL_CTX_set_quic_method(ssl_ctx.get(), &kSslQuicMethod); + return ssl_ctx; +} + +// static +TlsConnection* TlsConnection::ConnectionFromSsl(const SSL* ssl) { + return reinterpret_cast<TlsConnection*>(SSL_get_ex_data( + ssl, SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection())); +} + +const SSL_QUIC_METHOD TlsConnection::kSslQuicMethod{ + TlsConnection::SetEncryptionSecretCallback, + TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback, + TlsConnection::SendAlertCallback}; + +// static +int TlsConnection::SetEncryptionSecretCallback( + SSL* ssl, + enum ssl_encryption_level_t level, + const uint8_t* read_key, + const uint8_t* write_key, + size_t key_length) { + // TODO(nharper): replace these vectors and memcpys with spans (which + // unfortunately doesn't yet exist in quic/platform/api). + std::vector<uint8_t> read_secret(key_length), write_secret(key_length); + memcpy(read_secret.data(), read_key, key_length); + memcpy(write_secret.data(), write_key, key_length); + ConnectionFromSsl(ssl)->delegate_->SetEncryptionSecret( + QuicEncryptionLevel(level), read_secret, write_secret); + return 1; +} + +// static +int TlsConnection::WriteMessageCallback(SSL* ssl, + enum ssl_encryption_level_t level, + const uint8_t* data, + size_t len) { + ConnectionFromSsl(ssl)->delegate_->WriteMessage( + QuicEncryptionLevel(level), + QuicStringPiece(reinterpret_cast<const char*>(data), len)); + return 1; +} + +// static +int TlsConnection::FlushFlightCallback(SSL* ssl) { + ConnectionFromSsl(ssl)->delegate_->FlushFlight(); + return 1; +} + +// static +int TlsConnection::SendAlertCallback(SSL* ssl, + enum ssl_encryption_level_t level, + uint8_t desc) { + ConnectionFromSsl(ssl)->delegate_->SendAlert(QuicEncryptionLevel(level), + desc); + return 1; +} + +} // namespace quic
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_
diff --git a/quic/core/crypto/tls_server_connection.cc b/quic/core/crypto/tls_server_connection.cc new file mode 100644 index 0000000..a3a1815 --- /dev/null +++ b/quic/core/crypto/tls_server_connection.cc
@@ -0,0 +1,81 @@ +// 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. + +#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h" + +namespace quic { + +TlsServerConnection::TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate) + : TlsConnection(ssl_ctx, delegate->ConnectionDelegate()), + delegate_(delegate) {} + +// static +bssl::UniquePtr<SSL_CTX> TlsServerConnection::CreateSslCtx() { + bssl::UniquePtr<SSL_CTX> ssl_ctx = TlsConnection::CreateSslCtx(); + SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(), + &SelectCertificateCallback); + SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), &SelectAlpnCallback, nullptr); + return ssl_ctx; +} + +void TlsServerConnection::SetCertChain( + const std::vector<CRYPTO_BUFFER*>& cert_chain) { + SSL_set_chain_and_key(ssl(), cert_chain.data(), cert_chain.size(), nullptr, + &TlsServerConnection::kPrivateKeyMethod); +} + +const SSL_PRIVATE_KEY_METHOD TlsServerConnection::kPrivateKeyMethod{ + &TlsServerConnection::PrivateKeySign, + nullptr, // decrypt + &TlsServerConnection::PrivateKeyComplete, +}; + +// static +TlsServerConnection* TlsServerConnection::ConnectionFromSsl(SSL* ssl) { + return static_cast<TlsServerConnection*>( + TlsConnection::ConnectionFromSsl(ssl)); +} + +// static +int TlsServerConnection::SelectCertificateCallback(SSL* ssl, + int* out_alert, + void* arg) { + return ConnectionFromSsl(ssl)->delegate_->SelectCertificate(out_alert); +} + +// static +int TlsServerConnection::SelectAlpnCallback(SSL* ssl, + const uint8_t** out, + uint8_t* out_len, + const uint8_t* in, + unsigned in_len, + void* arg) { + return ConnectionFromSsl(ssl)->delegate_->SelectAlpn(out, out_len, in, + in_len); +} + +// static +ssl_private_key_result_t TlsServerConnection::PrivateKeySign(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t sig_alg, + const uint8_t* in, + size_t in_len) { + return ConnectionFromSsl(ssl)->delegate_->PrivateKeySign( + out, out_len, max_out, sig_alg, + QuicStringPiece(reinterpret_cast<const char*>(in), in_len)); +} + +// static +ssl_private_key_result_t TlsServerConnection::PrivateKeyComplete( + SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out) { + return ConnectionFromSsl(ssl)->delegate_->PrivateKeyComplete(out, out_len, + max_out); +} + +} // namespace quic
diff --git a/quic/core/crypto/tls_server_connection.h b/quic/core/crypto/tls_server_connection.h new file mode 100644 index 0000000..a5d087c --- /dev/null +++ b/quic/core/crypto/tls_server_connection.h
@@ -0,0 +1,111 @@ +// 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_SERVER_CONNECTION_H_ +#define QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_ + +#include "net/third_party/quiche/src/quic/core/crypto/tls_connection.h" + +namespace quic { + +// TlsServerConnection receives calls for client-specific BoringSSL callbacks +// and calls its Delegate for the implementation of those callbacks. +class TlsServerConnection : public TlsConnection { + public: + // A TlsServerConnection::Delegate implement the server-specific methods that + // are set as callbacks for an SSL object. + class Delegate { + public: + virtual ~Delegate() {} + + protected: + // Configures the certificate to use on |ssl_| based on the SNI sent by the + // client. Returns an SSL_TLSEXT_ERR_* value (see + // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_tlsext_servername_callback). + // + // If SelectCertificate returns SSL_TLSEXT_ERR_ALERT_FATAL, then it puts in + // |*out_alert| the TLS alert value that the server will send. + virtual int SelectCertificate(int* out_alert) = 0; + + // Selects which ALPN to use based on the list sent by the client. + virtual int SelectAlpn(const uint8_t** out, + uint8_t* out_len, + const uint8_t* in, + unsigned in_len) = 0; + + // Signs |in| using the signature algorithm specified by |sig_alg| (an + // SSL_SIGN_* value). If the signing operation cannot be completed + // synchronously, ssl_private_key_retry is returned. If there is an error + // signing, or if the signature is longer than |max_out|, then + // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success + // is returned with the signature put in |*out| and the length in + // |*out_len|. + virtual ssl_private_key_result_t PrivateKeySign(uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t sig_alg, + QuicStringPiece in) = 0; + + // When PrivateKeySign returns ssl_private_key_retry, PrivateKeyComplete + // will be called after the async sign operation has completed. + // PrivateKeyComplete puts the resulting signature in |*out| and length in + // |*out_len|. If the length is greater than |max_out| or if there was an + // error in signing, then ssl_private_key_failure is returned. Otherwise, + // ssl_private_key_success is returned. + virtual ssl_private_key_result_t PrivateKeyComplete(uint8_t* out, + size_t* out_len, + size_t max_out) = 0; + + // Provides the delegate for callbacks that are shared between client and + // server. + virtual TlsConnection::Delegate* ConnectionDelegate() = 0; + + friend class TlsServerConnection; + }; + + TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate); + + // Creates and configures an SSL_CTX that is appropriate for servers to use. + static bssl::UniquePtr<SSL_CTX> CreateSslCtx(); + + void SetCertChain(const std::vector<CRYPTO_BUFFER*>& cert_chain); + + private: + // Specialization of TlsConnection::ConnectionFromSsl. + static TlsServerConnection* ConnectionFromSsl(SSL* ssl); + + // These functions are registered as callbacks in BoringSSL and delegate their + // implementation to the matching methods in Delegate above. + static int SelectCertificateCallback(SSL* ssl, int* out_alert, void* arg); + static int SelectAlpnCallback(SSL* ssl, + const uint8_t** out, + uint8_t* out_len, + const uint8_t* in, + unsigned in_len, + void* arg); + + // |kPrivateKeyMethod| is a vtable pointing to PrivateKeySign and + // PrivateKeyComplete used by the TLS stack to compute the signature for the + // CertificateVerify message (using the server's private key). + static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod; + + // The following functions make up the contents of |kPrivateKeyMethod|. + static ssl_private_key_result_t PrivateKeySign(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t sig_alg, + const uint8_t* in, + size_t in_len); + static ssl_private_key_result_t PrivateKeyComplete(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out); + + Delegate* delegate_; +}; + +} // namespace quic + +#endif // QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_
diff --git a/quic/core/http/quic_client_promised_info_test.cc b/quic/core/http/quic_client_promised_info_test.cc index 104c049..24d4821 100644 --- a/quic/core/http/quic_client_promised_info_test.cc +++ b/quic/core/http/quic_client_promised_info_test.cc
@@ -10,7 +10,6 @@ #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h" #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" @@ -40,8 +39,7 @@ QuicServerId("example.com", 443, false), &crypto_config_, push_promise_index), - crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()), + crypto_config_(crypto_test_utils::ProofVerifierForTesting()), authorized_(true) {} MockQuicSpdyClientSession(const MockQuicSpdyClientSession&) = delete; MockQuicSpdyClientSession& operator=(const MockQuicSpdyClientSession&) =
diff --git a/quic/core/http/quic_client_push_promise_index_test.cc b/quic/core/http/quic_client_push_promise_index_test.cc index c12a328..401ea86 100644 --- a/quic/core/http/quic_client_push_promise_index_test.cc +++ b/quic/core/http/quic_client_push_promise_index_test.cc
@@ -8,7 +8,6 @@ #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h" #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" #include "net/third_party/quiche/src/quic/test_tools/mock_quic_client_promised_info.h" @@ -35,8 +34,7 @@ QuicServerId("example.com", 443, false), &crypto_config_, push_promise_index), - crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()) {} + crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {} MockQuicSpdyClientSession(const MockQuicSpdyClientSession&) = delete; MockQuicSpdyClientSession& operator=(const MockQuicSpdyClientSession&) = delete;
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc index c3fac3e..a0ce23e 100644 --- a/quic/core/http/quic_server_session_base_test.cc +++ b/quic/core/http/quic_server_session_base_test.cc
@@ -14,7 +14,6 @@ #include "net/third_party/quiche/src/quic/core/quic_connection.h" #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" @@ -125,8 +124,7 @@ : crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), std::move(proof_source), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), compressed_certs_cache_( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { config_.SetMaxIncomingBidirectionalStreamsToSend(kMaxStreamsForTest);
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc index 847de2b..9aff364 100644 --- a/quic/core/http/quic_spdy_client_session_test.cc +++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -13,7 +13,6 @@ #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h" #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" @@ -77,8 +76,7 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> { protected: QuicSpdyClientSessionTest() - : crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()), + : crypto_config_(crypto_test_utils::ProofVerifierForTesting()), promised_stream_id_( QuicUtils::GetInvalidStreamId(GetParam().transport_version)), associated_stream_id_(
diff --git a/quic/core/http/quic_spdy_client_stream_test.cc b/quic/core/http/quic_spdy_client_stream_test.cc index 6d63ad3..4354a2f 100644 --- a/quic/core/http/quic_spdy_client_stream_test.cc +++ b/quic/core/http/quic_spdy_client_stream_test.cc
@@ -10,7 +10,6 @@ #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h" #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" @@ -41,8 +40,7 @@ QuicServerId("example.com", 443, false), &crypto_config_, push_promise_index), - crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()) {} + crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {} MockQuicSpdyClientSession(const MockQuicSpdyClientSession&) = delete; MockQuicSpdyClientSession& operator=(const MockQuicSpdyClientSession&) = delete;
diff --git a/quic/core/quic_crypto_client_handshaker_test.cc b/quic/core/quic_crypto_client_handshaker_test.cc index 92cfab1..d9e33b7 100644 --- a/quic/core/quic_crypto_client_handshaker_test.cc +++ b/quic/core/quic_crypto_client_handshaker_test.cc
@@ -5,8 +5,6 @@ #include "net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h" #include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.pb.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" @@ -133,8 +131,7 @@ &alarm_factory_, Perspective::IS_CLIENT)), session_(connection_, false), - crypto_client_config_(QuicMakeUnique<InsecureProofVerifier>(), - quic::TlsClientHandshaker::CreateSslCtx()), + crypto_client_config_(QuicMakeUnique<InsecureProofVerifier>()), client_stream_(new QuicCryptoClientStream(server_id_, &session_, nullptr,
diff --git a/quic/core/quic_crypto_client_stream_test.cc b/quic/core/quic_crypto_client_stream_test.cc index e09546d..e0229bc 100644 --- a/quic/core/quic_crypto_client_stream_test.cc +++ b/quic/core/quic_crypto_client_stream_test.cc
@@ -13,8 +13,6 @@ #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/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" @@ -39,8 +37,7 @@ QuicCryptoClientStreamTest() : supported_versions_(AllSupportedVersions()), server_id_(kServerHostname, kServerPort, false), - crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()) { + crypto_config_(crypto_test_utils::ProofVerifierForTesting()) { CreateConnection(); } @@ -258,8 +255,7 @@ // Build a server config update message with certificates QuicCryptoServerConfig crypto_config( QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + crypto_test_utils::ProofSourceForTesting(), KeyExchangeSource::Default()); crypto_test_utils::SetupCryptoServerConfigForTest( connection_->clock(), QuicRandom::GetInstance(), &crypto_config); SourceAddressTokens tokens;
diff --git a/quic/core/quic_crypto_server_stream_test.cc b/quic/core/quic_crypto_server_stream_test.cc index 5105a27..238162c 100644 --- a/quic/core/quic_crypto_server_stream_test.cc +++ b/quic/core/quic_crypto_server_stream_test.cc
@@ -21,8 +21,6 @@ #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_session.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" @@ -60,13 +58,11 @@ : server_crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), std::move(proof_source), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), server_compressed_certs_cache_( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), server_id_(kServerHostname, kServerPort, false), - client_crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()) {} + client_crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {} void Initialize() { InitializeServer(); }
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc index 87742db..9817ea4 100644 --- a/quic/core/quic_dispatcher_test.cc +++ b/quic/core/quic_dispatcher_test.cc
@@ -19,7 +19,6 @@ #include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h" #include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" @@ -198,8 +197,7 @@ crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), std::move(proof_source), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), server_address_(QuicIpAddress::Any4(), 5), dispatcher_( new NiceMock<TestDispatcher>(&config_,
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc index db1f6b4..d90b6f5 100644 --- a/quic/core/tls_client_handshaker.cc +++ b/quic/core/tls_client_handshaker.cc
@@ -53,7 +53,8 @@ proof_verifier_(proof_verifier), verify_context_(std::move(verify_context)), user_agent_id_(user_agent_id), - crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {} + crypto_negotiated_params_(new QuicCryptoNegotiatedParameters), + tls_connection_(ssl_ctx, this) {} TlsClientHandshaker::~TlsClientHandshaker() { if (proof_verify_callback_) { @@ -63,7 +64,7 @@ // static bssl::UniquePtr<SSL_CTX> TlsClientHandshaker::CreateSslCtx() { - return TlsHandshaker::CreateSslCtx(); + return TlsClientConnection::CreateSslCtx(); } bool TlsClientHandshaker::CryptoConnect() { @@ -76,12 +77,6 @@ session()->connection()->InstallDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter)); state_ = STATE_HANDSHAKE_RUNNING; - // Configure certificate verification. - // TODO(nharper): This only verifies certs on initial connection, not on - // resumption. Chromium has this callback be a no-op and verifies the - // certificate after the connection is complete. We need to re-verify on - // resumption in case of expiration or revocation/distrust. - SSL_set_custom_verify(ssl(), SSL_VERIFY_PEER, &VerifyCallback); // Configure the SSL to be a client. SSL_set_connect_state(ssl()); @@ -298,19 +293,6 @@ handshake_confirmed_ = true; } -// static -TlsClientHandshaker* TlsClientHandshaker::HandshakerFromSsl(SSL* ssl) { - return static_cast<TlsClientHandshaker*>( - TlsHandshaker::HandshakerFromSsl(ssl)); -} - -// static -enum ssl_verify_result_t TlsClientHandshaker::VerifyCallback( - SSL* ssl, - uint8_t* out_alert) { - return HandshakerFromSsl(ssl)->VerifyCert(out_alert); -} - enum ssl_verify_result_t TlsClientHandshaker::VerifyCert(uint8_t* out_alert) { if (verify_result_ != ssl_verify_retry || state_ == STATE_CERT_VERIFY_PENDING) {
diff --git a/quic/core/tls_client_handshaker.h b/quic/core/tls_client_handshaker.h index 3647e10..d3e1e0c 100644 --- a/quic/core/tls_client_handshaker.h +++ b/quic/core/tls_client_handshaker.h
@@ -9,6 +9,7 @@ #include "third_party/boringssl/src/include/openssl/ssl.h" #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h" +#include "net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h" #include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h" #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h" #include "net/third_party/quiche/src/quic/core/tls_handshaker.h" @@ -19,8 +20,9 @@ // An implementation of QuicCryptoClientStream::HandshakerDelegate which uses // TLS 1.3 for the crypto handshake protocol. class QUIC_EXPORT_PRIVATE TlsClientHandshaker - : public QuicCryptoClientStream::HandshakerDelegate, - public TlsHandshaker { + : public TlsHandshaker, + public QuicCryptoClientStream::HandshakerDelegate, + public TlsClientConnection::Delegate { public: TlsClientHandshaker(QuicCryptoStream* stream, QuicSession* session, @@ -51,6 +53,17 @@ const override; CryptoMessageParser* crypto_message_parser() override; + protected: + TlsConnection* tls_connection() { return &tls_connection_; } + + void AdvanceHandshake() override; + void CloseConnection(QuicErrorCode error, + const std::string& reason_phrase) override; + + // TlsClientConnection::Delegate implementation: + enum ssl_verify_result_t VerifyCert(uint8_t* out_alert) override; + TlsConnection::Delegate* ConnectionDelegate() override { return this; } + private: // ProofVerifierCallbackImpl handles the result of an asynchronous certificate // verification operation. @@ -83,21 +96,6 @@ bool ProcessTransportParameters(std::string* error_details); void FinishHandshake(); - void AdvanceHandshake() override; - void CloseConnection(QuicErrorCode error, - const std::string& reason_phrase) override; - - // Certificate verification functions: - - enum ssl_verify_result_t VerifyCert(uint8_t* out_alert); - // Static method to supply to SSL_set_custom_verify. - static enum ssl_verify_result_t VerifyCallback(SSL* ssl, uint8_t* out_alert); - - // Takes an SSL* |ssl| and returns a pointer to the TlsClientHandshaker that - // it belongs to. This is a specialization of - // TlsHandshaker::HandshakerFromSsl. - static TlsClientHandshaker* HandshakerFromSsl(SSL* ssl); - QuicServerId server_id_; // Objects used for verifying the server's certificate chain. @@ -119,6 +117,8 @@ bool handshake_confirmed_ = false; QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> crypto_negotiated_params_; + + TlsClientConnection tls_connection_; }; } // namespace quic
diff --git a/quic/core/tls_handshaker.cc b/quic/core/tls_handshaker.cc index aeadfd4..3c82a49 100644 --- a/quic/core/tls_handshaker.cc +++ b/quic/core/tls_handshaker.cc
@@ -13,42 +13,12 @@ namespace quic { -namespace { - -class SslIndexSingleton { - public: - static SslIndexSingleton* GetInstance() { - static SslIndexSingleton* instance = new SslIndexSingleton(); - return instance; - } - - int HandshakerIndex() const { return ssl_ex_data_index_handshaker_; } - - private: - SslIndexSingleton() { - CRYPTO_library_init(); - ssl_ex_data_index_handshaker_ = - SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr); - CHECK_LE(0, ssl_ex_data_index_handshaker_); - } - - SslIndexSingleton(const SslIndexSingleton&) = delete; - SslIndexSingleton& operator=(const SslIndexSingleton&) = delete; - - int ssl_ex_data_index_handshaker_; -}; - -} // namespace - TlsHandshaker::TlsHandshaker(QuicCryptoStream* stream, QuicSession* session, SSL_CTX* ssl_ctx) : stream_(stream), session_(session) { QUIC_BUG_IF(!GetQuicFlag(FLAGS_quic_supports_tls_handshake)) << "Attempted to create TLS handshaker when TLS is disabled"; - ssl_.reset(SSL_new(ssl_ctx)); - SSL_set_ex_data(ssl(), SslIndexSingleton::GetInstance()->HandshakerIndex(), - this); } TlsHandshaker::~TlsHandshaker() {} @@ -62,7 +32,7 @@ // just received input at. If they mismatch, should ProcessInput return true // or false? If data is for a future encryption level, it should be queued for // later? - if (SSL_provide_quic_data(ssl(), BoringEncryptionLevel(level), + if (SSL_provide_quic_data(ssl(), TlsConnection::BoringEncryptionLevel(level), reinterpret_cast<const uint8_t*>(input.data()), input.size()) != 1) { // SSL_provide_quic_data can fail for 3 reasons: @@ -84,58 +54,6 @@ return true; } -// static -bssl::UniquePtr<SSL_CTX> TlsHandshaker::CreateSslCtx() { - CRYPTO_library_init(); - bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_with_buffers_method())); - SSL_CTX_set_min_proto_version(ssl_ctx.get(), TLS1_3_VERSION); - SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION); - SSL_CTX_set_quic_method(ssl_ctx.get(), &kSslQuicMethod); - return ssl_ctx; -} - -// static -TlsHandshaker* TlsHandshaker::HandshakerFromSsl(const SSL* ssl) { - return reinterpret_cast<TlsHandshaker*>(SSL_get_ex_data( - ssl, SslIndexSingleton::GetInstance()->HandshakerIndex())); -} - -// static -EncryptionLevel TlsHandshaker::QuicEncryptionLevel( - enum ssl_encryption_level_t level) { - switch (level) { - case ssl_encryption_initial: - return ENCRYPTION_INITIAL; - case ssl_encryption_early_data: - return ENCRYPTION_ZERO_RTT; - case ssl_encryption_handshake: - return ENCRYPTION_HANDSHAKE; - case ssl_encryption_application: - return ENCRYPTION_FORWARD_SECURE; - default: - QUIC_BUG << "Invalid ssl_encryption_level_t " << static_cast<int>(level); - return ENCRYPTION_INITIAL; - } -} - -// static -enum ssl_encryption_level_t TlsHandshaker::BoringEncryptionLevel( - EncryptionLevel level) { - switch (level) { - case ENCRYPTION_INITIAL: - return ssl_encryption_initial; - case ENCRYPTION_HANDSHAKE: - return ssl_encryption_handshake; - case ENCRYPTION_ZERO_RTT: - return ssl_encryption_early_data; - case ENCRYPTION_FORWARD_SECURE: - return ssl_encryption_application; - default: - QUIC_BUG << "Invalid encryption level " << static_cast<int>(level); - return ssl_encryption_initial; - } -} - const EVP_MD* TlsHandshaker::Prf() { return EVP_get_digestbynid( SSL_CIPHER_get_prf_nid(SSL_get_pending_cipher(ssl()))); @@ -159,53 +77,6 @@ return decrypter; } -const SSL_QUIC_METHOD TlsHandshaker::kSslQuicMethod{ - TlsHandshaker::SetEncryptionSecretCallback, - TlsHandshaker::WriteMessageCallback, TlsHandshaker::FlushFlightCallback, - TlsHandshaker::SendAlertCallback}; - -// static -int TlsHandshaker::SetEncryptionSecretCallback( - SSL* ssl, - enum ssl_encryption_level_t level, - const uint8_t* read_key, - const uint8_t* write_key, - size_t secret_len) { - // TODO(nharper): replace these vectors and memcpys with spans (which - // unfortunately doesn't yet exist in quic/platform/api). - std::vector<uint8_t> read_secret(secret_len), write_secret(secret_len); - memcpy(read_secret.data(), read_key, secret_len); - memcpy(write_secret.data(), write_key, secret_len); - HandshakerFromSsl(ssl)->SetEncryptionSecret(QuicEncryptionLevel(level), - read_secret, write_secret); - return 1; -} - -// static -int TlsHandshaker::WriteMessageCallback(SSL* ssl, - enum ssl_encryption_level_t level, - const uint8_t* data, - size_t len) { - HandshakerFromSsl(ssl)->WriteMessage( - QuicEncryptionLevel(level), - QuicStringPiece(reinterpret_cast<const char*>(data), len)); - return 1; -} - -// static -int TlsHandshaker::FlushFlightCallback(SSL* ssl) { - HandshakerFromSsl(ssl)->FlushFlight(); - return 1; -} - -// static -int TlsHandshaker::SendAlertCallback(SSL* ssl, - enum ssl_encryption_level_t level, - uint8_t desc) { - HandshakerFromSsl(ssl)->SendAlert(QuicEncryptionLevel(level), desc); - return 1; -} - void TlsHandshaker::SetEncryptionSecret( EncryptionLevel level, const std::vector<uint8_t>& read_secret,
diff --git a/quic/core/tls_handshaker.h b/quic/core/tls_handshaker.h index 9658923..b4f16e8 100644 --- a/quic/core/tls_handshaker.h +++ b/quic/core/tls_handshaker.h
@@ -11,6 +11,7 @@ #include "net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h" +#include "net/third_party/quiche/src/quic/core/crypto/tls_connection.h" #include "net/third_party/quiche/src/quic/core/quic_session.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" @@ -22,7 +23,8 @@ // provides functionality common to both the client and server, such as moving // messages between the TLS stack and the QUIC crypto stream, and handling // derivation of secrets. -class QUIC_EXPORT_PRIVATE TlsHandshaker : public CryptoMessageParser { +class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate, + public CryptoMessageParser { public: // TlsHandshaker does not take ownership of any of its arguments; they must // outlive the TlsHandshaker. @@ -55,21 +57,6 @@ virtual void CloseConnection(QuicErrorCode error, const std::string& reason_phrase) = 0; - // 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 TlsHandshaker that it - // belongs to. This is a helper method for implementing callbacks set on an - // SSL, as it allows the callback function to find the TlsHandshaker instance - // and call an instance method. - static TlsHandshaker* HandshakerFromSsl(const SSL* ssl); - - static EncryptionLevel QuicEncryptionLevel(enum ssl_encryption_level_t level); - static enum ssl_encryption_level_t BoringEncryptionLevel( - EncryptionLevel level); - // Returns the PRF used by the cipher suite negotiated in the TLS handshake. const EVP_MD* Prf(); @@ -78,35 +65,13 @@ std::unique_ptr<QuicDecrypter> CreateDecrypter( const std::vector<uint8_t>& pp_secret); - SSL* ssl() { return ssl_.get(); } + virtual TlsConnection* tls_connection() = 0; + + SSL* ssl() { return tls_connection()->ssl(); } + QuicCryptoStream* stream() { return stream_; } QuicSession* session() { return session_; } - private: - // TlsHandshaker implements SSL_QUIC_METHOD, which provides the interface - // between BoringSSL's TLS stack and a QUIC implementation. - static const SSL_QUIC_METHOD kSslQuicMethod; - - // Pointers to the following 4 functions form |kSslQuicMethod|. Each one - // is a wrapper around the corresponding instance method below. The |ssl| - // argument is used to look up correct TlsHandshaker instance on which to call - // the method. According to the BoringSSL documentation, these functions - // return 0 on error and 1 otherwise; here they never error and thus always - // return 1. - static int SetEncryptionSecretCallback(SSL* ssl, - enum ssl_encryption_level_t level, - const uint8_t* read_key, - const uint8_t* write_key, - size_t secret_len); - 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 alert); - // SetEncryptionSecret provides the encryption secret to use at a particular // encryption 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 @@ -115,29 +80,28 @@ // indicates whether it is used for encryption or decryption. void SetEncryptionSecret(EncryptionLevel level, const std::vector<uint8_t>& read_secret, - const std::vector<uint8_t>& write_secret); + const std::vector<uint8_t>& write_secret) override; // 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|. - void WriteMessage(EncryptionLevel level, QuicStringPiece data); + void WriteMessage(EncryptionLevel level, QuicStringPiece data) override; // 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. - void FlushFlight(); + void FlushFlight() override; // SendAlert causes this TlsHandshaker to close the QUIC connection with an // error code corresponding to the TLS alert description |desc|. - void SendAlert(EncryptionLevel level, uint8_t desc); + void SendAlert(EncryptionLevel level, uint8_t desc) override; + private: QuicCryptoStream* stream_; QuicSession* session_; QuicErrorCode parser_error_ = QUIC_NO_ERROR; std::string parser_error_detail_; - - bssl::UniquePtr<SSL> ssl_; }; } // namespace quic
diff --git a/quic/core/tls_handshaker_test.cc b/quic/core/tls_handshaker_test.cc index e710d7b..cc22c59 100644 --- a/quic/core/tls_handshaker_test.cc +++ b/quic/core/tls_handshaker_test.cc
@@ -4,6 +4,8 @@ #include <string> +#include "net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h" +#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" @@ -210,7 +212,7 @@ explicit TestQuicCryptoClientStream(QuicSession* session) : TestQuicCryptoStream(session), proof_verifier_(new FakeProofVerifier), - ssl_ctx_(TlsClientHandshaker::CreateSslCtx()), + ssl_ctx_(TlsClientConnection::CreateSslCtx()), handshaker_(new TlsClientHandshaker( this, session, @@ -242,7 +244,7 @@ FakeProofSource* proof_source) : TestQuicCryptoStream(session), proof_source_(proof_source), - ssl_ctx_(TlsServerHandshaker::CreateSslCtx()), + ssl_ctx_(TlsServerConnection::CreateSslCtx()), handshaker_(new TlsServerHandshaker(this, session, ssl_ctx_.get(),
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc index ca56e4d..fdda21f 100644 --- a/quic/core/tls_server_handshaker.cc +++ b/quic/core/tls_server_handshaker.cc
@@ -40,20 +40,9 @@ handshaker_ = nullptr; } -const SSL_PRIVATE_KEY_METHOD TlsServerHandshaker::kPrivateKeyMethod{ - &TlsServerHandshaker::PrivateKeySign, - nullptr, // decrypt - &TlsServerHandshaker::PrivateKeyComplete, -}; - // static bssl::UniquePtr<SSL_CTX> TlsServerHandshaker::CreateSslCtx() { - bssl::UniquePtr<SSL_CTX> ssl_ctx = TlsHandshaker::CreateSslCtx(); - SSL_CTX_set_tlsext_servername_callback( - ssl_ctx.get(), TlsServerHandshaker::SelectCertificateCallback); - SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), - TlsServerHandshaker::SelectAlpnCallback, nullptr); - return ssl_ctx; + return TlsServerConnection::CreateSslCtx(); } TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream, @@ -62,7 +51,8 @@ ProofSource* proof_source) : TlsHandshaker(stream, session, ssl_ctx), proof_source_(proof_source), - crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) { + crypto_negotiated_params_(new QuicCryptoNegotiatedParameters), + tls_connection_(ssl_ctx, this) { DCHECK_EQ(PROTOCOL_TLS1_3, session->connection()->version().handshake_protocol); CrypterPair crypters; @@ -264,25 +254,6 @@ handshake_confirmed_ = true; } -// static -TlsServerHandshaker* TlsServerHandshaker::HandshakerFromSsl(SSL* ssl) { - return static_cast<TlsServerHandshaker*>( - TlsHandshaker::HandshakerFromSsl(ssl)); -} - -// static -ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(SSL* ssl, - uint8_t* out, - size_t* out_len, - size_t max_out, - uint16_t sig_alg, - const uint8_t* in, - size_t in_len) { - return HandshakerFromSsl(ssl)->PrivateKeySign( - out, out_len, max_out, sig_alg, - QuicStringPiece(reinterpret_cast<const char*>(in), in_len)); -} - ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign( uint8_t* out, size_t* out_len, @@ -300,15 +271,6 @@ return ssl_private_key_retry; } -// static -ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete( - SSL* ssl, - uint8_t* out, - size_t* out_len, - size_t max_out) { - return HandshakerFromSsl(ssl)->PrivateKeyComplete(out, out_len, max_out); -} - ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete( uint8_t* out, size_t* out_len, @@ -326,13 +288,6 @@ return ssl_private_key_success; } -// static -int TlsServerHandshaker::SelectCertificateCallback(SSL* ssl, - int* out_alert, - void* arg) { - return HandshakerFromSsl(ssl)->SelectCertificate(out_alert); -} - int TlsServerHandshaker::SelectCertificate(int* out_alert) { const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name); if (hostname) { @@ -357,8 +312,7 @@ chain->certs[i].length(), nullptr); } - SSL_set_chain_and_key(ssl(), certs.data(), certs.size(), nullptr, - &kPrivateKeyMethod); + tls_connection_.SetCertChain(certs); for (size_t i = 0; i < certs.size(); i++) { CRYPTO_BUFFER_free(certs[i]); @@ -375,16 +329,6 @@ return SSL_TLSEXT_ERR_OK; } -// static -int TlsServerHandshaker::SelectAlpnCallback(SSL* ssl, - const uint8_t** out, - uint8_t* out_len, - const uint8_t* in, - unsigned in_len, - void* arg) { - return HandshakerFromSsl(ssl)->SelectAlpn(out, out_len, in, in_len); -} - int TlsServerHandshaker::SelectAlpn(const uint8_t** out, uint8_t* out_len, const uint8_t* in,
diff --git a/quic/core/tls_server_handshaker.h b/quic/core/tls_server_handshaker.h index e27d896..479342e 100644 --- a/quic/core/tls_server_handshaker.h +++ b/quic/core/tls_server_handshaker.h
@@ -9,6 +9,7 @@ #include "third_party/boringssl/src/include/openssl/pool.h" #include "third_party/boringssl/src/include/openssl/ssl.h" +#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h" #include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters.pb.h" #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h" #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h" @@ -20,8 +21,9 @@ // An implementation of QuicCryptoServerStream::HandshakerDelegate which uses // TLS 1.3 for the crypto handshake protocol. class QUIC_EXPORT_PRIVATE TlsServerHandshaker - : public QuicCryptoServerStream::HandshakerDelegate, - public TlsHandshaker { + : public TlsHandshaker, + public TlsServerConnection::Delegate, + public QuicCryptoServerStream::HandshakerDelegate { public: TlsServerHandshaker(QuicCryptoStream* stream, QuicSession* session, @@ -57,17 +59,30 @@ const override; CryptoMessageParser* crypto_message_parser() override; - // Calls SelectCertificate after looking up the TlsServerHandshaker from - // |ssl|. - static int SelectCertificateCallback(SSL* ssl, int* out_alert, void* arg); + protected: + TlsConnection* tls_connection() { return &tls_connection_; } - // Calls SelectAlpn after looking up the TlsServerHandshaker from |ssl|. - static int SelectAlpnCallback(SSL* ssl, - const uint8_t** out, - uint8_t* out_len, - const uint8_t* in, - unsigned in_len, - void* arg); + // Called when a new message is received on the crypto stream and is available + // for the TLS stack to read. + void AdvanceHandshake() override; + void CloseConnection(QuicErrorCode error, + const std::string& reason_phrase) override; + + // TlsServerConnection::Delegate implementation: + int SelectCertificate(int* out_alert) override; + int SelectAlpn(const uint8_t** out, + uint8_t* out_len, + const uint8_t* in, + unsigned in_len) override; + ssl_private_key_result_t PrivateKeySign(uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t sig_alg, + QuicStringPiece in) override; + ssl_private_key_result_t PrivateKeyComplete(uint8_t* out, + size_t* out_len, + size_t max_out) override; + TlsConnection::Delegate* ConnectionDelegate() override { return this; } private: class SignatureCallback : public ProofSource::SignatureCallback { @@ -90,17 +105,6 @@ STATE_CONNECTION_CLOSED, }; - // |kPrivateKeyMethod| is a vtable pointing to PrivateKeySign and - // PrivateKeyComplete used by the TLS stack to compute the signature for the - // CertificateVerify message (using the server's private key). - static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod; - - // Called when a new message is received on the crypto stream and is available - // for the TLS stack to read. - void AdvanceHandshake() override; - void CloseConnection(QuicErrorCode error, - const std::string& reason_phrase) override; - // Called when the TLS handshake is complete. void FinishHandshake(); @@ -109,61 +113,6 @@ bool SetTransportParameters(); bool ProcessTransportParameters(std::string* error_details); - // Calls the instance method PrivateKeySign after looking up the - // TlsServerHandshaker from |ssl|. - static ssl_private_key_result_t PrivateKeySign(SSL* ssl, - uint8_t* out, - size_t* out_len, - size_t max_out, - uint16_t sig_alg, - const uint8_t* in, - size_t in_len); - - // Signs |in| using the signature algorithm specified by |sig_alg| (an - // SSL_SIGN_* value). If the signing operation cannot be completed - // synchronously, ssl_private_key_retry is returned. If there is an error - // signing, or if the signature is longer than |max_out|, then - // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success is - // returned with the signature put in |*out| and the length in |*out_len|. - ssl_private_key_result_t PrivateKeySign(uint8_t* out, - size_t* out_len, - size_t max_out, - uint16_t sig_alg, - QuicStringPiece in); - - // Calls the instance method PrivateKeyComplete after looking up the - // TlsServerHandshaker from |ssl|. - static ssl_private_key_result_t PrivateKeyComplete(SSL* ssl, - uint8_t* out, - size_t* out_len, - size_t max_out); - - // When PrivateKeySign returns ssl_private_key_retry, PrivateKeyComplete will - // be called after the async sign operation has completed. PrivateKeyComplete - // puts the resulting signature in |*out| and length in |*out_len|. If the - // length is greater than |max_out| or if there was an error in signing, then - // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success is - // returned. - ssl_private_key_result_t PrivateKeyComplete(uint8_t* out, - size_t* out_len, - size_t max_out); - - // Configures the certificate to use on |ssl_| based on the SNI sent by the - // client. Returns an SSL_TLSEXT_ERR_* value (see - // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_tlsext_servername_callback). - // - // If SelectCertificate returns SSL_TLSEXT_ERR_ALERT_FATAL, then it puts in - // |*out_alert| the TLS alert value that the server will send. - int SelectCertificate(int* out_alert); - - // Selects which ALPN to use based on the list sent by the client. - int SelectAlpn(const uint8_t** out, - uint8_t* out_len, - const uint8_t* in, - unsigned in_len); - - static TlsServerHandshaker* HandshakerFromSsl(SSL* ssl); - State state_ = STATE_LISTENING; ProofSource* proof_source_; @@ -176,6 +125,7 @@ bool handshake_confirmed_ = false; QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> crypto_negotiated_params_; + TlsServerConnection tls_connection_; }; } // namespace quic
diff --git a/quic/test_tools/crypto_test_utils.cc b/quic/test_tools/crypto_test_utils.cc index 354856a..0b67287 100644 --- a/quic/test_tools/crypto_test_utils.cc +++ b/quic/test_tools/crypto_test_utils.cc
@@ -25,8 +25,6 @@ #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h" #include "net/third_party/quiche/src/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_clock.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" @@ -219,8 +217,7 @@ QuicCryptoServerConfig crypto_config( QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), - ProofSourceForTesting(), KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + ProofSourceForTesting(), KeyExchangeSource::Default()); QuicCompressedCertsCache compressed_certs_cache( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize); SetupCryptoServerConfigForTest( @@ -271,8 +268,7 @@ // Advance the time, because timers do not like uninitialized times. client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1)); - QuicCryptoClientConfig crypto_config(ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()); + QuicCryptoClientConfig crypto_config(ProofVerifierForTesting()); TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(), supported_versions, server_id, &crypto_config);
diff --git a/quic/test_tools/crypto_test_utils_test.cc b/quic/test_tools/crypto_test_utils_test.cc index 069413b..e7f9679 100644 --- a/quic/test_tools/crypto_test_utils_test.cc +++ b/quic/test_tools/crypto_test_utils_test.cc
@@ -6,7 +6,6 @@ #include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.pb.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" #include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h" @@ -110,8 +109,7 @@ MockClock clock; QuicCryptoServerConfig crypto_config( QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()); + crypto_test_utils::ProofSourceForTesting(), KeyExchangeSource::Default()); QuicSocketAddress server_addr(QuicIpAddress::Any4(), 5); QuicSocketAddress client_addr(QuicIpAddress::Loopback4(), 1); QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config(
diff --git a/quic/tools/quic_client_base.cc b/quic/tools/quic_client_base.cc index 9cecffe..b03f7cc 100644 --- a/quic/tools/quic_client_base.cc +++ b/quic/tools/quic_client_base.cc
@@ -8,7 +8,6 @@ #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" #include "net/third_party/quiche/src/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h" @@ -29,8 +28,7 @@ initialized_(false), local_port_(0), config_(config), - crypto_config_(std::move(proof_verifier), - TlsClientHandshaker::CreateSslCtx()), + crypto_config_(std::move(proof_verifier)), helper_(helper), alarm_factory_(alarm_factory), supported_versions_(supported_versions),
diff --git a/quic/tools/quic_server.cc b/quic/tools/quic_server.cc index 3696b7c..8820040 100644 --- a/quic/tools/quic_server.cc +++ b/quic/tools/quic_server.cc
@@ -24,7 +24,6 @@ #include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h" #include "net/third_party/quiche/src/quic/core/quic_packet_reader.h" #include "net/third_party/quiche/src/quic/core/quic_packets.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_clock.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" @@ -74,8 +73,7 @@ crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance(), std::move(proof_source), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), crypto_config_options_(crypto_config_options), version_manager_(supported_versions), packet_reader_(new QuicPacketReader()),
diff --git a/quic/tools/quic_server_test.cc b/quic/tools/quic_server_test.cc index bb007cb..b1a88a6 100644 --- a/quic/tools/quic_server_test.cc +++ b/quic/tools/quic_server_test.cc
@@ -8,7 +8,6 @@ #include "net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h" #include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" @@ -154,8 +153,7 @@ : crypto_config_("blah", QuicRandom::GetInstance(), crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), version_manager_(AllSupportedVersions()), dispatcher_( &config_,
diff --git a/quic/tools/quic_simple_server_session_test.cc b/quic/tools/quic_simple_server_session_test.cc index 9071e05..457f3fa 100644 --- a/quic/tools/quic_simple_server_session_test.cc +++ b/quic/tools/quic_simple_server_session_test.cc
@@ -13,7 +13,6 @@ #include "net/third_party/quiche/src/quic/core/quic_connection.h" #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" @@ -201,8 +200,7 @@ : crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx()), + KeyExchangeSource::Default()), compressed_certs_cache_( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc index fcceb33..9ce38fb 100644 --- a/quic/tools/quic_simple_server_stream_test.cc +++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -10,7 +10,6 @@ #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" @@ -176,8 +175,7 @@ QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), crypto_test_utils::ProofSourceForTesting(), - KeyExchangeSource::Default(), - TlsServerHandshaker::CreateSslCtx())), + KeyExchangeSource::Default())), compressed_certs_cache_( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), session_(connection_,