Blob Blame History Raw
From e4bcbd5885e93ea4620103efc303c9b61982851b Mon Sep 17 00:00:00 2001
From: Jeremy Barton <jbarton@microsoft.com>
Date: Tue, 4 Sep 2018 12:53:06 -0700
Subject: [PATCH 3/7] Add hybrid support for OpenSSL 1.0 and 1.1

This changes the functional code to use OpenSSL 1.1 API in the places where the API changed. "apibridge" provides equivalent methods for the OpenSSL 1.0 environment.

The following configurations have been tested:

* Non-portable against OpenSSL 1.0
* Non-portable against OpenSSL 1.1
* Portable, built against OpenSSL 1.0 and run against OpenSSL 1.0
* Portable, built against OpenSSL 1.0 and run against OpenSSL 1.1
* Portable, built against OpenSSL 1.1 and run against OpenSSL 1.0
* Portable, built against OpenSSL 1.1 and run against OpenSSL 1.1

In opensslshim, the PER_FUNCTION_BLOCK macro style has been broken up into a named purposes:

* REQUIRED_FUNCTION(fn)
  * API that we use unconditionally, regardless of version
  * Formerly PER_FUNCTION_BLOCK(fn, true)
* NEW_REQUIRED_FUNCTION(fn)
  * API that we use unconditionally in paths that only exist against OpenSSL 1.1, is not probed for when the runtime is 1.0
* LIGHTUP_FUNCTION(fn)
  * API that might not exist, must be probed with API_EXISTS checks before being utilized
  * Formerly PER_FUNCTION_BLOCK(fn, false)
* FALLBACK_FUNCTION(fn)
  * API that is required on OpenSSL 1.1, and when not found will bind to a method named local_#fn in the shim library
* RENAMED_FUNCTION(fn,oldfn)
  * Handles a rename with no signature change from oldfn to newfn, binds appropriately based on the runtime library.
* LEGACY_FUNCTION(fn)
  * API that we use unconditionally in paths that only exist against OpenSSL 1.0, is not probed for when the runtime is 1.1.

Two new #defines are available, but ideally need no further usage:

* NEED_OPENSSL_1_0
  * Defined when building portable, or on non-portable when the headers are OpenSSL 1.0
* NEED_OPENSSL_1_1
  * Defined when building portable, or on non-portable when the headers are OpenSSL 1.1
---
 .../SafeHandles/SafeEvpPKeyHandle.Unix.cs     |   7 +-
 .../CMakeLists.txt                            |   3 +-
 .../apibridge.cpp                             | 524 ++++++++++
 .../apibridge.h                               |  45 +
 .../configure.cmake                           |   5 -
 .../openssl.cpp                               | 199 ++--
 .../openssl.h                                 |  11 +
 .../openssl_1_0_structs.h                     | 139 +++
 .../opensslshim.cpp                           |  60 +-
 .../opensslshim.h                             | 928 ++++++++++++------
 .../pal_asn1.cpp                              |   2 +-
 .../pal_asn1.h                                |   2 +-
 .../pal_asn1_print.cpp                        |   9 +-
 .../pal_crypto_config.h.in                    |   2 -
 .../pal_dsa.cpp                               | 123 ++-
 .../pal_dsa.h                                 |  10 +-
 .../pal_evp.cpp                               |   6 +-
 .../pal_evp_cipher.cpp                        |  26 +-
 .../pal_evp_pkey.cpp                          |   2 +-
 .../pal_hmac.cpp                              |  12 +-
 .../pal_hmac.h                                |   1 -
 .../pal_rsa.cpp                               | 158 +--
 .../pal_rsa.h                                 |  16 +-
 .../pal_ssl.cpp                               | 144 ++-
 .../pal_x509.cpp                              |  16 +-
 .../pal_x509_root.cpp                         |   1 +
 .../Internal/Cryptography/OpenSslCipher.cs    |  19 +
 27 files changed, 1878 insertions(+), 592 deletions(-)
 create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp
 create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/apibridge.h
 create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/openssl.h
 create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h

diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs b/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs
index c706b1ce88..e51a7ca981 100644
--- a/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs
+++ b/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs
@@ -52,12 +52,9 @@ namespace System.Security.Cryptography
             // that we don't lose a tracked reference in low-memory situations.
             SafeEvpPKeyHandle safeHandle = new SafeEvpPKeyHandle();
 
-            int newRefCount = Interop.Crypto.UpRefEvpPkey(this);
+            int success = Interop.Crypto.UpRefEvpPkey(this);
 
-            // UpRefEvpPkey returns the number of references to this key, if it's less than 2
-            // (the incoming handle, and this one) then someone has already Disposed() this key
-            // into non-existence.
-            if (newRefCount < 2)
+            if (success != 1)
             {
                 Debug.Fail("Called UpRefEvpPkey on a key which was already marked for destruction");
                 throw Interop.Crypto.CreateOpenSslCryptographicException();
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt b/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt
index 352f456d07..9fef63fda8 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt
+++ b/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt
@@ -6,7 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
 # These are happening inside of OpenSSL-defined macros out of our control
 add_compile_options(-Wno-cast-align)
 
-add_definitions(-DPIC=1)
+add_definitions(-DPIC=1 -DOPENSSL_API_COMPAT=0x10100000L)
 
 if(CMAKE_STATIC_LIB_LINK)
    set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
@@ -16,6 +16,7 @@ find_package(OpenSSL REQUIRED)
 include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
 
 set(NATIVECRYPTO_SOURCES
+    apibridge.cpp
     openssl.cpp
     pal_asn1.cpp
     pal_asn1_print.cpp
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp
new file mode 100644
index 0000000000..fd43051c3f
--- /dev/null
+++ b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp
@@ -0,0 +1,524 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "opensslshim.h"
+#include "pal_crypto_types.h"
+#include "pal_types.h"
+
+#ifdef NEED_OPENSSL_1_0
+
+#include "apibridge.h"
+
+// Minimally define the structs from 1.0.x which went opaque in 1.1.0 for the
+// portable build building against the 1.1.x headers
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM
+#include "openssl_1_0_structs.h"
+
+#define CRYPTO_LOCK_X509 3
+#define CRYPTO_LOCK_EVP_PKEY 10
+
+#define SSL_CTRL_GET_SESSION_REUSED 8
+#define SSL_CTRL_OPTIONS 32
+
+#define SSL_ST_OK 3
+#endif
+
+extern "C" const ASN1_TIME* local_X509_get0_notBefore(const X509* x509)
+{
+    if (x509 && x509->cert_info && x509->cert_info->validity)
+    {
+        return x509->cert_info->validity->notBefore;
+    }
+
+    return nullptr;
+}
+
+extern "C" const ASN1_TIME* local_X509_get0_notAfter(const X509* x509)
+{
+    if (x509 && x509->cert_info && x509->cert_info->validity)
+    {
+        return x509->cert_info->validity->notAfter;
+    }
+
+    return nullptr;
+}
+
+extern "C" const ASN1_TIME* local_X509_CRL_get0_nextUpdate(const X509_CRL* crl)
+{
+    if (crl && crl->crl)
+    {
+        return crl->crl->nextUpdate;
+    }
+
+    return nullptr;
+}
+
+extern "C" int32_t local_X509_get_version(const X509* x509)
+{
+    if (x509 && x509->cert_info)
+    {
+        long ver = ASN1_INTEGER_get(x509->cert_info->version);
+        return (int32_t)ver;
+    }
+
+    return -1;
+}
+
+extern "C" X509_PUBKEY* local_X509_get_X509_PUBKEY(const X509* x509)
+{
+    if (x509)
+    {
+        return x509->cert_info->key;
+    }
+
+    return nullptr;
+}
+
+extern "C" int32_t local_X509_PUBKEY_get0_param(
+    ASN1_OBJECT** palgOid, const uint8_t** pkeyBytes, int* pkeyBytesLen, X509_ALGOR** palg, X509_PUBKEY* pubkey)
+{
+    if (palgOid)
+    {
+        *palgOid = pubkey->algor->algorithm;
+    }
+
+    if (pkeyBytes)
+    {
+        *pkeyBytes = pubkey->public_key->data;
+        *pkeyBytesLen = pubkey->public_key->length;
+    }
+
+    if (palg)
+    {
+        *palg = pubkey->algor;
+    }
+
+    return 1;
+}
+
+extern "C" const X509_ALGOR* local_X509_get0_tbs_sigalg(const X509* x509)
+{
+    if (x509 && x509->cert_info)
+    {
+        return x509->cert_info->signature;
+    }
+
+    return nullptr;
+}
+
+extern "C" ASN1_BIT_STRING* local_X509_get0_pubkey_bitstr(const X509* x509)
+{
+    if (x509 && x509->cert_info && x509->cert_info->key)
+    {
+        return x509->cert_info->key->public_key;
+    }
+
+    return nullptr;
+}
+
+extern "C" int32_t local_X509_NAME_get0_der(X509_NAME* x509Name, const uint8_t** pder, size_t* pderlen)
+{
+    if (!x509Name || !x509Name->bytes)
+    {
+        return 0;
+    }
+
+    if (pder)
+    {
+        *pder = (unsigned char*)x509Name->bytes->data;
+    }
+
+    if (pderlen)
+    {
+        *pderlen = x509Name->bytes->length;
+    }
+
+    return 1;
+}
+
+#ifndef SSLEAY_VERSION
+#define SSLEAY_VERSION 0
+#endif
+
+extern "C" const char* local_OpenSSL_version(int t)
+{
+    (void)t;
+    return SSLeay_version(SSLEAY_VERSION);
+}
+
+extern "C" const DSA_METHOD* local_DSA_get_method(const DSA* dsa)
+{
+    if (dsa)
+    {
+        return dsa->meth;
+    }
+
+    return nullptr;
+}
+
+extern "C" void local_DSA_get0_pqg(const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g)
+{
+    if (!dsa)
+    {
+        return;
+    }
+
+    if (p)
+    {
+        *p = dsa->p;
+    }
+
+    if (q)
+    {
+        *q = dsa->q;
+    }
+
+    if (g)
+    {
+        *g = dsa->g;
+    }
+}
+
+extern "C" const BIGNUM* local_DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey)
+{
+    if (dsa)
+    {
+        if (pubKey)
+        {
+            *pubKey = dsa->pub_key;
+        }
+
+        if (privKey)
+        {
+            *privKey = dsa->priv_key;
+        }
+    }
+
+    return nullptr;
+}
+
+extern "C" int32_t local_DSA_set0_pqg(DSA* dsa, BIGNUM* bnP, BIGNUM* bnQ, BIGNUM* bnG)
+{
+    if (!dsa)
+    {
+        return 0;
+    }
+
+    if ((dsa->p == nullptr && bnP == nullptr) || (dsa->q == nullptr && bnQ == nullptr) || (dsa->g == nullptr && bnG == nullptr))
+    {
+        return 0;
+    }
+
+    if (bnP)
+    {
+        BN_free(dsa->p);
+        dsa->p = bnP;
+    }
+
+    if (bnQ)
+    {
+        BN_free(dsa->q);
+        dsa->q = bnQ;
+    }
+
+    if (bnG)
+    {
+        BN_free(dsa->g);
+        dsa->g = bnG;
+    }
+
+    return 1;
+}
+
+extern "C" int32_t local_DSA_set0_key(DSA* dsa, BIGNUM* bnY, BIGNUM* bnX)
+{
+    if (!dsa)
+    {
+        return 0;
+    }
+
+    if (dsa->pub_key == nullptr && bnY == nullptr)
+    {
+        return 0;
+    }
+
+    if (bnY)
+    {
+        BN_free(dsa->pub_key);
+        dsa->pub_key = bnY;
+    }
+
+    if (bnX)
+    {
+        BN_free(dsa->priv_key);
+        dsa->priv_key = bnX;
+    }
+
+    return 1;
+}
+
+extern "C" int32_t local_EVP_PKEY_up_ref(EVP_PKEY* pkey)
+{
+    if (!pkey)
+    {
+        return 0;
+    }
+
+    return CRYPTO_add_lock(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY, __FILE__, __LINE__) > 1;
+}
+
+extern "C" EVP_CIPHER_CTX* local_EVP_CIPHER_CTX_new()
+{
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)calloc(1, sizeof(EVP_CIPHER_CTX));
+    return ctx;
+}
+
+extern "C" int32_t local_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX* ctx)
+{
+    if (ctx)
+    {
+        int ret = EVP_CIPHER_CTX_cleanup(ctx);
+        EVP_CIPHER_CTX_init(ctx);
+        return ret;
+    }
+
+    // OpenSSL 1.1 returns succes 1 on a NULL input
+    return 1;
+}
+
+extern "C" void local_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx)
+{
+    if (ctx)
+    {
+        local_EVP_CIPHER_CTX_reset(ctx);
+        free(ctx);
+    }
+}
+
+extern "C" HMAC_CTX* local_HMAC_CTX_new()
+{
+    HMAC_CTX* ctx = (HMAC_CTX*)calloc(1, sizeof(HMAC_CTX));
+
+    if (ctx)
+    {
+        HMAC_CTX_init(ctx);
+    }
+
+    return ctx;
+}
+
+extern "C" void local_HMAC_CTX_free(HMAC_CTX* ctx)
+{
+    if (ctx != nullptr)
+    {
+        HMAC_CTX_cleanup(ctx);
+        free(ctx);
+    }
+}
+
+extern "C" int32_t local_RSA_meth_get_flags(const RSA_METHOD* meth)
+{
+    if (meth)
+    {
+        return meth->flags;
+    }
+
+    return 0;
+}
+
+extern "C" void local_RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d)
+{
+    if (rsa)
+    {
+        if (n)
+        {
+            *n = rsa->n;
+        }
+
+        if (e)
+        {
+            *e = rsa->e;
+        }
+
+        if (d)
+        {
+            *d = rsa->d;
+        }
+    }
+}
+
+extern "C" void local_RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q)
+{
+    if (rsa)
+    {
+        if (p)
+        {
+            *p = rsa->p;
+        }
+
+        if (q)
+        {
+            *q = rsa->q;
+        }
+    }
+}
+
+extern "C" void local_RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp)
+{
+    if (rsa)
+    {
+        if (dmp1)
+        {
+            *dmp1 = rsa->dmp1;
+        }
+
+        if (dmq1)
+        {
+            *dmq1 = rsa->dmq1;
+        }
+
+        if (iqmp)
+        {
+            *iqmp = rsa->iqmp;
+        }
+    }
+}
+
+extern "C" int32_t local_RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d)
+{
+    if (rsa == nullptr)
+    {
+        return 0;
+    }
+
+    if ((rsa->n == nullptr && n == nullptr) || (rsa->e == nullptr && e == nullptr))
+    {
+        return 0;
+    }
+
+    if (n != nullptr)
+    {
+        BN_free(rsa->n);
+        rsa->n = n;
+    }
+
+    if (e != nullptr)
+    {
+        BN_free(rsa->e);
+        rsa->e = e;
+    }
+
+    if (d != nullptr)
+    {
+        BN_free(rsa->d);
+        rsa->d = d;
+    }
+
+    return 1;
+}
+
+extern "C" int32_t local_RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q)
+{
+    if (rsa == nullptr)
+    {
+        return 0;
+    }
+
+    if ((rsa->p == nullptr && p == nullptr) || (rsa->q == nullptr && q == nullptr))
+    {
+        return 0;
+    }
+
+    if (p != nullptr)
+    {
+        BN_free(rsa->p);
+        rsa->p = p;
+    }
+
+    if (q != nullptr)
+    {
+        BN_free(rsa->q);
+        rsa->q = q;
+    }
+
+    return 1;
+}
+
+extern "C" int32_t local_RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp)
+{
+    if (rsa == nullptr)
+    {
+        return 0;
+    }
+
+    if ((rsa->dmp1 == nullptr && dmp1 == nullptr) || (rsa->dmq1 == nullptr && dmq1 == nullptr) ||
+        (rsa->iqmp == nullptr && iqmp == nullptr))
+    {
+        return 0;
+    }
+
+    if (dmp1 != nullptr)
+    {
+        BN_free(rsa->dmp1);
+        rsa->dmp1 = dmp1;
+    }
+
+    if (dmq1 != nullptr)
+    {
+        BN_free(rsa->dmq1);
+        rsa->dmq1 = dmq1;
+    }
+
+    if (iqmp != nullptr)
+    {
+        BN_free(rsa->iqmp);
+        rsa->iqmp = iqmp;
+    }
+
+    return 1;
+}
+
+extern "C" int32_t local_SSL_is_init_finished(const SSL* ssl)
+{
+    return SSL_state(ssl) == SSL_ST_OK;
+}
+
+extern "C" X509Stack* local_X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx)
+{
+    return ctx ? ctx->untrusted : nullptr;
+}
+
+extern "C" X509* local_X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx)
+{
+    return ctx ? ctx->cert : nullptr;
+}
+
+extern "C" int32_t local_X509_up_ref(X509* x509)
+{
+    if (x509 != nullptr)
+    {
+        return CRYPTO_add_lock(&x509->references, 1, CRYPTO_LOCK_X509, __FILE__, __LINE__) > 1;
+    }
+
+    return 0;
+}
+
+extern "C" unsigned long local_SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options)
+{
+    // SSL_CTX_ctrl is signed long in and signed long out; but SSL_CTX_set_options,
+    // which was a macro call to SSL_CTX_ctrl in 1.0, is unsigned/unsigned.
+    return (unsigned long)SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, (long)options, nullptr);
+}
+
+extern "C" int local_SSL_session_reused(SSL* ssl)
+{
+    return (int)SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, nullptr);
+}
+
+extern "C" void local_SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level)
+{
+    (void)ctx;
+    (void)level;
+}
+#endif
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/apibridge.h b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.h
new file mode 100644
index 0000000000..39d2718a30
--- /dev/null
+++ b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.h
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Functions based on OpenSSL 1.1 API, used when building against/running with OpenSSL 1.0
+
+#pragma once
+#include "pal_types.h"
+
+extern "C" const BIGNUM* local_DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey);
+extern "C" void local_DSA_get0_pqg(const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g);
+extern "C" const DSA_METHOD* local_DSA_get_method(const DSA* dsa);
+extern "C" int32_t local_DSA_set0_key(DSA* dsa, BIGNUM* bnY, BIGNUM* bnX);
+extern "C" int32_t local_DSA_set0_pqg(DSA* dsa, BIGNUM* bnP, BIGNUM* bnQ, BIGNUM* bnG);
+extern "C" void local_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx);
+extern "C" EVP_CIPHER_CTX* local_EVP_CIPHER_CTX_new(void);
+extern "C" int32_t local_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX* ctx);
+extern "C" int32_t local_EVP_PKEY_up_ref(EVP_PKEY* pkey);
+extern "C" void local_HMAC_CTX_free(HMAC_CTX* ctx);
+extern "C" HMAC_CTX* local_HMAC_CTX_new(void);
+extern "C" const char* local_OpenSSL_version(int t);
+extern "C" void local_RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp);
+extern "C" void local_RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q);
+extern "C" void local_RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d);
+extern "C" int32_t local_RSA_meth_get_flags(const RSA_METHOD* meth);
+extern "C" int32_t local_RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp);
+extern "C" int32_t local_RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q);
+extern "C" int32_t local_RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d);
+extern "C" int32_t local_SSL_is_init_finished(const SSL* ssl);
+extern "C" unsigned long local_SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options);
+extern "C" void local_SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level);
+extern "C" int local_SSL_session_reused(SSL* ssl);
+extern "C" const ASN1_TIME* local_X509_CRL_get0_nextUpdate(const X509_CRL* crl);
+extern "C" int32_t local_X509_NAME_get0_der(X509_NAME* x509Name, const uint8_t** pder, size_t* pderlen);
+extern "C" int32_t local_X509_PUBKEY_get0_param(
+    ASN1_OBJECT** palgOid, const uint8_t** pkeyBytes, int* pkeyBytesLen, X509_ALGOR** palg, X509_PUBKEY* pubkey);
+extern "C" X509* local_X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx);
+extern "C" STACK_OF(X509) * local_X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx);
+extern "C" const ASN1_TIME* local_X509_get0_notAfter(const X509* x509);
+extern "C" const ASN1_TIME* local_X509_get0_notBefore(const X509* x509);
+extern "C" ASN1_BIT_STRING* local_X509_get0_pubkey_bitstr(const X509* x509);
+extern "C" const X509_ALGOR* local_X509_get0_tbs_sigalg(const X509* x509);
+extern "C" X509_PUBKEY* local_X509_get_X509_PUBKEY(const X509* x509);
+extern "C" int32_t local_X509_get_version(const X509* x509);
+extern "C" int32_t local_X509_up_ref(X509* x509);
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake b/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake
index 809ffe318e..cdc9f50f3c 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake
+++ b/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake
@@ -2,11 +2,6 @@ include(CheckLibraryExists)
 include(CheckFunctionExists)
 
 set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
