File 0003-CFE-2629-Openssl-1.1-compatibility.patch of Package cfengine

From b1d817e5e65a7db77c1a1b039229b894874f041d Mon Sep 17 00:00:00 2001
From: Dimitrios Apostolou <jimis@northern.tech>
Date: Wed, 25 Oct 2017 17:03:39 +0200
Subject: [PATCH 3/3] CFE-2629: Openssl 1.1 compatibility

Merge pull request #2916 from jimis/openssl_1_1
---
 cf-agent/cf-agent.c                                |   2 +
 cf-key/cf-key-functions.c                          |   6 +-
 cf-key/cf-key-functions.h                          |   1 +
 cf-serverd/cf-serverd-functions.c                  |   8 +-
 cf-serverd/server_classic.c                        |  49 ++-
 cf-serverd/server_common.c                         |  27 +-
 cf-serverd/server_tls.c                            |   4 +-
 configure.ac                                       |   2 +-
 libcfnet/client_code.c                             |  32 +-
 libcfnet/client_protocol.c                         |  34 +-
 libcfnet/connection_info.h                         |   2 +
 libcfnet/key.h                                     |   4 +-
 libcfnet/tls_generic.c                             |   4 +-
 libpromises/crypto.c                               |  58 +--
 libpromises/files_hashes.c                         | 111 +++---
 libpromises/files_hashes.h                         |   2 +-
 libpromises/generic_agent.c                        |  12 +-
 libpromises/locks.c                                |  32 +-
 libutils/Makefile.am                               |   1 +
 libutils/encode.c                                  |   1 +
 libutils/hash.c                                    |  69 ++--
 libutils/hashes.c                                  |  22 +-
 libutils/libcrypto-compat.c                        | 414 +++++++++++++++++++++
 libutils/libcrypto-compat.h                        |  62 +++
 libutils/string_lib.c                              |   2 +
 .../serial/nondefault_ciphers_tlsversion.srv       |   4 +-
 tests/unit/Makefile.am                             |  12 -
 tests/unit/crypto_symmetric_test.c                 |   8 +-
 tests/unit/tls_generic_test.c                      |  11 +
 29 files changed, 806 insertions(+), 190 deletions(-)
 create mode 100644 libutils/libcrypto-compat.c
 create mode 100644 libutils/libcrypto-compat.h

diff --git a/cf-agent/cf-agent.c b/cf-agent/cf-agent.c
index 9578b291b4ac..a11f6ff4daad 100644
--- a/cf-agent/cf-agent.c
+++ b/cf-agent/cf-agent.c
@@ -241,6 +241,8 @@ int main(int argc, char *argv[])
 
     GenericAgentDiscoverContext(ctx, config);
 
+    /* FIXME: (CFE-2709) ALWAYS_VALIDATE will always be false here, since it can
+     *        only change in KeepPromises(), five lines later on. */
     Policy *policy = SelectAndLoadPolicy(config, ctx, ALWAYS_VALIDATE, true);
 
     if (!policy)
diff --git a/cf-key/cf-key-functions.c b/cf-key/cf-key-functions.c
index 68b1657e9ed8..ee994af6ad38 100644
--- a/cf-key/cf-key-functions.c
+++ b/cf-key/cf-key-functions.c
@@ -27,6 +27,7 @@
 
 #include <openssl/bn.h>                                     /* BN_*, BIGNUM */
 #include <openssl/rand.h>                                   /* RAND_* */
+#include <libcrypto-compat.h>
 
 #include <lastseen.h>
 #include <dir.h>
@@ -48,6 +49,7 @@ RSA *LoadPublicKey(const char *filename)
 {
     FILE *fp;
     RSA *key;
+    const BIGNUM *n, *e;
 
     fp = safe_fopen(filename, "r");
     if (fp == NULL)
@@ -69,7 +71,9 @@ RSA *LoadPublicKey(const char *filename)
 
     fclose(fp);
 
-    if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
+    RSA_get0_key(key, &n, &e, NULL);
+
+    if (BN_num_bits(e) < 2 || !BN_is_odd(e))
     {
         Log(LOG_LEVEL_ERR, "Error while reading public key '%s' - RSA Exponent is too small or not odd. (BN_num_bits: %s)",
             filename, GetErrorStr());
diff --git a/cf-key/cf-key-functions.h b/cf-key/cf-key-functions.h
index 59b33a56cc6d..7080b2c624fa 100644
--- a/cf-key/cf-key-functions.h
+++ b/cf-key/cf-key-functions.h
@@ -39,6 +39,7 @@
 #include <eval_context.h>
 #include <crypto.h>
 
+
 extern bool LOOKUP_HOSTS;
 
 RSA *LoadPublicKey(const char *filename);
diff --git a/cf-serverd/cf-serverd-functions.c b/cf-serverd/cf-serverd-functions.c
index 8d10a0f5487f..346c6493f925 100644
--- a/cf-serverd/cf-serverd-functions.c
+++ b/cf-serverd/cf-serverd-functions.c
@@ -869,7 +869,13 @@ static void AcceptAndHandle(EvalContext *ctx, int sd)
 int StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config)
 {
     InitSignals();
-    ServerTLSInitialize();
+
+    bool tls_init_ok = ServerTLSInitialize();
+    if (!tls_init_ok)
+    {
+        return -1;
+    }
+
     int sd = SetServerListenState(ctx, QUEUESIZE, SERVER_LISTEN, &InitServer);
 
     /* Necessary for our use of select() to work in WaitForIncoming(): */
diff --git a/cf-serverd/server_classic.c b/cf-serverd/server_classic.c
index 97bc8abb0c90..2ebec9a390c4 100644
--- a/cf-serverd/server_classic.c
+++ b/cf-serverd/server_classic.c
@@ -23,7 +23,9 @@
 */
 #include <platform.h>
 
-#include <openssl/bn.h>                                         /* BN_* */
+#include <openssl/bn.h>                                    /* BN_* */
+#include <openssl/err.h>                                   /* ERR_get_error */
+#include <libcrypto-compat.h>
 
 #include <cf3.defs.h>
 #include <item_lib.h>                 /* IsMatchItemIn */
@@ -36,6 +38,7 @@
 #include <files_hashes.h>                             /* HashString */
 #include <crypto.h>                                   /* HavePublicKey */
 #include <cf-serverd-enterprise-stubs.h>              /* ReceiveCollectCall */
+#include <tls_generic.h>
 
 #include "server.h"                                /* ServerConnectionState */
 #include "server_common.h"                         /* ListPersistentClasses */
@@ -579,7 +582,11 @@ static int CheckStoreKey(ServerConnectionState *conn, RSA *key)
             "A public key was already known from %s/%s - no trust required",
             conn->hostname, conn->ipaddr);
 
-        if ((BN_cmp(savedkey->e, key->e) == 0) && (BN_cmp(savedkey->n, key->n) == 0))
+        const BIGNUM *key_n, *key_e, *savedkey_n, *savedkey_e;
+        RSA_get0_key(key, &key_n, &key_e, NULL);
+        RSA_get0_key(savedkey, &savedkey_n, &savedkey_e, NULL);
+
+        if ((BN_cmp(savedkey_e, key_e) == 0) && (BN_cmp(savedkey_n, key_n) == 0))
         {
             Log(LOG_LEVEL_VERBOSE,
                 "The public key identity was confirmed as %s@%s",
@@ -770,8 +777,9 @@ char iscrypt, enterprise_field;
     HashString(challenge, challenge_len, digest, digestType);
 }
 
+BIGNUM *newkey_n, *newkey_e;
+
 /* proposition C2 - Receive client's public key modulus */
-RSA *newkey = RSA_new();
 {
 
     int len_n = ReceiveTransaction(conn->conn_info, recvbuffer, NULL);
@@ -779,16 +787,14 @@ RSA *newkey = RSA_new();
     {
         Log(LOG_LEVEL_ERR, "Authentication failure: "
             "error while receiving public key modulus");
-        RSA_free(newkey);
         return false;
     }
 
-    if ((newkey->n = BN_mpi2bn(recvbuffer, len_n, NULL)) == NULL)
+    if ((newkey_n = BN_mpi2bn(recvbuffer, len_n, NULL)) == NULL)
     {
         Log(LOG_LEVEL_ERR, "Authentication failure: "
             "private decrypt of received public key modulus failed "
             "(%s)", CryptoLastErrorString());
-        RSA_free(newkey);
         return false;
     }
 }
@@ -800,20 +806,38 @@ RSA *newkey = RSA_new();
     {
         Log(LOG_LEVEL_ERR, "Authentication failure: "
             "error while receiving public key exponent");
-        RSA_free(newkey);
         return false;
     }
 
-    if ((newkey->e = BN_mpi2bn(recvbuffer, len_e, NULL)) == NULL)
+    if ((newkey_e = BN_mpi2bn(recvbuffer, len_e, NULL)) == NULL)
     {
         Log(LOG_LEVEL_ERR, "Authentication failure: "
             "private decrypt of received public key exponent failed "
             "(%s)", CryptoLastErrorString());
-        RSA_free(newkey);
+        BN_free(newkey_n);
         return false;
     }
 }
 
+RSA *newkey = RSA_new();
+if (newkey == NULL)
+{
+    Log(LOG_LEVEL_ERR, "Failed to allocate RSA key: %s",
+        TLSErrorString(ERR_get_error()));
+    BN_free(newkey_n);
+    BN_free(newkey_e);
+    return false;
+}
+if (RSA_set0_key(newkey, newkey_n, newkey_e, NULL) != 1)
+{
+    Log(LOG_LEVEL_ERR, "Failed to set RSA key: %s",
+        TLSErrorString(ERR_get_error()));
+    BN_free(newkey_n);
+    BN_free(newkey_e);
+    RSA_free(newkey);
+    return false;
+}
+
 /* Compute and store hash of the client's public key. */
 {
     Key *key = KeyNew(newkey, CF_DEFAULT_DIGEST);
@@ -897,12 +921,15 @@ RSA *newkey = RSA_new();
 
         char bignum_buf[CF_BUFSIZE] = { 0 };
 
+        const BIGNUM *n, *e;
+        RSA_get0_key(PUBKEY, &n, &e, NULL);
+
         /* proposition S4  - conditional */
-        int len_n = BN_bn2mpi(PUBKEY->n, bignum_buf);
+        int len_n = BN_bn2mpi(n, bignum_buf);
         SendTransaction(conn->conn_info, bignum_buf, len_n, CF_DONE);
 
         /* proposition S5  - conditional */
-        int len_e = BN_bn2mpi(PUBKEY->e, bignum_buf);
+        int len_e = BN_bn2mpi(e, bignum_buf);
         SendTransaction(conn->conn_info, bignum_buf, len_e, CF_DONE);
     }
 }
