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(
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) {
os << collector.describe();
return os;
......
......@@ -151,20 +151,21 @@ class 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
*/
virtual void ciphers(const std::string& ciphers);
/**
* Low-level method that attempts to set the provided ciphers on the
* SSL_CTX object, and throws if something goes wrong.
* Low-level method that attempts to set the provided TLS 1.2
* and below ciphers on the SSL_CTX object,
* and throws if something goes wrong.
*/
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>
void setCipherList(Iterator ibegin, Iterator iend) {
......@@ -559,6 +560,15 @@ class SSLContext {
void setSessionLifecycleCallbacks(
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();
protected:
......
......@@ -29,6 +29,7 @@ class SSLContextTest : public testing::Test {
public:
SSLContext ctx;
void verifySSLCipherList(const vector<string>& ciphers);
void verifySSLCiphersuites(const vector<string>& ciphersuites);
};
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()));
}
void SSLContextTest::verifySSLCiphersuites(const vector<string>& ciphersuites) {
ssl::SSLUniquePtr ssl(ctx.createSSL());
EXPECT_EQ(ciphersuites, test::getTLS13Ciphersuites(ssl.get()));
}
TEST_F(SSLContextTest, TestSetCipherString) {
ctx.ciphers("AES128-SHA:ECDHE-RSA-AES256-SHA384");
verifySSLCipherList({"AES128-SHA", "ECDHE-RSA-AES256-SHA384"});
......@@ -205,4 +211,24 @@ TEST_F(SSLContextTest, TestInvalidSigAlgThrows) {
}
}
#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
......@@ -71,5 +71,18 @@ std::vector<std::string> getNonTLS13CipherList(SSL* s) {
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 folly
......@@ -30,5 +30,7 @@ std::vector<std::string> getCiphersFromSSL(SSL* s);
std::vector<std::string> getNonTLS13CipherList(SSL* s);
std::vector<std::string> getTLS13Ciphersuites(SSL* s);
} // namespace test
} // 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