-
-# Check which versions of TLS the OpenSSL/ssl library supports
-check_library_exists(${OPENSSL_SSL_LIBRARY} "TLSv1_1_method" "" HAVE_TLS_V1_1)
-check_library_exists(${OPENSSL_SSL_LIBRARY} "TLSv1_2_method" "" HAVE_TLS_V1_2)
-
 set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
 
 check_function_exists(
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp b/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp
index 46396370b4..f419b755b7 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp
@@ -6,6 +6,7 @@
 #include "pal_utilities.h"
 #include "pal_safecrt.h"
 #include "opensslshim.h"
+#include "openssl.h"
 
 #include <assert.h>
 #include <limits.h>
@@ -78,7 +79,7 @@ extern "C" int32_t CryptoNative_GetX509Thumbprint(X509* x509, uint8_t* pBuf, int
         return -SHA_DIGEST_LENGTH;
     }
 
-    if (!X509_digest(x509, EVP_sha1(), pBuf, NULL))
+    if (!X509_digest(x509, EVP_sha1(), pBuf, nullptr))
     {
         return 0;
     }
@@ -97,14 +98,14 @@ Return values:
 NULL if the validity cannot be determined, a pointer to the ASN1_TIME structure for the NotBefore value
 otherwise.
 */
-extern "C" ASN1_TIME* CryptoNative_GetX509NotBefore(X509* x509)
+extern "C" const ASN1_TIME* CryptoNative_GetX509NotBefore(X509* x509)
 {
-    if (x509 && x509->cert_info && x509->cert_info->validity)
+    if (x509)
     {
-        return x509->cert_info->validity->notBefore;
+        return X509_get0_notBefore(x509);
     }
 
-    return NULL;
+    return nullptr;
 }
 
 /*
@@ -118,14 +119,14 @@ Return values:
 NULL if the validity cannot be determined, a pointer to the ASN1_TIME structure for the NotAfter value
 otherwise.
 */
-extern "C" ASN1_TIME* CryptoNative_GetX509NotAfter(X509* x509)
+extern "C" const ASN1_TIME* CryptoNative_GetX509NotAfter(X509* x509)
 {
-    if (x509 && x509->cert_info && x509->cert_info->validity)
+    if (x509)
     {
-        return x509->cert_info->validity->notAfter;
+        return X509_get0_notAfter(x509);
     }
 
-    return NULL;
+    return nullptr;
 }
 
 /*
@@ -139,14 +140,14 @@ Return values:
 NULL if the validity cannot be determined, a pointer to the ASN1_TIME structure for the NextUpdate value
 otherwise.
 */
-extern "C" ASN1_TIME* CryptoNative_GetX509CrlNextUpdate(X509_CRL* crl)
+extern "C" const ASN1_TIME* CryptoNative_GetX509CrlNextUpdate(X509_CRL* crl)
 {
     if (crl)
     {
-        return X509_CRL_get_nextUpdate(crl);
+        return X509_CRL_get0_nextUpdate(crl);
     }
 
-    return NULL;
+    return nullptr;
 }
 
 /*
@@ -165,9 +166,9 @@ The encoded value of the version, otherwise:
 */
 extern "C" int32_t CryptoNative_GetX509Version(X509* x509)
 {
-    if (x509 && x509->cert_info)
+    if (x509)
     {
-        long ver = ASN1_INTEGER_get(x509->cert_info->version);
+        long ver = X509_get_version(x509);
         return static_cast<int32_t>(ver);
     }
 
@@ -187,12 +188,18 @@ describing the object type.
 */
 extern "C" ASN1_OBJECT* CryptoNative_GetX509PublicKeyAlgorithm(X509* x509)
 {
-    if (x509 && x509->cert_info && x509->cert_info->key && x509->cert_info->key->algor)
+    if (x509)
     {
-        return x509->cert_info->key->algor->algorithm;
+        X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
+        ASN1_OBJECT* algOid;
+
+        if (pubkey && X509_PUBKEY_get0_param(&algOid, nullptr, nullptr, nullptr, pubkey))
+        {
+            return algOid;
+        }
     }
 
-    return NULL;
+    return nullptr;
 }
 
 /*
@@ -208,12 +215,17 @@ describing the object type.
 */
 extern "C" ASN1_OBJECT* CryptoNative_GetX509SignatureAlgorithm(X509* x509)
 {
-    if (x509 && x509->sig_alg && x509->sig_alg->algorithm)
+    if (x509)
     {
-        return x509->sig_alg->algorithm;
+        const X509_ALGOR* sigAlg = X509_get0_tbs_sigalg(x509);
+
+        if (sigAlg)
+        {
+            return sigAlg->algorithm;
+        }
     }
 
-    return NULL;
+    return nullptr;
 }
 
 /*
@@ -230,21 +242,35 @@ Any negative value: The input buffer size was reported as insufficient. A buffer
 */
 extern "C" int32_t CryptoNative_GetX509PublicKeyParameterBytes(X509* x509, uint8_t* pBuf, int32_t cBuf)
 {
-    if (!x509 || !x509->cert_info || !x509->cert_info->key || !x509->cert_info->key->algor)
+    if (!x509)
+    {
+        return 0;
+    }
+
+    X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509);
+
+    if (!pubkey)
+    {
+        return 0;
+    }
+
+    X509_ALGOR* alg;
+
+    if (!X509_PUBKEY_get0_param(nullptr, nullptr, nullptr, &alg, pubkey) || !alg)
     {
         return 0;
     }
 
-    ASN1_TYPE* parameter = x509->cert_info->key->algor->parameter;
+    ASN1_TYPE* parameter = alg->parameter;
 
     if (!parameter)
     {
         // If pBuf is NULL we're asking for the length, so return 0 (which is negative-zero)
         // If pBuf is non-NULL we're asking to fill the data, in which case we return 1.
-        return pBuf != NULL;
+        return pBuf != nullptr;
     }
-    
-    int len = i2d_ASN1_TYPE(parameter, NULL);
+
+    int len = i2d_ASN1_TYPE(parameter, nullptr);
 
     if (cBuf < len)
     {
@@ -275,12 +301,12 @@ the public key.
 */
 extern "C" ASN1_BIT_STRING* CryptoNative_GetX509PublicKeyBytes(X509* x509)
 {
-    if (x509 && x509->cert_info && x509->cert_info->key)
+    if (x509)
     {
-        return x509->cert_info->key->public_key;
+        return X509_get0_pubkey_bitstr(x509);
     }
 
-    return NULL;
+    return nullptr;
 }
 
 /*
@@ -353,7 +379,10 @@ Any negative value: The input buffer size was reported as insufficient. A buffer
 */
 extern "C" int32_t CryptoNative_GetX509NameRawBytes(X509_NAME* x509Name, uint8_t* pBuf, int32_t cBuf)
 {
-    if (!x509Name || !x509Name->bytes || cBuf < 0)
+    const uint8_t* nameBuf;
+    size_t nameBufLen;
+
+    if (!x509Name || cBuf < 0 || !X509_NAME_get0_der(x509Name, &nameBuf, &nameBufLen))
     {
         return 0;
     }
@@ -367,13 +396,13 @@ extern "C" int32_t CryptoNative_GetX509NameRawBytes(X509_NAME* x509Name, uint8_t
      * value is less than INT_MAX in it's native format; once we know it is not
      * too large, we can safely cast to an int to make sure it is not negative
      */
-    if (x509Name->bytes->length > INT_MAX)
+    if (nameBufLen > INT_MAX)
     {
         assert(0 && "Huge length X509_NAME");
         return 0;
     }
 
-    int length = static_cast<int>(x509Name->bytes->length);
+    int length = static_cast<int>(nameBufLen);
 
     if (length < 0)
     {
@@ -386,7 +415,7 @@ extern "C" int32_t CryptoNative_GetX509NameRawBytes(X509_NAME* x509Name, uint8_t
         return -length;
     }
 
-    memcpy_s(pBuf, UnsignedCast(cBuf), x509Name->bytes->data, UnsignedCast(length));
+    memcpy_s(pBuf, UnsignedCast(cBuf), nameBuf, UnsignedCast(length));
     return 1;
 }
 
@@ -437,9 +466,9 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32
 {
     static const char szOidUpn[] = "1.3.6.1.4.1.311.20.2.3";
 
-    if (!x509 || !x509->cert_info || nameType < NAME_TYPE_SIMPLE || nameType > NAME_TYPE_URL)
+    if (!x509 || nameType < NAME_TYPE_SIMPLE || nameType > NAME_TYPE_URL)
     {
-        return NULL;
+        return nullptr;
     }
 
     // Algorithm behaviors (pseudocode).  When forIssuer is true, replace "Subject" with "Issuer" and
@@ -454,15 +483,15 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32
     // UrlName: SAN.Entries.FirstOrDefault(type == GEN_URI);
     if (nameType == NAME_TYPE_SIMPLE)
     {
-        X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject;
+        X509_NAME* name = forIssuer ? X509_get_issuer_name(x509) : X509_get_subject_name(x509);
 
         if (name)
         {
-            ASN1_STRING* cn = NULL;
-            ASN1_STRING* ou = NULL;
-            ASN1_STRING* o = NULL;
-            ASN1_STRING* e = NULL;
-            ASN1_STRING* firstRdn = NULL;
+            ASN1_STRING* cn = nullptr;
+            ASN1_STRING* ou = nullptr;
+            ASN1_STRING* o = nullptr;
+            ASN1_STRING* e = nullptr;
+            ASN1_STRING* firstRdn = nullptr;
 
             // Walk the list backwards because it is stored in stack order
             for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i)
@@ -564,7 +593,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32
         }
 
         STACK_OF(GENERAL_NAME)* altNames = static_cast<STACK_OF(GENERAL_NAME)*>(
-            X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL));
+            X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, nullptr, nullptr));
 
         if (altNames)
         {
@@ -576,7 +605,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32
 
                 if (altName && altName->type == expectedType)
                 {
-                    ASN1_STRING* str = NULL;
+                    ASN1_STRING* str = nullptr;
 
                     switch (nameType)
                     {
@@ -629,7 +658,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32
 
     if (nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_DNS)
     {
-        X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject;
+        X509_NAME* name = forIssuer ? X509_get_issuer_name(x509) : X509_get_subject_name(x509);
         int expectedNid = NID_undef;
 
         switch (nameType)
@@ -674,7 +703,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32
         }
     }
 
-    return NULL;
+    return nullptr;
 }
 
 /*
@@ -821,7 +850,7 @@ extern "C" int32_t CryptoNative_CheckX509Hostname(X509* x509, const char* hostna
     int subjectNid = NID_commonName;
     int sanGenType = GEN_DNS;
     GENERAL_NAMES* san = static_cast<GENERAL_NAMES*>(
-        X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL));
+        X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr));
     char readSubject = 1;
     int success = 0;
 
@@ -909,7 +938,7 @@ extern "C" int32_t CryptoNative_CheckX509IpAddress(
 
     int subjectNid = NID_commonName;
     int sanGenType = GEN_IPADD;
-    GENERAL_NAMES* san = static_cast<GENERAL_NAMES*>(X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL));
+    GENERAL_NAMES* san = static_cast<GENERAL_NAMES*>(X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr));
     int success = 0;
 
     if (san)
@@ -1070,7 +1099,7 @@ otherwise NULL.
 */
 extern "C" X509* CryptoNative_ReadX509AsDerFromBio(BIO* bio)
 {
-    return d2i_X509_bio(bio, NULL);
+    return d2i_X509_bio(bio, nullptr);
 }
 
 /*
@@ -1242,6 +1271,26 @@ extern "C" int32_t CryptoNative_LookupFriendlyNameByOid(const char* oidValue, co
     return 0;
 }
 
+#ifndef OPENSSL_VERSION
+#define OPENSSL_VERSION 0
+#endif
+
+/*
+Function:
+SSLEayVersion
+
+Gets the version of openssl library.
+
+Return values:
+Textual description of the version on success.
+"not available" string on failure.
+*/
+extern "C" char* CryptoNative_SSLEayVersion()
+{
+    return strdup(OpenSSL_version(OPENSSL_VERSION));
+}
+
+#ifdef NEED_OPENSSL_1_0
 // Lock used to make sure EnsureopenSslInitialized itself is thread safe
 static pthread_mutex_t g_initLock = PTHREAD_MUTEX_INITIALIZER;
 
@@ -1262,6 +1311,10 @@ static void LockingCallback(int mode, int n, const char* file, int line)
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wthread-safety-analysis"
 
+#ifndef CRYPTO_LOCK
+#define CRYPTO_LOCK 1
+#endif
+
     int result;
     if (mode & CRYPTO_LOCK)
     {
@@ -1307,7 +1360,7 @@ Return values:
 0 on success
 non-zero on failure
 */
-extern "C" int32_t CryptoNative_EnsureOpenSslInitialized()
+static int32_t EnsureOpenSsl10Initialized()
 {
     int ret = 0;
     int numLocks = 0;
@@ -1383,25 +1436,53 @@ done:
                 pthread_mutex_destroy(&g_locks[i]); // ignore failures
             }
             delete[] g_locks;
-            g_locks = NULL;
+            g_locks = nullptr;
         }
     }
 
     pthread_mutex_unlock(&g_initLock);
     return ret;
 }
+#endif // NEED_OPENSSL_1_0 */
 
-/*
-Function:
-SSLEayVersion
+#ifdef NEED_OPENSSL_1_1
 
-Gets the version of openssl library.
+static int32_t EnsureOpenSsl11Initialized()
+{
+    // In OpenSSL 1.0 we call OPENSSL_add_all_algorithms_conf() and ERR_load_crypto_strings(),
+    // so do the same for 1.1
+    OPENSSL_init_ssl(
+        // OPENSSL_add_all_algorithms_conf
+            OPENSSL_INIT_ADD_ALL_CIPHERS |
+            OPENSSL_INIT_ADD_ALL_DIGESTS |
+            OPENSSL_INIT_LOAD_CONFIG |
+        // ERR_load_crypto_strings
+            OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
+            OPENSSL_INIT_LOAD_SSL_STRINGS,
+        nullptr);
 
-Return values:
-Textual description of the version on success.
-"not available" string on failure.
-*/
-extern "C" char* CryptoNative_SSLEayVersion()
+    return 0;
+}
+
+#endif
+
+extern "C" int32_t CryptoNative_EnsureOpenSslInitialized()
 {
-    return strdup(SSLeay_version(SSLEAY_VERSION));
+    // If portable then decide which OpenSSL we are, and call the right one.
+    // If 1.0, call the 1.0 one.
+    // Otherwise call the 1.1 one.
+#ifdef FEATURE_DISTRO_AGNOSTIC_SSL
+    if (API_EXISTS(SSL_state))
+    {
+        return EnsureOpenSsl10Initialized();
+    }
+    else
+    {
+        return EnsureOpenSsl11Initialized();
+    }
+#elif OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM
+    return EnsureOpenSsl10Initialized();
+#else
+    return EnsureOpenSsl11Initialized();
+#endif
 }
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/openssl.h b/src/Native/Unix/System.Security.Cryptography.Native/openssl.h
new file mode 100644
index 0000000000..372d6fd45a
--- /dev/null
+++ b/src/Native/Unix/System.Security.Cryptography.Native/openssl.h
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+#pragma once
+
+#include "pal_compiler.h"
+#include "opensslshim.h"
+
+extern "C" char* CryptoNative_SSLEayVersion();
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h b/src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h
new file mode 100644
index 0000000000..8852c3c1b3
--- /dev/null
+++ b/src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h
@@ -0,0 +1,139 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Definitions of structures from OpenSSL 1.0.2, modified as relevant to
+// building .NET Core.
+
+// The CRYPTO_EX_DATA struct is smaller in 1.1, which changes the packing of
+// dsa_st
+struct crypto_ex_data_10_st
+{
+    STACK_OF(void) * sk;
+    int dummy;
+};
+
+struct dsa_st
+{
+    int _ignored0;
+    long _ignored1;
+    int _ignored2;
+    BIGNUM* p;
+    BIGNUM* q;
+    BIGNUM* g;
+    BIGNUM* pub_key;
+    BIGNUM* priv_key;
+    const void* _ignored3;
+    const void* _ignored4;
+    int _ignored5;
+    const void* _ignored6;
+    int _ignored7;
+    struct crypto_ex_data_10_st ex_data;
+    const DSA_METHOD* meth;
+};
+
+struct evp_cipher_ctx_st
+{
+    // 0xA8 is the sizeof value when building against OpenSSL 1.0.2 on
+    // Ubuntu 16.04
+    unsigned char _ignored0[0xA8];
+};
+
+struct evp_pkey_st
+{
+    int _ignored0;
+    int _ignored1;
+    int references;
+};
+
+struct hmac_ctx_st
+{
+    // 0x120 is the sizeof value when building against OpenSSL 1.0.2 on
+    // Ubuntu 16.04
+    unsigned char _ignored0[0x120];
+};
+
+struct rsa_meth_st
+{
+    const void* _ignored0;
+    const void* _ignored1;
+    const void* _ignored2;
+    const void* _ignored3;
+    const void* _ignored4;
+    const void* _ignored5;
+    const void* _ignored6;
+    const void* _ignored7;
+    const void* _ignored8;
+    int flags;
+};
+
+struct rsa_st
+{
+    int _ignored0;
+    long _ignored1;
+    const RSA_METHOD* meth;
+    const void* _ignored2;
+    BIGNUM* n;
+    BIGNUM* e;
+    BIGNUM* d;
+    BIGNUM* p;
+    BIGNUM* q;
+    BIGNUM* dmp1;
+    BIGNUM* dmq1;
+    BIGNUM* iqmp;
+};
+
+struct x509_cinf_st
+{
+    ASN1_INTEGER* version;
+    ASN1_INTEGER* serialNumber;
+    X509_ALGOR* signature;
+    X509_NAME* issuer;
+    X509_VAL* validity;
+    X509_NAME* subject;
+    X509_PUBKEY* key;
+};
+
+struct X509_crl_info_st
+{
+    const void* _ignored0;
+    const void* _ignored1;
+    const void* _ignored2;
+    const void* _ignored3;
+    ASN1_TIME* nextUpdate;
+};
+
+struct X509_crl_st
+{
+    X509_CRL_INFO* crl;
+};
+
+struct X509_name_st
+{
+    STACK_OF(X509_NAME_ENTRY) * entries;
+    int _ignored0;
+    BUF_MEM* bytes;
+};
+
+struct X509_pubkey_st
+{
+    X509_ALGOR* algor;
+    ASN1_BIT_STRING* public_key;
+};
+
+struct x509_st
+{
+    X509_CINF* cert_info;
+    const void* _ignored0;
+    const void* _ignored1;
+    int _ignored2;
+    int references;
+};
+
+struct x509_store_ctx_st
+{
+    const void* _ignored0;
+    int _ignored1;
+    X509* cert;
+    STACK_OF(X509*) untrusted;
+};
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp
index f4e1cb71cb..585f7ac23f 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp
@@ -5,13 +5,25 @@
 
 #include <dlfcn.h>
 #include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
 
 #include "opensslshim.h"
 
-// Define pointers to all the used ICU functions
-#define PER_FUNCTION_BLOCK(fn, isRequired) decltype(fn) fn##_ptr;
+// Define pointers to all the used OpenSSL functions
+#define REQUIRED_FUNCTION(fn) __typeof(fn) fn##_ptr;
+#define NEW_REQUIRED_FUNCTION(fn) __typeof(fn) fn##_ptr;
+#define LIGHTUP_FUNCTION(fn) __typeof(fn) fn##_ptr;
+#define FALLBACK_FUNCTION(fn) __typeof(fn) fn##_ptr;
+#define RENAMED_FUNCTION(fn,oldfn) __typeof(fn) fn##_ptr;
+#define LEGACY_FUNCTION(fn) __typeof(fn) fn##_ptr;
 FOR_ALL_OPENSSL_FUNCTIONS
-#undef PER_FUNCTION_BLOCK
+#undef LEGACY_FUNCTION
+#undef RENAMED_FUNCTION
+#undef FALLBACK_FUNCTION
+#undef LIGHTUP_FUNCTION
+#undef NEW_REQUIRED_FUNCTION
+#undef REQUIRED_FUNCTION
 
 // x.x.x, considering the max number of decimal digits for each component
 static const int MaxVersionStringLength = 32;
@@ -35,6 +47,12 @@ bool OpenLibrary()
         libssl = dlopen(soName, RTLD_LAZY);
     }
 