diff --git a/cf-serverd/server_common.c b/cf-serverd/server_common.c
index 931689dff977..4cce4a7e9a1f 100644
--- a/cf-serverd/server_common.c
+++ b/cf-serverd/server_common.c
@@ -43,6 +43,7 @@ static const int CF_NOSIZE = -1;
 #include <pipes.h>
 #include <classic.h>                  /* SendSocketStream */
 #include <net.h>                      /* SendTransaction,ReceiveTransaction */
+#include <openssl/err.h>                                   /* ERR_get_error */
 #include <tls_generic.h>              /* TLSSend */
 #include <rlist.h>
 #include <cf-serverd-enterprise-stubs.h>
@@ -557,7 +558,6 @@ void CfEncryptGetFile(ServerFileGetState *args)
     unsigned char iv[32] =
         { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
     int blocksize = CF_BUFSIZE - 4 * CF_INBAND_OFFSET;
-    EVP_CIPHER_CTX ctx;
     char *key, enctype;
     struct stat sb;
     ConnectionInfo *conn_info = args->conn->conn_info;
@@ -579,9 +579,16 @@ void CfEncryptGetFile(ServerFileGetState *args)
         Log(LOG_LEVEL_INFO, "REFUSE access to file: %s", filename);
         RefuseAccess(args->conn, args->replyfile);
         FailedTransfer(conn_info);
+        return;
     }
 
-    EVP_CIPHER_CTX_init(&ctx);
+    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+    if (ctx == NULL)
+    {
+        Log(LOG_LEVEL_ERR, "Failed to allocate cipher: %s",
+            TLSErrorString(ERR_get_error()));
+        return;
+    }
 
     if ((fd = safe_open(filename, O_RDONLY)) == -1)
     {
@@ -630,20 +637,20 @@ void CfEncryptGetFile(ServerFileGetState *args)
 
             if (n_read > 0)
             {
-                EVP_EncryptInit_ex(&ctx, CfengineCipher(enctype), NULL, key, iv);
+                EVP_EncryptInit_ex(ctx, CfengineCipher(enctype), NULL, key, iv);
 
-                if (!EVP_EncryptUpdate(&ctx, out, &cipherlen, sendbuffer, n_read))
+                if (!EVP_EncryptUpdate(ctx, out, &cipherlen, sendbuffer, n_read))
                 {
                     FailedTransfer(conn_info);
-                    EVP_CIPHER_CTX_cleanup(&ctx);
+                    EVP_CIPHER_CTX_free(ctx);
                     close(fd);
                     return;
                 }
 
-                if (!EVP_EncryptFinal_ex(&ctx, out + cipherlen, &finlen))
+                if (!EVP_EncryptFinal_ex(ctx, out + cipherlen, &finlen))
                 {
                     FailedTransfer(conn_info);
-                    EVP_CIPHER_CTX_cleanup(&ctx);
+                    EVP_CIPHER_CTX_free(ctx);
                     close(fd);
                     return;
                 }
@@ -654,7 +661,7 @@ void CfEncryptGetFile(ServerFileGetState *args)
                 if (SendTransaction(conn_info, out, cipherlen + finlen, CF_DONE) == -1)
                 {
                     Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr());
-                    EVP_CIPHER_CTX_cleanup(&ctx);
+                    EVP_CIPHER_CTX_free(ctx);
                     close(fd);
                     return;
                 }
@@ -666,14 +673,14 @@ void CfEncryptGetFile(ServerFileGetState *args)
                 {
                     Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr());
                     close(fd);
-                    EVP_CIPHER_CTX_cleanup(&ctx);
+                    EVP_CIPHER_CTX_free(ctx);
                     return;
                 }
             }
         }
     }
 
-    EVP_CIPHER_CTX_cleanup(&ctx);
+    EVP_CIPHER_CTX_free(ctx);
     close(fd);
 }
 
diff --git a/cf-serverd/server_tls.c b/cf-serverd/server_tls.c
index 2bbc17f55f1b..0edcfc9b3a54 100644
--- a/cf-serverd/server_tls.c
+++ b/cf-serverd/server_tls.c
@@ -186,7 +186,9 @@ void ServerTLSDeInitialize()
  */
 int ServerTLSPeek(ConnectionInfo *conn_info)
 {
-    assert(SSLSERVERCONTEXT != NULL && PRIVKEY != NULL && PUBKEY != NULL);
+    assert(SSLSERVERCONTEXT != NULL);
+    assert(PRIVKEY != NULL);
+    assert(PUBKEY  != NULL);
 
     assert(ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_UNDEFINED);
 
diff --git a/configure.ac b/configure.ac
index 93323facd299..2eab4527e85c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -435,7 +435,7 @@ fi
 
 CF3_WITH_LIBRARY(openssl, [
    AC_CHECK_LIB(crypto, RSA_generate_key_ex, [], [])
-   AC_CHECK_LIB(ssl, SSL_library_init, [], [])
+   AC_CHECK_LIB(ssl, SSL_free, [], [])
    AC_CHECK_DECLS([SSL_CTX_clear_options], [], [], [[#include <openssl/ssl.h>]])
    AC_CHECK_HEADERS([openssl/opensslv.h], [], [AC_MSG_ERROR(Cannot find OpenSSL)])
 
diff --git a/libcfnet/client_code.c b/libcfnet/client_code.c
index f6348a16e021..0c1314d720f9 100644
--- a/libcfnet/client_code.c
+++ b/libcfnet/client_code.c
@@ -28,6 +28,8 @@
 #include <connection_info.h>
 #include <classic.h>                  /* RecvSocketStream */
 #include <net.h>                      /* SendTransaction,ReceiveTransaction */
+#include <openssl/err.h>                                   /* ERR_get_error */
+#include <libcrypto-compat.h>
 #include <tls_client.h>               /* TLSTry */
 #include <tls_generic.h>              /* TLSVerifyPeer */
 #include <dir.h>
@@ -42,7 +44,6 @@
 #include <string_lib.h>                           /* MemSpan,MemSpanInverse */
 #include <misc_lib.h>                                   /* ProgrammingError */
 #include <printsize.h>                                         /* PRINTSIZE */
-
 #include <lastseen.h>                                            /* LastSaw */
 
 
@@ -514,7 +515,6 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
     char *buf, in[CF_BUFSIZE], out[CF_BUFSIZE], workbuf[CF_BUFSIZE], cfchangedstr[265];
     unsigned char iv[32] =
         { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
-    EVP_CIPHER_CTX crypto_ctx;
 
     snprintf(cfchangedstr, 255, "%s%s", CF_CHANGEDSTR1, CF_CHANGEDSTR2);
 
@@ -543,7 +543,6 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
     }
 
     workbuf[0] = '\0';
-    EVP_CIPHER_CTX_init(&crypto_ctx);
 
     snprintf(in, CF_BUFSIZE - CF_PROTO_OFFSET, "GET dummykey %s", source);
     cipherlen = EncryptString(out, sizeof(out), in, strlen(in) + 1, conn->encryption_type, conn->session_key);
@@ -568,6 +567,15 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
         return false;
     }
 
+    EVP_CIPHER_CTX *crypto_ctx = EVP_CIPHER_CTX_new();
+    if (crypto_ctx == NULL)
+    {
+        Log(LOG_LEVEL_ERR, "Failed to allocate cipher: %s",
+            TLSErrorString(ERR_get_error()));
+        close(dd);
+        return false;
+    }
+
     buf = xmalloc(CF_BUFSIZE + sizeof(int));
 
     bool   last_write_made_hole = false;
@@ -577,7 +585,9 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
     {
         if ((cipherlen = ReceiveTransaction(conn->conn_info, buf, &more)) == -1)
         {
+            close(dd);
             free(buf);
+            EVP_CIPHER_CTX_free(crypto_ctx);
             return false;
         }
 
@@ -591,6 +601,7 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
             Log(LOG_LEVEL_INFO, "Network access to '%s:%s' denied", conn->this_server, source);
             close(dd);
             free(buf);
+            EVP_CIPHER_CTX_free(crypto_ctx);
             return false;
         }
 
@@ -599,22 +610,25 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
             Log(LOG_LEVEL_INFO, "Source '%s:%s' changed while copying", conn->this_server, source);
             close(dd);
             free(buf);
+            EVP_CIPHER_CTX_free(crypto_ctx);
             return false;
         }
 
-        EVP_DecryptInit_ex(&crypto_ctx, CfengineCipher(CfEnterpriseOptions()), NULL, conn->session_key, iv);
+        EVP_DecryptInit_ex(crypto_ctx, CfengineCipher(CfEnterpriseOptions()), NULL, conn->session_key, iv);
 
-        if (!EVP_DecryptUpdate(&crypto_ctx, workbuf, &plainlen, buf, cipherlen))
+        if (!EVP_DecryptUpdate(crypto_ctx, workbuf, &plainlen, buf, cipherlen))
         {
             close(dd);
             free(buf);
+            EVP_CIPHER_CTX_free(crypto_ctx);
             return false;
         }
 
-        if (!EVP_DecryptFinal_ex(&crypto_ctx, workbuf + plainlen, &finlen))
+        if (!EVP_DecryptFinal_ex(crypto_ctx, workbuf + plainlen, &finlen))
         {
             close(dd);
             free(buf);
+            EVP_CIPHER_CTX_free(crypto_ctx);
             return false;
         }
 
@@ -631,7 +645,7 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
             unlink(dest);
             close(dd);
             conn->error = true;
-            EVP_CIPHER_CTX_cleanup(&crypto_ctx);
+            EVP_CIPHER_CTX_free(crypto_ctx);
             return false;
         }
 
@@ -646,12 +660,12 @@ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size,
     {
         unlink(dest);
         free(buf);
-        EVP_CIPHER_CTX_cleanup(&crypto_ctx);
+        EVP_CIPHER_CTX_free(crypto_ctx);
         return false;
     }
 
     free(buf);
-    EVP_CIPHER_CTX_cleanup(&crypto_ctx);
+    EVP_CIPHER_CTX_free(crypto_ctx);
     return true;
 }
 
diff --git a/libcfnet/client_protocol.c b/libcfnet/client_protocol.c
index ca2ddb4f94b1..db5909999ebe 100644
--- a/libcfnet/client_protocol.c
+++ b/libcfnet/client_protocol.c
@@ -24,7 +24,9 @@
 
 #include <client_protocol.h>
 
-#include <openssl/bn.h>                                         /* BN_* */
+#include <openssl/bn.h>                                    /* BN_* */
+#include <openssl/err.h>                                   /* ERR_get_error */
+#include <libcrypto-compat.h>
 
 #include <communication.h>
 #include <net.h>
@@ -43,6 +45,7 @@ extern char VFQNAME[];
 #include <known_dirs.h>
 #include <hash.h>
 #include <connection_info.h>
+#include <tls_generic.h>                                  /* TLSErrorString */
 
 
 /*********************************************************************/
@@ -196,7 +199,10 @@ static bool SetSessionKey(AgentConnection *conn)
         return false;
     }
 
-    conn->session_key = (unsigned char *) bp->d;
+    conn->session_key = xmalloc(BN_num_bytes(bp));
+    BN_bn2bin(bp, conn->session_key);
+
+    BN_clear_free(bp);
     return true;
 }
 
@@ -293,13 +299,16 @@ int AuthenticateAgent(AgentConnection *conn, bool trust_key)
 /*Send the public key - we don't know if server has it */
 /* proposition C2 */
 
+    const BIGNUM *pubkey_n, *pubkey_e;
+    RSA_get0_key(PUBKEY, &pubkey_n, &pubkey_e, NULL);
+
     memset(sendbuffer, 0, CF_EXPANDSIZE);
-    len = BN_bn2mpi(PUBKEY->n, sendbuffer);
+    len = BN_bn2mpi(pubkey_n, sendbuffer);
     SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE);        /* No need to encrypt the public key ... */
 
 /* proposition C3 */
     memset(sendbuffer, 0, CF_EXPANDSIZE);
-    len = BN_bn2mpi(PUBKEY->e, sendbuffer);
+    len = BN_bn2mpi(pubkey_e, sendbuffer);
     SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE);
 
 /* check reply about public key - server can break conn_info here */
@@ -432,7 +441,8 @@ int AuthenticateAgent(AgentConnection *conn, bool trust_key)
             return false;
         }
 
-        if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL)
+        BIGNUM *newkey_n, *newkey_e;
+        if ((newkey_n = BN_mpi2bn(in, len, NULL)) == NULL)
         {
             Log(LOG_LEVEL_ERR,
                 "Private key decrypt failed. (BN_mpi2bn: %s)",
@@ -447,15 +457,27 @@ int AuthenticateAgent(AgentConnection *conn, bool trust_key)
         {
             Log(LOG_LEVEL_INFO, "Protocol error in RSA authentation from IP '%s'",
                  conn->this_server);
+            BN_clear_free(newkey_n);
             RSA_free(newkey);
             return false;
         }
 
-        if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL)
+        if ((newkey_e = BN_mpi2bn(in, len, NULL)) == NULL)
         {
             Log(LOG_LEVEL_ERR,
                 "Public key decrypt failed. (BN_mpi2bn: %s)",
                 CryptoLastErrorString());
+            BN_clear_free(newkey_n);
+            RSA_free(newkey);
+            return false;
+        }
+
+        if (RSA_set0_key(newkey, newkey_n, newkey_e, NULL) != 1)
+        {
+            Log(LOG_LEVEL_ERR, "Failed to set RSA key: %s",
+                TLSErrorString(ERR_get_error()));
+            BN_clear_free(newkey_e);
+            BN_clear_free(newkey_n);
             RSA_free(newkey);
             return false;
         }
diff --git a/libcfnet/connection_info.h b/libcfnet/connection_info.h
index 4d1dfff2d73a..d2eaf46a95d0 100644
--- a/libcfnet/connection_info.h
+++ b/libcfnet/connection_info.h
@@ -27,7 +27,9 @@
 
 
 #include <platform.h>
+
 #include <openssl/ssl.h>
+
 #include <key.h>
 
 
diff --git a/libcfnet/key.h b/libcfnet/key.h
index 5ddab0e09a9d..efebce763a7e 100644
--- a/libcfnet/key.h
+++ b/libcfnet/key.h
@@ -25,9 +25,11 @@
 #ifndef KEY_H
 #define KEY_H
 
-#include <hash.h>
 #include <openssl/rsa.h>
 
+#include <hash.h>
+
+
 /**
   @brief Structure to simplify the key management.
 
diff --git a/libcfnet/tls_generic.c b/libcfnet/tls_generic.c
index db74be34221d..0e255a4441d0 100644
--- a/libcfnet/tls_generic.c
+++ b/libcfnet/tls_generic.c
@@ -88,7 +88,7 @@ static int CompareCertToRSA(X509 *cert, RSA *rsa_key)
             TLSErrorString(ERR_get_error()));
         goto ret1;
     }
-    if (EVP_PKEY_type(cert_pkey->type) != EVP_PKEY_RSA)
+    if (EVP_PKEY_base_id(cert_pkey) != EVP_PKEY_RSA)
     {
         Log(LOG_LEVEL_ERR,
             "Received key of unknown type, only RSA currently supported!");
@@ -300,7 +300,7 @@ int TLSVerifyPeer(ConnectionInfo *conn_info, const char *remoteip, const char *u
         retval = -1;
         goto ret2;
     }
-    if (EVP_PKEY_type(received_pubkey->type) != EVP_PKEY_RSA)
+    if (EVP_PKEY_base_id(received_pubkey) != EVP_PKEY_RSA)
     {
         Log(LOG_LEVEL_ERR,
             "Received key of unknown type, only RSA currently supported!");
diff --git a/libpromises/crypto.c b/libpromises/crypto.c
index 36fbb9c903c2..56138f7fbd2a 100644
--- a/libpromises/crypto.c
+++ b/libpromises/crypto.c
@@ -27,6 +27,7 @@
 #include <openssl/err.h>                                        /* ERR_* */
 #include <openssl/rand.h>                                       /* RAND_* */
 #include <openssl/bn.h>                                         /* BN_* */
+#include <libcrypto-compat.h>
 
 #include <cf3.defs.h>
 #include <lastseen.h>
@@ -220,11 +221,15 @@ bool LoadSecretKeys(void)
         fclose(fp);
     }
 
-    if (PUBKEY != NULL
-        && ((BN_num_bits(PUBKEY->e) < 2) || (!BN_is_odd(PUBKEY->e))))
+    if (PUBKEY != NULL)
     {
-        Log(LOG_LEVEL_ERR, "The public key RSA exponent is too small or not odd");
-        return false;
+        const BIGNUM *n, *e;
+        RSA_get0_key(PUBKEY, &n, &e, NULL);
+        if ((BN_num_bits(e) < 2) || (!BN_is_odd(e)))
+        {
+            Log(LOG_LEVEL_ERR, "The public key RSA exponent is too small or not odd");
+            return false;
+        }
     }
 
     return true;
@@ -366,12 +371,16 @@ RSA *HavePublicKey(const char *username, const char *ipaddress, const char *dige
 
     fclose(fp);
 
-    if ((BN_num_bits(newkey->e) < 2) || (!BN_is_odd(newkey->e)))
     {
-        Log(LOG_LEVEL_ERR, "RSA Exponent too small or not odd for key: %s",
-            newname);
-        RSA_free(newkey);
-        return NULL;
+        const BIGNUM *n, *e;
+        RSA_get0_key(newkey, &n, &e, NULL);
+        if ((BN_num_bits(e) < 2) || (!BN_is_odd(e)))
+        {
+            Log(LOG_LEVEL_ERR, "RSA Exponent too small or not odd for key: %s",
+                newname);
+            RSA_free(newkey);
+            return NULL;
+        }
     }
 
     return newkey;
@@ -438,7 +447,6 @@ int EncryptString(char *out, size_t out_size, const char *in, int plainlen,
     int cipherlen = 0, tmplen;
     unsigned char iv[32] =
         { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
-    EVP_CIPHER_CTX ctx;
 
     if (key == NULL)
         ProgrammingError("EncryptString: session key == NULL");
@@ -451,18 +459,18 @@ int EncryptString(char *out, size_t out_size, const char *in, int plainlen,
                           max_ciphertext_size, out_size);
     }
 
-    EVP_CIPHER_CTX_init(&ctx);
-    EVP_EncryptInit_ex(&ctx, CfengineCipher(type), NULL, key, iv);
+    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+    EVP_EncryptInit_ex(ctx, CfengineCipher(type), NULL, key, iv);
 
-    if (!EVP_EncryptUpdate(&ctx, out, &cipherlen, in, plainlen))
+    if (!EVP_EncryptUpdate(ctx, out, &cipherlen, in, plainlen))
     {
-        EVP_CIPHER_CTX_cleanup(&ctx);
+        EVP_CIPHER_CTX_free(ctx);
         return -1;
     }
 
-    if (!EVP_EncryptFinal_ex(&ctx, out + cipherlen, &tmplen))
+    if (!EVP_EncryptFinal_ex(ctx, out + cipherlen, &tmplen))
     {
-        EVP_CIPHER_CTX_cleanup(&ctx);
+        EVP_CIPHER_CTX_free(ctx);
         return -1;
     }
 
@@ -474,7 +482,7 @@ int EncryptString(char *out, size_t out_size, const char *in, int plainlen,
                           cipherlen, max_ciphertext_size);
     }
 
-    EVP_CIPHER_CTX_cleanup(&ctx);
+    EVP_CIPHER_CTX_free(ctx);
     return cipherlen;
 }
 
@@ -521,7 +529,6 @@ int DecryptString(char *out, size_t out_size, const char *in, int cipherlen,
     int plainlen = 0, tmplen;
     unsigned char iv[32] =
         { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
-    EVP_CIPHER_CTX ctx;
 
     if (key == NULL)
         ProgrammingError("DecryptString: session key == NULL");
@@ -534,22 +541,22 @@ int DecryptString(char *out, size_t out_size, const char *in, int cipherlen,
                           max_plaintext_size, out_size);
     }
 
-    EVP_CIPHER_CTX_init(&ctx);
-    EVP_DecryptInit_ex(&ctx, CfengineCipher(type), NULL, key, iv);
+    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+    EVP_DecryptInit_ex(ctx, CfengineCipher(type), NULL, key, iv);
 
-    if (!EVP_DecryptUpdate(&ctx, out, &plainlen, in, cipherlen))
+    if (!EVP_DecryptUpdate(ctx, out, &plainlen, in, cipherlen))
     {
         Log(LOG_LEVEL_ERR, "Failed to decrypt string");
-        EVP_CIPHER_CTX_cleanup(&ctx);
+        EVP_CIPHER_CTX_free(ctx);
         return -1;
     }
 
-    if (!EVP_DecryptFinal_ex(&ctx, out + plainlen, &tmplen))
+    if (!EVP_DecryptFinal_ex(ctx, out + plainlen, &tmplen))
     {
         unsigned long err = ERR_get_error();
 
         Log(LOG_LEVEL_ERR, "Failed to decrypt at final of cipher length %d. (EVP_DecryptFinal_ex: %s)", cipherlen, ERR_error_string(err, NULL));
-        EVP_CIPHER_CTX_cleanup(&ctx);
+        EVP_CIPHER_CTX_free(ctx);
         return -1;
     }
 
@@ -561,8 +568,7 @@ int DecryptString(char *out, size_t out_size, const char *in, int cipherlen,
                           plainlen, max_plaintext_size);
     }
 
-    EVP_CIPHER_CTX_cleanup(&ctx);
-
+    EVP_CIPHER_CTX_free(ctx);
     return plainlen;
 }
 
diff --git a/libpromises/files_hashes.c b/libpromises/files_hashes.c
index 8663e2d06081..ce9d54ea129d 100644
--- a/libpromises/files_hashes.c
+++ b/libpromises/files_hashes.c
@@ -24,8 +24,10 @@
 
 #include <files_hashes.h>
 
+#include <openssl/err.h>                                        /* ERR_* */
 #include <openssl/bn.h>                                         /* BN_* */
 #include <openssl/evp.h>                                        /* EVP_* */
+#include <libcrypto-compat.h>
 
 #include <dbm_api.h>
 #include <files_interfaces.h>
@@ -40,7 +42,6 @@
 void HashFile(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type)
 {
     FILE *file;
-    EVP_MD_CTX context;
     int len, md_len;
     unsigned char buffer[1024];
     const EVP_MD *md = NULL;
@@ -48,30 +49,37 @@ void HashFile(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], H
     if ((file = safe_fopen(filename, "rb")) == NULL)
     {
         Log(LOG_LEVEL_INFO, "Cannot open file for hashing '%s'. (fopen: %s)", filename, GetErrorStr());
+        return;
     }
-    else
-    {
-        md = EVP_get_digestbyname(HashNameFromId(type));
 
-        EVP_DigestInit(&context, md);
+    md = EVP_get_digestbyname(HashNameFromId(type));
 
+    EVP_MD_CTX *context = EVP_MD_CTX_new();
+    if (context == NULL)
+    {
+        Log(LOG_LEVEL_ERR, "Failed to allocate openssl hashing context");
+        return;
+    }
+
+    if (EVP_DigestInit(context, md) == 1)
+    {
         while ((len = fread(buffer, 1, 1024, file)))
         {
-            EVP_DigestUpdate(&context, buffer, len);
+            EVP_DigestUpdate(context, buffer, len);
         }
 
-        EVP_DigestFinal(&context, digest, &md_len);
-
-        /* Digest length stored in md_len */
-        fclose(file);
+        EVP_DigestFinal(context, digest, &md_len);
     }
+
+    /* Digest length stored in md_len */
+    fclose(file);
+    EVP_MD_CTX_free(context);
 }
 
 /*******************************************************************/
 
 void HashString(const char *buffer, int len, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type)
 {
-    EVP_MD_CTX context;
     const EVP_MD *md = NULL;
     int md_len;
 
@@ -89,10 +97,18 @@ void HashString(const char *buffer, int len, unsigned char digest[EVP_MAX_MD_SIZ
         {
             Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", HashNameFromId(type));
         }
-        else if (EVP_DigestInit(&context, md))
+
+        EVP_MD_CTX *context = EVP_MD_CTX_new();
+        if (context == NULL)
+        {
+            Log(LOG_LEVEL_ERR, "Failed to allocate openssl hashing context");
+            return;
+        }
+
+        if (EVP_DigestInit(context, md) == 1)
         {
-            EVP_DigestUpdate(&context, (unsigned char *) buffer, (size_t) len);
-            EVP_DigestFinal(&context, digest, &md_len);
+            EVP_DigestUpdate(context, buffer, len);
+            EVP_DigestFinal(context, digest, &md_len);
         }
         else
         {
@@ -100,63 +116,60 @@ void HashString(const char *buffer, int len, unsigned char digest[EVP_MAX_MD_SIZ
             // TODO: handle this someway
         }
 
+        EVP_MD_CTX_free(context);
         break;
     }
 }
 
 /*******************************************************************/
 
-void HashPubKey(RSA *key, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type)
+void HashPubKey(const RSA *key, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type)
 {
-    EVP_MD_CTX context;
-    const EVP_MD *md = NULL;
-    int md_len, i, buf_len, actlen;
-    unsigned char *buffer;
-
-    if (key->n)
+    if (type == HASH_METHOD_CRYPT)
     {
-        buf_len = (size_t) BN_num_bytes(key->n);
+        Log(LOG_LEVEL_ERR, "The crypt support is not presently implemented, please use sha256 instead");
+        return;
     }
-    else
+
+    const EVP_MD *md = EVP_get_digestbyname(HashNameFromId(type));
+    if (md == NULL)
     {
-        buf_len = 0;
+        Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", HashNameFromId(type));
     }
 
-    if (key->e)
+    EVP_MD_CTX *context = EVP_MD_CTX_new();
+    if (context == NULL)
     {
-        if (buf_len < (i = (size_t) BN_num_bytes(key->e)))
-        {
-            buf_len = i;
-        }
+        Log(LOG_LEVEL_ERR, "Failed to allocate openssl hashing context");
+        return;
     }
 
-    buffer = xmalloc(buf_len + 10);
+    const BIGNUM *n, *e;
+    RSA_get0_key(key, &n, &e, NULL);
 
-    switch (type)
-    {
-    case HASH_METHOD_CRYPT:
-        Log(LOG_LEVEL_ERR, "The crypt support is not presently implemented, please use sha256 instead");
-        break;
+    size_t n_len = (n == NULL) ? 0 : (size_t) BN_num_bytes(n);
+    size_t e_len = (e == NULL) ? 0 : (size_t) BN_num_bytes(e);
+    size_t buf_len = MAX(n_len, e_len);
 
-    default:
-        md = EVP_get_digestbyname(HashNameFromId(type));
+    unsigned char buffer[buf_len];
+    int md_len, actlen;
 
-        if (md == NULL)
-        {
-            Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", HashNameFromId(type));
-        }
+    if (EVP_DigestInit(context, md) == 1)
+    {
+        actlen = BN_bn2bin(n, buffer);
+        CF_ASSERT(actlen <= buf_len, "Buffer overflow n, %d > %zu!",
+                  actlen, buf_len);
+        EVP_DigestUpdate(context, buffer, actlen);
 
-        EVP_DigestInit(&context, md);
+        actlen = BN_bn2bin(e, buffer);
+        CF_ASSERT(actlen <= buf_len, "Buffer overflow e, %d > %zu!",
+                  actlen, buf_len);
+        EVP_DigestUpdate(context, buffer, actlen);
 
-        actlen = BN_bn2bin(key->n, buffer);
-        EVP_DigestUpdate(&context, buffer, actlen);
-        actlen = BN_bn2bin(key->e, buffer);
-        EVP_DigestUpdate(&context, buffer, actlen);
-        EVP_DigestFinal(&context, digest, &md_len);
-        break;
+        EVP_DigestFinal(context, digest, &md_len);
     }
 
-    free(buffer);
+    EVP_MD_CTX_free(context);
 }
 
 /*******************************************************************/
diff --git a/libpromises/files_hashes.h b/libpromises/files_hashes.h
index 0f6194291593..636a9ab2cd35 100644
--- a/libpromises/files_hashes.h
+++ b/libpromises/files_hashes.h
@@ -40,7 +40,7 @@ int HashesMatch(const unsigned char digest1[EVP_MAX_MD_SIZE + 1],
 char *HashPrintSafe(char *dst, size_t dst_size, const unsigned char *digest,
                     HashMethod type, bool use_prefix);
 char *SkipHashType(char *hash);
-void HashPubKey(RSA *key, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type);
+void HashPubKey(const RSA *key, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type);
 
 
 #endif
diff --git a/libpromises/generic_agent.c b/libpromises/generic_agent.c
index b8c32f0baf59..0a247e55ee83 100644
--- a/libpromises/generic_agent.c
+++ b/libpromises/generic_agent.c
@@ -66,6 +66,9 @@
 #include <loading.h>
 #include <signals.h>
 #include <addr_lib.h>
+#include <openssl/evp.h>
+#include <libcrypto-compat.h>
+
 
 static pthread_once_t pid_cleanup_once = PTHREAD_ONCE_INIT; /* GLOBAL_T */
 
@@ -1163,16 +1166,17 @@ static bool GeneratePolicyReleaseIDFromTree(char *release_id_out, size_t out_siz
     }
 
     // fallback, produce some pseudo sha1 hash
-    EVP_MD_CTX crypto_ctx;
-    EVP_DigestInit(&crypto_ctx, EVP_get_digestbyname(HashNameFromId(GENERIC_AGENT_CHECKSUM_METHOD)));
+    EVP_MD_CTX *crypto_ctx = EVP_MD_CTX_new();
+    EVP_DigestInit(crypto_ctx, EVP_get_digestbyname(HashNameFromId(GENERIC_AGENT_CHECKSUM_METHOD)));
 
     bool success = HashDirectoryTree(policy_dir,
                                      (const char *[]) { ".cf", ".dat", ".txt", ".conf", ".mustache", ".json", ".yaml", NULL},
-                                     &crypto_ctx);
+                                     crypto_ctx);
 
     int md_len;
     unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 };
-    EVP_DigestFinal(&crypto_ctx, digest, &md_len);
+    EVP_DigestFinal(crypto_ctx, digest, &md_len);
+    EVP_MD_CTX_free(crypto_ctx);
 
     HashPrintSafe(release_id_out, out_size, digest,
                   GENERIC_AGENT_CHECKSUM_METHOD, false);
diff --git a/libpromises/locks.c b/libpromises/locks.c
index 8ebac0cd4a92..5f2542ee4def 100644
--- a/libpromises/locks.c
+++ b/libpromises/locks.c
@@ -39,6 +39,9 @@
 #include <misc_lib.h>
 #include <known_dirs.h>
 #include <sysinfo.h>
+#include <openssl/evp.h>
+#include <libcrypto-compat.h>
+
 
 #define CFLOGSIZE 1048576       /* Size of lock-log before rotation */
 #define CF_LOCKHORIZON ((time_t)(SECONDS_PER_WEEK * 4))
@@ -509,7 +512,7 @@ void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char diges
 {
     static const char PACK_UPIFELAPSED_SALT[] = "packageuplist";
 
-    EVP_MD_CTX context;
+    EVP_MD_CTX *context = EVP_MD_CTX_new();
     int md_len;
     const EVP_MD *md = NULL;
     Rlist *rp;
@@ -520,29 +523,29 @@ void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char diges
 
     md = EVP_get_digestbyname(HashNameFromId(type));
 
-    EVP_DigestInit(&context, md);
+    EVP_DigestInit(context, md);
 
 // multiple packages (promisers) may share same package_list_update_ifelapsed lock
     if ( (!salt) || strcmp(salt, PACK_UPIFELAPSED_SALT) )
     {
-        EVP_DigestUpdate(&context, pp->promiser, strlen(pp->promiser));
+        EVP_DigestUpdate(context, pp->promiser, strlen(pp->promiser));
     }
 
     if (pp->comment)
     {
-        EVP_DigestUpdate(&context, pp->comment, strlen(pp->comment));
+        EVP_DigestUpdate(context, pp->comment, strlen(pp->comment));
     }
 
     if (pp->parent_promise_type && pp->parent_promise_type->parent_bundle)
     {
         if (pp->parent_promise_type->parent_bundle->ns)
         {
-            EVP_DigestUpdate(&context, pp->parent_promise_type->parent_bundle->ns, strlen(pp->parent_promise_type->parent_bundle->ns));
+            EVP_DigestUpdate(context, pp->parent_promise_type->parent_bundle->ns, strlen(pp->parent_promise_type->parent_bundle->ns));
         }
 
         if (pp->parent_promise_type->parent_bundle->name)
         {
-            EVP_DigestUpdate(&context, pp->parent_promise_type->parent_bundle->name, strlen(pp->parent_promise_type->parent_bundle->name));
+            EVP_DigestUpdate(context, pp->parent_promise_type->parent_bundle->name, strlen(pp->parent_promise_type->parent_bundle->name));
         }
     }
 
@@ -550,7 +553,7 @@ void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char diges
 
     if (salt)
     {
-        EVP_DigestUpdate(&context, salt, strlen(salt));
+        EVP_DigestUpdate(context, salt, strlen(salt));
     }
 
     if (pp->conlist)
@@ -559,7 +562,7 @@ void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char diges
         {
             Constraint *cp = SeqAt(pp->conlist, i);
 
-            EVP_DigestUpdate(&context, cp->lval, strlen(cp->lval));
+            EVP_DigestUpdate(context, cp->lval, strlen(cp->lval));
 
             // don't hash rvals that change (e.g. times)
             doHash = true;
@@ -581,13 +584,13 @@ void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char diges
             switch (cp->rval.type)
             {
             case RVAL_TYPE_SCALAR:
-                EVP_DigestUpdate(&context, cp->rval.item, strlen(cp->rval.item));
+                EVP_DigestUpdate(context, cp->rval.item, strlen(cp->rval.item));
                 break;
 
             case RVAL_TYPE_LIST:
                 for (rp = cp->rval.item; rp != NULL; rp = rp->next)
                 {
-                    EVP_DigestUpdate(&context, RlistScalarValue(rp), strlen(RlistScalarValue(rp)));
+                    EVP_DigestUpdate(context, RlistScalarValue(rp), strlen(RlistScalarValue(rp)));
                 }
                 break;
 
@@ -597,18 +600,18 @@ void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char diges
 
                 fp = (FnCall *) cp->rval.item;
 
-                EVP_DigestUpdate(&context, fp->name, strlen(fp->name));
+                EVP_DigestUpdate(context, fp->name, strlen(fp->name));
 
                 for (rp = fp->args; rp != NULL; rp = rp->next)
                 {
                     switch (rp->val.type)
                     {
                     case RVAL_TYPE_SCALAR:
-                        EVP_DigestUpdate(&context, RlistScalarValue(rp), strlen(RlistScalarValue(rp)));
+                        EVP_DigestUpdate(context, RlistScalarValue(rp), strlen(RlistScalarValue(rp)));
                         break;
 
                     case RVAL_TYPE_FNCALL:
-                        EVP_DigestUpdate(&context, RlistFnCallValue(rp)->name, strlen(RlistFnCallValue(rp)->name));
+                        EVP_DigestUpdate(context, RlistFnCallValue(rp)->name, strlen(RlistFnCallValue(rp)->name));
                         break;
 
                     default:
@@ -624,7 +627,8 @@ void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char diges
         }
     }
 
-    EVP_DigestFinal(&context, digest, &md_len);
+    EVP_DigestFinal(context, digest, &md_len);
+    EVP_MD_CTX_free(context);
 
 /* Digest length stored in md_len */
 }
diff --git a/libutils/Makefile.am b/libutils/Makefile.am
index c55379418a7a..f9dc629ceb6e 100644
--- a/libutils/Makefile.am
+++ b/libutils/Makefile.am
@@ -75,6 +75,7 @@ libutils_la_SOURCES = \
 	regex.c regex.h \
 	encode.c encode.h \
 	pcre_wrap.c pcre_wrap.h \
+	libcrypto-compat.c libcrypto-compat.h \
 	printsize.h
 
 if !NT
diff --git a/libutils/encode.c b/libutils/encode.c
index c0ee32714767..dc03729f8f1d 100644
--- a/libutils/encode.c
+++ b/libutils/encode.c
@@ -28,6 +28,7 @@
 #include <openssl/buffer.h>                                 /* BUF_MEM */
 #include <openssl/bio.h>                                    /* BIO_* */
 #include <openssl/evp.h>                                    /* BIO_f_base64 */
+#include <libcrypto-compat.h>
 
 #include <alloc.h>
 
diff --git a/libutils/hash.c b/libutils/hash.c
index 4e27152698ff..9a52944fb8f4 100644
--- a/libutils/hash.c
+++ b/libutils/hash.c
@@ -26,10 +26,13 @@
 
 #include <openssl/evp.h>                                       /* EVP_* */
 #include <openssl/bn.h>                                        /* BN_bn2bin */
+#include <libcrypto-compat.h>
 
 #include <alloc.h>
 #include <logging.h>
 #include <hash.h>
+#include <misc_lib.h>
+
 
 static const char *const CF_DIGEST_TYPES[10] =
 {
@@ -198,49 +201,55 @@ Hash *HashNewFromKey(const RSA *rsa, HashMethod method)
     {
         return NULL;
     }
-    EVP_MD_CTX *context = NULL;
-    const EVP_MD *md = NULL;
-    int md_len = 0;
-    unsigned char *buffer = NULL;
-    int buffer_length = 0;
-    int actual_length = 0;
 
-    if (rsa->n)
-    {
-        buffer_length = (size_t) BN_num_bytes(rsa->n);
-    }
-    else
+    const BIGNUM *n, *e;
+    RSA_get0_key(rsa, &n, &e, NULL);
+
+    size_t n_len = (n == NULL) ? 0 : (size_t) BN_num_bytes(n);
+    size_t e_len = (e == NULL) ? 0 : (size_t) BN_num_bytes(e);
+    size_t buf_len = MAX(n_len, e_len);
+
+    const EVP_MD *md = EVP_get_digestbyname(CF_DIGEST_TYPES[method]);
+    if (md == NULL)
     {
-        buffer_length = 0;
+        Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", CF_DIGEST_TYPES[method]);
+        return NULL;
     }
 
-    if (rsa->e)
+    EVP_MD_CTX *context = EVP_MD_CTX_new();
+    if (context == NULL)
     {
-        if (buffer_length < (size_t) BN_num_bytes(rsa->e))
-        {
-            buffer_length = (size_t) BN_num_bytes(rsa->e);
-        }
+        Log(LOG_LEVEL_ERR, "Failed to allocate openssl hashing context");
+        return NULL;
     }
-    md = EVP_get_digestbyname(CF_DIGEST_TYPES[method]);
-    if (md == NULL)
+
+    if (EVP_DigestInit_ex(context, md, NULL) != 1)
     {
-        Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", CF_DIGEST_TYPES[method]);
+        EVP_MD_CTX_free(context);
         return NULL;
     }
+
+    unsigned char buffer[buf_len];
+    int md_len, actlen;
+
+    actlen = BN_bn2bin(n, buffer);
+    CF_ASSERT(actlen <= buf_len, "Buffer overflow n, %d > %zu!",
+              actlen, buf_len);
+    EVP_DigestUpdate(context, buffer, actlen);
+
+    actlen = BN_bn2bin(e, buffer);
+    CF_ASSERT(actlen <= buf_len, "Buffer overflow e, %d > %zu!",
+              actlen, buf_len);
+    EVP_DigestUpdate(context, buffer, actlen);
+
     Hash *hash = HashBasicInit(method);
-    context = EVP_MD_CTX_create();
-    EVP_DigestInit_ex(context, md, NULL);
-    buffer = xmalloc(buffer_length);
-    actual_length = BN_bn2bin(rsa->n, buffer);
-    EVP_DigestUpdate(context, buffer, actual_length);
-    actual_length = BN_bn2bin(rsa->e, buffer);
-    EVP_DigestUpdate(context, buffer, actual_length);
     EVP_DigestFinal_ex(context, hash->digest, &md_len);
-    EVP_MD_CTX_destroy(context);
-    free (buffer);
+
+    EVP_MD_CTX_free(context);
+
     /* Update the printable representation */
     HashCalculatePrintableRepresentation(hash);
-    /* Return the hash */
+
     return hash;
 }
 
diff --git a/libutils/hashes.c b/libutils/hashes.c
index b074ed2e43c5..1213c886ca77 100644
--- a/libutils/hashes.c
+++ b/libutils/hashes.c
@@ -27,6 +27,7 @@
 #include <file_lib.h>
 
 #include <openssl/evp.h>
+#include <libcrypto-compat.h>
 
 
 int FileChecksum(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1])
@@ -40,25 +41,36 @@ int FileChecksum(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1]
     else
     {
         const EVP_MD *md = EVP_get_digestbyname("md5");
-
         if (!md)
         {
             fclose(file);
             return 0;
         }
 
-        EVP_MD_CTX context;
-        EVP_DigestInit(&context, md);
+        EVP_MD_CTX *context = EVP_MD_CTX_new();
+        if (context == NULL)
+        {
+            fclose(file);
+            return 0;
+        }
+
+        if (EVP_DigestInit_ex(context, md, NULL) != 1)
+        {
+            fclose(file);
+            EVP_MD_CTX_free(context);
+            return 0;
+        }
 
         int len = 0;
         unsigned char buffer[1024];
         while ((len = fread(buffer, 1, 1024, file)))
         {
-            EVP_DigestUpdate(&context, buffer, len);
+            EVP_DigestUpdate(context, buffer, len);
         }
 
         unsigned int md_len = 0;
-        EVP_DigestFinal(&context, digest, &md_len);
+        EVP_DigestFinal(context, digest, &md_len);
+        EVP_MD_CTX_free(context);
         fclose(file);
 
         return md_len;
diff --git a/libutils/libcrypto-compat.c b/libutils/libcrypto-compat.c
new file mode 100644
index 000000000000..3fc39092a16d
--- /dev/null
+++ b/libutils/libcrypto-compat.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+
+#include <libcrypto-compat.h>
+
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+#include <string.h>
+#include <openssl/engine.h>
+#include <openssl/bn.h>                                         /* BN_* */
+
+
+static void *OPENSSL_zalloc(size_t num)
+{
+    void *ret = OPENSSL_malloc(num);
+
+    if (ret != NULL)
+        memset(ret, 0, num);
+    return ret;
+}
+
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+    /* If the fields n and e in r are NULL, the corresponding input
+     * parameters MUST be non-NULL for n and e.  d may be
+     * left NULL (in case only the public key is used).
+     */
+    if ((r->n == NULL && n == NULL)
+        || (r->e == NULL && e == NULL))
+        return 0;
+
+    if (n != NULL) {
+        BN_free(r->n);
+        r->n = n;
+    }
+    if (e != NULL) {
+        BN_free(r->e);
+        r->e = e;
+    }
+    if (d != NULL) {
+        BN_free(r->d);
+        r->d = d;
+    }
+
+    return 1;
+}
+
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
+{
+    /* If the fields p and q in r are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((r->p == NULL && p == NULL)
+        || (r->q == NULL && q == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(r->p);
+        r->p = p;
+    }
+    if (q != NULL) {
+        BN_free(r->q);
+        r->q = q;
+    }
+
+    return 1;
+}
+
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
+{
+    /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((r->dmp1 == NULL && dmp1 == NULL)
+        || (r->dmq1 == NULL && dmq1 == NULL)
+        || (r->iqmp == NULL && iqmp == NULL))
+        return 0;
+
+    if (dmp1 != NULL) {
+        BN_free(r->dmp1);
+        r->dmp1 = dmp1;
+    }
+    if (dmq1 != NULL) {
+        BN_free(r->dmq1);
+        r->dmq1 = dmq1;
+    }
+    if (iqmp != NULL) {
+        BN_free(r->iqmp);
+        r->iqmp = iqmp;
+    }
+
+    return 1;
+}
+
+void RSA_get0_key(const RSA *r,
+                  const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+    if (n != NULL)
+        *n = r->n;
+    if (e != NULL)
+        *e = r->e;
+    if (d != NULL)
+        *d = r->d;
+}
+
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
+{
+    if (p != NULL)
+        *p = r->p;
+    if (q != NULL)
+        *q = r->q;
+}
+
+void RSA_get0_crt_params(const RSA *r,
+                         const BIGNUM **dmp1, const BIGNUM **dmq1,
+                         const BIGNUM **iqmp)
+{
+    if (dmp1 != NULL)
+        *dmp1 = r->dmp1;
+    if (dmq1 != NULL)
+        *dmq1 = r->dmq1;
+    if (iqmp != NULL)
+        *iqmp = r->iqmp;
+}
+
+void DSA_get0_pqg(const DSA *d,
+                  const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+    if (p != NULL)
+        *p = d->p;
+    if (q != NULL)
+        *q = d->q;
+    if (g != NULL)
+        *g = d->g;
+}
+
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+    /* If the fields p, q and g in d are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((d->p == NULL && p == NULL)
+        || (d->q == NULL && q == NULL)
+        || (d->g == NULL && g == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(d->p);
+        d->p = p;
+    }
+    if (q != NULL) {
+        BN_free(d->q);
+        d->q = q;
+    }
+    if (g != NULL) {
+        BN_free(d->g);
+        d->g = g;
+    }
+
+    return 1;
+}
+
+void DSA_get0_key(const DSA *d,
+                  const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+    if (pub_key != NULL)
+        *pub_key = d->pub_key;
+    if (priv_key != NULL)
+        *priv_key = d->priv_key;
+}
+
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+    /* If the field pub_key in d is NULL, the corresponding input
+     * parameters MUST be non-NULL.  The priv_key field may
+     * be left NULL.
+     */
+    if (d->pub_key == NULL && pub_key == NULL)
+        return 0;
+
+    if (pub_key != NULL) {
+        BN_free(d->pub_key);
+        d->pub_key = pub_key;
+    }
+    if (priv_key != NULL) {
+        BN_free(d->priv_key);
+        d->priv_key = priv_key;
+    }
+
+    return 1;
+}
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+void DH_get0_pqg(const DH *dh,
+                 const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+    if (p != NULL)
+        *p = dh->p;
+    if (q != NULL)
+        *q = dh->q;
+    if (g != NULL)
+        *g = dh->g;
+}
+
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+    /* If the fields p and g in d are NULL, the corresponding input
+     * parameters MUST be non-NULL.  q may remain NULL.
+     */
+    if ((dh->p == NULL && p == NULL)
+        || (dh->g == NULL && g == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(dh->p);
+        dh->p = p;
+    }
+    if (q != NULL) {
+        BN_free(dh->q);
+        dh->q = q;
+    }
+    if (g != NULL) {
+        BN_free(dh->g);
+        dh->g = g;
+    }
+
+    if (q != NULL) {
+        dh->length = BN_num_bits(q);
+    }
+
+    return 1;
+}
+
+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+    if (pub_key != NULL)
+        *pub_key = dh->pub_key;
+    if (priv_key != NULL)
+        *priv_key = dh->priv_key;
+}
+
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+    /* If the field pub_key in dh is NULL, the corresponding input
+     * parameters MUST be non-NULL.  The priv_key field may
+     * be left NULL.
+     */
+    if (dh->pub_key == NULL && pub_key == NULL)
+        return 0;
+
+    if (pub_key != NULL) {
+        BN_free(dh->pub_key);
+        dh->pub_key = pub_key;
+    }
+    if (priv_key != NULL) {
+        BN_free(dh->priv_key);
+        dh->priv_key = priv_key;
+    }
+
+    return 1;
+}
+
+int DH_set_length(DH *dh, long length)
+{
+    dh->length = length;
+    return 1;
+}
+
+const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx)
+{
+    return ctx->iv;
+}
+
+unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx)
+{
+    return ctx->iv;
+}
+
+EVP_MD_CTX *EVP_MD_CTX_new(void)
+{
+    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
+}
+
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+    EVP_MD_CTX_cleanup(ctx);
+    OPENSSL_free(ctx);
+}
+
+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
+{
+    RSA_METHOD *ret;
+
+    ret = OPENSSL_malloc(sizeof(RSA_METHOD));
+
+    if (ret != NULL) {
+        memcpy(ret, meth, sizeof(*meth));
+        ret->name = OPENSSL_strdup(meth->name);
+        if (ret->name == NULL) {
+            OPENSSL_free(ret);
+            return NULL;
+        }
+    }
+
+    return ret;
+}
+
+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
+{
+    char *tmpname;
+
+    tmpname = OPENSSL_strdup(name);
+    if (tmpname == NULL) {
+        return 0;
+    }
+
+    OPENSSL_free((char *)meth->name);
+    meth->name = tmpname;
+
+    return 1;
+}
+
+int RSA_meth_set_priv_enc(RSA_METHOD *meth,
+                          int (*priv_enc) (int flen, const unsigned char *from,
+                                           unsigned char *to, RSA *rsa,
+                                           int padding))
+{
+    meth->rsa_priv_enc = priv_enc;
+    return 1;
+}
+
+int RSA_meth_set_priv_dec(RSA_METHOD *meth,
+                          int (*priv_dec) (int flen, const unsigned char *from,
+                                           unsigned char *to, RSA *rsa,
+                                           int padding))
+{
+    meth->rsa_priv_dec = priv_dec;
+    return 1;
+}
+
+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa))
+{
+    meth->finish = finish;
+    return 1;
+}
+
+void RSA_meth_free(RSA_METHOD *meth)
+{
+    if (meth != NULL) {
+        OPENSSL_free((char *)meth->name);
+        OPENSSL_free(meth);
+    }
+}
+
+int RSA_bits(const RSA *r)
+{
+    return (BN_num_bits(r->n));
+}
+
+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
+{
+    if (pkey->type != EVP_PKEY_RSA) {
+        return NULL;
+    }
+    return pkey->pkey.rsa;
+}
+
+
+#endif /* OPENSSL_VERSION_NUMBER */
diff --git a/libutils/libcrypto-compat.h b/libutils/libcrypto-compat.h
new file mode 100644
index 000000000000..fa3eb1444a1e
--- /dev/null
+++ b/libutils/libcrypto-compat.h
@@ -0,0 +1,62 @@
+#ifndef LIBCRYPTO_COMPAT_H
+#define LIBCRYPTO_COMPAT_H
+
+#include <platform.h>
+#include <openssl/opensslv.h>
+
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/ecdsa.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
+void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
+void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);
+
+void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
+int DH_set_length(DH *dh, long length);
+
+const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
+unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
+EVP_MD_CTX *EVP_MD_CTX_new(void);
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
+#define EVP_CIPHER_impl_ctx_size(e) e->ctx_size
+#define EVP_CIPHER_CTX_get_cipher_data(ctx) ctx->cipher_data
+
+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
+#define RSA_meth_get_finish(meth) meth->finish
+int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
+int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa));
+void RSA_meth_free(RSA_METHOD *meth);
+
+int RSA_bits(const RSA *r);
+
+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
+
+#endif /* OPENSSL_VERSION_NUMBER */
+
+#endif /* LIBCRYPTO_COMPAT_H */
diff --git a/libutils/string_lib.c b/libutils/string_lib.c
index 8f4d58dcb376..2b8ef041eee6 100644
--- a/libutils/string_lib.c
+++ b/libutils/string_lib.c
@@ -28,12 +28,14 @@
 #include <openssl/buffer.h>                                 /* BUF_MEM */
 #include <openssl/bio.h>                                    /* BIO_* */
 #include <openssl/evp.h>                                    /* BIO_f_base64 */
