Commit 95c8e072 authored by Anirudh Ramachandran's avatar Anirudh Ramachandran Committed by Facebook Github Bot

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
parent 7d0d018f
......@@ -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<SSLContext>& 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;
......
......@@ -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;
}
......
......@@ -26,11 +26,13 @@
#include <openssl/ecdsa.h>
#endif
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rsa.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <folly/Memory.h>
#include <folly/portability/OpenSSL.h>
namespace folly {
namespace ssl {
......@@ -65,11 +67,19 @@ using EvpPkeyCtxUniquePtr = std::unique_ptr<EVP_PKEY_CTX, EvpPkeyCtxDeleter>;
#else
struct EVP_PKEY_CTX;
#endif
using EvpMdCtxDeleter =
folly::static_function_deleter<EVP_MD_CTX, &EVP_MD_CTX_destroy>;
folly::static_function_deleter<EVP_MD_CTX, &EVP_MD_CTX_free>;
using EvpMdCtxUniquePtr = std::unique_ptr<EVP_MD_CTX, EvpMdCtxDeleter>;
// HMAC
using HmacCtxDeleter = folly::static_function_deleter<HMAC_CTX, &HMAC_CTX_free>;
using HmacCtxUniquePtr = std::unique_ptr<HMAC_CTX, HmacCtxDeleter>;
// BIO
using BioMethodDeleter =
folly::static_function_deleter<BIO_METHOD, &BIO_meth_free>;
using BioMethodUniquePtr = std::unique_ptr<BIO_METHOD, BioMethodDeleter>;
using BioDeleter = folly::static_function_deleter<BIO, &BIO_vfree>;
using BioUniquePtr = std::unique_ptr<BIO, BioDeleter>;
using BioChainDeleter = folly::static_function_deleter<BIO, &BIO_free_all>;
......
......@@ -26,7 +26,7 @@
#include <unordered_map>
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_METHOD*>(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<char*>(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 (
......
......@@ -16,6 +16,7 @@
#pragma once
#include <folly/Range.h>
#include <folly/io/async/ssl/OpenSSLPtrTypes.h>
#include <folly/portability/Sockets.h>
#include <openssl/ssl.h>
......@@ -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);
};
......
......@@ -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;
......
......@@ -14,17 +14,22 @@
* limitations under the License.
*/
#include <folly/portability/OpenSSL.h>
#include <stdexcept>
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
}
}
......@@ -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 <folly/portability/Windows.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <cstdint>
......@@ -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
......@@ -16,6 +16,8 @@
#pragma once
#include <folly/io/async/ssl/OpenSSLPtrTypes.h>
#include <folly/portability/OpenSSL.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
......@@ -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(
......
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