portability/Malloc.h \
portability/Math.h \
portability/Memory.h \
+ portability/OpenSSL.h \
portability/PThread.h \
portability/Sockets.h \
portability/Stdio.h \
SpookyHashV1.h \
SpookyHashV2.h \
ssl/OpenSSLHash.h \
+ ssl/OpenSSLVersionFinder.h \
ssl/SSLSession.h \
- ssl/detail/OpenSSLVersionFinder.h \
ssl/detail/SSLSessionImpl.h \
stats/BucketedTimeSeries-defs.h \
stats/BucketedTimeSeries.h \
portability/Libgen.cpp \
portability/Malloc.cpp \
portability/Memory.cpp \
+ portability/OpenSSL.cpp \
portability/Sockets.cpp \
portability/Stdio.cpp \
portability/Stdlib.cpp \
#include <folly/Bits.h>
#include <folly/SocketAddress.h>
#include <folly/SpinLock.h>
-#include <folly/io/IOBuf.h>
#include <folly/io/Cursor.h>
+#include <folly/io/IOBuf.h>
+#include <folly/portability/OpenSSL.h>
#include <folly/portability/Unistd.h>
using folly::SocketAddress;
using folly::AsyncSSLSocket;
using folly::Optional;
using folly::SSLContext;
+// For OpenSSL portability API
+using namespace folly::ssl;
using folly::ssl::OpenSSLUtils;
// We have one single dummy SSL context so that we can implement attach
// previously called.
// We need to update the initial_ctx if necessary
auto sslCtx = ctx->getSSLCtx();
+ SSL_CTX_up_ref(sslCtx);
#ifndef OPENSSL_NO_TLSEXT
- CRYPTO_add(&sslCtx->references, 1, CRYPTO_LOCK_SSL_CTX);
// note that detachSSLContext has already freed ssl_->initial_ctx
ssl_->initial_ctx = sslCtx;
#endif
sslSession_ = session;
if (!takeOwnership && session != nullptr) {
// Increment the reference count
- CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ // This API exists in BoringSSL and OpenSSL 1.1.0
+ SSL_SESSION_up_ref(session);
}
}
};
namespace folly {
+//
+// For OpenSSL portability API
+using namespace folly::ssl;
bool SSLContext::initialized_ = false;
#include <random>
// This has to come before SSL.
+#include <folly/portability/OpenSSL.h>
#include <folly/portability/Sockets.h>
#include <openssl/ssl.h>
*/
#include <folly/io/async/ssl/OpenSSLUtils.h>
#include <folly/ScopeGuard.h>
+#include <folly/portability/OpenSSL.h>
#include <folly/portability/Sockets.h>
#include <glog/logging.h>
#include <openssl/bio.h>
#include <openssl/x509v3.h>
#include <unordered_map>
-#define OPENSSL_IS_101 (OPENSSL_VERSION_NUMBER >= 0x1000105fL && \
- OPENSSL_VERSION_NUMBER < 0x1000200fL)
-#define OPENSSL_IS_102 (OPENSSL_VERSION_NUMBER >= 0x1000200fL && \
- OPENSSL_VERSION_NUMBER < 0x10100000L)
-#define OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-
namespace {
#if defined(OPENSSL_IS_BORINGSSL)
// BoringSSL doesn't (as of May 2016) export the equivalent
bool OpenSSLUtils::getTLSMasterKey(
const SSL_SESSION* session,
MutableByteRange keyOut) {
-#if OPENSSL_IS_101 || OPENSSL_IS_102
+#if FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_102
if (session &&
session->master_key_length == static_cast<int>(keyOut.size())) {
auto masterKey = session->master_key;
masterKey, masterKey + session->master_key_length, keyOut.begin());
return true;
}
+#else
+ (SSL_SESSION*)session;
+ (MutableByteRange) keyOut;
#endif
return false;
}
bool OpenSSLUtils::getTLSClientRandom(
const SSL* ssl,
MutableByteRange randomOut) {
-#if OPENSSL_IS_101 || OPENSSL_IS_102
+#if FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_102
if ((SSL_version(ssl) >> 8) == TLS1_VERSION_MAJOR && ssl->s3 &&
randomOut.size() == SSL3_RANDOM_SIZE) {
auto clientRandom = ssl->s3->client_random;
std::copy(clientRandom, clientRandom + SSL3_RANDOM_SIZE, randomOut.begin());
return true;
}
+#else
+ (SSL*)ssl;
+ (MutableByteRange) randomOut;
#endif
return false;
}
}
}
- for (int i = 0; i < sk_GENERAL_NAME_num(altNames); i++) {
+ for (size_t i = 0; i < (size_t)sk_GENERAL_NAME_num(altNames); i++) {
auto name = sk_GENERAL_NAME_value(altNames, i);
if ((addr4 != nullptr || addr6 != nullptr) && name->type == GEN_IPADD) {
// Extra const-ness for paranoia
BIO_METHOD* bioMeth,
int (*meth)(BIO*, char*, int)) {
bool ret = false;
-#if OPENSSL_IS_110
ret = (BIO_meth_set_read(bioMeth, meth) == 1);
-#elif (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_IS_101 || OPENSSL_IS_102)
- bioMeth->bread = meth;
- ret = true;
-#endif
-
return ret;
}
BIO_METHOD* bioMeth,
int (*meth)(BIO*, const char*, int)) {
bool ret = false;
-#if OPENSSL_IS_110
ret = (BIO_meth_set_write(bioMeth, meth) == 1);
-#elif (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_IS_101 || OPENSSL_IS_102)
- bioMeth->bwrite = meth;
- ret = true;
-#endif
-
return ret;
}
TEST(SSLErrorsTest, TestMessage) {
ERR_load_crypto_strings();
- auto err = ERR_PACK(
+ unsigned long err;
+#ifdef OPENSSL_IS_BORINGSSL
+ err = ERR_PACK(ERR_LIB_X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+#else
+ err = ERR_PACK(
ERR_LIB_X509,
X509_F_X509_STORE_ADD_CERT,
X509_R_CERT_ALREADY_IN_HASH_TABLE);
+#endif
SSLException ex(0, err, 0, 0);
+
+// This is flaky - we should not be testing error strings
+// which may change version to version
+#if defined(OPENSSL_IS_BORINGSSL)
+ std::string expectedMsg =
+ "AsyncSocketException: error:0b000069:X.509 certificate routines:"
+ "OPENSSL_internal:CERT_ALREADY_IN_HASH_TABLE, type = SSL error";
+#else
std::string expectedMsg =
"AsyncSocketException: error:0B07C065:"
"x509 certificate routines:X509_STORE_add_cert:"
"cert already in hash table, type = SSL error";
+#endif
std::string actual = ex.what();
EXPECT_EQ(expectedMsg, actual);
}
/**
* Test bad renegotiation
*/
+#if !defined(OPENSSL_IS_BORINGSSL)
TEST(AsyncSSLSocketTest, Renegotiate) {
EventBase eventBase;
auto clientCtx = std::make_shared<SSLContext>();
eventBase.loop();
ASSERT_TRUE(server.renegotiationError_);
}
+#endif
/**
* Negative test for handshakeError().
// mismatch should result in a fatal alert, but this is OpenSSL's current
// behavior and we want to know if it changes.
expectNoProtocol();
- } else {
+ }
+#if defined(OPENSSL_IS_BORINGSSL)
+ // BoringSSL also doesn't fatal on mismatch but behaves slightly differently
+ // from OpenSSL 1.0.2h+ - it doesn't select a protocol if both ends support
+ // NPN *and* ALPN
+ else if (
+ GetParam().first == SSLContext::NextProtocolType::ANY &&
+ GetParam().second == SSLContext::NextProtocolType::ANY) {
+ expectNoProtocol();
+ }
+#endif
+ else {
expectProtocol("blub");
expectProtocolType(
{SSLContext::NextProtocolType::NPN, SSLContext::NextProtocolType::NPN});
cerr << "SSLClientTimeoutTest test completed" << endl;
}
-// This is a FB-only extension, and the tests will fail without it
+// The next 3 tests need an FB-only extension, and will fail without it
#ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
/**
* Test SSL server async cache
cerr << "SSLServerAsyncCacheTest test completed" << endl;
}
-
/**
* Test SSL server accept timeout with cache path
*/
cerr << "SSLServerCacheCloseTest test completed" << endl;
}
-#endif
+#endif // !SSL_ERROR_WANT_SESS_CACHE_LOOKUP
/**
* Verify Client Ciphers obtained using SSL MSG Callback.
serverCtx->loadClientCAList(testCA);
clientCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY);
- clientCtx->ciphers("AES256-SHA:RC4-MD5");
+ clientCtx->ciphers("AES256-SHA:AES128-SHA");
clientCtx->loadPrivateKey(testKey);
clientCtx->loadCertificate(testCert);
clientCtx->loadTrustedCertificates(testCA);
eventBase.loop();
- EXPECT_EQ(server.clientCiphers_, "AES256-SHA:RC4-MD5:00ff");
+#if defined(OPENSSL_IS_BORINGSSL)
+ EXPECT_EQ(server.clientCiphers_, "AES256-SHA:AES128-SHA");
+#else
+ EXPECT_EQ(server.clientCiphers_, "AES256-SHA:AES128-SHA:00ff");
+#endif
EXPECT_EQ(server.chosenCipher_, "AES256-SHA");
EXPECT_TRUE(client.handshakeVerify_);
EXPECT_TRUE(client.handshakeSuccess_);
handshakeCallback.waitForHandshake();
EXPECT_NE(handshakeCallback.errorString_.find("SSL routines"),
std::string::npos);
+#if defined(OPENSSL_IS_BORINGSSL)
+ EXPECT_NE(
+ handshakeCallback.errorString_.find("ENCRYPTED_LENGTH_TOO_LONG"),
+ std::string::npos);
+#else
EXPECT_NE(handshakeCallback.errorString_.find("unknown protocol"),
std::string::npos);
+#endif
}
TEST(AsyncSSLSocketTest, TestSSLCipherCodeToNameMap) {
sock.close();
}
+#if !defined(OPENSSL_IS_BORINGSSL)
TEST(AsyncSSLSocketTest, ConnectTFOTimeout) {
// Start listening on a local port
ConnectTimeoutCallback acceptCallback;
EXPECT_THROW(
socket->open(std::chrono::milliseconds(20)), AsyncSocketException);
}
+#endif
+#if !defined(OPENSSL_IS_BORINGSSL)
TEST(AsyncSSLSocketTest, ConnectTFOFallbackTimeout) {
// Start listening on a local port
ConnectTimeoutCallback acceptCallback;
evb.loop();
EXPECT_EQ(ConnCallback::State::ERROR, ccb.state);
}
+#endif
TEST(AsyncSSLSocketTest, HandshakeTFOFallbackTimeout) {
// Start listening on a local port
int* copyflag) {
*copyflag = 0;
asyncCallbacks_++;
+ (void)ssl;
#ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
if (!SSL_want_sess_cache_lookup(ssl)) {
// libssl.so mismatch
signal(SIGPIPE, SIG_IGN);
#endif
folly::SSLContext::setSSLLockTypes({
+#ifdef CRYPTO_LOCK_EVP_PKEY
{CRYPTO_LOCK_EVP_PKEY, folly::SSLContext::LOCK_NONE},
+#endif
+#ifdef CRYPTO_LOCK_SSL_SESSION
{CRYPTO_LOCK_SSL_SESSION, folly::SSLContext::LOCK_SPINLOCK},
- {CRYPTO_LOCK_SSL_CTX, folly::SSLContext::LOCK_NONE}});
+#endif
+#ifdef CRYPTO_LOCK_SSL_CTX
+ {CRYPTO_LOCK_SSL_CTX, folly::SSLContext::LOCK_NONE}
+#endif
+ });
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
return RUN_ALL_TESTS();
--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <folly/portability/OpenSSL.h>
+
+namespace folly {
+namespace ssl {
+
+#ifdef OPENSSL_IS_BORINGSSL
+int SSL_CTX_set1_sigalgs_list(SSL_CTX*, const char*) {
+ return 1; // 0 implies error
+}
+
+int TLS1_get_client_version(SSL* s) {
+ return s->client_version;
+}
+
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int)) {
+ biom->bread = read;
+ return 1;
+}
+
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) {
+ biom->bwrite = write;
+ return 1;
+}
+
+#elif FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_101
+int SSL_CTX_up_ref(SSL_CTX* ctx) {
+ return CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
+}
+
+int SSL_SESSION_up_ref(SSL_SESSION* session) {
+ return CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
+}
+
+int X509_up_ref(X509* x) {
+ return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+}
+
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int)) {
+ biom->bread = read;
+ return 1;
+}
+
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) {
+ biom->bwrite = write;
+ return 1;
+}
+
+#elif FOLLY_OPENSSL_IS_110
+
+#endif
+}
+}
--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+namespace folly {
+namespace ssl {
+
+// BoringSSL doesn't have notion of versioning although it defines
+// OPENSSL_VERSION_NUMBER to maintain compatibility. The following variables are
+// intended to be specific to OpenSSL.
+#if !defined(OPENSSL_IS_BORINGSSL)
+#define FOLLY_OPENSSL_IS_101 \
+ (OPENSSL_VERSION_NUMBER >= 0x1000105fL && \
+ OPENSSL_VERSION_NUMBER < 0x1000200fL)
+#define FOLLY_OPENSSL_IS_102 \
+ (OPENSSL_VERSION_NUMBER >= 0x1000200fL && \
+ OPENSSL_VERSION_NUMBER < 0x10100000L)
+#define FOLLY_OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#endif // !defined(OPENSSL_IS_BORINGSSL)
+
+// This class attempts to "unify" the OpenSSL libssl APIs between OpenSSL 1.0.2,
+// 1.1.0 and BoringSSL. The general idea is to provide wrapper methods for 1.0.2
+// which already exist in BoringSSL and 1.1.0, but there are few APIs such as
+// SSL_CTX_set1_sigalgs_list and so on which exist in 1.0.2 but were removed
+// in BoringSSL
+
+#ifdef OPENSSL_IS_BORINGSSL
+
+int SSL_CTX_set1_sigalgs_list(SSL_CTX* ctx, const char* sigalgs_list);
+int TLS1_get_client_version(SSL* s);
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int));
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int));
+
+#elif FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_101
+
+int SSL_CTX_up_ref(SSL_CTX* session);
+int SSL_SESSION_up_ref(SSL_SESSION* session);
+int X509_up_ref(X509* x);
+int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int));
+int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int));
+
+#elif FOLLY_OPENSSL_IS_110
+
+#else
+#warning Compiling with unsupported OpenSSL version
+#endif
+
+} // ssl
+} // folly
--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <folly/Conv.h>
+#include <folly/portability/OpenSSL.h>
+
+#include <openssl/crypto.h>
+#include <openssl/opensslv.h>
+
+// This is used to find the OpenSSL version at runtime. Just returning
+// OPENSSL_VERSION_NUMBER is insufficient as runtime version may be different
+// from the compile-time version
+struct OpenSSLVersionFinder {
+ static std::string getOpenSSLLongVersion(void) {
+#ifdef OPENSSL_VERSION_TEXT
+ return SSLeay_version(SSLEAY_VERSION);
+#elif defined(OPENSSL_VERSION_NUMBER)
+ return folly::format("0x{:x}", OPENSSL_VERSION_NUMBER).str();
+#else
+ return "";
+#endif
+ }
+
+ uint64_t getOpenSSLNumericVersion(void) {
+#ifdef OPENSSL_VERSION_NUMBER
+ return SSLeay();
+#else
+ return 0;
+#endif
+ }
+};
#pragma once
#include <folly/Memory.h>
-#include <folly/ssl/detail/OpenSSLVersionFinder.h>
+#include <folly/portability/OpenSSL.h>
#include <folly/ssl/detail/SSLSessionImpl.h>
namespace folly {
+++ /dev/null
-/*
- * Copyright 2016 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <folly/Conv.h>
-
-#include <openssl/crypto.h>
-#include <openssl/opensslv.h>
-
-// BoringSSL doesn't have notion of versioning although it defines
-// OPENSSL_VERSION_NUMBER to maintain compatibility. The following variables are
-// intended to be specific to OpenSSL.
-#if !defined(OPENSSL_IS_BORINGSSL)
-# define OPENSSL_IS_101 \
- (OPENSSL_VERSION_NUMBER >= 0x1000105fL && \
- OPENSSL_VERSION_NUMBER < 0x1000200fL)
-# define OPENSSL_IS_102 \
- (OPENSSL_VERSION_NUMBER >= 0x1000200fL && \
- OPENSSL_VERSION_NUMBER < 0x10100000L)
-# define OPENSSL_IS_110 (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-#endif // !defined(OPENSSL_IS_BORINGSSL)
-
-// This is used to find the OpenSSL version at runtime. Just returning
-// OPENSSL_VERSION_NUMBER is insufficient as runtime version may be different
-// from the compile-time version
-struct OpenSSLVersionFinder {
- static std::string getOpenSSLLongVersion(void) {
-#ifdef OPENSSL_VERSION_TEXT
- return SSLeay_version(SSLEAY_VERSION);
-#elif defined(OPENSSL_VERSION_NUMBER)
- return folly::format("0x{:x}", OPENSSL_VERSION_NUMBER).str();
-#else
- return "";
-#endif
- }
-
- uint64_t getOpenSSLNumericVersion(void) {
-#ifdef OPENSSL_VERSION_NUMBER
- return SSLeay();
-#else
- return 0;
-#endif
- }
-};
*/
#include <folly/ssl/detail/SSLSessionImpl.h>
-#include <folly/ssl/detail/OpenSSLVersionFinder.h>
+#include <folly/portability/OpenSSL.h>
+#include <folly/ssl/OpenSSLVersionFinder.h>
namespace folly {
namespace ssl {
if (session_) {
const unsigned char* ptr = nullptr;
unsigned int len = 0;
-#if defined(OPENSSL_IS_102) || defined(OPENSSL_IS_101)
- len = session_->session_id_length;
- ptr = session_->session_id;
-#elif defined(OPENSSL_IS_110) || defined(OPENSSL_IS_BORINGSSL)
ptr = SSL_SESSION_get_id(session_, &len);
-#endif
ret.assign(ptr, ptr + len);
}
return ret;
void SSLSessionImpl::upRef() {
if (session_) {
-#if defined(OPENSSL_IS_102) || defined(OPENSSL_IS_101)
- CRYPTO_add(&session_->references, 1, CRYPTO_LOCK_SSL_SESSION);
-#elif defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_110)
SSL_SESSION_up_ref(session_);
-#endif
}
}