Commit a247041e authored by Andrew Huang's avatar Andrew Huang Committed by Facebook GitHub Bot

Add ability to set TLS 1.3 ciphersuites in SSLContext

Summary: Add support for Openssl's TLS 1.3 ciphersuites API. SSL_CTX_set_ciphersuites was added in OpenSSL 1.1.1, so guard it with a prereq.

Reviewed By: yfeldblum, mingtaoy

Differential Revision: D24542765

fbshipit-source-id: d281bb2262cd456823da1896c0c77c3ba4ab78ce
parent 9a1bfc69
...@@ -771,6 +771,15 @@ void SSLContext::setSessionLifecycleCallbacks( ...@@ -771,6 +771,15 @@ void SSLContext::setSessionLifecycleCallbacks(
sessionLifecycleCallbacks_ = std::move(cb); sessionLifecycleCallbacks_ = std::move(cb);
} }
#if FOLLY_OPENSSL_PREREQ(1, 1, 1)
void SSLContext::setCiphersuitesOrThrow(const std::string& ciphersuites) {
auto rc = SSL_CTX_set_ciphersuites(ctx_, ciphersuites.c_str());
if (rc == 0) {
throw std::runtime_error("SSL_CTX_set_ciphersuites: " + getErrors());
}
}
#endif // FOLLY_OPENSSL_PREREQ(1, 1, 1)
std::ostream& operator<<(std::ostream& os, const PasswordCollector& collector) { std::ostream& operator<<(std::ostream& os, const PasswordCollector& collector) {
os << collector.describe(); os << collector.describe();
return os; return os;
......
...@@ -151,20 +151,21 @@ class SSLContext { ...@@ -151,20 +151,21 @@ class SSLContext {
virtual ~SSLContext(); virtual ~SSLContext();
/** /**
* Set default ciphers to be used in SSL handshake process. * Set default TLS 1.2 and below ciphers to be used in SSL handshake process.
* *
* @param ciphers A list of ciphers to use for TLSv1.0 * @param ciphers A list of ciphers to use for TLSv1.0
*/ */
virtual void ciphers(const std::string& ciphers); virtual void ciphers(const std::string& ciphers);
/** /**
* Low-level method that attempts to set the provided ciphers on the * Low-level method that attempts to set the provided TLS 1.2
* SSL_CTX object, and throws if something goes wrong. * and below ciphers on the SSL_CTX object,
* and throws if something goes wrong.
*/ */
virtual void setCiphersOrThrow(const std::string& ciphers); virtual void setCiphersOrThrow(const std::string& ciphers);
/** /**
* Set default ciphers to be used in SSL handshake process. * Set default TLS 1.2 and below ciphers to be used in SSL handshake process.
*/ */
template <typename Iterator> template <typename Iterator>
void setCipherList(Iterator ibegin, Iterator iend) { void setCipherList(Iterator ibegin, Iterator iend) {
...@@ -559,6 +560,15 @@ class SSLContext { ...@@ -559,6 +560,15 @@ class SSLContext {
void setSessionLifecycleCallbacks( void setSessionLifecycleCallbacks(
std::unique_ptr<SessionLifecycleCallbacks> cb); std::unique_ptr<SessionLifecycleCallbacks> cb);
#if FOLLY_OPENSSL_PREREQ(1, 1, 1)
/**
* Set the TLS 1.3 ciphersuites to be used in the SSL handshake, in
* order of preference.
* Throws if unsuccessful.
*/
void setCiphersuitesOrThrow(const std::string& ciphersuites);
#endif
[[deprecated("Use folly::ssl::init")]] static void initializeOpenSSL(); [[deprecated("Use folly::ssl::init")]] static void initializeOpenSSL();
protected: protected:
......
...@@ -29,6 +29,7 @@ class SSLContextTest : public testing::Test { ...@@ -29,6 +29,7 @@ class SSLContextTest : public testing::Test {
public: public:
SSLContext ctx; SSLContext ctx;
void verifySSLCipherList(const vector<string>& ciphers); void verifySSLCipherList(const vector<string>& ciphers);
void verifySSLCiphersuites(const vector<string>& ciphersuites);
}; };
void SSLContextTest::verifySSLCipherList(const vector<string>& ciphers) { void SSLContextTest::verifySSLCipherList(const vector<string>& ciphers) {
...@@ -36,6 +37,11 @@ void SSLContextTest::verifySSLCipherList(const vector<string>& ciphers) { ...@@ -36,6 +37,11 @@ void SSLContextTest::verifySSLCipherList(const vector<string>& ciphers) {
EXPECT_EQ(ciphers, test::getNonTLS13CipherList(ssl.get())); EXPECT_EQ(ciphers, test::getNonTLS13CipherList(ssl.get()));
} }
void SSLContextTest::verifySSLCiphersuites(const vector<string>& ciphersuites) {
ssl::SSLUniquePtr ssl(ctx.createSSL());
EXPECT_EQ(ciphersuites, test::getTLS13Ciphersuites(ssl.get()));
}
TEST_F(SSLContextTest, TestSetCipherString) { TEST_F(SSLContextTest, TestSetCipherString) {
ctx.ciphers("AES128-SHA:ECDHE-RSA-AES256-SHA384"); ctx.ciphers("AES128-SHA:ECDHE-RSA-AES256-SHA384");
verifySSLCipherList({"AES128-SHA", "ECDHE-RSA-AES256-SHA384"}); verifySSLCipherList({"AES128-SHA", "ECDHE-RSA-AES256-SHA384"});
...@@ -205,4 +211,24 @@ TEST_F(SSLContextTest, TestInvalidSigAlgThrows) { ...@@ -205,4 +211,24 @@ TEST_F(SSLContextTest, TestInvalidSigAlgThrows) {
} }
} }
#endif #endif
#if FOLLY_OPENSSL_PREREQ(1, 1, 1)
TEST_F(SSLContextTest, TestSetCiphersuites) {
std::vector<std::string> ciphersuitesList{
"TLS_AES_128_CCM_SHA256",
"TLS_AES_128_GCM_SHA256",
};
std::string ciphersuites;
folly::join(":", ciphersuitesList, ciphersuites);
ctx.setCiphersuitesOrThrow(ciphersuites);
verifySSLCiphersuites(ciphersuitesList);
}
TEST_F(SSLContextTest, TestSetInvalidCiphersuite) {
EXPECT_THROW(
ctx.setCiphersuitesOrThrow("ECDHE-ECDSA-AES256-GCM-SHA384"),
std::runtime_error);
}
#endif // FOLLY_OPENSSL_PREREQ(1, 1, 1)
} // namespace folly } // namespace folly
...@@ -71,5 +71,18 @@ std::vector<std::string> getNonTLS13CipherList(SSL* s) { ...@@ -71,5 +71,18 @@ std::vector<std::string> getNonTLS13CipherList(SSL* s) {
return ciphers; return ciphers;
} }
std::vector<std::string> getTLS13Ciphersuites(SSL* s) {
auto ciphers = getCiphersFromSSL(s);
ciphers.erase(
std::remove_if(
begin(ciphers),
end(ciphers),
[](const std::string& cipher) {
return suitesFor13.count(cipher) == 0;
}),
end(ciphers));
return ciphers;
}
} // namespace test } // namespace test
} // namespace folly } // namespace folly
...@@ -30,5 +30,7 @@ std::vector<std::string> getCiphersFromSSL(SSL* s); ...@@ -30,5 +30,7 @@ std::vector<std::string> getCiphersFromSSL(SSL* s);
std::vector<std::string> getNonTLS13CipherList(SSL* s); std::vector<std::string> getNonTLS13CipherList(SSL* s);
std::vector<std::string> getTLS13Ciphersuites(SSL* s);
} // namespace test } // namespace test
} // namespace folly } // namespace folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment