Blame SOURCES/0003-Add-hybrid-support-for-OpenSSL-1.0-and-1.1.patch

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