+    if (libssl == nullptr)
+    {
+        // Prefer OpenSSL 1.1.x
+        libssl = dlopen("libssl.so.1.1", RTLD_LAZY);
+    }
+
     if (libssl == nullptr)
     {
         // Debian 9 has dropped support for SSLv3 and so they have bumped their soname. Let's try it
@@ -63,17 +81,41 @@ void InitializeOpenSSLShim()
 {
     if (!OpenLibrary())
     {
-        fprintf(stderr, "No usable version of the libssl was found\n");
+        fprintf(stderr, "No usable version of libssl was found\n");
         abort();
     }
 
-    // Get pointers to all the ICU functions that are needed
-#define PER_FUNCTION_BLOCK(fn, isRequired) \
-    fn##_ptr = reinterpret_cast<decltype(fn)>(dlsym(libssl, #fn)); \
-    if ((fn##_ptr) == NULL && isRequired) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); }
+    // A function defined in libcrypto.so.1.0.0/libssl.so.1.0.0 that is not defined in
+    // libcrypto.so.1.1.0/libssl.so.1.1.0
+    const void* v1_0_sentinel = dlsym(libssl, "SSL_state");
+
+    // Get pointers to all the functions that are needed
+#define REQUIRED_FUNCTION(fn) \
+    if (!(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); }
+
+#define NEW_REQUIRED_FUNCTION(fn) \
+    if (!v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); }
+
+#define LIGHTUP_FUNCTION(fn) \
+    fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn));
+
+#define FALLBACK_FUNCTION(fn) \
+    if (!(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fn##_ptr = (__typeof(fn))local_##fn; }
+
+#define RENAMED_FUNCTION(fn,oldfn) \
+    if (!v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); } \
+    if (v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #oldfn)))) { fprintf(stderr, "Cannot get required symbol " #oldfn " from libssl\n"); abort(); }
+
+#define LEGACY_FUNCTION(fn) \
+    if (v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); }
 
     FOR_ALL_OPENSSL_FUNCTIONS
-#undef PER_FUNCTION_BLOCK    
+#undef LEGACY_FUNCTION
+#undef RENAMED_FUNCTION
+#undef FALLBACK_FUNCTION
+#undef LIGHTUP_FUNCTION
+#undef NEW_REQUIRED_FUNCTION
+#undef REQUIRED_FUNCTION
 }
 
 __attribute__((destructor))
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
index afb2559d12..c10cc1d534 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
@@ -3,7 +3,7 @@
 // See the LICENSE file in the project root for more information.
 //
 
-// Enable calling OpenSSL functions through shims to enable support for 
+// Enable calling OpenSSL functions through shims to enable support for
 // different versioned so files naming and different configuration options
 // on various Linux distributions.
 
@@ -16,8 +16,8 @@
 #include <openssl/bn.h>
 #include <openssl/crypto.h>
 #include <openssl/dsa.h>
-#include <openssl/ecdsa.h>
 #include <openssl/ec.h>
+#include <openssl/ecdsa.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
@@ -35,34 +35,137 @@
 #include <openssl/x509v3.h>
 
 #include "pal_crypto_config.h"
+#define OPENSSL_VERSION_1_1_0_RTM 0x10100000L
+#define OPENSSL_VERSION_1_0_2_RTM 0x10002000L
+
+#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM
+
+// Remove problematic #defines
+#undef SSL_get_state
+#undef SSL_is_init_finished
+#undef X509_get_X509_PUBKEY
+#undef X509_get_version
+
+#endif
+
+#ifdef EVP_MD_CTX_create
+#undef EVP_MD_CTX_create
+#undef EVP_MD_CTX_init
+#undef EVP_MD_CTX_destroy
+#undef SSLv23_method
+#endif
+
+#if defined FEATURE_DISTRO_AGNOSTIC_SSL || OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM
+#include "apibridge.h"
+#endif
 
 #ifdef FEATURE_DISTRO_AGNOSTIC_SSL
 
+#define NEED_OPENSSL_1_0 true
+#define NEED_OPENSSL_1_1 true
+
 #if !HAVE_OPENSSL_EC2M
 // In portable build, we need to support the following functions even if they were not present
 // on the build OS. The shim will detect their presence at runtime.
 #undef HAVE_OPENSSL_EC2M
 #define HAVE_OPENSSL_EC2M 1
-const EC_METHOD *EC_GF2m_simple_method(void);
-int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
-int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
-int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
-        const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
-int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
-        const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
+extern "C" const EC_METHOD* EC_GF2m_simple_method(void);
+extern "C" int EC_GROUP_get_curve_GF2m(const EC_GROUP* group, BIGNUM* p, BIGNUM* a, BIGNUM* b, BN_CTX* ctx);
+extern "C" int EC_GROUP_set_curve_GF2m(EC_GROUP* group, const BIGNUM* p, const BIGNUM* a, const BIGNUM* b, BN_CTX* ctx);
+extern "C" int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP* group, const EC_POINT* p, BIGNUM* x, BIGNUM* y, BN_CTX* ctx);
+extern "C" int EC_POINT_set_affine_coordinates_GF2m(
+    const EC_GROUP* group, EC_POINT* p, const BIGNUM* x, const BIGNUM* y, BN_CTX* ctx);
+#endif
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM
+typedef struct stack_st _STACK;
+extern "C" ASN1_STRING* d2i_ASN1_type_bytes(ASN1_STRING** a, const unsigned char** pp, long length, int type);
+extern "C" int CRYPTO_add_lock(int* pointer, int amount, int type, const char* file, int line);
+extern "C" int CRYPTO_num_locks(void);
+extern "C" void CRYPTO_set_locking_callback(void (*func)(int mode, int type, const char* file, int line));
+extern "C" void ERR_load_crypto_strings(void);
+extern "C" int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX* a);
+extern "C" int EVP_CIPHER_CTX_init(EVP_CIPHER_CTX* a);
+extern "C" void HMAC_CTX_cleanup(HMAC_CTX* ctx);
+extern "C" void HMAC_CTX_init(HMAC_CTX* ctx);
+extern "C" void OPENSSL_add_all_algorithms_conf(void);
+extern "C" int SSL_library_init(void);
+extern "C" void SSL_load_error_strings(void);
+extern "C" int SSL_state(const SSL* ssl);
+extern "C" const char* SSLeay_version(int t);
+#else
+typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
+typedef struct stack_st OPENSSL_STACK;
+
+#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
+#define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L
+#define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L
+#define OPENSSL_INIT_LOAD_CONFIG 0x00000040L
+#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
+
+extern "C" const BIGNUM* DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey);
+extern "C" void DSA_get0_pqg(const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g);
+extern "C" const DSA_METHOD* DSA_get_method(const DSA* dsa);
+extern "C" int32_t DSA_set0_key(DSA* dsa, BIGNUM* bnY, BIGNUM* bnX);
+extern "C" int32_t DSA_set0_pqg(DSA* dsa, BIGNUM* bnP, BIGNUM* bnQ, BIGNUM* bnG);
+extern "C" void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx);
+extern "C" EVP_CIPHER_CTX* EVP_CIPHER_CTX_new(void);
+extern "C" int32_t EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX* ctx);
+extern "C" void EVP_MD_CTX_free(EVP_MD_CTX* ctx);
+extern "C" EVP_MD_CTX* EVP_MD_CTX_new(void);
+extern "C" int32_t EVP_PKEY_up_ref(EVP_PKEY* pkey);
+extern "C" void HMAC_CTX_free(HMAC_CTX* ctx);
+extern "C" HMAC_CTX* HMAC_CTX_new(void);
+extern "C" int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS* settings);
+extern "C" void OPENSSL_sk_free(OPENSSL_STACK*);
+extern "C" OPENSSL_STACK* OPENSSL_sk_new_null(void);
+extern "C" int OPENSSL_sk_num(const OPENSSL_STACK*);
+extern "C" void OPENSSL_sk_pop_free(OPENSSL_STACK* st, void (*func)(void*));
+extern "C" int OPENSSL_sk_push(OPENSSL_STACK* st, const void* data);
+extern "C" void* OPENSSL_sk_value(const OPENSSL_STACK*, int);
+extern "C" const char* OpenSSL_version(int type);
+extern "C" unsigned long OpenSSL_version_num();
+extern "C" void RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp);
+extern "C" void RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q);
+extern "C" void RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d);
+extern "C" int32_t RSA_meth_get_flags(const RSA_METHOD* meth);
+extern "C" int32_t RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp);
+extern "C" int32_t RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q);
+extern "C" int32_t RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d);
+extern "C" int32_t SSL_is_init_finished(SSL* ssl);
+#undef SSL_CTX_set_options
+extern "C" unsigned long SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options);
+extern "C" void SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level);
+#undef SSL_session_reused
+extern "C" int SSL_session_reused(SSL* ssl);
+extern "C" const SSL_METHOD* TLS_method(void);
+extern "C" const ASN1_TIME* X509_CRL_get0_nextUpdate(const X509_CRL* crl);
+extern "C" int32_t X509_NAME_get0_der(X509_NAME* x509Name, const uint8_t** pder, size_t* pderlen);
+extern "C" int32_t X509_PUBKEY_get0_param(
+    ASN1_OBJECT** palgOid, const uint8_t** pkeyBytes, int* pkeyBytesLen, X509_ALGOR** palg, X509_PUBKEY* pubkey);
+extern "C" X509* X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx);
+extern "C" STACK_OF(X509) * X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx);
+extern "C" const ASN1_TIME* X509_get0_notAfter(const X509* x509);
+extern "C" const ASN1_TIME* X509_get0_notBefore(const X509* x509);
+extern "C" ASN1_BIT_STRING* X509_get0_pubkey_bitstr(const X509* x509);
+extern "C" const X509_ALGOR* X509_get0_tbs_sigalg(const X509* x509);
+extern "C" X509_PUBKEY* X509_get_X509_PUBKEY(const X509* x509);
+extern "C" int32_t X509_get_version(const X509* x509);
+extern "C" int32_t X509_up_ref(X509* x509);
 #endif
 
 #if !HAVE_OPENSSL_ALPN
 #undef HAVE_OPENSSL_ALPN
 #define HAVE_OPENSSL_ALPN 1
-int SSL_CTX_set_alpn_protos(SSL_CTX* ctx, const unsigned char* protos, unsigned int protos_len);
-void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, int (*cb) (SSL *ssl,
-                                            const unsigned char **out,
-                                            unsigned char *outlen,
-                                            const unsigned char *in,
-                                            unsigned int inlen,
-                                            void *arg), void *arg);
-void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsigned int* len);
+extern "C" int SSL_CTX_set_alpn_protos(SSL_CTX* ctx, const unsigned char* protos, unsigned int protos_len);
+extern "C" void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx,
+                                int (*cb)(SSL* ssl,
+                                          const unsigned char** out,
+                                          unsigned char* outlen,
+                                          const unsigned char* in,
+                                          unsigned int inlen,
+                                          void* arg),
+                                void* arg);
+extern "C" void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsigned int* len);
 #endif
 
 #define API_EXISTS(fn) (fn != nullptr)
@@ -70,304 +173,350 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi
 // List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
 // Forgetting to add a function here results in build failure with message reporting the function
 // that needs to be added.
+
 #define FOR_ALL_OPENSSL_FUNCTIONS \