+#include <libcrypto-compat.h>
 
 #include <alloc.h>
 #include <writer.h>
 #include <misc_lib.h>
 #include <logging.h>
 
+
 char *StringVFormat(const char *fmt, va_list ap)
 {
     char *value;
diff --git a/tests/acceptance/16_cf-serverd/serial/nondefault_ciphers_tlsversion.srv b/tests/acceptance/16_cf-serverd/serial/nondefault_ciphers_tlsversion.srv
index 39ed761fbc9d..9dad9f2a066d 100644
--- a/tests/acceptance/16_cf-serverd/serial/nondefault_ciphers_tlsversion.srv
+++ b/tests/acceptance/16_cf-serverd/serial/nondefault_ciphers_tlsversion.srv
@@ -14,8 +14,8 @@ body server control
 {
       port => "9888";
 
-      # Only this non-default cipher is to be accepted
-      allowciphers    => "RC4-MD5";
+      # Only this cipher is to be accepted
+      allowciphers    => "AES128-GCM-SHA256";
 
       # Allow only TLSv1.1 or higher
       allowtlsversion => "1.1";
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index 9db71ed02184..073973c64158 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -420,18 +420,6 @@ mon_load_test_LDADD = ../../libpromises/libpromises.la libtest.la
 mon_processes_test_SOURCES = mon_processes_test.c ../../cf-monitord/mon.h ../../cf-monitord/mon_processes.c
 mon_processes_test_LDADD = ../../libpromises/libpromises.la libtest.la
 
-# tls_generic_test uses stub functions interposition which does not work (yet)
-# under OS X. Another way of stubbing functions from libpromises is needed.
-if !XNU
-check_PROGRAMS += tls_generic_test
-tls_generic_test_SOURCES = tls_generic_test.c
-tls_generic_test_LDADD = libtest.la \
-	../../libutils/libutils.la \
-	../../libpromises/libpromises.la \
-	../../libcfnet/libcfnet.la \
-	../../cf-serverd/libcf-serverd.la
-endif
-
 version_test_SOURCES = version_test.c
 
 hash_test_SOURCES = hash_test.c
diff --git a/tests/unit/crypto_symmetric_test.c b/tests/unit/crypto_symmetric_test.c
index 8bbdc4546079..89a34d040f31 100644
--- a/tests/unit/crypto_symmetric_test.c
+++ b/tests/unit/crypto_symmetric_test.c
@@ -30,11 +30,11 @@ static void test_cipher_init(void)
 {
     unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
     unsigned char iv[] = {1,2,3,4,5,6,7,8};
-    EVP_CIPHER_CTX ctx;
+    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
 
-    EVP_CIPHER_CTX_init(&ctx);
-    EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), NULL, key, iv);
-    EVP_CIPHER_CTX_cleanup(&ctx);
+    EVP_CIPHER_CTX_init(ctx);
+    EVP_EncryptInit_ex(ctx, EVP_bf_cbc(), NULL, key, iv);
+    EVP_CIPHER_CTX_free(ctx);
 }
 
 static void test_symmetric_encrypt(void)
diff --git a/tests/unit/tls_generic_test.c b/tests/unit/tls_generic_test.c
index 69579ecbf457..4b98c901c999 100644
--- a/tests/unit/tls_generic_test.c
+++ b/tests/unit/tls_generic_test.c
@@ -1,3 +1,14 @@
+/*
+ * WARNING: THIS TEST HAS BEEN DISABLED
+ *
+ * This test is written in a very unportable manner: it replicates source code
+ * of OpenSSL, it uses internals of data structures etc. Do not re-enable it
+ * unless you delete all the code from the OpenSSL internals, and refactor it
+ * to mock the library routines properly, for example with `ld --wrap`. See
+ * "CMocka" and "Mimick" unit testing frameworks.
+ */
+
+
 #include <test.h>
 
 #include <sys/socket.h>
-- 
2.15.1