From 95c8e0726ef79fd286e11e02d7a6c279be8fceae Mon Sep 17 00:00:00 2001 From: Anirudh Ramachandran Date: Mon, 3 Apr 2017 23:29:59 -0700 Subject: [PATCH] OpenSSL 1.1.0 compatibility Summary: Add more layers to support compiling with OpenSSL 1.1.0 Reviewed By: yfeldblum Differential Revision: D4406876 fbshipit-source-id: 8eff7e4f8e096605fc9e1093ef533b5afe0ee539 --- folly/io/async/AsyncSSLSocket.cpp | 62 ++++++++------ folly/io/async/SSLContext.cpp | 4 +- folly/io/async/ssl/OpenSSLPtrTypes.h | 12 ++- folly/io/async/ssl/OpenSSLUtils.cpp | 60 ++++++++++--- folly/io/async/ssl/OpenSSLUtils.h | 17 +++- folly/io/async/test/AsyncSSLSocketTest.h | 2 + folly/portability/OpenSSL.cpp | 102 ++++++++++++++++++----- folly/portability/OpenSSL.h | 73 ++++++++++++---- folly/ssl/OpenSSLHash.h | 36 ++++---- 9 files changed, 269 insertions(+), 99 deletions(-) diff --git a/folly/io/async/AsyncSSLSocket.cpp b/folly/io/async/AsyncSSLSocket.cpp index 3d16fc68..f8e315fb 100644 --- a/folly/io/async/AsyncSSLSocket.cpp +++ b/folly/io/async/AsyncSSLSocket.cpp @@ -177,14 +177,20 @@ void setup_SSL_CTX(SSL_CTX *ctx) { } -BIO_METHOD sslBioMethod; +// Note: This is a Leaky Meyer's Singleton. The reason we can't use a non-leaky +// thing is because we will be setting this BIO_METHOD* inside BIOs owned by +// various SSL objects which may get callbacks even during teardown. We may +// eventually try to fix this +static BIO_METHOD* getSSLBioMethod() { + static auto const instance = OpenSSLUtils::newSocketBioMethod().release(); + return instance; +} void* initsslBioMethod(void) { - memcpy(&sslBioMethod, BIO_s_socket(), sizeof(sslBioMethod)); + auto sslBioMethod = getSSLBioMethod(); // override the bwrite method for MSG_EOR support - OpenSSLUtils::setCustomBioWriteMethod( - &sslBioMethod, AsyncSSLSocket::bioWrite); - OpenSSLUtils::setCustomBioReadMethod(&sslBioMethod, AsyncSSLSocket::bioRead); + OpenSSLUtils::setCustomBioWriteMethod(sslBioMethod, AsyncSSLSocket::bioWrite); + OpenSSLUtils::setCustomBioReadMethod(sslBioMethod, AsyncSSLSocket::bioRead); // Note that the sslBioMethod.type and sslBioMethod.name are not // set here. openssl code seems to be checking ".type == BIO_TYPE_SOCKET" and @@ -480,7 +486,6 @@ void AsyncSSLSocket::sslAccept( checkForImmediateRead(); } -#if OPENSSL_VERSION_NUMBER >= 0x009080bfL void AsyncSSLSocket::attachSSLContext( const std::shared_ptr& ctx) { @@ -503,10 +508,16 @@ void AsyncSSLSocket::attachSSLContext( // We need to update the initial_ctx if necessary auto sslCtx = ctx->getSSLCtx(); SSL_CTX_up_ref(sslCtx); -#ifndef OPENSSL_NO_TLSEXT - // note that detachSSLContext has already freed ssl_->initial_ctx - ssl_->initial_ctx = sslCtx; -#endif + + // The 'initial_ctx' inside an SSL* points to the context that it was created + // with, which is also where session callbacks and servername callbacks + // happen. + // When we switch to a different SSL_CTX, we want to update the initial_ctx as + // well so that any callbacks don't go to a different object + // NOTE: this will only work if we have access to ssl_ internals, so it may + // not work on + // OpenSSL version >= 1.1.0 + OpenSSLUtils::setSSLInitialCtx(ssl_, sslCtx); // Detach sets the socket's context to the dummy context. Thus we must acquire // this lock. SpinLockGuard guard(dummyCtxLock); @@ -521,14 +532,20 @@ void AsyncSSLSocket::detachSSLContext() { if (!ssl_) { return; } -// Detach the initial_ctx as well. Internally w/ OPENSSL_NO_TLSEXT -// it is used for session info. It will be reattached in attachSSLContext -#ifndef OPENSSL_NO_TLSEXT - if (ssl_->initial_ctx) { - SSL_CTX_free(ssl_->initial_ctx); - ssl_->initial_ctx = nullptr; + // The 'initial_ctx' inside an SSL* points to the context that it was created + // with, which is also where session callbacks and servername callbacks + // happen. + // Detach the initial_ctx as well. It will be reattached in attachSSLContext + // it is used for session info. + // NOTE: this will only work if we have access to ssl_ internals, so it may + // not work on + // OpenSSL version >= 1.1.0 + SSL_CTX* initialCtx = OpenSSLUtils::getSSLInitialCtx(ssl_); + if (initialCtx) { + SSL_CTX_free(initialCtx); + OpenSSLUtils::setSSLInitialCtx(ssl_, nullptr); } -#endif + SpinLockGuard guard(dummyCtxLock); if (nullptr == dummyCtx) { // We need to lazily initialize the dummy context so we don't @@ -541,7 +558,6 @@ void AsyncSSLSocket::detachSSLContext() { // would not be thread safe. SSL_set_SSL_CTX(ssl_, dummyCtx->getSSLCtx()); } -#endif #if FOLLY_OPENSSL_HAS_SNI void AsyncSSLSocket::switchServerSSLContext( @@ -574,10 +590,8 @@ bool AsyncSSLSocket::isServerNameMatch() const { return false; } - if(!ss->tlsext_hostname) { - return false; - } - return (tlsextHostname_.compare(ss->tlsext_hostname) ? false : true); + auto tlsextHostname = SSL_SESSION_get0_hostname(ss); + return (tlsextHostname && !tlsextHostname_.compare(tlsextHostname)); } void AsyncSSLSocket::setServerName(std::string serverName) noexcept { @@ -723,7 +737,7 @@ void AsyncSSLSocket::applyVerificationOptions(SSL * ssl) { } bool AsyncSSLSocket::setupSSLBio() { - auto sslBio = BIO_new(&sslBioMethod); + auto sslBio = BIO_new(getSSLBioMethod()); if (!sslBio) { return false; @@ -911,7 +925,7 @@ int AsyncSSLSocket::getSSLVersion() const { const char *AsyncSSLSocket::getSSLCertSigAlgName() const { X509 *cert = (ssl_ != nullptr) ? SSL_get_certificate(ssl_) : nullptr; if (cert) { - int nid = OBJ_obj2nid(cert->sig_alg->algorithm); + int nid = X509_get_signature_nid(cert); return OBJ_nid2ln(nid); } return nullptr; diff --git a/folly/io/async/SSLContext.cpp b/folly/io/async/SSLContext.cpp index 4874cdc1..f3ca89f5 100644 --- a/folly/io/async/SSLContext.cpp +++ b/folly/io/async/SSLContext.cpp @@ -833,7 +833,7 @@ void SSLContext::initializeOpenSSLLocked() { SSL_load_error_strings(); ERR_load_crypto_strings(); // static locking - locks().reset(new SSLLock[size_t(::CRYPTO_num_locks())]); + locks().reset(new SSLLock[size_t(CRYPTO_num_locks())]); for (auto it: lockTypes()) { locks()[size_t(it.first)].lockType = it.second; } @@ -869,7 +869,7 @@ void SSLContext::cleanupOpenSSLLocked() { CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); EVP_cleanup(); - ERR_remove_state(0); + ERR_clear_error(); locks().reset(); initialized_ = false; } diff --git a/folly/io/async/ssl/OpenSSLPtrTypes.h b/folly/io/async/ssl/OpenSSLPtrTypes.h index 8e4be98a..dfc55cc3 100644 --- a/folly/io/async/ssl/OpenSSLPtrTypes.h +++ b/folly/io/async/ssl/OpenSSLPtrTypes.h @@ -26,11 +26,13 @@ #include #endif #include +#include #include #include #include #include +#include namespace folly { namespace ssl { @@ -65,11 +67,19 @@ using EvpPkeyCtxUniquePtr = std::unique_ptr; #else struct EVP_PKEY_CTX; #endif + using EvpMdCtxDeleter = - folly::static_function_deleter; + folly::static_function_deleter; using EvpMdCtxUniquePtr = std::unique_ptr; +// HMAC +using HmacCtxDeleter = folly::static_function_deleter; +using HmacCtxUniquePtr = std::unique_ptr; + // BIO +using BioMethodDeleter = + folly::static_function_deleter; +using BioMethodUniquePtr = std::unique_ptr; using BioDeleter = folly::static_function_deleter; using BioUniquePtr = std::unique_ptr; using BioChainDeleter = folly::static_function_deleter; diff --git a/folly/io/async/ssl/OpenSSLUtils.cpp b/folly/io/async/ssl/OpenSSLUtils.cpp index 232fcc41..db25b8bd 100644 --- a/folly/io/async/ssl/OpenSSLUtils.cpp +++ b/folly/io/async/ssl/OpenSSLUtils.cpp @@ -26,7 +26,7 @@ #include namespace { -#if defined(OPENSSL_IS_BORINGSSL) +#ifdef OPENSSL_IS_BORINGSSL // BoringSSL doesn't (as of May 2016) export the equivalent // of BIO_sock_should_retry, so this is one way around it :( static int boringssl_bio_fd_should_retry(int err); @@ -196,6 +196,48 @@ const std::string& OpenSSLUtils::getCipherName(uint16_t cipherCode) { } } +void OpenSSLUtils::setSSLInitialCtx(SSL* ssl, SSL_CTX* ctx) { +#if !FOLLY_OPENSSL_IS_110 && !defined(OPENSSL_NO_TLSEXT) + if (ssl) { + ssl->initial_ctx = ctx; + } +#endif +} + +SSL_CTX* OpenSSLUtils::getSSLInitialCtx(SSL* ssl) { +#if !FOLLY_OPENSSL_IS_110 && !defined(OPENSSL_NO_TLSEXT) + if (ssl) { + return ssl->initial_ctx; + } +#endif + return nullptr; +} + +BioMethodUniquePtr OpenSSLUtils::newSocketBioMethod() { + BIO_METHOD* newmeth = nullptr; +#if FOLLY_OPENSSL_IS_110 + if (!(newmeth = BIO_meth_new(BIO_TYPE_SOCKET, "socket_bio_method"))) { + return nullptr; + } + auto meth = const_cast(BIO_s_socket()); + BIO_meth_set_create(newmeth, BIO_meth_get_create(meth)); + BIO_meth_set_destroy(newmeth, BIO_meth_get_destroy(meth)); + BIO_meth_set_ctrl(newmeth, BIO_meth_get_ctrl(meth)); + BIO_meth_set_callback_ctrl(newmeth, BIO_meth_get_callback_ctrl(meth)); + BIO_meth_set_read(newmeth, BIO_meth_get_read(meth)); + BIO_meth_set_write(newmeth, BIO_meth_get_write(meth)); + BIO_meth_set_gets(newmeth, BIO_meth_get_gets(meth)); + BIO_meth_set_puts(newmeth, BIO_meth_get_puts(meth)); +#else + if (!(newmeth = (BIO_METHOD*)OPENSSL_malloc(sizeof(BIO_METHOD)))) { + return nullptr; + } + memcpy(newmeth, BIO_s_socket(), sizeof(BIO_METHOD)); +#endif + + return BioMethodUniquePtr(newmeth); +} + bool OpenSSLUtils::setCustomBioReadMethod( BIO_METHOD* bioMeth, int (*meth)(BIO*, char*, int)) { @@ -214,7 +256,7 @@ bool OpenSSLUtils::setCustomBioWriteMethod( int OpenSSLUtils::getBioShouldRetryWrite(int r) { int ret = 0; -#if defined(OPENSSL_IS_BORINGSSL) +#ifdef OPENSSL_IS_BORINGSSL ret = boringssl_bio_fd_should_retry(r); #else ret = BIO_sock_should_retry(r); @@ -223,7 +265,7 @@ int OpenSSLUtils::getBioShouldRetryWrite(int r) { } void OpenSSLUtils::setBioAppData(BIO* b, void* ptr) { -#if defined(OPENSSL_IS_BORINGSSL) +#ifdef OPENSSL_IS_BORINGSSL BIO_set_callback_arg(b, static_cast(ptr)); #else BIO_set_app_data(b, ptr); @@ -231,21 +273,13 @@ void OpenSSLUtils::setBioAppData(BIO* b, void* ptr) { } void* OpenSSLUtils::getBioAppData(BIO* b) { -#if defined(OPENSSL_IS_BORINGSSL) +#ifdef OPENSSL_IS_BORINGSSL return BIO_get_callback_arg(b); #else return BIO_get_app_data(b); #endif } -void OpenSSLUtils::setCustomBioMethod(BIO* b, BIO_METHOD* meth) { -#if defined(OPENSSL_IS_BORINGSSL) - b->method = meth; -#else - BIO_set(b, meth); -#endif -} - int OpenSSLUtils::getBioFd(BIO* b, int* fd) { #ifdef _WIN32 int ret = portability::sockets::socket_to_fd((SOCKET)BIO_get_fd(b, fd)); @@ -275,7 +309,7 @@ void OpenSSLUtils::setBioFd(BIO* b, int fd, int flags) { } // folly namespace { -#if defined(OPENSSL_IS_BORINGSSL) +#ifdef OPENSSL_IS_BORINGSSL static int boringssl_bio_fd_non_fatal_error(int err) { if ( diff --git a/folly/io/async/ssl/OpenSSLUtils.h b/folly/io/async/ssl/OpenSSLUtils.h index 9a3ac3d5..877df156 100644 --- a/folly/io/async/ssl/OpenSSLUtils.h +++ b/folly/io/async/ssl/OpenSSLUtils.h @@ -16,6 +16,7 @@ #pragma once #include +#include #include #include @@ -91,10 +92,25 @@ class OpenSSLUtils { */ static const std::string& getCipherName(uint16_t cipherCode); + /** + * Set the 'initial_ctx' SSL_CTX* inside an SSL. The initial_ctx is used to + * point to the SSL_CTX on which servername callback and session callbacks, + * as well as session caching stats are set. If we want to enforce SSL_CTX + * thread-based ownership (e.g., thread-local SSL_CTX) in the application, we + * need to also set/reset the initial_ctx when we call SSL_set_SSL_CTX. + * + * @param ssl SSL pointer + * @param ctx SSL_CTX pointer + * @return Cipher name, or empty if the code is not found + */ + static void setSSLInitialCtx(SSL* ssl, SSL_CTX* ctx); + static SSL_CTX* getSSLInitialCtx(SSL* ssl); + /** * Wrappers for BIO operations that may be different across different * versions/flavors of OpenSSL (including forks like BoringSSL) */ + static BioMethodUniquePtr newSocketBioMethod(); static bool setCustomBioReadMethod( BIO_METHOD* bioMeth, int (*meth)(BIO*, char*, int)); @@ -104,7 +120,6 @@ class OpenSSLUtils { static int getBioShouldRetryWrite(int ret); static void setBioAppData(BIO* b, void* ptr); static void* getBioAppData(BIO* b); - static void setCustomBioMethod(BIO*, BIO_METHOD*); static int getBioFd(BIO* b, int* fd); static void setBioFd(BIO* b, int fd, int flags); }; diff --git a/folly/io/async/test/AsyncSSLSocketTest.h b/folly/io/async/test/AsyncSSLSocketTest.h index ff70d3b8..e4a73c19 100644 --- a/folly/io/async/test/AsyncSSLSocketTest.h +++ b/folly/io/async/test/AsyncSSLSocketTest.h @@ -755,8 +755,10 @@ class TestSSLAsyncCacheServer : public TestSSLServer { int lookupDelay = 100) : TestSSLServer(acb) { SSL_CTX *sslCtx = ctx_->getSSLCtx(); +#ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP SSL_CTX_sess_set_get_cb(sslCtx, TestSSLAsyncCacheServer::getSessionCallback); +#endif SSL_CTX_set_session_cache_mode( sslCtx, SSL_SESS_CACHE_NO_INTERNAL | SSL_SESS_CACHE_SERVER); asyncCallbacks_ = 0; diff --git a/folly/portability/OpenSSL.cpp b/folly/portability/OpenSSL.cpp index b1cb9cf0..04512f64 100644 --- a/folly/portability/OpenSSL.cpp +++ b/folly/portability/OpenSSL.cpp @@ -14,17 +14,22 @@ * limitations under the License. */ #include +#include 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; +#if FOLLY_OPENSSL_IS_110 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in 1.1.0 only +//////////////////////////////////////////////////////////////////////////////// + +#else +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in BoringSSL and OpenSSL != 1.1.0 (1.0.2, 1.0.1, 1.0.0...) +//////////////////////////////////////////////////////////////////////////////// +void BIO_meth_free(BIO_METHOD* biom) { + OPENSSL_free((void*)biom); } int BIO_meth_set_read(BIO_METHOD* biom, int (*read)(BIO*, char*, int)) { @@ -37,19 +42,57 @@ int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) { return 1; } -#elif FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_100 +void EVP_MD_CTX_free(EVP_MD_CTX* ctx) { + EVP_MD_CTX_destroy(ctx); +} -#if FOLLY_OPENSSL_IS_100 -uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c) { - return c->id; +const char* SSL_SESSION_get0_hostname(const SSL_SESSION* s) { + return s->tlsext_hostname; } -int TLS1_get_client_version(const SSL* s) { - return (s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0; +EVP_MD_CTX* EVP_MD_CTX_new(void) { + EVP_MD_CTX* ctx = (EVP_MD_CTX*)OPENSSL_malloc(sizeof(EVP_MD_CTX)); + if (!ctx) { + throw std::runtime_error("Cannot allocate EVP_MD_CTX"); + } + EVP_MD_CTX_init(ctx); + return ctx; } -#endif +HMAC_CTX* HMAC_CTX_new(void) { + HMAC_CTX* ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(HMAC_CTX)); + if (!ctx) { + throw std::runtime_error("Cannot allocate HMAC_CTX"); + } + HMAC_CTX_init(ctx); + return ctx; +} + +void HMAC_CTX_free(HMAC_CTX* ctx) { + if (ctx) { + OPENSSL_free(ctx); + } +} + +#ifdef OPENSSL_IS_BORINGSSL +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in BoringSSL only +//////////////////////////////////////////////////////////////////////////////// +int SSL_CTX_set1_sigalgs_list(SSL_CTX*, const char*) { + return 1; // 0 implies error +} +int TLS1_get_client_version(SSL* s) { + // Note that this isn't the client version, and the API to + // get this has been hidden. It may be found by parsing the + // ClientHello (there is a callback via the SSL_HANDSHAKE struct) + return s->version; +} + +#elif FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_100 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in 1.0.2 and 1.0.1/1.0.0 (both deprecated) +//////////////////////////////////////////////////////////////////////////////// int SSL_CTX_up_ref(SSL_CTX* ctx) { return CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); } @@ -62,18 +105,35 @@ 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; +#if FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_100 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in 1.0.1/1.0.0 (both deprecated) +//////////////////////////////////////////////////////////////////////////////// +int X509_get_signature_nid(X509* cert) { + return OBJ_obj2nid(cert->sig_alg->algorithm); } -int BIO_meth_set_write(BIO_METHOD* biom, int (*write)(BIO*, const char*, int)) { - biom->bwrite = write; - return 1; +#endif + +#if FOLLY_OPENSSL_IS_100 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed only in 1.0.0 only (deprecated) +//////////////////////////////////////////////////////////////////////////////// +uint32_t SSL_CIPHER_get_id(const SSL_CIPHER* c) { + return c->id; } -#elif FOLLY_OPENSSL_IS_110 +int TLS1_get_client_version(const SSL* s) { + return (s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0; +} #endif + +#endif // !(OPENSSL_IS_BORINGSSL || +// FOLLY_OPENSSL_IS_101 || +// FOLLY_OPENSSL_IS_102 || +// FOLLY_OPENSSL_IS_100) + +#endif // !FOLLY_OPENSSL_IS_110 } } diff --git a/folly/portability/OpenSSL.h b/folly/portability/OpenSSL.h index faf14f78..dc6ac483 100644 --- a/folly/portability/OpenSSL.h +++ b/folly/portability/OpenSSL.h @@ -14,11 +14,21 @@ * limitations under the License. */ +// +// This class attempts to "unify" the OpenSSL libcrypto/libssl APIs between +// OpenSSL 1.0.2, 1.1.0 (and some earlier versions) and BoringSSL. The general +// idea is to provide namespaced wrapper methods for versions which do not +// 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 +// + #pragma once // This must come before the OpenSSL includes. #include +#include #include #include #include @@ -60,39 +70,68 @@ namespace ssl { #define FOLLY_OPENSSL_HAS_SNI 0 #endif -// 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 +#if FOLLY_OPENSSL_IS_110 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in 1.1.0 only +//////////////////////////////////////////////////////////////////////////////// + +#else +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in BoringSSL and OpenSSL != 1.1.0 (1.0.2, 1.0.1, 1.0.0...) +//////////////////////////////////////////////////////////////////////////////// +void BIO_meth_free(BIO_METHOD* biom); +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)); +void EVP_MD_CTX_free(EVP_MD_CTX* ctx); +const char* SSL_SESSION_get0_hostname(const SSL_SESSION* s); + +EVP_MD_CTX* EVP_MD_CTX_new(void); +void EVP_MD_CTX_free(EVP_MD_CTX* ctx); + +HMAC_CTX* HMAC_CTX_new(void); +void HMAC_CTX_free(HMAC_CTX* ctx); #ifdef OPENSSL_IS_BORINGSSL +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in BoringSSL only +//////////////////////////////////////////////////////////////////////////////// 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 || FOLLY_OPENSSL_IS_100 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in 1.0.2 and 1.0.1/1.0.0 (both deprecated) +//////////////////////////////////////////////////////////////////////////////// -#if FOLLY_OPENSSL_IS_100 +int SSL_CTX_up_ref(SSL_CTX* session); +int SSL_SESSION_up_ref(SSL_SESSION* session); +int X509_up_ref(X509* x); -uint32_t SSL_CIPHER_get_id(const SSL_CIPHER*); -int TLS1_get_client_version(const SSL*); +#if FOLLY_OPENSSL_IS_101 || FOLLY_OPENSSL_IS_100 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed in 1.0.1/1.0.0 (both deprecated) +//////////////////////////////////////////////////////////////////////////////// +int X509_get_signature_nid(X509* cert); #endif -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)); +#if FOLLY_OPENSSL_IS_100 +//////////////////////////////////////////////////////////////////////////////// +// APIs needed only in 1.0.0 only (deprecated) +//////////////////////////////////////////////////////////////////////////////// -#elif FOLLY_OPENSSL_IS_110 +uint32_t SSL_CIPHER_get_id(const SSL_CIPHER*); +int TLS1_get_client_version(const SSL*); +#endif #else #warning Compiling with unsupported OpenSSL version -#endif + +#endif // !(OPENSSL_IS_BORINGSSL || FOLLY_OPENSSL_IS_101 || +// FOLLY_OPENSSL_IS_102 || FOLLY_OPENSSL_IS_100) + +#endif // !FOLLY_OPENSSL_IS_110 } // ssl } // folly diff --git a/folly/ssl/OpenSSLHash.h b/folly/ssl/OpenSSLHash.h index da05bb0b..5d11e3b7 100644 --- a/folly/ssl/OpenSSLHash.h +++ b/folly/ssl/OpenSSLHash.h @@ -16,6 +16,8 @@ #pragma once +#include +#include #include #include #include @@ -33,18 +35,15 @@ class OpenSSLHash { class Digest { public: - Digest() { - EVP_MD_CTX_init(&ctx_); - } - ~Digest() { - EVP_MD_CTX_cleanup(&ctx_); - } + Digest() : ctx_(EVP_MD_CTX_new()) {} + void hash_init(const EVP_MD* md) { md_ = md; - check_libssl_result(1, EVP_DigestInit_ex(&ctx_, md, nullptr)); + check_libssl_result(1, EVP_DigestInit_ex(ctx_.get(), md, nullptr)); } void hash_update(ByteRange data) { - check_libssl_result(1, EVP_DigestUpdate(&ctx_, data.data(), data.size())); + check_libssl_result( + 1, EVP_DigestUpdate(ctx_.get(), data.data(), data.size())); } void hash_update(const IOBuf& data) { for (auto r : data) { @@ -55,13 +54,13 @@ class OpenSSLHash { const auto size = EVP_MD_size(md_); check_out_size(size_t(size), out); unsigned int len = 0; - check_libssl_result(1, EVP_DigestFinal_ex(&ctx_, out.data(), &len)); + check_libssl_result(1, EVP_DigestFinal_ex(ctx_.get(), out.data(), &len)); check_libssl_result(size, int(len)); md_ = nullptr; } private: const EVP_MD* md_ = nullptr; - EVP_MD_CTX ctx_; + EvpMdCtxUniquePtr ctx_{nullptr}; }; static void hash( @@ -97,19 +96,16 @@ class OpenSSLHash { class Hmac { public: - Hmac() { - HMAC_CTX_init(&ctx_); - } - ~Hmac() { - HMAC_CTX_cleanup(&ctx_); - } + Hmac() : ctx_(HMAC_CTX_new()) {} + void hash_init(const EVP_MD* md, ByteRange key) { md_ = md; check_libssl_result( - 1, HMAC_Init_ex(&ctx_, key.data(), int(key.size()), md_, nullptr)); + 1, + HMAC_Init_ex(ctx_.get(), key.data(), int(key.size()), md_, nullptr)); } void hash_update(ByteRange data) { - check_libssl_result(1, HMAC_Update(&ctx_, data.data(), data.size())); + check_libssl_result(1, HMAC_Update(ctx_.get(), data.data(), data.size())); } void hash_update(const IOBuf& data) { for (auto r : data) { @@ -120,13 +116,13 @@ class OpenSSLHash { const auto size = EVP_MD_size(md_); check_out_size(size_t(size), out); unsigned int len = 0; - check_libssl_result(1, HMAC_Final(&ctx_, out.data(), &len)); + check_libssl_result(1, HMAC_Final(ctx_.get(), out.data(), &len)); check_libssl_result(size, int(len)); md_ = nullptr; } private: const EVP_MD* md_ = nullptr; - HMAC_CTX ctx_; + HmacCtxUniquePtr ctx_{nullptr}; }; static void hmac( -- 2.34.1