-    PER_FUNCTION_BLOCK(ASN1_BIT_STRING_free, true) \
-    PER_FUNCTION_BLOCK(ASN1_INTEGER_get, true) \
-    PER_FUNCTION_BLOCK(ASN1_OBJECT_free, true) \
-    PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_free, true) \
-    PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_new, true) \
-    PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_set, true) \
-    PER_FUNCTION_BLOCK(ASN1_STRING_free, true) \
-    PER_FUNCTION_BLOCK(ASN1_STRING_print_ex, true) \
-    PER_FUNCTION_BLOCK(BASIC_CONSTRAINTS_free, true) \
-    PER_FUNCTION_BLOCK(BIO_ctrl, true) \
-    PER_FUNCTION_BLOCK(BIO_ctrl_pending, true) \
-    PER_FUNCTION_BLOCK(BIO_free, true) \
-    PER_FUNCTION_BLOCK(BIO_gets, true) \
-    PER_FUNCTION_BLOCK(BIO_new, true) \
-    PER_FUNCTION_BLOCK(BIO_new_file, true) \
-    PER_FUNCTION_BLOCK(BIO_read, true) \
-    PER_FUNCTION_BLOCK(BIO_s_mem, true) \
-    PER_FUNCTION_BLOCK(BIO_write, true) \
-    PER_FUNCTION_BLOCK(BN_bin2bn, true) \
-    PER_FUNCTION_BLOCK(BN_bn2bin, true) \
-    PER_FUNCTION_BLOCK(BN_clear_free, true) \
-    PER_FUNCTION_BLOCK(BN_free, true) \
-    PER_FUNCTION_BLOCK(BN_new, true) \
-    PER_FUNCTION_BLOCK(BN_num_bits, true) \
-    PER_FUNCTION_BLOCK(CRYPTO_add_lock, true) \
-    PER_FUNCTION_BLOCK(CRYPTO_num_locks, true) \
-    PER_FUNCTION_BLOCK(CRYPTO_set_locking_callback, true) \
-    PER_FUNCTION_BLOCK(d2i_ASN1_BIT_STRING, true) \
-    PER_FUNCTION_BLOCK(d2i_ASN1_OCTET_STRING, true) \
-    PER_FUNCTION_BLOCK(d2i_ASN1_type_bytes, true) \
-    PER_FUNCTION_BLOCK(d2i_BASIC_CONSTRAINTS, true) \
-    PER_FUNCTION_BLOCK(d2i_EXTENDED_KEY_USAGE, true) \
-    PER_FUNCTION_BLOCK(d2i_PKCS12, true) \
-    PER_FUNCTION_BLOCK(d2i_PKCS12_bio, true) \
-    PER_FUNCTION_BLOCK(d2i_PKCS7, true) \
-    PER_FUNCTION_BLOCK(d2i_PKCS7_bio, true) \
-    PER_FUNCTION_BLOCK(d2i_RSAPublicKey, true) \
-    PER_FUNCTION_BLOCK(d2i_X509, true) \
-    PER_FUNCTION_BLOCK(d2i_X509_bio, true) \
-    PER_FUNCTION_BLOCK(d2i_X509_CRL, true) \
-    PER_FUNCTION_BLOCK(d2i_X509_NAME, true) \
-    PER_FUNCTION_BLOCK(DSA_free, true) \
-    PER_FUNCTION_BLOCK(DSA_generate_key, true) \
-    PER_FUNCTION_BLOCK(DSA_generate_parameters_ex, true) \
-    PER_FUNCTION_BLOCK(DSA_new, true) \
-    PER_FUNCTION_BLOCK(DSA_OpenSSL, true) \
-    PER_FUNCTION_BLOCK(DSA_sign, true) \
-    PER_FUNCTION_BLOCK(DSA_size, true) \
-    PER_FUNCTION_BLOCK(DSA_up_ref, true) \
-    PER_FUNCTION_BLOCK(DSA_verify, true) \
-    PER_FUNCTION_BLOCK(ECDSA_sign, true) \
-    PER_FUNCTION_BLOCK(ECDSA_size, true) \
-    PER_FUNCTION_BLOCK(ECDSA_verify, true) \
-    PER_FUNCTION_BLOCK(EC_GFp_mont_method, true) \
-    PER_FUNCTION_BLOCK(EC_GFp_simple_method, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_check, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_free, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get0_generator, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get0_seed, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get_cofactor, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get_curve_GFp, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get_curve_name, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get_degree, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get_order, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get_seed_len, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_method_of, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_new, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_set_curve_GFp, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_set_generator, true) \
-    PER_FUNCTION_BLOCK(EC_GROUP_set_seed, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_check_key, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_free, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_generate_key, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_get0_group, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_get0_private_key, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_get0_public_key, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_new, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_new_by_curve_name, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_set_group, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_set_private_key, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_set_public_key_affine_coordinates, true) \
-    PER_FUNCTION_BLOCK(EC_KEY_up_ref, true) \
-    PER_FUNCTION_BLOCK(EC_METHOD_get_field_type, true) \
-    PER_FUNCTION_BLOCK(EC_POINT_free, true) \
-    PER_FUNCTION_BLOCK(EC_POINT_get_affine_coordinates_GFp, true) \
-    PER_FUNCTION_BLOCK(EC_POINT_new, true) \
-    PER_FUNCTION_BLOCK(EC_POINT_set_affine_coordinates_GFp, true) \
-    PER_FUNCTION_BLOCK(ERR_clear_error, true) \
-    PER_FUNCTION_BLOCK(ERR_error_string_n, true) \
-    PER_FUNCTION_BLOCK(ERR_get_error, true) \
-    PER_FUNCTION_BLOCK(ERR_load_crypto_strings, true) \
-    PER_FUNCTION_BLOCK(ERR_put_error, true) \
-    PER_FUNCTION_BLOCK(ERR_peek_error, true) \
-    PER_FUNCTION_BLOCK(ERR_peek_last_error, true) \
-    PER_FUNCTION_BLOCK(ERR_reason_error_string, true) \
-    PER_FUNCTION_BLOCK(EVP_aes_128_cbc, true) \
-    PER_FUNCTION_BLOCK(EVP_aes_128_ecb, true) \
-    PER_FUNCTION_BLOCK(EVP_aes_192_cbc, true) \
-    PER_FUNCTION_BLOCK(EVP_aes_192_ecb, true) \
-    PER_FUNCTION_BLOCK(EVP_aes_256_cbc, true) \
-    PER_FUNCTION_BLOCK(EVP_aes_256_ecb, true) \
-    PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_cleanup, true) \
-    PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_ctrl, true) \
-    PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_init, true) \
-    PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_set_key_length, true) \
-    PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_set_padding, true) \
-    PER_FUNCTION_BLOCK(EVP_CipherFinal_ex, true) \
-    PER_FUNCTION_BLOCK(EVP_CipherInit_ex, true) \
-    PER_FUNCTION_BLOCK(EVP_CipherUpdate, true) \
-    PER_FUNCTION_BLOCK(EVP_des_cbc, true) \
-    PER_FUNCTION_BLOCK(EVP_des_ecb, true) \
-    PER_FUNCTION_BLOCK(EVP_des_ede3, true) \
-    PER_FUNCTION_BLOCK(EVP_des_ede3_cbc, true) \
-    PER_FUNCTION_BLOCK(EVP_DigestFinal_ex, true) \
-    PER_FUNCTION_BLOCK(EVP_DigestInit_ex, true) \
-    PER_FUNCTION_BLOCK(EVP_DigestUpdate, true) \
-    PER_FUNCTION_BLOCK(EVP_get_digestbyname, true) \
-    PER_FUNCTION_BLOCK(EVP_md5, true) \
-    PER_FUNCTION_BLOCK(EVP_MD_CTX_create, true) \
-    PER_FUNCTION_BLOCK(EVP_MD_CTX_destroy, true) \
-    PER_FUNCTION_BLOCK(EVP_MD_size, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_CTX_free, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_CTX_new, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_derive_set_peer, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_derive_init, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_derive, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_free, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_get1_DSA, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_get1_EC_KEY, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_get1_RSA, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_new, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_set1_DSA, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_set1_EC_KEY, true) \
-    PER_FUNCTION_BLOCK(EVP_PKEY_set1_RSA, true) \
-    PER_FUNCTION_BLOCK(EVP_rc2_cbc, true) \
-    PER_FUNCTION_BLOCK(EVP_rc2_ecb, true) \
-    PER_FUNCTION_BLOCK(EVP_sha1, true) \
-    PER_FUNCTION_BLOCK(EVP_sha256, true) \
-    PER_FUNCTION_BLOCK(EVP_sha384, true) \
-    PER_FUNCTION_BLOCK(EVP_sha512, true) \
-    PER_FUNCTION_BLOCK(EXTENDED_KEY_USAGE_free, true) \
-    PER_FUNCTION_BLOCK(GENERAL_NAMES_free, true) \
-    PER_FUNCTION_BLOCK(HMAC_CTX_cleanup, true) \
-    PER_FUNCTION_BLOCK(HMAC_CTX_init, true) \
-    PER_FUNCTION_BLOCK(HMAC_Final, true) \
-    PER_FUNCTION_BLOCK(HMAC_Init_ex, true) \
-    PER_FUNCTION_BLOCK(HMAC_Update, true) \
-    PER_FUNCTION_BLOCK(i2d_ASN1_INTEGER, true) \
-    PER_FUNCTION_BLOCK(i2d_ASN1_TYPE, true) \
-    PER_FUNCTION_BLOCK(i2d_PKCS12, true) \
-    PER_FUNCTION_BLOCK(i2d_PKCS7, true) \
-    PER_FUNCTION_BLOCK(i2d_X509, true) \
-    PER_FUNCTION_BLOCK(i2d_X509_PUBKEY, true) \
-    PER_FUNCTION_BLOCK(OBJ_ln2nid, true) \
-    PER_FUNCTION_BLOCK(OBJ_nid2ln, true) \
-    PER_FUNCTION_BLOCK(OBJ_nid2sn, true) \
-    PER_FUNCTION_BLOCK(OBJ_nid2obj, true) \
-    PER_FUNCTION_BLOCK(OBJ_obj2nid, true) \
-    PER_FUNCTION_BLOCK(OBJ_obj2txt, true) \
-    PER_FUNCTION_BLOCK(OBJ_sn2nid, true) \
-    PER_FUNCTION_BLOCK(OBJ_txt2nid, true) \
-    PER_FUNCTION_BLOCK(OBJ_txt2obj, true) \
-    PER_FUNCTION_BLOCK(OPENSSL_add_all_algorithms_conf, true) \
-    PER_FUNCTION_BLOCK(OPENSSL_cleanse, true) \
-    PER_FUNCTION_BLOCK(PEM_read_bio_PKCS7, true) \
-    PER_FUNCTION_BLOCK(PEM_read_bio_X509_AUX, true) \
-    PER_FUNCTION_BLOCK(PEM_read_bio_X509_CRL, true) \
-    PER_FUNCTION_BLOCK(PEM_write_bio_X509_CRL, true) \
-    PER_FUNCTION_BLOCK(PKCS12_create, true) \
-    PER_FUNCTION_BLOCK(PKCS12_free, true) \
-    PER_FUNCTION_BLOCK(PKCS12_parse, true) \
-    PER_FUNCTION_BLOCK(PKCS7_add_certificate, true) \
-    PER_FUNCTION_BLOCK(PKCS7_content_new, true) \
-    PER_FUNCTION_BLOCK(PKCS7_free, true) \
-    PER_FUNCTION_BLOCK(PKCS7_new, true) \
-    PER_FUNCTION_BLOCK(PKCS7_set_type, true) \
-    PER_FUNCTION_BLOCK(RAND_bytes, true) \
-    PER_FUNCTION_BLOCK(RAND_poll, true) \
-    PER_FUNCTION_BLOCK(RSA_free, true) \
-    PER_FUNCTION_BLOCK(RSA_generate_key_ex, true) \
-    PER_FUNCTION_BLOCK(RSA_get_method, true) \
-    PER_FUNCTION_BLOCK(RSA_new, true) \
-    PER_FUNCTION_BLOCK(RSA_private_decrypt, true) \
-    PER_FUNCTION_BLOCK(RSA_private_encrypt, true) \
-    PER_FUNCTION_BLOCK(RSA_public_decrypt, true) \
-    PER_FUNCTION_BLOCK(RSA_public_encrypt, true) \
-    PER_FUNCTION_BLOCK(RSA_sign, true) \
-    PER_FUNCTION_BLOCK(RSA_size, true) \
-    PER_FUNCTION_BLOCK(RSA_up_ref, true) \
-    PER_FUNCTION_BLOCK(RSA_verify, true) \
-    PER_FUNCTION_BLOCK(sk_free, true) \
-    PER_FUNCTION_BLOCK(sk_new_null, true) \
-    PER_FUNCTION_BLOCK(sk_num, true) \
-    PER_FUNCTION_BLOCK(sk_pop_free, true) \
-    PER_FUNCTION_BLOCK(sk_push, true) \
-    PER_FUNCTION_BLOCK(sk_value, true) \
-    PER_FUNCTION_BLOCK(SSL_CIPHER_description, true) \
-    PER_FUNCTION_BLOCK(SSL_ctrl, true) \
-    PER_FUNCTION_BLOCK(SSL_set_quiet_shutdown, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_check_private_key, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_ctrl, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_free, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_new, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_set_alpn_protos, false) \
-    PER_FUNCTION_BLOCK(SSL_CTX_set_alpn_select_cb, false) \
-    PER_FUNCTION_BLOCK(SSL_CTX_set_cert_verify_callback, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_set_cipher_list, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_set_client_cert_cb, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_set_quiet_shutdown, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_set_verify, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_use_certificate, true) \
-    PER_FUNCTION_BLOCK(SSL_CTX_use_PrivateKey, true) \
-    PER_FUNCTION_BLOCK(SSL_do_handshake, true) \
-    PER_FUNCTION_BLOCK(SSL_free, true) \
-    PER_FUNCTION_BLOCK(SSL_get_client_CA_list, true) \
-    PER_FUNCTION_BLOCK(SSL_get_current_cipher, true) \
-    PER_FUNCTION_BLOCK(SSL_get_error, true) \
-    PER_FUNCTION_BLOCK(SSL_get_finished, true) \
-    PER_FUNCTION_BLOCK(SSL_get_peer_cert_chain, true) \
-    PER_FUNCTION_BLOCK(SSL_get_peer_certificate, true) \
-    PER_FUNCTION_BLOCK(SSL_get_peer_finished, true) \
-    PER_FUNCTION_BLOCK(SSL_get_SSL_CTX, true) \
-    PER_FUNCTION_BLOCK(SSL_get_version, true) \
-    PER_FUNCTION_BLOCK(SSL_get0_alpn_selected, false) \
-    PER_FUNCTION_BLOCK(SSL_library_init, true) \
-    PER_FUNCTION_BLOCK(SSL_load_error_strings, true) \
-    PER_FUNCTION_BLOCK(SSL_new, true) \
-    PER_FUNCTION_BLOCK(SSL_read, true) \
-    PER_FUNCTION_BLOCK(SSL_renegotiate_pending, true) \
-    PER_FUNCTION_BLOCK(SSL_set_accept_state, true) \
-    PER_FUNCTION_BLOCK(SSL_set_bio, true) \
-    PER_FUNCTION_BLOCK(SSL_set_connect_state, true) \
-    PER_FUNCTION_BLOCK(SSL_shutdown, true) \
-    PER_FUNCTION_BLOCK(SSL_state, true) \
-    PER_FUNCTION_BLOCK(SSLeay_version, true) \
-    PER_FUNCTION_BLOCK(SSLv23_method, true) \
-    PER_FUNCTION_BLOCK(SSL_write, true) \
-    PER_FUNCTION_BLOCK(TLSv1_1_method, true) \
-    PER_FUNCTION_BLOCK(TLSv1_2_method, true) \
-    PER_FUNCTION_BLOCK(TLSv1_method, true) \
-    PER_FUNCTION_BLOCK(X509_check_issued, true) \
-    PER_FUNCTION_BLOCK(X509_check_purpose, true) \
-    PER_FUNCTION_BLOCK(X509_CRL_free, true) \
-    PER_FUNCTION_BLOCK(X509_digest, true) \
-    PER_FUNCTION_BLOCK(X509_dup, true) \
-    PER_FUNCTION_BLOCK(X509_EXTENSION_create_by_OBJ, true) \
-    PER_FUNCTION_BLOCK(X509_EXTENSION_free, true) \
-    PER_FUNCTION_BLOCK(X509_EXTENSION_get_critical, true) \
-    PER_FUNCTION_BLOCK(X509_EXTENSION_get_data, true) \
-    PER_FUNCTION_BLOCK(X509_EXTENSION_get_object, true) \
-    PER_FUNCTION_BLOCK(X509_free, true) \
-    PER_FUNCTION_BLOCK(X509_get_default_cert_dir, true) \
-    PER_FUNCTION_BLOCK(X509_get_default_cert_dir_env, true) \
-    PER_FUNCTION_BLOCK(X509_get_default_cert_file, true) \
-    PER_FUNCTION_BLOCK(X509_get_default_cert_file_env, true) \
-    PER_FUNCTION_BLOCK(X509_get_ext, true) \
-    PER_FUNCTION_BLOCK(X509_get_ext_count, true) \
-    PER_FUNCTION_BLOCK(X509_get_ext_d2i, true) \
-    PER_FUNCTION_BLOCK(X509_get_issuer_name, true) \
-    PER_FUNCTION_BLOCK(X509_get_serialNumber, true) \
-    PER_FUNCTION_BLOCK(X509_get_subject_name, true) \
-    PER_FUNCTION_BLOCK(X509_issuer_name_hash, true) \
-    PER_FUNCTION_BLOCK(X509_NAME_entry_count, true) \
-    PER_FUNCTION_BLOCK(X509_NAME_ENTRY_get_data, true) \
-    PER_FUNCTION_BLOCK(X509_NAME_ENTRY_get_object, true) \
-    PER_FUNCTION_BLOCK(X509_NAME_free, true) \
-    PER_FUNCTION_BLOCK(X509_NAME_get_entry, true) \
-    PER_FUNCTION_BLOCK(X509_NAME_get_index_by_NID, true) \
-    PER_FUNCTION_BLOCK(X509_PUBKEY_get, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_add_cert, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_add_crl, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_free, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_get0_param, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_get1_chain, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_get_error, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_get_error_depth, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_init, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_new, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_set_flags, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_CTX_set_verify_cb, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_free, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_new, true) \
-    PER_FUNCTION_BLOCK(X509_STORE_set_flags, true) \
-    PER_FUNCTION_BLOCK(X509V3_EXT_print, true) \
-    PER_FUNCTION_BLOCK(X509_verify_cert, true) \
-    PER_FUNCTION_BLOCK(X509_verify_cert_error_string, true) \
-    PER_FUNCTION_BLOCK(X509_VERIFY_PARAM_set_time, true) \
-    PER_FUNCTION_BLOCK(EC_GF2m_simple_method, false) \
-    PER_FUNCTION_BLOCK(EC_GROUP_get_curve_GF2m, false) \
-    PER_FUNCTION_BLOCK(EC_GROUP_set_curve_GF2m, false) \
-    PER_FUNCTION_BLOCK(EC_POINT_get_affine_coordinates_GF2m, false) \
-    PER_FUNCTION_BLOCK(EC_POINT_set_affine_coordinates_GF2m, false) \
+    REQUIRED_FUNCTION(ASN1_BIT_STRING_free) \
+    REQUIRED_FUNCTION(ASN1_INTEGER_get) \
+    REQUIRED_FUNCTION(ASN1_OBJECT_free) \
+    REQUIRED_FUNCTION(ASN1_OCTET_STRING_free) \
+    REQUIRED_FUNCTION(ASN1_OCTET_STRING_new) \
+    REQUIRED_FUNCTION(ASN1_OCTET_STRING_set) \
+    REQUIRED_FUNCTION(ASN1_STRING_free) \
+    REQUIRED_FUNCTION(ASN1_STRING_print_ex) \
+    REQUIRED_FUNCTION(BASIC_CONSTRAINTS_free) \
+    REQUIRED_FUNCTION(BIO_ctrl) \
+    REQUIRED_FUNCTION(BIO_ctrl_pending) \
+    REQUIRED_FUNCTION(BIO_free) \
+    REQUIRED_FUNCTION(BIO_gets) \
+    REQUIRED_FUNCTION(BIO_new) \
+    REQUIRED_FUNCTION(BIO_new_file) \
+    REQUIRED_FUNCTION(BIO_read) \
+    REQUIRED_FUNCTION(BIO_s_mem) \
+    REQUIRED_FUNCTION(BIO_write) \
+    REQUIRED_FUNCTION(BN_bin2bn) \
+    REQUIRED_FUNCTION(BN_bn2bin) \
+    REQUIRED_FUNCTION(BN_clear_free) \
+    REQUIRED_FUNCTION(BN_free) \
+    REQUIRED_FUNCTION(BN_new) \
+    REQUIRED_FUNCTION(BN_num_bits) \
+    LEGACY_FUNCTION(CRYPTO_add_lock) \
+    LEGACY_FUNCTION(CRYPTO_num_locks) \
+    LEGACY_FUNCTION(CRYPTO_set_locking_callback) \
+    REQUIRED_FUNCTION(d2i_ASN1_BIT_STRING) \
+    REQUIRED_FUNCTION(d2i_ASN1_OCTET_STRING) \
+    LEGACY_FUNCTION(d2i_ASN1_type_bytes) \
+    REQUIRED_FUNCTION(d2i_BASIC_CONSTRAINTS) \
+    REQUIRED_FUNCTION(d2i_EXTENDED_KEY_USAGE) \
+    REQUIRED_FUNCTION(d2i_PKCS12) \
+    REQUIRED_FUNCTION(d2i_PKCS12_bio) \
+    REQUIRED_FUNCTION(d2i_PKCS7) \
+    REQUIRED_FUNCTION(d2i_PKCS7_bio) \
+    REQUIRED_FUNCTION(d2i_RSAPublicKey) \
+    REQUIRED_FUNCTION(d2i_X509) \
+    REQUIRED_FUNCTION(d2i_X509_bio) \
+    REQUIRED_FUNCTION(d2i_X509_CRL) \
+    REQUIRED_FUNCTION(d2i_X509_NAME) \
+    REQUIRED_FUNCTION(DSA_free) \
+    REQUIRED_FUNCTION(DSA_generate_key) \
+    REQUIRED_FUNCTION(DSA_generate_parameters_ex) \
+    FALLBACK_FUNCTION(DSA_get0_key) \
+    FALLBACK_FUNCTION(DSA_get0_pqg) \
+    FALLBACK_FUNCTION(DSA_get_method) \
+    REQUIRED_FUNCTION(DSA_new) \
+    REQUIRED_FUNCTION(DSA_OpenSSL) \
+    FALLBACK_FUNCTION(DSA_set0_key) \
+    FALLBACK_FUNCTION(DSA_set0_pqg) \
+    REQUIRED_FUNCTION(DSA_sign) \
+    REQUIRED_FUNCTION(DSA_size) \
+    REQUIRED_FUNCTION(DSA_up_ref) \
+    REQUIRED_FUNCTION(DSA_verify) \
+    REQUIRED_FUNCTION(ECDSA_sign) \
+    REQUIRED_FUNCTION(ECDSA_size) \
+    REQUIRED_FUNCTION(ECDSA_verify) \
+    REQUIRED_FUNCTION(EC_GFp_mont_method) \
+    REQUIRED_FUNCTION(EC_GFp_simple_method) \
+    REQUIRED_FUNCTION(EC_GROUP_check) \
+    REQUIRED_FUNCTION(EC_GROUP_free) \
+    REQUIRED_FUNCTION(EC_GROUP_get0_generator) \
+    REQUIRED_FUNCTION(EC_GROUP_get0_seed) \
+    REQUIRED_FUNCTION(EC_GROUP_get_cofactor) \
+    REQUIRED_FUNCTION(EC_GROUP_get_curve_GFp) \
+    REQUIRED_FUNCTION(EC_GROUP_get_curve_name) \
+    REQUIRED_FUNCTION(EC_GROUP_get_degree) \
+    REQUIRED_FUNCTION(EC_GROUP_get_order) \
+    REQUIRED_FUNCTION(EC_GROUP_get_seed_len) \
+    REQUIRED_FUNCTION(EC_GROUP_method_of) \
+    REQUIRED_FUNCTION(EC_GROUP_new) \
+    REQUIRED_FUNCTION(EC_GROUP_set_curve_GFp) \
+    REQUIRED_FUNCTION(EC_GROUP_set_generator) \
+    REQUIRED_FUNCTION(EC_GROUP_set_seed) \
+    REQUIRED_FUNCTION(EC_KEY_check_key) \
+    REQUIRED_FUNCTION(EC_KEY_free) \
+    REQUIRED_FUNCTION(EC_KEY_generate_key) \
+    REQUIRED_FUNCTION(EC_KEY_get0_group) \
+    REQUIRED_FUNCTION(EC_KEY_get0_private_key) \
+    REQUIRED_FUNCTION(EC_KEY_get0_public_key) \
+    REQUIRED_FUNCTION(EC_KEY_new) \
+    REQUIRED_FUNCTION(EC_KEY_new_by_curve_name) \
+    REQUIRED_FUNCTION(EC_KEY_set_group) \
+    REQUIRED_FUNCTION(EC_KEY_set_private_key) \
+    REQUIRED_FUNCTION(EC_KEY_set_public_key_affine_coordinates) \
+    REQUIRED_FUNCTION(EC_KEY_up_ref) \
+    REQUIRED_FUNCTION(EC_METHOD_get_field_type) \
+    REQUIRED_FUNCTION(EC_POINT_free) \
+    REQUIRED_FUNCTION(EC_POINT_get_affine_coordinates_GFp) \
+    REQUIRED_FUNCTION(EC_POINT_new) \
+    REQUIRED_FUNCTION(EC_POINT_set_affine_coordinates_GFp) \
+    REQUIRED_FUNCTION(ERR_clear_error) \
+    REQUIRED_FUNCTION(ERR_error_string_n) \
+    REQUIRED_FUNCTION(ERR_get_error) \
+    LEGACY_FUNCTION(ERR_load_crypto_strings) \
+    REQUIRED_FUNCTION(ERR_put_error) \
+    REQUIRED_FUNCTION(ERR_peek_error) \
+    REQUIRED_FUNCTION(ERR_peek_last_error) \
+    REQUIRED_FUNCTION(ERR_reason_error_string) \
+    REQUIRED_FUNCTION(EVP_aes_128_cbc) \
+    REQUIRED_FUNCTION(EVP_aes_128_ecb) \
+    REQUIRED_FUNCTION(EVP_aes_192_cbc) \
+    REQUIRED_FUNCTION(EVP_aes_192_ecb) \
+    REQUIRED_FUNCTION(EVP_aes_256_cbc) \
+    REQUIRED_FUNCTION(EVP_aes_256_ecb) \
+    LEGACY_FUNCTION(EVP_CIPHER_CTX_cleanup) \
+    REQUIRED_FUNCTION(EVP_CIPHER_CTX_ctrl) \
+    FALLBACK_FUNCTION(EVP_CIPHER_CTX_free) \
+    LEGACY_FUNCTION(EVP_CIPHER_CTX_init) \
+    FALLBACK_FUNCTION(EVP_CIPHER_CTX_new) \
+    FALLBACK_FUNCTION(EVP_CIPHER_CTX_reset) \
+    REQUIRED_FUNCTION(EVP_CIPHER_CTX_set_key_length) \
+    REQUIRED_FUNCTION(EVP_CIPHER_CTX_set_padding) \
+    REQUIRED_FUNCTION(EVP_CipherFinal_ex) \
+    REQUIRED_FUNCTION(EVP_CipherInit_ex) \
+    REQUIRED_FUNCTION(EVP_CipherUpdate) \
+    REQUIRED_FUNCTION(EVP_des_cbc) \
+    REQUIRED_FUNCTION(EVP_des_ecb) \
+    REQUIRED_FUNCTION(EVP_des_ede3) \
+    REQUIRED_FUNCTION(EVP_des_ede3_cbc) \
+    REQUIRED_FUNCTION(EVP_DigestFinal_ex) \
+    REQUIRED_FUNCTION(EVP_DigestInit_ex) \
+    REQUIRED_FUNCTION(EVP_DigestUpdate) \
+    REQUIRED_FUNCTION(EVP_get_digestbyname) \
+    REQUIRED_FUNCTION(EVP_md5) \
+    RENAMED_FUNCTION(EVP_MD_CTX_free, EVP_MD_CTX_destroy) \
+    RENAMED_FUNCTION(EVP_MD_CTX_new, EVP_MD_CTX_create) \
+    REQUIRED_FUNCTION(EVP_MD_size) \
+    REQUIRED_FUNCTION(EVP_PKEY_CTX_free) \
+    REQUIRED_FUNCTION(EVP_PKEY_CTX_new) \
+    REQUIRED_FUNCTION(EVP_PKEY_derive_set_peer) \
+    REQUIRED_FUNCTION(EVP_PKEY_derive_init) \
+    REQUIRED_FUNCTION(EVP_PKEY_derive) \
+    REQUIRED_FUNCTION(EVP_PKEY_free) \
+    REQUIRED_FUNCTION(EVP_PKEY_get1_DSA) \
+    REQUIRED_FUNCTION(EVP_PKEY_get1_EC_KEY) \
+    REQUIRED_FUNCTION(EVP_PKEY_get1_RSA) \
+    REQUIRED_FUNCTION(EVP_PKEY_new) \
+    REQUIRED_FUNCTION(EVP_PKEY_set1_DSA) \
+    REQUIRED_FUNCTION(EVP_PKEY_set1_EC_KEY) \
+    REQUIRED_FUNCTION(EVP_PKEY_set1_RSA) \
+    FALLBACK_FUNCTION(EVP_PKEY_up_ref) \
+    REQUIRED_FUNCTION(EVP_rc2_cbc) \
+    REQUIRED_FUNCTION(EVP_rc2_ecb) \
+    REQUIRED_FUNCTION(EVP_sha1) \
+    REQUIRED_FUNCTION(EVP_sha256) \
+    REQUIRED_FUNCTION(EVP_sha384) \
+    REQUIRED_FUNCTION(EVP_sha512) \
+    REQUIRED_FUNCTION(EXTENDED_KEY_USAGE_free) \
+    REQUIRED_FUNCTION(GENERAL_NAMES_free) \
+    LEGACY_FUNCTION(HMAC_CTX_cleanup) \
+    FALLBACK_FUNCTION(HMAC_CTX_free) \
+    LEGACY_FUNCTION(HMAC_CTX_init) \
+    FALLBACK_FUNCTION(HMAC_CTX_new) \
+    REQUIRED_FUNCTION(HMAC_Final) \
+    REQUIRED_FUNCTION(HMAC_Init_ex) \
+    REQUIRED_FUNCTION(HMAC_Update) \
+    REQUIRED_FUNCTION(i2d_ASN1_INTEGER) \
+    REQUIRED_FUNCTION(i2d_ASN1_TYPE) \
+    REQUIRED_FUNCTION(i2d_PKCS12) \
+    REQUIRED_FUNCTION(i2d_PKCS7) \
+    REQUIRED_FUNCTION(i2d_X509) \
+    REQUIRED_FUNCTION(i2d_X509_PUBKEY) \
+    REQUIRED_FUNCTION(OBJ_ln2nid) \
+    REQUIRED_FUNCTION(OBJ_nid2ln) \
+    REQUIRED_FUNCTION(OBJ_nid2sn) \
+    REQUIRED_FUNCTION(OBJ_nid2obj) \
+    REQUIRED_FUNCTION(OBJ_obj2nid) \
+    REQUIRED_FUNCTION(OBJ_obj2txt) \
+    REQUIRED_FUNCTION(OBJ_sn2nid) \
+    REQUIRED_FUNCTION(OBJ_txt2nid) \
+    REQUIRED_FUNCTION(OBJ_txt2obj) \
+    LEGACY_FUNCTION(OPENSSL_add_all_algorithms_conf) \
+    REQUIRED_FUNCTION(OPENSSL_cleanse) \
+    NEW_REQUIRED_FUNCTION(OPENSSL_init_ssl) \
+    RENAMED_FUNCTION(OPENSSL_sk_free, sk_free) \
+    RENAMED_FUNCTION(OPENSSL_sk_new_null, sk_new_null) \
+    RENAMED_FUNCTION(OPENSSL_sk_num, sk_num) \
+    RENAMED_FUNCTION(OPENSSL_sk_pop_free, sk_pop_free) \
+    RENAMED_FUNCTION(OPENSSL_sk_push, sk_push) \
+    RENAMED_FUNCTION(OPENSSL_sk_value, sk_value) \
+    FALLBACK_FUNCTION(OpenSSL_version) \
+    RENAMED_FUNCTION(OpenSSL_version_num, SSLeay) \
+    REQUIRED_FUNCTION(PEM_read_bio_PKCS7) \
+    REQUIRED_FUNCTION(PEM_read_bio_X509_AUX) \
+    REQUIRED_FUNCTION(PEM_read_bio_X509_CRL) \
+    REQUIRED_FUNCTION(PEM_write_bio_X509_CRL) \
+    REQUIRED_FUNCTION(PKCS12_create) \
+    REQUIRED_FUNCTION(PKCS12_free) \
+    REQUIRED_FUNCTION(PKCS12_parse) \
+    REQUIRED_FUNCTION(PKCS7_add_certificate) \
+    REQUIRED_FUNCTION(PKCS7_free) \
+    REQUIRED_FUNCTION(PKCS7_new) \
+    REQUIRED_FUNCTION(PKCS7_set_type) \
+    REQUIRED_FUNCTION(PKCS7_content_new) \
+    REQUIRED_FUNCTION(RAND_bytes) \
+    REQUIRED_FUNCTION(RAND_poll) \
+    REQUIRED_FUNCTION(RSA_free) \
+    REQUIRED_FUNCTION(RSA_generate_key_ex) \
+    REQUIRED_FUNCTION(RSA_get_method) \
+    FALLBACK_FUNCTION(RSA_get0_crt_params) \
+    FALLBACK_FUNCTION(RSA_get0_factors) \
+    FALLBACK_FUNCTION(RSA_get0_key) \
+    FALLBACK_FUNCTION(RSA_meth_get_flags) \
+    REQUIRED_FUNCTION(RSA_new) \
+    REQUIRED_FUNCTION(RSA_private_decrypt) \
+    REQUIRED_FUNCTION(RSA_private_encrypt) \
+    REQUIRED_FUNCTION(RSA_public_decrypt) \
+    REQUIRED_FUNCTION(RSA_public_encrypt) \
+    FALLBACK_FUNCTION(RSA_set0_crt_params) \
+    FALLBACK_FUNCTION(RSA_set0_factors) \
+    FALLBACK_FUNCTION(RSA_set0_key) \
+    REQUIRED_FUNCTION(RSA_sign) \
+    REQUIRED_FUNCTION(RSA_size) \
+    REQUIRED_FUNCTION(RSA_up_ref) \
+    REQUIRED_FUNCTION(RSA_verify) \
+    REQUIRED_FUNCTION(SSL_CIPHER_description) \
+    REQUIRED_FUNCTION(SSL_CIPHER_get_bits) \
+    REQUIRED_FUNCTION(SSL_ctrl) \
+    REQUIRED_FUNCTION(SSL_set_quiet_shutdown) \
+    REQUIRED_FUNCTION(SSL_CTX_check_private_key) \
+    REQUIRED_FUNCTION(SSL_CTX_ctrl) \
+    REQUIRED_FUNCTION(SSL_CTX_free) \
+    FALLBACK_FUNCTION(SSL_is_init_finished) \
+    REQUIRED_FUNCTION(SSL_CTX_new) \
+    LIGHTUP_FUNCTION(SSL_CTX_set_alpn_protos) \
+    LIGHTUP_FUNCTION(SSL_CTX_set_alpn_select_cb) \
+    REQUIRED_FUNCTION(SSL_CTX_set_cert_verify_callback) \
+    REQUIRED_FUNCTION(SSL_CTX_set_cipher_list) \
+    REQUIRED_FUNCTION(SSL_CTX_set_client_cert_cb) \
+    REQUIRED_FUNCTION(SSL_CTX_set_quiet_shutdown) \
+    FALLBACK_FUNCTION(SSL_CTX_set_options) \
+    FALLBACK_FUNCTION(SSL_CTX_set_security_level) \
+    REQUIRED_FUNCTION(SSL_CTX_set_verify) \
+    REQUIRED_FUNCTION(SSL_CTX_use_certificate) \
+    REQUIRED_FUNCTION(SSL_CTX_use_PrivateKey) \
+    REQUIRED_FUNCTION(SSL_do_handshake) \
+    REQUIRED_FUNCTION(SSL_free) \
+    REQUIRED_FUNCTION(SSL_get_client_CA_list) \
+    REQUIRED_FUNCTION(SSL_get_current_cipher) \
+    REQUIRED_FUNCTION(SSL_get_error) \
+    REQUIRED_FUNCTION(SSL_get_finished) \
+    REQUIRED_FUNCTION(SSL_get_peer_cert_chain) \
+    REQUIRED_FUNCTION(SSL_get_peer_certificate) \
+    REQUIRED_FUNCTION(SSL_get_peer_finished) \
+    REQUIRED_FUNCTION(SSL_get_SSL_CTX) \
+    REQUIRED_FUNCTION(SSL_get_version) \
+    LIGHTUP_FUNCTION(SSL_get0_alpn_selected) \
+    LEGACY_FUNCTION(SSL_library_init) \
+    LEGACY_FUNCTION(SSL_load_error_strings) \
+    REQUIRED_FUNCTION(SSL_new) \
+    REQUIRED_FUNCTION(SSL_read) \
+    REQUIRED_FUNCTION(SSL_renegotiate_pending) \
+    FALLBACK_FUNCTION(SSL_session_reused) \
+    REQUIRED_FUNCTION(SSL_set_accept_state) \
+    REQUIRED_FUNCTION(SSL_set_bio) \
+    REQUIRED_FUNCTION(SSL_set_connect_state) \
+    REQUIRED_FUNCTION(SSL_shutdown) \
+    LEGACY_FUNCTION(SSL_state) \
+    LEGACY_FUNCTION(SSLeay_version) \
+    RENAMED_FUNCTION(TLS_method, SSLv23_method) \
+    REQUIRED_FUNCTION(SSL_write) \
+    REQUIRED_FUNCTION(X509_check_issued) \
+    REQUIRED_FUNCTION(X509_check_purpose) \
+    REQUIRED_FUNCTION(X509_CRL_free) \
+    FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
+    REQUIRED_FUNCTION(X509_digest) \
+    REQUIRED_FUNCTION(X509_dup) \
+    REQUIRED_FUNCTION(X509_EXTENSION_create_by_OBJ) \
+    REQUIRED_FUNCTION(X509_EXTENSION_free) \
+    REQUIRED_FUNCTION(X509_EXTENSION_get_critical) \
+    REQUIRED_FUNCTION(X509_EXTENSION_get_data) \
+    REQUIRED_FUNCTION(X509_EXTENSION_get_object) \
+    REQUIRED_FUNCTION(X509_free) \
+    REQUIRED_FUNCTION(X509_get_default_cert_dir) \
+    REQUIRED_FUNCTION(X509_get_default_cert_dir_env) \
+    REQUIRED_FUNCTION(X509_get_default_cert_file) \
+    REQUIRED_FUNCTION(X509_get_default_cert_file_env) \
+    REQUIRED_FUNCTION(X509_get_ext) \
+    REQUIRED_FUNCTION(X509_get_ext_count) \
+    REQUIRED_FUNCTION(X509_get_ext_d2i) \
+    REQUIRED_FUNCTION(X509_get_issuer_name) \
+    REQUIRED_FUNCTION(X509_get_serialNumber) \
+    REQUIRED_FUNCTION(X509_get_subject_name) \
+    FALLBACK_FUNCTION(X509_get_version) \
+    FALLBACK_FUNCTION(X509_get_X509_PUBKEY) \
+    FALLBACK_FUNCTION(X509_get0_notBefore) \
+    FALLBACK_FUNCTION(X509_get0_notAfter) \
+    FALLBACK_FUNCTION(X509_get0_pubkey_bitstr) \
+    FALLBACK_FUNCTION(X509_get0_tbs_sigalg) \
+    REQUIRED_FUNCTION(X509_issuer_name_hash) \
+    REQUIRED_FUNCTION(X509_NAME_entry_count) \
+    REQUIRED_FUNCTION(X509_NAME_ENTRY_get_data) \
+    REQUIRED_FUNCTION(X509_NAME_ENTRY_get_object) \
+    REQUIRED_FUNCTION(X509_NAME_free) \
+    REQUIRED_FUNCTION(X509_NAME_get_entry) \
+    REQUIRED_FUNCTION(X509_NAME_get_index_by_NID) \
+    FALLBACK_FUNCTION(X509_NAME_get0_der) \
+    REQUIRED_FUNCTION(X509_PUBKEY_get) \
+    FALLBACK_FUNCTION(X509_PUBKEY_get0_param) \
+    REQUIRED_FUNCTION(X509_STORE_add_cert) \
+    REQUIRED_FUNCTION(X509_STORE_add_crl) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_free) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_get0_param) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_get1_chain) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_get_error) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_get_error_depth) \
+    FALLBACK_FUNCTION(X509_STORE_CTX_get0_cert) \
+    FALLBACK_FUNCTION(X509_STORE_CTX_get0_untrusted) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_init) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_new) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_set_flags) \
+    REQUIRED_FUNCTION(X509_STORE_CTX_set_verify_cb) \
+    REQUIRED_FUNCTION(X509_STORE_free) \
+    REQUIRED_FUNCTION(X509_STORE_new) \
+    REQUIRED_FUNCTION(X509_STORE_set_flags) \
+    REQUIRED_FUNCTION(X509V3_EXT_print) \
+    FALLBACK_FUNCTION(X509_up_ref) \
+    REQUIRED_FUNCTION(X509_verify_cert) \
+    REQUIRED_FUNCTION(X509_verify_cert_error_string) \
+    REQUIRED_FUNCTION(X509_VERIFY_PARAM_set_time) \
+    LIGHTUP_FUNCTION(EC_GF2m_simple_method) \
+    LIGHTUP_FUNCTION(EC_GROUP_get_curve_GF2m) \
+    LIGHTUP_FUNCTION(EC_GROUP_set_curve_GF2m) \
+    LIGHTUP_FUNCTION(EC_POINT_get_affine_coordinates_GF2m) \
+    LIGHTUP_FUNCTION(EC_POINT_set_affine_coordinates_GF2m) \
     
 // Declare pointers to all the used OpenSSL functions
-#define PER_FUNCTION_BLOCK(fn, isRequired) extern decltype(fn)* fn##_ptr;
+#define REQUIRED_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr;
+#define NEW_REQUIRED_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr;
+#define LIGHTUP_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr;
+#define FALLBACK_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr;
+#define RENAMED_FUNCTION(fn,oldfn) extern "C" __typeof(fn)* fn##_ptr;
+#define LEGACY_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr;
 FOR_ALL_OPENSSL_FUNCTIONS
-#undef PER_FUNCTION_BLOCK
+#undef LEGACY_FUNCTION
+#undef RENAMED_FUNCTION
+#undef FALLBACK_FUNCTION
+#undef LIGHTUP_FUNCTION
+#undef NEW_REQUIRED_FUNCTION
+#undef REQUIRED_FUNCTION
 
 // Redefine all calls to OpenSSL functions as calls through pointers that are set
 // to the functions from the libssl.so selected by the shim.
@@ -415,8 +564,13 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define DSA_free DSA_free_ptr
 #define DSA_generate_key DSA_generate_key_ptr
 #define DSA_generate_parameters_ex DSA_generate_parameters_ex_ptr
+#define DSA_get0_key DSA_get0_key_ptr
+#define DSA_get0_pqg DSA_get0_pqg_ptr
+#define DSA_get_method DSA_get_method_ptr
 #define DSA_new DSA_new_ptr
 #define DSA_OpenSSL DSA_OpenSSL_ptr
+#define DSA_set0_key DSA_set0_key_ptr
+#define DSA_set0_pqg DSA_set0_pqg_ptr
 #define DSA_sign DSA_sign_ptr
 #define DSA_size DSA_size_ptr
 #define DSA_up_ref DSA_up_ref_ptr
@@ -474,7 +628,10 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define EVP_aes_256_ecb EVP_aes_256_ecb_ptr
 #define EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup_ptr
 #define EVP_CIPHER_CTX_ctrl EVP_CIPHER_CTX_ctrl_ptr
+#define EVP_CIPHER_CTX_free EVP_CIPHER_CTX_free_ptr
 #define EVP_CIPHER_CTX_init EVP_CIPHER_CTX_init_ptr
+#define EVP_CIPHER_CTX_new EVP_CIPHER_CTX_new_ptr
+#define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_reset_ptr
 #define EVP_CIPHER_CTX_set_key_length EVP_CIPHER_CTX_set_key_length_ptr
 #define EVP_CIPHER_CTX_set_padding EVP_CIPHER_CTX_set_padding_ptr
 #define EVP_CipherFinal_ex EVP_CipherFinal_ex_ptr
@@ -489,8 +646,8 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define EVP_DigestUpdate EVP_DigestUpdate_ptr
 #define EVP_get_digestbyname EVP_get_digestbyname_ptr
 #define EVP_md5 EVP_md5_ptr
-#define EVP_MD_CTX_create EVP_MD_CTX_create_ptr
-#define EVP_MD_CTX_destroy EVP_MD_CTX_destroy_ptr
+#define EVP_MD_CTX_free EVP_MD_CTX_free_ptr
+#define EVP_MD_CTX_new EVP_MD_CTX_new_ptr
 #define EVP_MD_size EVP_MD_size_ptr
 #define EVP_PKEY_CTX_free EVP_PKEY_CTX_free_ptr
 #define EVP_PKEY_CTX_new EVP_PKEY_CTX_new_ptr
@@ -505,6 +662,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define EVP_PKEY_set1_DSA EVP_PKEY_set1_DSA_ptr
 #define EVP_PKEY_set1_EC_KEY EVP_PKEY_set1_EC_KEY_ptr
 #define EVP_PKEY_set1_RSA EVP_PKEY_set1_RSA_ptr
+#define EVP_PKEY_up_ref EVP_PKEY_up_ref_ptr
 #define EVP_rc2_cbc EVP_rc2_cbc_ptr
 #define EVP_rc2_ecb EVP_rc2_ecb_ptr
 #define EVP_sha1 EVP_sha1_ptr
@@ -514,7 +672,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define EXTENDED_KEY_USAGE_free EXTENDED_KEY_USAGE_free_ptr
 #define GENERAL_NAMES_free GENERAL_NAMES_free_ptr
 #define HMAC_CTX_cleanup HMAC_CTX_cleanup_ptr
+#define HMAC_CTX_free HMAC_CTX_free_ptr
 #define HMAC_CTX_init HMAC_CTX_init_ptr
+#define HMAC_CTX_new HMAC_CTX_new_ptr
 #define HMAC_Final HMAC_Final_ptr
 #define HMAC_Init_ex HMAC_Init_ex_ptr
 #define HMAC_Update HMAC_Update_ptr
@@ -535,6 +695,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define OBJ_txt2obj OBJ_txt2obj_ptr
 #define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
 #define OPENSSL_cleanse OPENSSL_cleanse_ptr
+#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
+#define OPENSSL_sk_free OPENSSL_sk_free_ptr
+#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
+#define OPENSSL_sk_num OPENSSL_sk_num_ptr
+#define OPENSSL_sk_pop_free OPENSSL_sk_pop_free_ptr
+#define OPENSSL_sk_push OPENSSL_sk_push_ptr
+#define OPENSSL_sk_value OPENSSL_sk_value_ptr
+#define OpenSSL_version OpenSSL_version_ptr
+#define OpenSSL_version_num OpenSSL_version_num_ptr
 #define PEM_read_bio_PKCS7 PEM_read_bio_PKCS7_ptr
 #define PEM_read_bio_X509_AUX PEM_read_bio_X509_AUX_ptr
 #define PEM_read_bio_X509_CRL PEM_read_bio_X509_CRL_ptr
@@ -551,22 +720,30 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define RAND_poll RAND_poll_ptr
 #define RSA_free RSA_free_ptr
 #define RSA_generate_key_ex RSA_generate_key_ex_ptr
+#define RSA_get0_crt_params RSA_get0_crt_params_ptr
+#define RSA_get0_factors RSA_get0_factors_ptr
+#define RSA_get0_key RSA_get0_key_ptr
 #define RSA_get_method RSA_get_method_ptr
+#define RSA_meth_get_flags RSA_meth_get_flags_ptr
 #define RSA_new RSA_new_ptr
 #define RSA_private_decrypt RSA_private_decrypt_ptr
 #define RSA_private_encrypt RSA_private_encrypt_ptr
 #define RSA_public_decrypt RSA_public_decrypt_ptr
 #define RSA_public_encrypt RSA_public_encrypt_ptr
+#define RSA_set0_crt_params RSA_set0_crt_params_ptr
+#define RSA_set0_factors RSA_set0_factors_ptr
+#define RSA_set0_key RSA_set0_key_ptr
 #define RSA_sign RSA_sign_ptr
 #define RSA_size RSA_size_ptr
 #define RSA_up_ref RSA_up_ref_ptr
 #define RSA_verify RSA_verify_ptr
-#define sk_free sk_free_ptr
-#define sk_new_null sk_new_null_ptr
-#define sk_num sk_num_ptr
-#define sk_pop_free sk_pop_free_ptr
-#define sk_push sk_push_ptr
-#define sk_value sk_value_ptr
+#define sk_free OPENSSL_sk_free_ptr
+#define sk_new_null OPENSSL_sk_new_null_ptr
+#define sk_num OPENSSL_sk_num_ptr
+#define sk_pop_free OPENSSL_sk_pop_free_ptr
+#define sk_push OPENSSL_sk_push_ptr
+#define sk_value OPENSSL_sk_value_ptr
+#define SSL_CIPHER_get_bits SSL_CIPHER_get_bits_ptr
 #define SSL_CIPHER_description SSL_CIPHER_description_ptr
 #define SSL_ctrl SSL_ctrl_ptr
 #define SSL_set_quiet_shutdown SSL_set_quiet_shutdown_ptr
@@ -579,7 +756,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define SSL_CTX_set_cert_verify_callback SSL_CTX_set_cert_verify_callback_ptr
 #define SSL_CTX_set_cipher_list SSL_CTX_set_cipher_list_ptr
 #define SSL_CTX_set_client_cert_cb SSL_CTX_set_client_cert_cb_ptr
+#define SSL_CTX_set_options SSL_CTX_set_options_ptr
 #define SSL_CTX_set_quiet_shutdown SSL_CTX_set_quiet_shutdown_ptr
+#define SSL_CTX_set_security_level SSL_CTX_set_security_level_ptr
 #define SSL_CTX_set_verify SSL_CTX_set_verify_ptr
 #define SSL_CTX_use_certificate SSL_CTX_use_certificate_ptr
 #define SSL_CTX_use_PrivateKey SSL_CTX_use_PrivateKey_ptr
@@ -595,25 +774,26 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define SSL_get_SSL_CTX SSL_get_SSL_CTX_ptr
 #define SSL_get_version SSL_get_version_ptr
 #define SSL_get0_alpn_selected SSL_get0_alpn_selected_ptr
+#define SSL_is_init_finished SSL_is_init_finished_ptr
 #define SSL_library_init SSL_library_init_ptr
 #define SSL_load_error_strings SSL_load_error_strings_ptr
 #define SSL_new SSL_new_ptr
 #define SSL_read SSL_read_ptr
 #define SSL_renegotiate_pending SSL_renegotiate_pending_ptr
+#define SSL_session_reused SSL_session_reused_ptr
 #define SSL_set_accept_state SSL_set_accept_state_ptr
 #define SSL_set_bio SSL_set_bio_ptr
 #define SSL_set_connect_state SSL_set_connect_state_ptr
 #define SSL_shutdown SSL_shutdown_ptr
 #define SSL_state SSL_state_ptr
 #define SSLeay_version SSLeay_version_ptr
-#define SSLv23_method SSLv23_method_ptr
+#define SSLeay SSLeay_ptr
 #define SSL_write SSL_write_ptr
-#define TLSv1_1_method TLSv1_1_method_ptr
-#define TLSv1_2_method TLSv1_2_method_ptr
-#define TLSv1_method TLSv1_method_ptr
+#define TLS_method TLS_method_ptr
 #define X509_check_issued X509_check_issued_ptr
 #define X509_check_purpose X509_check_purpose_ptr
 #define X509_CRL_free X509_CRL_free_ptr
+#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
 #define X509_digest X509_digest_ptr
 #define X509_dup X509_dup_ptr
 #define X509_EXTENSION_create_by_OBJ X509_EXTENSION_create_by_OBJ_ptr
@@ -622,6 +802,10 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define X509_EXTENSION_get_data X509_EXTENSION_get_data_ptr
 #define X509_EXTENSION_get_object X509_EXTENSION_get_object_ptr
 #define X509_free X509_free_ptr
+#define X509_get0_notAfter X509_get0_notAfter_ptr
+#define X509_get0_notBefore X509_get0_notBefore_ptr
+#define X509_get0_pubkey_bitstr X509_get0_pubkey_bitstr_ptr
+#define X509_get0_tbs_sigalg X509_get0_tbs_sigalg_ptr
 #define X509_get_default_cert_dir X509_get_default_cert_dir_ptr
 #define X509_get_default_cert_dir_env X509_get_default_cert_dir_env_ptr
 #define X509_get_default_cert_file X509_get_default_cert_file_ptr
@@ -632,18 +816,24 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define X509_get_issuer_name X509_get_issuer_name_ptr
 #define X509_get_serialNumber X509_get_serialNumber_ptr
 #define X509_get_subject_name X509_get_subject_name_ptr
+#define X509_get_X509_PUBKEY X509_get_X509_PUBKEY_ptr
+#define X509_get_version X509_get_version_ptr
 #define X509_issuer_name_hash X509_issuer_name_hash_ptr
 #define X509_NAME_entry_count X509_NAME_entry_count_ptr
 #define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_get_data_ptr
 #define X509_NAME_ENTRY_get_object X509_NAME_ENTRY_get_object_ptr
 #define X509_NAME_free X509_NAME_free_ptr
+#define X509_NAME_get0_der X509_NAME_get0_der_ptr
 #define X509_NAME_get_entry X509_NAME_get_entry_ptr
 #define X509_NAME_get_index_by_NID X509_NAME_get_index_by_NID_ptr
+#define X509_PUBKEY_get0_param X509_PUBKEY_get0_param_ptr
 #define X509_PUBKEY_get X509_PUBKEY_get_ptr
 #define X509_STORE_add_cert X509_STORE_add_cert_ptr
 #define X509_STORE_add_crl X509_STORE_add_crl_ptr
 #define X509_STORE_CTX_free X509_STORE_CTX_free_ptr
+#define X509_STORE_CTX_get0_cert X509_STORE_CTX_get0_cert_ptr
 #define X509_STORE_CTX_get0_param X509_STORE_CTX_get0_param_ptr
+#define X509_STORE_CTX_get0_untrusted X509_STORE_CTX_get0_untrusted_ptr
 #define X509_STORE_CTX_get1_chain X509_STORE_CTX_get1_chain_ptr
 #define X509_STORE_CTX_get_error X509_STORE_CTX_get_error_ptr
 #define X509_STORE_CTX_get_error_depth X509_STORE_CTX_get_error_depth_ptr
@@ -655,6 +845,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define X509_STORE_new X509_STORE_new_ptr
 #define X509_STORE_set_flags X509_STORE_set_flags_ptr
 #define X509V3_EXT_print X509V3_EXT_print_ptr
+#define X509_up_ref X509_up_ref_ptr
 #define X509_verify_cert X509_verify_cert_ptr
 #define X509_verify_cert_error_string X509_verify_cert_error_string_ptr
 #define X509_VERIFY_PARAM_set_time X509_VERIFY_PARAM_set_time_ptr
@@ -664,8 +855,99 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define EC_POINT_get_affine_coordinates_GF2m EC_POINT_get_affine_coordinates_GF2m_ptr
 #define EC_POINT_set_affine_coordinates_GF2m EC_POINT_set_affine_coordinates_GF2m_ptr
 
+
+// STACK_OF types will have been declared with inline functions to handle the pointer casting.
+// Since these inline functions are strongly bound to the OPENSSL_sk_* functions in 1.1 we need to
+// rebind things here.
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM
+// type-safe OPENSSL_sk_free
+#define sk_GENERAL_NAME_free(stack) OPENSSL_sk_free((OPENSSL_STACK*)(1 ? stack : (STACK_OF(GENERAL_NAME)*)0))
+
+// type-safe OPENSSL_sk_num
+#define sk_ASN1_OBJECT_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(ASN1_OBJECT)*)0))
+#define sk_GENERAL_NAME_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(GENERAL_NAME)*)0))
+#define sk_X509_NAME_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509_NAME)*)0))
+#define sk_X509_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509)*)0))
+
+// type-safe OPENSSL_sk_new_null
+#define sk_X509_new_null() (STACK_OF(X509)*)OPENSSL_sk_new_null()
+#define sk_X509_NAME_new_null() (STACK_OF(X509_NAME)*)OPENSSL_sk_new_null()
+
+// type-safe OPENSSL_sk_push
+#define sk_X509_push(stack,value) OPENSSL_sk_push((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509)*)0), (const void*)(1 ? value : (X509*)0))
+#define sk_X509_NAME_push(stack,value) OPENSSL_sk_push((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509_NAME)*)0), (const void*)(1 ? value : (X509_NAME*)0))
+
+// type-safe OPENSSL_sk_pop_free
+#define sk_X509_pop_free(stack, freefunc) OPENSSL_sk_pop_free((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509)*)0), (OPENSSL_sk_freefunc)(1 ? freefunc : (sk_X509_freefunc)0))
+#define sk_X509_NAME_pop_free(stack, freefunc) OPENSSL_sk_pop_free((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509_NAME)*)0), (OPENSSL_sk_freefunc)(1 ? freefunc : (sk_X509_NAME_freefunc)0))
+
+// type-safe OPENSSL_sk_value
+#define sk_ASN1_OBJECT_value(stack, idx) (ASN1_OBJECT*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(ASN1_OBJECT)*)0), idx)
+#define sk_GENERAL_NAME_value(stack, idx) (GENERAL_NAME*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(GENERAL_NAME)*)0), idx)
+#define sk_X509_NAME_value(stack, idx) (X509_NAME*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509_NAME)*)0), idx)
+#define sk_X509_value(stack, idx) (X509*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509)*)0), idx)
+#endif
+
+
 #else // FEATURE_DISTRO_AGNOSTIC_SSL
 
 #define API_EXISTS(fn) true
 
+#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM
+
+#define NEED_OPENSSL_1_0 true
+
+// Alias "future" API to the local_ version.
+#define DSA_get0_key local_DSA_get0_key
+#define DSA_get0_pqg local_DSA_get0_pqg
+#define DSA_get_method local_DSA_get_method
+#define DSA_set0_key local_DSA_set0_key
+#define DSA_set0_pqg local_DSA_set0_pqg
+#define EVP_CIPHER_CTX_free local_EVP_CIPHER_CTX_free
+#define EVP_CIPHER_CTX_new local_EVP_CIPHER_CTX_new
+#define EVP_CIPHER_CTX_reset local_EVP_CIPHER_CTX_reset
+#define EVP_PKEY_up_ref local_EVP_PKEY_up_ref
+#define HMAC_CTX_free local_HMAC_CTX_free
+#define HMAC_CTX_new local_HMAC_CTX_new
+#define OpenSSL_version local_OpenSSL_version
+#define RSA_get0_crt_params local_RSA_get0_crt_params
+#define RSA_get0_factors local_RSA_get0_factors
+#define RSA_get0_key local_RSA_get0_key
+#define RSA_meth_get_flags local_RSA_meth_get_flags
+#define RSA_set0_crt_params local_RSA_set0_crt_params
+#define RSA_set0_factors local_RSA_set0_factors
+#define RSA_set0_key local_RSA_set0_key
+#define SSL_CTX_set_security_level local_SSL_CTX_set_security_level
+#define SSL_is_init_finished local_SSL_is_init_finished
+#define X509_CRL_get0_nextUpdate local_X509_CRL_get0_nextUpdate
+#define X509_NAME_get0_der local_X509_NAME_get0_der
+#define X509_PUBKEY_get0_param local_X509_PUBKEY_get0_param
+#define X509_STORE_CTX_get0_cert local_X509_STORE_CTX_get0_cert
+#define X509_STORE_CTX_get0_untrusted local_X509_STORE_CTX_get0_untrusted
+#define X509_get0_notAfter local_X509_get0_notAfter
+#define X509_get0_notBefore local_X509_get0_notBefore
+#define X509_get0_pubkey_bitstr local_X509_get0_pubkey_bitstr
+#define X509_get0_tbs_sigalg local_X509_get0_tbs_sigalg
+#define X509_get_X509_PUBKEY local_X509_get_X509_PUBKEY
+#define X509_get_version local_X509_get_version
+#define X509_up_ref local_X509_up_ref
+
+// Restore the old names for RENAMED_FUNCTION functions.
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define OPENSSL_sk_free sk_free
+#define OPENSSL_sk_new_null sk_new_null
+#define OPENSSL_sk_num sk_num
+#define OPENSSL_sk_pop_free sk_pop_free
+#define OPENSSL_sk_push sk_push
+#define OPENSSL_sk_value sk_value
+#define TLS_method SSLv23_method
+#define OpenSSL_version_num SSLeay
+
+#else // if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM
+
+#define NEED_OPENSSL_1_1 true
+
+#endif
+
 #endif // FEATURE_DISTRO_AGNOSTIC_SSL
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp
index 5429592e57..006881aa33 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp
@@ -42,7 +42,7 @@ extern "C" int32_t CryptoNative_ObjSn2Nid(const char* sn)
     return OBJ_sn2nid(sn);
 }
 
-extern "C" ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid)
+extern "C" const ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid)
 {
     return OBJ_nid2obj(nid);
 }
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h
index 6ec1795d25..6f9445aa9f 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h
@@ -42,7 +42,7 @@ extern "C" int32_t CryptoNative_ObjSn2Nid(const char* sn);
 /*
 Direct shim to OBJ_nid2obj.
 */
-extern "C" ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid);
+extern "C" const ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid);
 
 /*
 Direct shim to ASN1_OBJECT_free.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp
index 01a544f5e9..328b5e5935 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp
@@ -31,12 +31,19 @@ static_assert(PAL_ASN1_STRFLGS_UTF8_CONVERT == ASN1_STRFLGS_UTF8_CONVERT, "");
 
 extern "C" ASN1_STRING* CryptoNative_DecodeAsn1TypeBytes(const uint8_t* buf, int32_t len, Asn1StringTypeFlags type)
 {
-    if (!buf || !len)
+#if NEED_OPENSSL_1_0
+    if (!API_EXISTS(d2i_ASN1_type_bytes) || !buf || !len)
     {
         return nullptr;
     }
 
     return d2i_ASN1_type_bytes(nullptr, &buf, len, type);
+#else
+    (void)buf;
+    (void)len;
+    (void)type;
+    return nullptr;
+#endif
 }
 
 extern "C" int32_t CryptoNative_Asn1StringPrintEx(BIO* out, ASN1_STRING* str, Asn1StringPrintFlags flags)
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in b/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in
index 6aea13f2c6..1aa48ba9d7 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in
@@ -1,6 +1,4 @@
 #pragma once
 
-#cmakedefine01 HAVE_TLS_V1_1
-#cmakedefine01 HAVE_TLS_V1_2
 #cmakedefine01 HAVE_OPENSSL_EC2M
 #cmakedefine01 HAVE_OPENSSL_ALPN
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp
index af9ce59d64..74d76a89d7 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp
@@ -45,12 +45,34 @@ extern "C" int32_t CryptoNative_DsaSizeSignature(DSA* dsa)
 
 extern "C" int32_t CryptoNative_DsaSizeP(DSA* dsa)
 {
-    return BN_num_bytes(dsa->p);
+    if (dsa)
+    {
+        const BIGNUM* p;
+        DSA_get0_pqg(dsa, &p, nullptr, nullptr);
+
+        if (p)
+        {
+            return BN_num_bytes(p);
+        }
+    }
+
+    return -1;
 }
 
 extern "C" int32_t CryptoNative_DsaSizeQ(DSA* dsa)
 {
-    return BN_num_bytes(dsa->q);
+    if (dsa)
+    {
+        const BIGNUM* q;
+        DSA_get0_pqg(dsa, nullptr, &q, nullptr);
+
+        if (q)
+        {
+            return BN_num_bytes(q);
+        }
+    }
+
+    return -1;
 }
 
 extern "C" int32_t CryptoNative_DsaSign(
@@ -67,11 +89,18 @@ extern "C" int32_t CryptoNative_DsaSign(
     }
 
     // DSA_OpenSSL() returns a shared pointer, no need to free/cache.
-    if (dsa->meth == DSA_OpenSSL() && dsa->priv_key == nullptr)
+    if (DSA_get_method(dsa) == DSA_OpenSSL())
     {
-        *outSignatureLength = 0;
-        ERR_PUT_error(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, DSA_R_MISSING_PARAMETERS, __FILE__, __LINE__);
-        return 0;
+        const BIGNUM* privKey;
+
+        DSA_get0_key(dsa, nullptr, &privKey);
+
+        if (!privKey)
+        {
+            *outSignatureLength = 0;
+            ERR_PUT_error(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, DSA_R_MISSING_PARAMETERS, __FILE__, __LINE__);
+            return 0;
+        }
     }
 
     unsigned int unsignedSigLen = 0;
@@ -111,11 +140,11 @@ extern "C" int32_t CryptoNative_DsaVerify(
 
 extern "C" int32_t CryptoNative_GetDsaParameters(
     const DSA* dsa,
-    BIGNUM** p, int32_t* pLength,
-    BIGNUM** q, int32_t* qLength,
-    BIGNUM** g, int32_t* gLength,
-    BIGNUM** y, int32_t* yLength,
-    BIGNUM** x, int32_t* xLength)
+    const BIGNUM** p, int32_t* pLength,
+    const BIGNUM** q, int32_t* qLength,
+    const BIGNUM** g, int32_t* gLength,
+    const BIGNUM** y, int32_t* yLength,
+    const BIGNUM** x, int32_t* xLength)
 {
     if (!dsa || !p || !q || !g || !y || !x)
     {
@@ -129,39 +158,28 @@ extern "C" int32_t CryptoNative_GetDsaParameters(
         if (x) *x = nullptr; if (xLength) *xLength = 0;
         return 0;
     }
-    
-    *p = dsa->p; *pLength = BN_num_bytes(*p);
-    *q = dsa->q; *qLength = BN_num_bytes(*q);
-    *g = dsa->g; *gLength = BN_num_bytes(*g);
-    *y = dsa->pub_key; *yLength = BN_num_bytes(*y);
-
-    // dsa->priv_key is optional
-    *x = dsa->priv_key;
+
+    DSA_get0_pqg(dsa, p, q, g);
+    *pLength = BN_num_bytes(*p);
+    *qLength = BN_num_bytes(*q);
+    *gLength = BN_num_bytes(*g);
+
+    DSA_get0_key(dsa, y, x);
+    *yLength = BN_num_bytes(*y);
+    // x (the private key) is optional
     *xLength = (*x == nullptr) ? 0 : BN_num_bytes(*x);
 
     return 1;
 }
 
-static int32_t SetDsaParameter(BIGNUM** dsaFieldAddress, uint8_t* buffer, int32_t bufferLength)
+static BIGNUM* MakeBignum(uint8_t* buffer, int32_t bufferLength)
 {
-    assert(dsaFieldAddress != nullptr);
-    if (dsaFieldAddress)
+    if (buffer && bufferLength)
     {
-        if (!buffer || !bufferLength)
-        {
-            *dsaFieldAddress = nullptr;
-            return 1;
-        }
-        else
-        {
-            BIGNUM* bigNum = BN_bin2bn(buffer, bufferLength, nullptr);
-            *dsaFieldAddress = bigNum;
-
-            return bigNum != nullptr;
-        }
+        return BN_bin2bn(buffer, bufferLength, nullptr);
     }
 
-    return 0;
+    return nullptr;
 }
 
 extern "C" int32_t CryptoNative_DsaKeyCreateByExplicitParameters(
@@ -191,10 +209,33 @@ extern "C" int32_t CryptoNative_DsaKeyCreateByExplicitParameters(
 
     DSA* dsa = *outDsa;
 
-    return
-        SetDsaParameter(&dsa->p, p, pLength) &&
-        SetDsaParameter(&dsa->q, q, qLength) &&
-        SetDsaParameter(&dsa->g, g, gLength) &&
-        SetDsaParameter(&dsa->pub_key, y, yLength) &&
-        SetDsaParameter(&dsa->priv_key, x, xLength);
+    BIGNUM* bnP = MakeBignum(p, pLength);
+    BIGNUM* bnQ = MakeBignum(q, qLength);
+    BIGNUM* bnG = MakeBignum(g, gLength);
+
+    if (!DSA_set0_pqg(dsa, bnP, bnQ, bnG))
+    {
+        // BN_free handles NULL input
+        BN_free(bnP);
+        BN_free(bnQ);
+        BN_free(bnG);
+        return 0;
+    }
+
+    // Control was transferred, do not free.
+    bnP = nullptr;
+    bnQ = nullptr;
+    bnG = nullptr;
+
+    BIGNUM* bnY = MakeBignum(y, yLength);
+    BIGNUM* bnX = MakeBignum(x, xLength);
+
+    if (!DSA_set0_key(dsa, bnY, bnX))
+    {
+        BN_free(bnY);
+        BN_free(bnX);
+        return 0;
+    }
+
+    return 1;
 }
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h
index ede7065992..0236741ffa 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h
@@ -87,11 +87,11 @@ Returns 1 upon success, otherwise 0.
 */
 extern "C" int32_t CryptoNative_GetDsaParameters(
     const DSA* dsa,
-    BIGNUM** p, int32_t* pLength,
-    BIGNUM** q, int32_t* qLength,
-    BIGNUM** g, int32_t* gLength,
-    BIGNUM** y, int32_t* yLength,
-    BIGNUM** x, int32_t* xLength);
+    const BIGNUM** p, int32_t* pLength,
+    const BIGNUM** q, int32_t* qLength,
+    const BIGNUM** g, int32_t* gLength,
+    const BIGNUM** y, int32_t* yLength,
+    const BIGNUM** x, int32_t* xLength);
 
 /*
 Sets all the parameters on the DSA instance.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp
index 1fbadce9af..d3157ead17 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp
@@ -10,7 +10,7 @@
 
 extern "C" EVP_MD_CTX* CryptoNative_EvpMdCtxCreate(const EVP_MD* type)
 {
-    EVP_MD_CTX* ctx = EVP_MD_CTX_create();
+    EVP_MD_CTX* ctx = EVP_MD_CTX_new();
     if (ctx == nullptr)
     {
         // Allocation failed
@@ -20,7 +20,7 @@ extern "C" EVP_MD_CTX* CryptoNative_EvpMdCtxCreate(const EVP_MD* type)
     int ret = EVP_DigestInit_ex(ctx, type, nullptr);
     if (!ret)
     {
-        EVP_MD_CTX_destroy(ctx);
+        EVP_MD_CTX_free(ctx);
         return nullptr;
     }
 
@@ -31,7 +31,7 @@ extern "C" void CryptoNative_EvpMdCtxDestroy(EVP_MD_CTX* ctx)
 {
     if (ctx != nullptr)
     {
-        EVP_MD_CTX_destroy(ctx);
+        EVP_MD_CTX_free(ctx);
     }
 }
 
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp
index 1f2e80e114..1dc218cac3 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp
@@ -5,7 +5,6 @@
 #include "pal_evp_cipher.h"
 
 #include <assert.h>
-#include <memory>
 
 #define SUCCESS 1
 #define KEEP_CURRENT_DIRECTION -1
@@ -19,28 +18,34 @@ CryptoNative_EvpCipherCreate(const EVP_CIPHER* type, uint8_t* key, unsigned char
 extern "C" EVP_CIPHER_CTX*
 CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyLength, int32_t effectiveKeyLength, unsigned char* iv, int32_t enc)
 {
-    std::unique_ptr<EVP_CIPHER_CTX> ctx(new (std::nothrow) EVP_CIPHER_CTX);
+    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
     if (ctx == nullptr)
     {
         // Allocation failed
         return nullptr;
     }
 
-    EVP_CIPHER_CTX_init(ctx.get());
+    if (!EVP_CIPHER_CTX_reset(ctx))
+    {
+        EVP_CIPHER_CTX_free(ctx);
+        return nullptr;
+    }
 
     // Perform partial initialization so we can set the key lengths
-    int ret = EVP_CipherInit_ex(ctx.get(), type, nullptr, nullptr, nullptr, 0);
+    int ret = EVP_CipherInit_ex(ctx, type, nullptr, nullptr, nullptr, 0);
     if (!ret)
     {
+        EVP_CIPHER_CTX_free(ctx);
         return nullptr;
     }
 
     if (keyLength > 0)
     {
         // Necessary when the default key size is different than current
-        ret = EVP_CIPHER_CTX_set_key_length(ctx.get(), keyLength / 8);
+        ret = EVP_CIPHER_CTX_set_key_length(ctx, keyLength / 8);
         if (!ret)
         {
+            EVP_CIPHER_CTX_free(ctx);
             return nullptr;
         }
     }
@@ -48,29 +53,30 @@ CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyL
     if (effectiveKeyLength > 0)
     {
         // Necessary for RC2
-        ret = EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_SET_RC2_KEY_BITS, effectiveKeyLength, nullptr);
+        ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, effectiveKeyLength, nullptr);
         if (ret <= 0)
         {
+            EVP_CIPHER_CTX_free(ctx);
             return nullptr;
         }
     }
 
     // Perform final initialization specifying the remaining arguments
-    ret = EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key, iv, enc);
+    ret = EVP_CipherInit_ex(ctx, nullptr, nullptr, key, iv, enc);
     if (!ret)
     {
+        EVP_CIPHER_CTX_free(ctx);
         return nullptr;
     }
 
-    return ctx.release();
+    return ctx;
 }
 
 extern "C" void CryptoNative_EvpCipherDestroy(EVP_CIPHER_CTX* ctx)
 {
     if (ctx != nullptr)
     {
-        EVP_CIPHER_CTX_cleanup(ctx);
-        delete ctx;
+        EVP_CIPHER_CTX_free(ctx);
     }
 }
 
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp
index 384030740e..f27e93325f 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp
@@ -24,5 +24,5 @@ extern "C" int32_t CryptoNative_UpRefEvpPkey(EVP_PKEY* pkey)
         return 0;
     }
 
-    return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+    return EVP_PKEY_up_ref(pkey);
 }
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp
index 10eef6809c..539dc07683 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp
@@ -7,7 +7,6 @@
 #include "pal_hmac.h"
 
 #include <assert.h>
-#include <memory>
 
 extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen, const EVP_MD* md)
 {
@@ -15,7 +14,7 @@ extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen,
     assert(keyLen >= 0);
     assert(md != nullptr);
 
-    std::unique_ptr<HMAC_CTX> ctx(new (std::nothrow) HMAC_CTX);
+    HMAC_CTX* ctx = HMAC_CTX_new();
     if (ctx == nullptr)
     {
         // Allocation failed
@@ -28,23 +27,22 @@ extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen,
     if (keyLen == 0)
         key = &_;
 
-    HMAC_CTX_init(ctx.get());
-    int ret = HMAC_Init_ex(ctx.get(), key, keyLen, md, nullptr);
+    int ret = HMAC_Init_ex(ctx, key, keyLen, md, nullptr);
 
     if (!ret)
     {
+        free(ctx);
         return nullptr;
     }
 
-    return ctx.release();
+    return ctx;
 }
 
 extern "C" void CryptoNative_HmacDestroy(HMAC_CTX* ctx)
 {
     if (ctx != nullptr)
     {
-        HMAC_CTX_cleanup(ctx);
-        delete ctx;
+        HMAC_CTX_free(ctx);
     }
 }
 
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h
index 131e148c00..570d28e70c 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h
@@ -12,7 +12,6 @@
 
 // Forward declarations - shim API must not depend on knowing layout of these types.
 typedef struct hmac_ctx_st HMAC_CTX;
-typedef struct env_md_st EVP_MD;
 
 /**
  * Creates and initializes an HMAC_CTX with the given key and EVP_MD.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp
index 9ad896aa72..7fa6585c99 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp
@@ -58,8 +58,13 @@ static int HasNoPrivateKey(RSA* rsa)
 
     // The method has descibed itself as having the private key external to the structure.
     // That doesn't mean it's actually present, but we can't tell.
-    if (meth->flags & RSA_FLAG_EXT_PKEY)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-qual"
+    if (RSA_meth_get_flags((RSA_METHOD*)meth) & RSA_FLAG_EXT_PKEY)
+#pragma clang diagnostic pop
+    {
         return 0;
+    }
 
     // In the event that there's a middle-ground where we report failure when success is expected,
     // one could do something like check if the RSA_METHOD intercepts all private key operations:
@@ -72,11 +77,27 @@ static int HasNoPrivateKey(RSA* rsa)
 
     // The module is documented as accepting either d or the full set of CRT parameters (p, q, dp, dq, qInv)
     // So if we see d, we're good. Otherwise, if any of the rest are missing, we're public-only.
-    if (rsa->d != nullptr)
+    const BIGNUM* d;
+    RSA_get0_key(rsa, nullptr, nullptr, &d);
+
+    if (d != nullptr)
+    {
         return 0;
+    }
+
+    const BIGNUM* p;
+    const BIGNUM* q;
+    const BIGNUM* dmp1;
+    const BIGNUM* dmq1;
+    const BIGNUM* iqmp;
 
-    if (rsa->p == nullptr || rsa->q == nullptr || rsa->dmp1 == nullptr || rsa->dmq1 == nullptr || rsa->iqmp == nullptr)
+    RSA_get0_factors(rsa, &p, &q);
+    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+
+    if (p == nullptr || q == nullptr || dmp1 == nullptr || dmq1 == nullptr || iqmp == nullptr)
+    {
         return 1;
+    }
 
     return 0;
 }
@@ -93,7 +114,7 @@ CryptoNative_RsaPrivateDecrypt(int32_t flen, const uint8_t* from, uint8_t* to, R
 {
     if (HasNoPrivateKey(rsa))
     {
-        ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
+        ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_DECRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
         return -1;
     }
 
@@ -105,7 +126,7 @@ extern "C" int32_t CryptoNative_RsaSignPrimitive(int32_t flen, const uint8_t* fr
 {
     if (HasNoPrivateKey(rsa))
     {
-        ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
+        ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_ENCRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
         return -1;
     }
 
@@ -169,14 +190,14 @@ CryptoNative_RsaVerify(int32_t type, const uint8_t* m, int32_t mlen, uint8_t* si
 }
 
 extern "C" int32_t CryptoNative_GetRsaParameters(const RSA* rsa,
-                                                 BIGNUM** n,
-                                                 BIGNUM** e,
-                                                 BIGNUM** d,
-                                                 BIGNUM** p,
-                                                 BIGNUM** dmp1,
-                                                 BIGNUM** q,
-                                                 BIGNUM** dmq1,
-                                                 BIGNUM** iqmp)
+                                                 const BIGNUM** n,
+                                                 const BIGNUM** e,
+                                                 const BIGNUM** d,
+                                                 const BIGNUM** p,
+                                                 const BIGNUM** dmp1,
+                                                 const BIGNUM** q,
+                                                 const BIGNUM** dmq1,
+                                                 const BIGNUM** iqmp)
 {
     if (!rsa || !n || !e || !d || !p || !dmp1 || !q || !dmq1 || !iqmp)
     {
@@ -203,57 +224,40 @@ extern "C" int32_t CryptoNative_GetRsaParameters(const RSA* rsa,
         return 0;
     }
 
-    *n = rsa->n;
-    *e = rsa->e;
-    *d = rsa->d;
-    *p = rsa->p;
-    *dmp1 = rsa->dmp1;
-    *q = rsa->q;
-    *dmq1 = rsa->dmq1;
-    *iqmp = rsa->iqmp;
+    RSA_get0_key(rsa, n, e, d);
+    RSA_get0_factors(rsa, p, q);
+    RSA_get0_crt_params(rsa, dmp1, dmq1, iqmp);
 
     return 1;
 }
 
-static int32_t SetRsaParameter(BIGNUM** rsaFieldAddress, uint8_t* buffer, int32_t bufferLength)
+static BIGNUM* MakeBignum(uint8_t* buffer, int32_t bufferLength)
 {
-    assert(rsaFieldAddress != nullptr);
-    if (rsaFieldAddress)
+    if (buffer && bufferLength)
     {
-        if (!buffer || !bufferLength)
-        {
-            *rsaFieldAddress = nullptr;
-            return 1;
-        }
-        else
-        {
-            BIGNUM* bigNum = BN_bin2bn(buffer, bufferLength, nullptr);
-            *rsaFieldAddress = bigNum;
-
-            return bigNum != nullptr;
-        }
+        return BN_bin2bn(buffer, bufferLength, nullptr);
     }
 
-    return 0;
+    return nullptr;
 }
 
 extern "C" int32_t CryptoNative_SetRsaParameters(RSA* rsa,
-                                              uint8_t* n,
-                                              int32_t nLength,
-                                              uint8_t* e,
-                                              int32_t eLength,
-                                              uint8_t* d,
-                                              int32_t dLength,
-                                              uint8_t* p,
-                                              int32_t pLength,
-                                              uint8_t* dmp1,
-                                              int32_t dmp1Length,
-                                              uint8_t* q,
-                                              int32_t qLength,
-                                              uint8_t* dmq1,
-                                              int32_t dmq1Length,
-                                              uint8_t* iqmp,
-                                              int32_t iqmpLength)
+                                                 uint8_t* n,
+                                                 int32_t nLength,
+                                                 uint8_t* e,
+                                                 int32_t eLength,
+                                                 uint8_t* d,
+                                                 int32_t dLength,
+                                                 uint8_t* p,
+                                                 int32_t pLength,
+                                                 uint8_t* dmp1,
+                                                 int32_t dmp1Length,
+                                                 uint8_t* q,
+                                                 int32_t qLength,
+                                                 uint8_t* dmq1,
+                                                 int32_t dmq1Length,
+                                                 uint8_t* iqmp,
+                                                 int32_t iqmpLength)
 {
     if (!rsa)
     {
@@ -261,13 +265,43 @@ extern "C" int32_t CryptoNative_SetRsaParameters(RSA* rsa,
         return 0;
     }
 
-    return 
-        SetRsaParameter(&rsa->n, n, nLength) &&
-        SetRsaParameter(&rsa->e, e, eLength) &&
-        SetRsaParameter(&rsa->d, d, dLength) &&
-        SetRsaParameter(&rsa->p, p, pLength) &&
-        SetRsaParameter(&rsa->dmp1, dmp1, dmp1Length) &&
-        SetRsaParameter(&rsa->q, q, qLength) &&
-        SetRsaParameter(&rsa->dmq1, dmq1, dmq1Length) &&
-        SetRsaParameter(&rsa->iqmp, iqmp, iqmpLength);
+    BIGNUM* bnN = MakeBignum(n, nLength);
+    BIGNUM* bnE = MakeBignum(e, eLength);
+    BIGNUM* bnD = MakeBignum(d, dLength);
+
+    if (!RSA_set0_key(rsa, bnN, bnE, bnD))
+    {
+        // BN_free handles NULL input
+        BN_free(bnN);
+        BN_free(bnE);
+        BN_free(bnD);
+        return 0;
+    }
+
+    if (bnD != nullptr)
+    {
+        BIGNUM* bnP = MakeBignum(p, pLength);
+        BIGNUM* bnQ = MakeBignum(q, qLength);
+
+        if (!RSA_set0_factors(rsa, bnP, bnQ))
+        {
+            BN_free(bnP);
+            BN_free(bnQ);
+            return 0;
+        }
+
+        BIGNUM* bnDmp1 = MakeBignum(dmp1, dmp1Length);
+        BIGNUM* bnDmq1 = MakeBignum(dmq1, dmq1Length);
+        BIGNUM* bnIqmp = MakeBignum(iqmp, iqmpLength);
+
+        if (!RSA_set0_crt_params(rsa, bnDmp1, bnDmq1, bnIqmp))
+        {
+            BN_free(bnDmp1);
+            BN_free(bnDmq1);
+            BN_free(bnIqmp);
+            return 0;
+        }
+    }
+
+    return 1;
 }
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h
index c4a2737ced..b075911c47 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h
@@ -114,14 +114,14 @@ Gets all the parameters from the RSA instance.
 Returns 1 upon success, otherwise 0.
 */
 extern "C" int32_t CryptoNative_GetRsaParameters(const RSA* rsa,
-                                                 BIGNUM** n,
-                                                 BIGNUM** e,
-                                                 BIGNUM** d,
-                                                 BIGNUM** p,
-                                                 BIGNUM** dmp1,
-                                                 BIGNUM** q,
-                                                 BIGNUM** dmq1,
-                                                 BIGNUM** iqmp);
+                                                const BIGNUM** n,
+                                                const BIGNUM** e,
+                                                const BIGNUM** d,
+                                                const BIGNUM** p,
+                                                const BIGNUM** dmp1,
+                                                const BIGNUM** q,
+                                                const BIGNUM** dmq1,
+                                                const BIGNUM** iqmp);
 
 /*
 Sets all the parameters on the RSA instance.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp
index 0d87a8a5f1..b0ebba0ce1 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 #include "pal_ssl.h"
+#include "openssl.h"
 
 #include <assert.h>
 #include <string.h>
@@ -16,16 +17,34 @@ static_assert(PAL_SSL_ERROR_ZERO_RETURN == SSL_ERROR_ZERO_RETURN, "");
 
 extern "C" int32_t CryptoNative_EnsureOpenSslInitialized();
 
-extern "C" void CryptoNative_EnsureLibSslInitialized()
+#ifdef NEED_OPENSSL_1_0
+static void EnsureLibSsl10Initialized()
 {
-    CryptoNative_EnsureOpenSslInitialized();
     SSL_library_init();
     SSL_load_error_strings();
 }
+#endif
+
+extern "C" void CryptoNative_EnsureLibSslInitialized()
+{
+    CryptoNative_EnsureOpenSslInitialized();
+
+    // If portable, call the 1.0 initializer when needed.
+    // If 1.0, call it statically.
+    // In 1.1 no action is required, since EnsureOpenSslInitialized does both libraries.
+#ifdef FEATURE_DISTRO_AGNOSTIC_SSL
+    if (API_EXISTS(SSL_state))
+    {
+        EnsureLibSsl10Initialized();
+    }
+#elif OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM
+    EnsureLibSsl10Initialized();
+#endif
+}
 
 extern "C" const SSL_METHOD* CryptoNative_SslV2_3Method()
 {
-    const SSL_METHOD* method = SSLv23_method();
+    const SSL_METHOD* method = TLS_method();
     assert(method != nullptr);
     return method;
 }
@@ -51,19 +70,39 @@ Returns 1 on success, 0 on failure.
 */
 static long TrySetECDHNamedCurve(SSL_CTX* ctx)
 {
-	long result = 0;
-#ifdef SSL_CTX_set_ecdh_auto
-	result = SSL_CTX_set_ecdh_auto(ctx, 1);
-#else
-	EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
-	if (ecdh != nullptr)
-	{
-		result = SSL_CTX_set_tmp_ecdh(ctx, ecdh);
-		EC_KEY_free(ecdh);
-	}
+#ifdef NEED_OPENSSL_1_0
+    long result = 0;
+    unsigned long version = OpenSSL_version_num();
+
+    if (version >= OPENSSL_VERSION_1_1_0_RTM)
+    {
+        // OpenSSL 1.1+ automatically set up ECDH
+        result = 1;
+    }
+    else if (version >= OPENSSL_VERSION_1_0_2_RTM)
+    {
+#ifndef SSL_CTRL_SET_ECDH_AUTO
+#define SSL_CTRL_SET_ECDH_AUTO 94
 #endif
+        // Expanded form of SSL_CTX_set_ecdh_auto(ctx, 1)
+        result = SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, 1, nullptr);
+    }
+    else
+    {
+        EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+
+        if (ecdh != nullptr)
+        {
+            result = SSL_CTX_set_tmp_ecdh(ctx, ecdh);
+            EC_KEY_free(ecdh);
+        }
+    }
 
 	return result;
+#else
+    (void)ctx;
+    return 1;
+#endif
 }
 
 extern "C" void CryptoNative_SetProtocolOptions(SSL_CTX* ctx, SslProtocols protocols)
@@ -80,7 +119,7 @@ extern "C" void CryptoNative_SetProtocolOptions(SSL_CTX* ctx, SslProtocols proto
         return;
     }
 
-    long protocolOptions = 0;
+    unsigned long protocolOptions = 0;
 
     if ((protocols & PAL_SSL_SSL2) != PAL_SSL_SSL2)
     {
@@ -94,20 +133,26 @@ extern "C" void CryptoNative_SetProtocolOptions(SSL_CTX* ctx, SslProtocols proto
     {
         protocolOptions |= SSL_OP_NO_TLSv1;
     }
-#if HAVE_TLS_V1_1
     if ((protocols & PAL_SSL_TLS11) != PAL_SSL_TLS11)
     {
         protocolOptions |= SSL_OP_NO_TLSv1_1;
     }
-#endif
-#if HAVE_TLS_V1_2
     if ((protocols & PAL_SSL_TLS12) != PAL_SSL_TLS12)
     {
         protocolOptions |= SSL_OP_NO_TLSv1_2;
     }
+
+    // protocol options were specified, and there's no handler yet for TLS 1.3.
+#ifndef SSL_OP_NO_TLSv1_3
+#define SSL_OP_NO_TLSv1_3 0x20000000U
 #endif
+    protocolOptions |= SSL_OP_NO_TLSv1_3;
 
+    // OpenSSL 1.0 calls this long, OpenSSL 1.1 calls it unsigned long.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsign-conversion"
     SSL_CTX_set_options(ctx, protocolOptions);
+#pragma clang diagnostic pop
 }
 
 extern "C" SSL* CryptoNative_SslCreate(SSL_CTX* ctx)
@@ -254,54 +299,54 @@ static ExchangeAlgorithmType MapExchangeAlgorithmType(const char* keyExchange, s
 
 static void GetHashAlgorithmTypeAndSize(const char* mac,
                                         size_t macLength,
-                                        HashAlgorithmType& dataHashAlg,
-                                        DataHashSize& hashKeySize)
+                                        HashAlgorithmType* dataHashAlg,
+                                        DataHashSize* hashKeySize)
 {
     if (StringSpanEquals(mac, "MD5", macLength))
     {
-        dataHashAlg = HashAlgorithmType::Md5;
-        hashKeySize = DataHashSize::MD5_HashKeySize;
+        *dataHashAlg = HashAlgorithmType::Md5;
+        *hashKeySize = DataHashSize::MD5_HashKeySize;
         return;
     }
     if (StringSpanEquals(mac, "SHA1", macLength))
     {
-        dataHashAlg = HashAlgorithmType::Sha1;
-        hashKeySize = DataHashSize::SHA1_HashKeySize;
+        *dataHashAlg = HashAlgorithmType::Sha1;
+        *hashKeySize = DataHashSize::SHA1_HashKeySize;
         return;
     }
     if (StringSpanEquals(mac, "GOST94", macLength))
     {
-        dataHashAlg = HashAlgorithmType::SSL_GOST94;
-        hashKeySize = DataHashSize::GOST_HashKeySize;
+        *dataHashAlg = HashAlgorithmType::SSL_GOST94;
+        *hashKeySize = DataHashSize::GOST_HashKeySize;
         return;
     }
     if (StringSpanEquals(mac, "GOST89", macLength))
     {
-        dataHashAlg = HashAlgorithmType::SSL_GOST89;
-        hashKeySize = DataHashSize::GOST_HashKeySize;
+        *dataHashAlg = HashAlgorithmType::SSL_GOST89;
+        *hashKeySize = DataHashSize::GOST_HashKeySize;
         return;
     }
     if (StringSpanEquals(mac, "SHA256", macLength))
     {
-        dataHashAlg = HashAlgorithmType::SSL_SHA256;
-        hashKeySize = DataHashSize::SHA256_HashKeySize;
+        *dataHashAlg = HashAlgorithmType::SSL_SHA256;
+        *hashKeySize = DataHashSize::SHA256_HashKeySize;
         return;
     }
     if (StringSpanEquals(mac, "SHA384", macLength))
     {
-        dataHashAlg = HashAlgorithmType::SSL_SHA384;
-        hashKeySize = DataHashSize::SHA384_HashKeySize;
+        *dataHashAlg = HashAlgorithmType::SSL_SHA384;
+        *hashKeySize = DataHashSize::SHA384_HashKeySize;
         return;
     }
     if (StringSpanEquals(mac, "AEAD", macLength))
     {
-        dataHashAlg = HashAlgorithmType::SSL_AEAD;
-        hashKeySize = DataHashSize::Default;
+        *dataHashAlg = HashAlgorithmType::SSL_AEAD;
+        *hashKeySize = DataHashSize::Default;
         return;
     }
 
-    dataHashAlg = HashAlgorithmType::None;
-    hashKeySize = DataHashSize::Default;
+    *dataHashAlg = HashAlgorithmType::None;
+    *hashKeySize = DataHashSize::Default;
 }
 
 /*
@@ -340,10 +385,10 @@ Parses the Kx, Enc, and Mac values out of the SSL_CIPHER_description and
 maps the values to the corresponding .NET enum value.
 */
 static bool GetSslConnectionInfoFromDescription(const SSL_CIPHER* cipher,
-                                                CipherAlgorithmType& dataCipherAlg,
-                                                ExchangeAlgorithmType& keyExchangeAlg,
-                                                HashAlgorithmType& dataHashAlg,
-                                                DataHashSize& hashKeySize)
+                                                CipherAlgorithmType* dataCipherAlg,
+                                                ExchangeAlgorithmType* keyExchangeAlg,
+                                                HashAlgorithmType* dataHashAlg,
+                                                DataHashSize* hashKeySize)
 {
     const int descriptionLength = 256;
     char description[descriptionLength] = {};
@@ -370,8 +415,8 @@ static bool GetSslConnectionInfoFromDescription(const SSL_CIPHER* cipher,
         return false;
     }
 
-    keyExchangeAlg = MapExchangeAlgorithmType(keyExchange, keyExchangeLength);
-    dataCipherAlg = MapCipherAlgorithmType(encryption, encryptionLength);
+    *keyExchangeAlg = MapExchangeAlgorithmType(keyExchange, keyExchangeLength);
+    *dataCipherAlg = MapCipherAlgorithmType(encryption, encryptionLength);
     GetHashAlgorithmTypeAndSize(mac, macLength, dataHashAlg, hashKeySize);
     return true;
 }
@@ -396,8 +441,9 @@ extern "C" int32_t CryptoNative_GetSslConnectionInfo(SSL* ssl,
         goto err;
     }
 
-    *dataKeySize = cipher->alg_bits;
-    if (GetSslConnectionInfoFromDescription(cipher, *dataCipherAlg, *keyExchangeAlg, *dataHashAlg, *hashKeySize))
+    SSL_CIPHER_get_bits(cipher, dataKeySize);
+
+    if (GetSslConnectionInfoFromDescription(cipher, dataCipherAlg, keyExchangeAlg, dataHashAlg, hashKeySize))
     {
         return 1;
     }
@@ -453,7 +499,7 @@ extern "C" int32_t CryptoNative_SslDoHandshake(SSL* ssl)
 
 extern "C" int32_t CryptoNative_IsSslStateOK(SSL* ssl)
 {
-    return SSL_state(ssl) == SSL_ST_OK;
+    return SSL_is_init_finished(ssl);
 }
 
 extern "C" X509* CryptoNative_SslGetPeerCertificate(SSL* ssl)
@@ -517,6 +563,8 @@ CryptoNative_SslCtxSetCertVerifyCallback(SSL_CTX* ctx, SslCtxSetCertVerifyCallba
 extern "C" int32_t CryptoNative_SetEncryptionPolicy(SSL_CTX* ctx, EncryptionPolicy policy)
 {
     const char* cipherString = nullptr;
+    bool clearSecLevel = false;
+
     switch (policy)
     {
         case EncryptionPolicy::RequireEncryption:
@@ -525,15 +573,23 @@ extern "C" int32_t CryptoNative_SetEncryptionPolicy(SSL_CTX* ctx, EncryptionPoli
 
         case EncryptionPolicy::AllowNoEncryption:
             cipherString = SSL_TXT_AllIncludingNull;
+            clearSecLevel = true;
             break;
 
         case EncryptionPolicy::NoEncryption:
             cipherString = SSL_TXT_eNULL;
+            clearSecLevel = true;
             break;
     }
 
     assert(cipherString != nullptr);
 
+    if (clearSecLevel)
+    {
+        // No minimum security policy, same as OpenSSL 1.0
+        SSL_CTX_set_security_level(ctx, 0);
+    }
+
     return SSL_CTX_set_cipher_list(ctx, cipherString);
 }
 
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp
index 3118c9aa2c..b51bb77575 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp
@@ -230,12 +230,22 @@ extern "C" X509Stack* CryptoNative_X509StoreCtxGetChain(X509_STORE_CTX* ctx)
 
 extern "C" X509Stack* CryptoNative_X509StoreCtxGetSharedUntrusted(X509_STORE_CTX* ctx)
 {
-    return ctx ? ctx->untrusted : nullptr;
+    if (ctx)
+    {
+        return X509_STORE_CTX_get0_untrusted(ctx);
+    }
+
+    return nullptr;
 }
 
 extern "C" X509* CryptoNative_X509StoreCtxGetTargetCert(X509_STORE_CTX* ctx)
 {
-    return ctx ? ctx->cert : nullptr;
+    if (ctx)
+    {
+        return X509_STORE_CTX_get0_cert(ctx);
+    }
+
+    return nullptr;
 }
 
 extern "C" X509VerifyStatusCode CryptoNative_X509StoreCtxGetError(X509_STORE_CTX* ctx)
@@ -302,7 +312,7 @@ extern "C" X509* CryptoNative_X509UpRef(X509* x509)
 {
     if (x509 != nullptr)
     {
-        CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
+        X509_up_ref(x509);
     }
 
     return x509;
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp
index 2132a81836..cc11e654dd 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#include "pal_types.h"
 #include "pal_x509_root.h"
 
 #include <assert.h>
diff --git a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs
index 47912ff085..8f870feae3 100644
--- a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Buffers;
 using System.Diagnostics;
 using System.Security.Cryptography;
 using Microsoft.Win32.SafeHandles;
@@ -49,6 +50,24 @@ namespace Internal.Cryptography
             Debug.Assert(outputOffset >= 0);
             Debug.Assert(output.Length - outputOffset >= count);
 
+            // OpenSSL 1.1 does not allow partial overlap.
+            if (input == output && inputOffset != outputOffset)
+            {
+                byte[] tmp = ArrayPool<byte>.Shared.Rent(count);
+
+                try
+                {
+                    int written = CipherUpdate(input, inputOffset, count, tmp, 0);
+                    Buffer.BlockCopy(tmp, 0, output, outputOffset, written);
+                    return written;
+                }
+                finally
+                {
+                    CryptographicOperations.ZeroMemory(tmp.AsSpan(0, count));
+                    ArrayPool<byte>.Shared.Return(tmp);
+                }
+            }
+
             return CipherUpdate(input, inputOffset, count, output, outputOffset);
         }
 
-- 
2.20.1