libssh: bump to 0.7.6 CVE-2018-10933 fix 7209/head
authorKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Wed, 17 Oct 2018 07:12:48 +0000 (08:12 +0100)
committerKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Mon, 29 Oct 2018 09:08:11 +0000 (09:08 +0000)
Bump from 0.7.5 to 0.7.6.  Upstream changelog:

Fixed CVE-2018-10933
Added support for OpenSSL 1.1
Added SHA256 support for ssh_get_publickey_hash()
Fixed config parsing
Fixed random memory corruption when importing pubkeys

Backported upstream patches since 0.7.6 to fix interactive
authentication issues amongst other things:

9d5cf209 libcrypto: Fix memory leak in evp_final()
10397321 gssapi: Set correct state after sending GSSAPI_RESPONSE (select mechanism OID)
7ad80ba1 server: Fix compile error
acb0e4f4 examples: Explicitly track auth state in samplesshd-kbdint
3fe7510b messages: Check that the requested service is 'ssh-connection'
734e3ce6 server: Set correct state after sending INFO_REQUEST (Kbd Interactive)
e4c6d591 packet: Add missing break in ssh_packet_incoming_filter()
f81ca616 misc: Add strndup implementation if not provides by the OS

Refresh patches.
Remove local backport for OpenSSL 1.1 support as is now in release
Remove PKG_INSTALL & CMAKE vars that are defaulted anyway
Add PKG_CPE_ID:=cpe:/a:libssh:libssh for CVE tracking
Remove BROKEN tag as is no longer broken

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
libs/libssh/Makefile
libs/libssh/patches/0001-misc-Add-strndup-implementation-if-not-provides-by-t.patch [new file with mode: 0644]
libs/libssh/patches/0002-packet-Add-missing-break-in-ssh_packet_incoming_filt.patch [new file with mode: 0644]
libs/libssh/patches/0003-server-Set-correct-state-after-sending-INFO_REQUEST-.patch [new file with mode: 0644]
libs/libssh/patches/0004-messages-Check-that-the-requested-service-is-ssh-con.patch [new file with mode: 0644]
libs/libssh/patches/0005-examples-Explicitly-track-auth-state-in-samplesshd-k.patch [new file with mode: 0644]
libs/libssh/patches/0006-server-Fix-compile-error.patch [new file with mode: 0644]
libs/libssh/patches/0007-gssapi-Set-correct-state-after-sending-GSSAPI_RESPON.patch [new file with mode: 0644]
libs/libssh/patches/0008-libcrypto-Fix-memory-leak-in-evp_final.patch [new file with mode: 0644]
libs/libssh/patches/001-compile.patch
libs/libssh/patches/005-openssl-1.1.patch [deleted file]

index e6a372ee4c22fd6b814e7117af9312795a668da1..6ffb700458515a2cc37b9695514a979c576c0bce 100644 (file)
@@ -11,17 +11,18 @@ PKG_LICENSE:=LGPL-2.1+ BSD-2-Clause
 PKG_MAINTAINER:=Mislav Novakovic <mislav.novakovic@sartura.hr>
 
 PKG_NAME:=libssh
-PKG_VERSION:=0.7.5
-PKG_RELEASE:=2
+PKG_VERSION:=0.7.6
+PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
-PKG_SOURCE_URL:=https://red.libssh.org/attachments/download/218/
-PKG_HASH:=54e86dd5dc20e5367e58f3caab337ce37675f863f80df85b6b1614966a337095
+PKG_SOURCE_URL:=https://www.libssh.org/files/0.7/
+PKG_HASH:=1d607d3859274f755942324afb0f887ee22edd157f9596a2e69e3a28ec6d1092
+
+PKG_CPE_ID:=cpe:/a:libssh:libssh
 
 CMAKE_INSTALL:=1
 
 PKG_BUILD_PARALLEL:=1
-PKG_INSTALL:=1
 PKG_USE_MIPS16:=0
 
 include $(INCLUDE_DIR)/package.mk
@@ -32,7 +33,7 @@ define Package/libssh
   CATEGORY:=Libraries
   URL:=$(PKG_SOURCE_URL)
   TITLE:=SSH library
-  DEPENDS:=+libpthread +librt +zlib +libopenssl @BROKEN
+  DEPENDS:=+libpthread +librt +zlib +libopenssl
 endef
 
 define Package/libssh/description
@@ -41,8 +42,6 @@ define Package/libssh/description
 endef
 
 CMAKE_OPTIONS = \
-       -DCMAKE_INSTALL_PREFIX:PATH=/usr \
-       -DCMAKE_BUILD_TYPE:STRING=Release \
        -DHAVE_STRTOULL=1 \
        -DHAVE_GETADDRINFO=1 \
        -DHAVE_TERMIOS_H=1 \
diff --git a/libs/libssh/patches/0001-misc-Add-strndup-implementation-if-not-provides-by-t.patch b/libs/libssh/patches/0001-misc-Add-strndup-implementation-if-not-provides-by-t.patch
new file mode 100644 (file)
index 0000000..5813704
--- /dev/null
@@ -0,0 +1,83 @@
+From f81ca6161223e3566ce78a427571235fb6848fe9 Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@cryptomilk.org>
+Date: Wed, 29 Aug 2018 18:41:15 +0200
+Subject: [PATCH 1/8] misc: Add strndup implementation if not provides by the
+ OS
+
+Fixes T112
+
+Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
+(cherry picked from commit 247983e9820fd264cb5a59c14cc12846c028bd08)
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ ConfigureChecks.cmake |  1 +
+ config.h.cmake        |  3 +++
+ include/libssh/priv.h |  4 ++++
+ src/misc.c            | 21 +++++++++++++++++++++
+ 4 files changed, 29 insertions(+)
+
+--- a/ConfigureChecks.cmake
++++ b/ConfigureChecks.cmake
+@@ -115,6 +115,7 @@ endif (NOT WITH_GCRYPT)
+ check_function_exists(isblank HAVE_ISBLANK)
+ check_function_exists(strncpy HAVE_STRNCPY)
++check_function_exists(strndup HAVE_STRNDUP)
+ check_function_exists(strtoull HAVE_STRTOULL)
+ if (NOT WIN32)
+--- a/config.h.cmake
++++ b/config.h.cmake
+@@ -103,6 +103,9 @@
+ /* Define to 1 if you have the `strncpy' function. */
+ #cmakedefine HAVE_STRNCPY 1
++/* Define to 1 if you have the `strndup' function. */
++#cmakedefine HAVE_STRNDUP 1
++
+ /* Define to 1 if you have the `cfmakeraw' function. */
+ #cmakedefine HAVE_CFMAKERAW 1
+--- a/include/libssh/priv.h
++++ b/include/libssh/priv.h
+@@ -43,6 +43,10 @@
+ # endif
+ #endif /* !defined(HAVE_STRTOULL) */
++#if !defined(HAVE_STRNDUP)
++char *strndup(const char *s, size_t n);
++#endif /* ! HAVE_STRNDUP */
++
+ #ifdef HAVE_BYTESWAP_H
+ #include <byteswap.h>
+ #endif
+--- a/src/misc.c
++++ b/src/misc.c
+@@ -1028,6 +1028,27 @@ int ssh_match_group(const char *group, c
+     return 0;
+ }
++#if !defined(HAVE_STRNDUP)
++char *strndup(const char *s, size_t n)
++{
++    char *x = NULL;
++
++    if (n + 1 < n) {
++        return NULL;
++    }
++
++    x = malloc(n + 1);
++    if (x == NULL) {
++        return NULL;
++    }
++
++    memcpy(x, s, n);
++    x[n] = '\0';
++
++    return x;
++}
++#endif /* ! HAVE_STRNDUP */
++
+ /** @} */
+ /* vim: set ts=4 sw=4 et cindent: */
diff --git a/libs/libssh/patches/0002-packet-Add-missing-break-in-ssh_packet_incoming_filt.patch b/libs/libssh/patches/0002-packet-Add-missing-break-in-ssh_packet_incoming_filt.patch
new file mode 100644 (file)
index 0000000..1db276c
--- /dev/null
@@ -0,0 +1,24 @@
+From e4c6d591df6a9c34c1ff3ec9f367c7257122bef3 Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@cryptomilk.org>
+Date: Wed, 17 Oct 2018 07:23:10 +0200
+Subject: [PATCH 2/8] packet: Add missing break in ssh_packet_incoming_filter()
+
+CID 1396239
+
+Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
+(cherry picked from commit fe618a35dc4be3e73ddf29d0c4a96b98d3b9c48f)
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/packet.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/src/packet.c
++++ b/src/packet.c
+@@ -285,6 +285,7 @@ static enum ssh_packet_filter_result_e s
+             (session->dh_handshake_state != DH_STATE_FINISHED))
+         {
+             rc = SSH_PACKET_DENIED;
++            break;
+         }
+         rc = SSH_PACKET_ALLOWED;
diff --git a/libs/libssh/patches/0003-server-Set-correct-state-after-sending-INFO_REQUEST-.patch b/libs/libssh/patches/0003-server-Set-correct-state-after-sending-INFO_REQUEST-.patch
new file mode 100644 (file)
index 0000000..b5d0113
--- /dev/null
@@ -0,0 +1,24 @@
+From 734e3ce6747a5ed120b93a1ff253b3fde5f20024 Mon Sep 17 00:00:00 2001
+From: Meng Tan <mtan@wallix.com>
+Date: Wed, 17 Oct 2018 14:50:08 +0200
+Subject: [PATCH 3/8] server: Set correct state after sending INFO_REQUEST (Kbd
+ Interactive)
+
+Signed-off-by: Meng Tan <mtan@wallix.com>
+Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
+(cherry picked from commit 4ea46eecce9f4e676150fe27fec34e1570b70ace)
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/server.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/src/server.c
++++ b/src/server.c
+@@ -976,6 +976,7 @@ int ssh_message_auth_interactive_request
+     msg->session->kbdint->prompts = NULL;
+     msg->session->kbdint->echo = NULL;
+   }
++  msg->session->auth.state = SSH_AUTH_STATE_INFO;
+   return rc;
+ }
diff --git a/libs/libssh/patches/0004-messages-Check-that-the-requested-service-is-ssh-con.patch b/libs/libssh/patches/0004-messages-Check-that-the-requested-service-is-ssh-con.patch
new file mode 100644 (file)
index 0000000..059a69c
--- /dev/null
@@ -0,0 +1,37 @@
+From 3fe7510b261098e3937ab5417935916a46e6727b Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@cryptomilk.org>
+Date: Fri, 19 Oct 2018 11:40:44 +0200
+Subject: [PATCH 4/8] messages: Check that the requested service is
+ 'ssh-connection'
+
+Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
+(cherry picked from commit 9c200d3ef4f62d724d3bae2563b81c38cc31e215)
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/messages.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/src/messages.c
++++ b/src/messages.c
+@@ -649,6 +649,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_
+   ssh_message msg = NULL;
+   char *service = NULL;
+   char *method = NULL;
++  int cmp;
+   int rc;
+   (void)user;
+@@ -675,6 +676,13 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_
+       service, method,
+       msg->auth_request.username);
++  cmp = strcmp(service, "ssh-connection");
++  if (cmp != 0) {
++      SSH_LOG(SSH_LOG_WARNING,
++              "Invalid service request: %s",
++              service);
++      goto end;
++  }
+   if (strcmp(method, "none") == 0) {
+     msg->auth_request.method = SSH_AUTH_METHOD_NONE;
diff --git a/libs/libssh/patches/0005-examples-Explicitly-track-auth-state-in-samplesshd-k.patch b/libs/libssh/patches/0005-examples-Explicitly-track-auth-state-in-samplesshd-k.patch
new file mode 100644 (file)
index 0000000..10bff43
--- /dev/null
@@ -0,0 +1,72 @@
+From acb0e4f401440ca325e441064d2cb4b896fb9a3d Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@cryptomilk.org>
+Date: Wed, 17 Oct 2018 17:32:54 +0200
+Subject: [PATCH 5/8] examples: Explicitly track auth state in
+ samplesshd-kbdint
+
+Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
+(cherry picked from commit 0ff566b6dde5cd27653aa35280feceefad5d5224)
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ examples/samplesshd-kbdint.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+--- a/examples/samplesshd-kbdint.c
++++ b/examples/samplesshd-kbdint.c
+@@ -23,6 +23,7 @@ clients must be made or how a client sho
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>
++#include <stdbool.h>
+ #define SSHD_USER "libssh"
+ #define SSHD_PASSWORD "libssh"
+@@ -36,6 +37,7 @@ clients must be made or how a client sho
+ #endif
+ static int port = 22;
++static bool authenticated = false;
+ #ifdef WITH_PCAP
+ static const char *pcap_file = "debug.server.pcap";
+@@ -61,11 +63,20 @@ static void cleanup_pcap(void) {
+ #endif
+-static int auth_password(const char *user, const char *password){
+-    if(strcmp(user, SSHD_USER))
++static int auth_password(const char *user, const char *password)
++{
++    int cmp;
++
++    cmp = strcmp(user, SSHD_USER);
++    if (cmp != 0) {
+         return 0;
+-    if(strcmp(password, SSHD_PASSWORD))
++    }
++    cmp = strcmp(password, SSHD_PASSWORD);
++    if (cmp != 0) {
+         return 0;
++    }
++
++    authenticated = true;
+     return 1; // authenticated
+ }
+ #ifdef HAVE_ARGP_H
+@@ -200,6 +211,7 @@ static int kbdint_check_response(ssh_ses
+         return 0;
+     }
++    authenticated = true;
+     return 1;
+ }
+@@ -328,7 +340,7 @@ int main(int argc, char **argv){
+     /* proceed to authentication */
+     auth = authenticate(session);
+-    if(!auth){
++    if (!auth || !authenticated) {
+         printf("Authentication error: %s\n", ssh_get_error(session));
+         ssh_disconnect(session);
+         return 1;
diff --git a/libs/libssh/patches/0006-server-Fix-compile-error.patch b/libs/libssh/patches/0006-server-Fix-compile-error.patch
new file mode 100644 (file)
index 0000000..a60688c
--- /dev/null
@@ -0,0 +1,22 @@
+From 7ad80ba1cc48f7af1f192692d100a6255d97b843 Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@cryptomilk.org>
+Date: Wed, 24 Oct 2018 19:57:17 +0200
+Subject: [PATCH 6/8] server: Fix compile error
+
+Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/server.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/src/server.c
++++ b/src/server.c
+@@ -976,7 +976,7 @@ int ssh_message_auth_interactive_request
+     msg->session->kbdint->prompts = NULL;
+     msg->session->kbdint->echo = NULL;
+   }
+-  msg->session->auth.state = SSH_AUTH_STATE_INFO;
++  msg->session->auth_state = SSH_AUTH_STATE_INFO;
+   return rc;
+ }
diff --git a/libs/libssh/patches/0007-gssapi-Set-correct-state-after-sending-GSSAPI_RESPON.patch b/libs/libssh/patches/0007-gssapi-Set-correct-state-after-sending-GSSAPI_RESPON.patch
new file mode 100644 (file)
index 0000000..b3a9804
--- /dev/null
@@ -0,0 +1,24 @@
+From 103973215443f6e02e010114a3f7ac19eb6f3c8c Mon Sep 17 00:00:00 2001
+From: Meng Tan <mtan@wallix.com>
+Date: Thu, 25 Oct 2018 17:06:06 +0200
+Subject: [PATCH 7/8] gssapi: Set correct state after sending GSSAPI_RESPONSE
+ (select mechanism OID)
+
+Signed-off-by: Meng Tan <mtan@wallix.com>
+Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
+(cherry picked from commit bce8d567053232debd6ec490af5a7d27e1160f39)
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/gssapi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/src/gssapi.c
++++ b/src/gssapi.c
+@@ -120,6 +120,7 @@ static int ssh_gssapi_send_response(ssh_
+         ssh_set_error_oom(session);
+         return SSH_ERROR;
+     }
++    session->auth_state = SSH_AUTH_STATE_GSSAPI_TOKEN;
+     packet_send(session);
+     SSH_LOG(SSH_LOG_PACKET,
diff --git a/libs/libssh/patches/0008-libcrypto-Fix-memory-leak-in-evp_final.patch b/libs/libssh/patches/0008-libcrypto-Fix-memory-leak-in-evp_final.patch
new file mode 100644 (file)
index 0000000..64f6e3f
--- /dev/null
@@ -0,0 +1,24 @@
+From 9d5cf209df4c260546e1468cc15fbbbfba3097c6 Mon Sep 17 00:00:00 2001
+From: Andreas Schneider <asn@cryptomilk.org>
+Date: Sat, 27 Oct 2018 22:15:56 +0200
+Subject: [PATCH 8/8] libcrypto: Fix memory leak in evp_final()
+
+Fixes T116
+
+Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
+(cherry picked from commit a2807474621e51b386ea26ce2a01d2b1aa295c7b)
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/libcrypto.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/src/libcrypto.c
++++ b/src/libcrypto.c
+@@ -165,6 +165,7 @@ void evp_update(EVPCTX ctx, const void *
+ void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
+ {
+     EVP_DigestFinal(ctx, md, mdlen);
++    EVP_MD_CTX_free(ctx);
+ }
+ #endif
index bbc994ba62699571119818e9bd590b2a6f8b8f93..c89179247646b263b78f44561f257b73dd9ccc71 100644 (file)
@@ -21,7 +21,7 @@
  
  set(PACKAGE ${APPLICATION_NAME})
  set(VERSION ${APPLICATION_VERSION})
-@@ -270,6 +269,8 @@ if (WITH_GSSAPI AND NOT GSSAPI_FOUND)
+@@ -272,6 +271,8 @@ if (WITH_GSSAPI AND NOT GSSAPI_FOUND)
  endif (WITH_GSSAPI AND NOT GSSAPI_FOUND)
  
  # ENDIAN
diff --git a/libs/libssh/patches/005-openssl-1.1.patch b/libs/libssh/patches/005-openssl-1.1.patch
deleted file mode 100644 (file)
index a5916a5..0000000
+++ /dev/null
@@ -1,1159 +0,0 @@
---- a/src/libcrypto.c
-+++ b/src/libcrypto.c
-@@ -43,10 +43,12 @@
- #include <openssl/hmac.h>
- #include <openssl/opensslv.h>
- #include <openssl/rand.h>
-+#include "libcrypto-compat.h"
- #ifdef HAVE_OPENSSL_AES_H
- #define HAS_AES
- #include <openssl/aes.h>
-+#include <openssl/modes.h>
- #endif
- #ifdef HAVE_OPENSSL_BLOWFISH_H
- #define HAS_BLOWFISH
-@@ -133,18 +135,20 @@ static const EVP_MD *nid_to_evpmd(int ni
- void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen)
- {
-     const EVP_MD *evp_md = nid_to_evpmd(nid);
--    EVP_MD_CTX md;
-+    EVP_MD_CTX *md;
--    EVP_DigestInit(&md, evp_md);
--    EVP_DigestUpdate(&md, digest, len);
--    EVP_DigestFinal(&md, hash, hlen);
-+    md = EVP_MD_CTX_new();
-+    EVP_DigestInit(md, evp_md);
-+    EVP_DigestUpdate(md, digest, len);
-+    EVP_DigestFinal(md, hash, hlen);
-+    EVP_MD_CTX_free(md);
- }
- EVPCTX evp_init(int nid)
- {
-     const EVP_MD *evp_md = nid_to_evpmd(nid);
--    EVPCTX ctx = malloc(sizeof(EVP_MD_CTX));
-+    EVPCTX ctx = EVP_MD_CTX_new();
-     if (ctx == NULL) {
-         return NULL;
-     }
-@@ -322,32 +326,33 @@ void ssh_mac_final(unsigned char *md, ss
- HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
-   HMACCTX ctx = NULL;
--  ctx = malloc(sizeof(*ctx));
-+  ctx = HMAC_CTX_new();
-   if (ctx == NULL) {
-     return NULL;
-   }
- #ifndef OLD_CRYPTO
--  HMAC_CTX_init(ctx); // openssl 0.9.7 requires it.
-+  HMAC_CTX_reset(ctx); // openssl 0.9.7 requires it.
- #endif
-   switch(type) {
-     case SSH_HMAC_SHA1:
--      HMAC_Init(ctx, key, len, EVP_sha1());
-+      HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL);
-       break;
-     case SSH_HMAC_SHA256:
--      HMAC_Init(ctx, key, len, EVP_sha256());
-+      HMAC_Init_ex(ctx, key, len, EVP_sha256(), NULL);
-       break;
-     case SSH_HMAC_SHA384:
--      HMAC_Init(ctx, key, len, EVP_sha384());
-+      HMAC_Init_ex(ctx, key, len, EVP_sha384(), NULL);
-       break;
-     case SSH_HMAC_SHA512:
--      HMAC_Init(ctx, key, len, EVP_sha512());
-+      HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL);
-       break;
-     case SSH_HMAC_MD5:
--      HMAC_Init(ctx, key, len, EVP_md5());
-+      HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL);
-       break;
-     default:
-+      HMAC_CTX_free(ctx);
-       SAFE_FREE(ctx);
-       ctx = NULL;
-   }
-@@ -363,7 +368,8 @@ void hmac_final(HMACCTX ctx, unsigned ch
-   HMAC_Final(ctx,hashmacbuf,len);
- #ifndef OLD_CRYPTO
--  HMAC_CTX_cleanup(ctx);
-+  HMAC_CTX_free(ctx);
-+  ctx = NULL;
- #else
-   HMAC_cleanup(ctx);
- #endif
-@@ -455,7 +461,11 @@ static void aes_ctr128_encrypt(struct ss
-    * Same for num, which is being used to store the current offset in blocksize in CTR
-    * function.
-    */
-+#if OPENSSL_VERSION_NUMBER < 0x10100000L
-   AES_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer, &num);
-+#else
-+  CRYPTO_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer, &num, (block128_f)AES_encrypt);
-+#endif
- }
- #endif /* BROKEN_AES_CTR */
- #endif /* HAS_AES */
---- a/src/pki_crypto.c
-+++ b/src/pki_crypto.c
-@@ -31,6 +31,7 @@
- #include <openssl/dsa.h>
- #include <openssl/err.h>
- #include <openssl/rsa.h>
-+#include "libcrypto-compat.h"
- #ifdef HAVE_OPENSSL_EC_H
- #include <openssl/ec.h>
-@@ -230,7 +231,10 @@ ssh_key pki_key_dup(const ssh_key key, i
-     }
-     switch (key->type) {
--    case SSH_KEYTYPE_DSS:
-+    case SSH_KEYTYPE_DSS: {
-+        const BIGNUM *p = NULL, *q = NULL, *g = NULL,
-+          *pub_key = NULL, *priv_key = NULL;
-+        BIGNUM *np, *nq, *ng, *npub_key, *npriv_key;
-         new->dsa = DSA_new();
-         if (new->dsa == NULL) {
-             goto fail;
-@@ -243,36 +247,54 @@ ssh_key pki_key_dup(const ssh_key key, i
-          * pub_key  = public key y = g^x
-          * priv_key = private key x
-          */
--        new->dsa->p = BN_dup(key->dsa->p);
--        if (new->dsa->p == NULL) {
-+        DSA_get0_pqg(key->dsa, &p, &q, &g);
-+        np = BN_dup(p);
-+        nq = BN_dup(q);
-+        ng = BN_dup(g);
-+        if (np == NULL || nq == NULL || ng == NULL) {
-+            BN_free(np);
-+            BN_free(nq);
-+            BN_free(ng);
-             goto fail;
-         }
--        new->dsa->q = BN_dup(key->dsa->q);
--        if (new->dsa->q == NULL) {
-+        rc = DSA_set0_pqg(new->dsa, np, nq, ng);
-+        if (rc == 0) {
-+            BN_free(np);
-+            BN_free(nq);
-+            BN_free(ng);
-             goto fail;
-         }
--        new->dsa->g = BN_dup(key->dsa->g);
--        if (new->dsa->g == NULL) {
-+        DSA_get0_key(key->dsa, &pub_key, &priv_key);
-+        npub_key = BN_dup(pub_key);
-+        if (npub_key == NULL) {
-             goto fail;
-         }
--        new->dsa->pub_key = BN_dup(key->dsa->pub_key);
--        if (new->dsa->pub_key == NULL) {
-+        rc = DSA_set0_key(new->dsa, npub_key, NULL);
-+        if (rc == 0) {
-             goto fail;
-         }
-         if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
--            new->dsa->priv_key = BN_dup(key->dsa->priv_key);
--            if (new->dsa->priv_key == NULL) {
-+            npriv_key = BN_dup(priv_key);
-+            if (npriv_key == NULL) {
-+                goto fail;
-+            }
-+
-+            rc = DSA_set0_key(new->dsa, NULL, npriv_key);
-+            if (rc == 0) {
-                 goto fail;
-             }
-         }
-         break;
-+    }
-     case SSH_KEYTYPE_RSA:
--    case SSH_KEYTYPE_RSA1:
-+    case SSH_KEYTYPE_RSA1: {
-+        const BIGNUM *n = NULL, *e = NULL, *d = NULL;
-+        BIGNUM *nn, *ne, *nd;
-         new->rsa = RSA_new();
-         if (new->rsa == NULL) {
-             goto fail;
-@@ -288,62 +310,82 @@ ssh_key pki_key_dup(const ssh_key key, i
-          * dmq1 = d mod (q-1)
-          * iqmp = q^-1 mod p
-          */
--        new->rsa->n = BN_dup(key->rsa->n);
--        if (new->rsa->n == NULL) {
-+        RSA_get0_key(key->rsa, &n, &e, &d);
-+        nn = BN_dup(n);
-+        ne = BN_dup(e);
-+        if (nn == NULL || ne == NULL) {
-+            BN_free(nn);
-+            BN_free(ne);
-             goto fail;
-         }
--        new->rsa->e = BN_dup(key->rsa->e);
--        if (new->rsa->e == NULL) {
-+        rc = RSA_set0_key(new->rsa, nn, ne, NULL);
-+        if (rc == 0) {
-+            BN_free(nn);
-+            BN_free(ne);
-             goto fail;
-         }
-         if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
--            new->rsa->d = BN_dup(key->rsa->d);
--            if (new->rsa->d == NULL) {
-+            const BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL,
-+              *dmq1 = NULL, *iqmp = NULL;
-+            BIGNUM *np, *nq, *ndmp1, *ndmq1, *niqmp;
-+
-+            nd = BN_dup(d);
-+            if (nd == NULL) {
-+                goto fail;
-+            }
-+
-+            rc = RSA_set0_key(new->rsa, NULL, NULL, nd);
-+            if (rc == 0) {
-                 goto fail;
-             }
-             /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the
-              * RSA operations are much faster when these values are available.
-              */
--            if (key->rsa->p != NULL) {
--                new->rsa->p = BN_dup(key->rsa->p);
--                if (new->rsa->p == NULL) {
-+            RSA_get0_factors(key->rsa, &p, &q);
-+            if (p != NULL && q != NULL) { /* need to set both of them */
-+                np = BN_dup(p);
-+                nq = BN_dup(q);
-+                if (np == NULL || nq == NULL) {
-+                    BN_free(np);
-+                    BN_free(nq);
-                     goto fail;
-                 }
--            }
--            if (key->rsa->q != NULL) {
--                new->rsa->q = BN_dup(key->rsa->q);
--                if (new->rsa->q == NULL) {
-+                rc = RSA_set0_factors(new->rsa, np, nq);
-+                if (rc == 0) {
-+                    BN_free(np);
-+                    BN_free(nq);
-                     goto fail;
-                 }
-             }
--            if (key->rsa->dmp1 != NULL) {
--                new->rsa->dmp1 = BN_dup(key->rsa->dmp1);
--                if (new->rsa->dmp1 == NULL) {
-+            RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp);
-+            if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) {
-+                ndmp1 = BN_dup(dmp1);
-+                ndmq1 = BN_dup(dmq1);
-+                niqmp = BN_dup(iqmp);
-+                if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL) {
-+                    BN_free(ndmp1);
-+                    BN_free(ndmq1);
-+                    BN_free(niqmp);
-                     goto fail;
-                 }
--            }
--            if (key->rsa->dmq1 != NULL) {
--                new->rsa->dmq1 = BN_dup(key->rsa->dmq1);
--                if (new->rsa->dmq1 == NULL) {
--                    goto fail;
--                }
--            }
--
--            if (key->rsa->iqmp != NULL) {
--                new->rsa->iqmp = BN_dup(key->rsa->iqmp);
--                if (new->rsa->iqmp == NULL) {
-+                rc =  RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp);
-+                if (rc == 0) {
-+                    BN_free(ndmp1);
-+                    BN_free(ndmq1);
-+                    BN_free(niqmp);
-                     goto fail;
-                 }
-             }
-         }
-         break;
-+    }
-     case SSH_KEYTYPE_ECDSA:
- #ifdef HAVE_OPENSSL_ECC
-         new->ecdsa_nid = key->ecdsa_nid;
-@@ -409,11 +451,30 @@ int pki_key_generate_rsa(ssh_key key, in
- int pki_key_generate_dss(ssh_key key, int parameter){
-     int rc;
-+#if OPENSSL_VERSION_NUMBER > 0x10100000L
-+    key->dsa = DSA_new();
-+    if (key->dsa == NULL) {
-+        return SSH_ERROR;
-+    }
-+    rc = DSA_generate_parameters_ex(key->dsa,
-+                                    parameter,
-+                                    NULL,  /* seed */
-+                                    0,     /* seed_len */
-+                                    NULL,  /* counter_ret */
-+                                    NULL,  /* h_ret */
-+                                    NULL); /* cb */
-+    if (rc != 1) {
-+        DSA_free(key->dsa);
-+        key->dsa = NULL;
-+        return SSH_ERROR;
-+    }
-+#else
-     key->dsa = DSA_generate_parameters(parameter, NULL, 0, NULL, NULL,
-             NULL, NULL);
-     if(key->dsa == NULL){
-         return SSH_ERROR;
-     }
-+#endif
-     rc = DSA_generate_key(key->dsa);
-     if (rc != 1){
-         DSA_free(key->dsa);
-@@ -466,51 +527,64 @@ int pki_key_compare(const ssh_key k1,
-                     enum ssh_keycmp_e what)
- {
-     switch (k1->type) {
--        case SSH_KEYTYPE_DSS:
-+        case SSH_KEYTYPE_DSS: {
-+            const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2,
-+                *pub_key1, *pub_key2, *priv_key1, *priv_key2;
-             if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) {
-                 return 1;
-             }
--            if (bignum_cmp(k1->dsa->p, k2->dsa->p) != 0) {
-+            DSA_get0_pqg(k1->dsa, &p1, &q1, &g1);
-+            DSA_get0_pqg(k2->dsa, &p2, &q2, &g2);
-+            if (bignum_cmp(p1, p2) != 0) {
-                 return 1;
-             }
--            if (bignum_cmp(k1->dsa->q, k2->dsa->q) != 0) {
-+            if (bignum_cmp(q1, q2) != 0) {
-                 return 1;
-             }
--            if (bignum_cmp(k1->dsa->g, k2->dsa->g) != 0) {
-+            if (bignum_cmp(g1, g2) != 0) {
-                 return 1;
-             }
--            if (bignum_cmp(k1->dsa->pub_key, k2->dsa->pub_key) != 0) {
-+            DSA_get0_key(k1->dsa, &pub_key1, &priv_key1);
-+            DSA_get0_key(k2->dsa, &pub_key2, &priv_key2);
-+            if (bignum_cmp(pub_key1, pub_key2) != 0) {
-                 return 1;
-             }
-             if (what == SSH_KEY_CMP_PRIVATE) {
--                if (bignum_cmp(k1->dsa->priv_key, k2->dsa->priv_key) != 0) {
-+                if (bignum_cmp(priv_key1, priv_key2) != 0) {
-                     return 1;
-                 }
-             }
-             break;
-+        }
-         case SSH_KEYTYPE_RSA:
--        case SSH_KEYTYPE_RSA1:
-+        case SSH_KEYTYPE_RSA1: {
-+            const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2;
-             if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) {
-                 return 1;
-             }
--            if (bignum_cmp(k1->rsa->e, k2->rsa->e) != 0) {
-+            RSA_get0_key(k1->rsa, &n1, &e1, NULL);
-+            RSA_get0_key(k2->rsa, &n2, &e2, NULL);
-+            if (bignum_cmp(e1, e2) != 0) {
-                 return 1;
-             }
--            if (bignum_cmp(k1->rsa->n, k2->rsa->n) != 0) {
-+            if (bignum_cmp(n1, n2) != 0) {
-                 return 1;
-             }
-             if (what == SSH_KEY_CMP_PRIVATE) {
--                if (bignum_cmp(k1->rsa->p, k2->rsa->p) != 0) {
-+                RSA_get0_factors(k1->rsa, &p1, &q1);
-+                RSA_get0_factors(k2->rsa, &p2, &q2);
-+                if (bignum_cmp(p1, p2) != 0) {
-                     return 1;
-                 }
--                if (bignum_cmp(k1->rsa->q, k2->rsa->q) != 0) {
-+                if (bignum_cmp(q1, q2) != 0) {
-                     return 1;
-                 }
-             }
-             break;
-+        }
-         case SSH_KEYTYPE_ECDSA:
- #ifdef HAVE_OPENSSL_ECC
-             {
-@@ -586,7 +660,7 @@ ssh_string pki_private_key_to_pem(const
-             } else {
-                 rc = PEM_write_bio_DSAPrivateKey(mem,
-                                                  key->dsa,
--                                                 NULL, /* cipher */
-+                                                 EVP_aes_128_cbc(),
-                                                  NULL, /* kstr */
-                                                  0, /* klen */
-                                                  NULL, /* auth_fn */
-@@ -611,7 +685,7 @@ ssh_string pki_private_key_to_pem(const
-             } else {
-                 rc = PEM_write_bio_RSAPrivateKey(mem,
-                                                  key->rsa,
--                                                 NULL, /* cipher */
-+                                                 EVP_aes_128_cbc(),
-                                                  NULL, /* kstr */
-                                                  0, /* klen */
-                                                  NULL, /* auth_fn */
-@@ -621,8 +695,8 @@ ssh_string pki_private_key_to_pem(const
-                 goto err;
-             }
-             break;
--        case SSH_KEYTYPE_ECDSA:
- #ifdef HAVE_ECC
-+        case SSH_KEYTYPE_ECDSA:
-             if (passphrase == NULL) {
-                 struct pem_get_password_struct pgp = { auth_fn, auth_data };
-@@ -636,7 +710,7 @@ ssh_string pki_private_key_to_pem(const
-             } else {
-                 rc = PEM_write_bio_ECPrivateKey(mem,
-                                                 key->ecdsa,
--                                                NULL, /* cipher */
-+                                                EVP_aes_128_cbc(),
-                                                 NULL, /* kstr */
-                                                 0, /* klen */
-                                                 NULL, /* auth_fn */
-@@ -819,43 +893,65 @@ int pki_pubkey_build_dss(ssh_key key,
-                          ssh_string q,
-                          ssh_string g,
-                          ssh_string pubkey) {
-+    int rc;
-+    BIGNUM *bp, *bq, *bg, *bpub_key;
-+
-     key->dsa = DSA_new();
-     if (key->dsa == NULL) {
-         return SSH_ERROR;
-     }
--    key->dsa->p = make_string_bn(p);
--    key->dsa->q = make_string_bn(q);
--    key->dsa->g = make_string_bn(g);
--    key->dsa->pub_key = make_string_bn(pubkey);
--    if (key->dsa->p == NULL ||
--        key->dsa->q == NULL ||
--        key->dsa->g == NULL ||
--        key->dsa->pub_key == NULL) {
--        DSA_free(key->dsa);
--        return SSH_ERROR;
-+    bp = make_string_bn(p);
-+    bq = make_string_bn(q);
-+    bg = make_string_bn(g);
-+    bpub_key = make_string_bn(pubkey);
-+    if (bp == NULL || bq == NULL ||
-+        bg == NULL || bpub_key == NULL) {
-+        goto fail;
-+    }
-+
-+    rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
-+    if (rc == 0) {
-+        goto fail;
-+    }
-+
-+    rc = DSA_set0_key(key->dsa, bpub_key, NULL);
-+    if (rc == 0) {
-+        goto fail;
-     }
-     return SSH_OK;
-+fail:
-+    DSA_free(key->dsa);
-+    return SSH_ERROR;
- }
- int pki_pubkey_build_rsa(ssh_key key,
-                          ssh_string e,
-                          ssh_string n) {
-+    int rc;
-+    BIGNUM *be, *bn;
-+
-     key->rsa = RSA_new();
-     if (key->rsa == NULL) {
-         return SSH_ERROR;
-     }
--    key->rsa->e = make_string_bn(e);
--    key->rsa->n = make_string_bn(n);
--    if (key->rsa->e == NULL ||
--        key->rsa->n == NULL) {
--        RSA_free(key->rsa);
--        return SSH_ERROR;
-+    be = make_string_bn(e);
-+    bn = make_string_bn(n);
-+    if (be == NULL || bn == NULL) {
-+        goto fail;
-+    }
-+
-+    rc = RSA_set0_key(key->rsa, bn, be, NULL);
-+    if (rc == 0) {
-+        goto fail;
-     }
-     return SSH_OK;
-+fail:
-+    RSA_free(key->rsa);
-+    return SSH_ERROR;
- }
- ssh_string pki_publickey_to_blob(const ssh_key key)
-@@ -889,23 +985,26 @@ ssh_string pki_publickey_to_blob(const s
-     }
-     switch (key->type) {
--        case SSH_KEYTYPE_DSS:
--            p = make_bignum_string(key->dsa->p);
-+        case SSH_KEYTYPE_DSS: {
-+            const BIGNUM *bp, *bq, *bg, *bpub_key;
-+            DSA_get0_pqg(key->dsa, &bp, &bq, &bg);
-+            p = make_bignum_string((BIGNUM *)bp);
-             if (p == NULL) {
-                 goto fail;
-             }
--            q = make_bignum_string(key->dsa->q);
-+            q = make_bignum_string((BIGNUM *)bq);
-             if (q == NULL) {
-                 goto fail;
-             }
--            g = make_bignum_string(key->dsa->g);
-+            g = make_bignum_string((BIGNUM *)bg);
-             if (g == NULL) {
-                 goto fail;
-             }
--            n = make_bignum_string(key->dsa->pub_key);
-+            DSA_get0_key(key->dsa, &bpub_key, NULL);
-+            n = make_bignum_string((BIGNUM *)bpub_key);
-             if (n == NULL) {
-                 goto fail;
-             }
-@@ -937,14 +1036,17 @@ ssh_string pki_publickey_to_blob(const s
-             n = NULL;
-             break;
-+        }
-         case SSH_KEYTYPE_RSA:
--        case SSH_KEYTYPE_RSA1:
--            e = make_bignum_string(key->rsa->e);
-+        case SSH_KEYTYPE_RSA1: {
-+            const BIGNUM *be, *bn;
-+            RSA_get0_key(key->rsa, &bn, &be, NULL);
-+            e = make_bignum_string((BIGNUM *)be);
-             if (e == NULL) {
-                 goto fail;
-             }
--            n = make_bignum_string(key->rsa->n);
-+            n = make_bignum_string((BIGNUM *)bn);
-             if (n == NULL) {
-                 goto fail;
-             }
-@@ -964,6 +1066,7 @@ ssh_string pki_publickey_to_blob(const s
-             n = NULL;
-             break;
-+        }
-         case SSH_KEYTYPE_ECDSA:
- #ifdef HAVE_OPENSSL_ECC
-             rc = ssh_buffer_reinit(buffer);
-@@ -1065,13 +1168,15 @@ int pki_export_pubkey_rsa1(const ssh_key
-     char *e;
-     char *n;
-     int rsa_size = RSA_size(key->rsa);
-+    const BIGNUM *be, *bn;
--    e = bignum_bn2dec(key->rsa->e);
-+    RSA_get0_key(key->rsa, &bn, &be, NULL);
-+    e = bignum_bn2dec(be);
-     if (e == NULL) {
-         return SSH_ERROR;
-     }
--    n = bignum_bn2dec(key->rsa->n);
-+    n = bignum_bn2dec(bn);
-     if (n == NULL) {
-         OPENSSL_free(e);
-         return SSH_ERROR;
-@@ -1136,6 +1241,7 @@ static ssh_string pki_dsa_signature_to_b
- {
-     char buffer[40] = { 0 };
-     ssh_string sig_blob = NULL;
-+    const BIGNUM *pr, *ps;
-     ssh_string r;
-     int r_len, r_offset_in, r_offset_out;
-@@ -1143,12 +1249,13 @@ static ssh_string pki_dsa_signature_to_b
-     ssh_string s;
-     int s_len, s_offset_in, s_offset_out;
--    r = make_bignum_string(sig->dsa_sig->r);
-+    DSA_SIG_get0(sig->dsa_sig, &pr, &ps);
-+    r = make_bignum_string((BIGNUM *)pr);
-     if (r == NULL) {
-         return NULL;
-     }
--    s = make_bignum_string(sig->dsa_sig->s);
-+    s = make_bignum_string((BIGNUM *)ps);
-     if (s == NULL) {
-         ssh_string_free(r);
-         return NULL;
-@@ -1201,13 +1308,15 @@ ssh_string pki_signature_to_blob(const s
-             ssh_string s;
-             ssh_buffer b;
-             int rc;
-+            const BIGNUM *pr, *ps;
-             b = ssh_buffer_new();
-             if (b == NULL) {
-                 return NULL;
-             }
--            r = make_bignum_string(sig->ecdsa_sig->r);
-+            ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps);
-+            r = make_bignum_string((BIGNUM *)pr);
-             if (r == NULL) {
-                 ssh_buffer_free(b);
-                 return NULL;
-@@ -1219,7 +1328,7 @@ ssh_string pki_signature_to_blob(const s
-                 return NULL;
-             }
--            s = make_bignum_string(sig->ecdsa_sig->s);
-+            s = make_bignum_string((BIGNUM *)ps);
-             if (s == NULL) {
-                 ssh_buffer_free(b);
-                 return NULL;
-@@ -1324,6 +1433,7 @@ ssh_signature pki_signature_from_blob(co
-     ssh_string s;
-     size_t len;
-     int rc;
-+    BIGNUM *pr = NULL, *ps = NULL;
-     sig = ssh_signature_new();
-     if (sig == NULL) {
-@@ -1363,9 +1473,9 @@ ssh_signature pki_signature_from_blob(co
-             }
-             ssh_string_fill(r, ssh_string_data(sig_blob), 20);
--            sig->dsa_sig->r = make_string_bn(r);
-+            pr = make_string_bn(r);
-             ssh_string_free(r);
--            if (sig->dsa_sig->r == NULL) {
-+            if (pr == NULL) {
-                 ssh_signature_free(sig);
-                 return NULL;
-             }
-@@ -1377,9 +1487,15 @@ ssh_signature pki_signature_from_blob(co
-             }
-             ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
--            sig->dsa_sig->s = make_string_bn(s);
-+            ps = make_string_bn(s);
-             ssh_string_free(s);
--            if (sig->dsa_sig->s == NULL) {
-+            if (ps == NULL) {
-+                ssh_signature_free(sig);
-+                return NULL;
-+            }
-+
-+            rc = DSA_SIG_set0(sig->dsa_sig, pr, ps);
-+            if (rc == 0) {
-                 ssh_signature_free(sig);
-                 return NULL;
-             }
-@@ -1427,17 +1543,17 @@ ssh_signature pki_signature_from_blob(co
-                 ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
- #endif
--                make_string_bn_inplace(r, sig->ecdsa_sig->r);
-+                pr = make_string_bn(r);
-                 ssh_string_burn(r);
-                 ssh_string_free(r);
--                if (sig->ecdsa_sig->r == NULL) {
-+                if (pr == NULL) {
-                     ssh_buffer_free(b);
-                     ssh_signature_free(sig);
-                     return NULL;
-                 }
-                 s = buffer_get_ssh_string(b);
--                rlen = buffer_get_rest_len(b);
-+                rlen = buffer_get_len(b);
-                 ssh_buffer_free(b);
-                 if (s == NULL) {
-                     ssh_signature_free(sig);
-@@ -1448,10 +1564,16 @@ ssh_signature pki_signature_from_blob(co
-                 ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
- #endif
--                make_string_bn_inplace(s, sig->ecdsa_sig->s);
-+                ps = make_string_bn(s);
-                 ssh_string_burn(s);
-                 ssh_string_free(s);
--                if (sig->ecdsa_sig->s == NULL) {
-+                if (ps == NULL) {
-+                    ssh_signature_free(sig);
-+                    return NULL;
-+                }
-+
-+                rc = ECDSA_SIG_set0(sig->ecdsa_sig, pr, ps);
-+                if (rc == 0) {
-                     ssh_signature_free(sig);
-                     return NULL;
-                 }
-@@ -1578,8 +1700,12 @@ ssh_signature pki_do_sign(const ssh_key
-             }
- #ifdef DEBUG_CRYPTO
--            ssh_print_bignum("r", sig->dsa_sig->r);
--            ssh_print_bignum("s", sig->dsa_sig->s);
-+            {
-+                const BIGNUM *pr, *ps;
-+                DSA_SIG_get0(sig->dsa_sig, &pr, &ps);
-+                ssh_print_bignum("r", (BIGNUM *) pr);
-+                ssh_print_bignum("s", (BIGNUM *) ps);
-+            }
- #endif
-             break;
-@@ -1601,8 +1727,12 @@ ssh_signature pki_do_sign(const ssh_key
-             }
- # ifdef DEBUG_CRYPTO
--            ssh_print_bignum("r", sig->ecdsa_sig->r);
--            ssh_print_bignum("s", sig->ecdsa_sig->s);
-+            {
-+                const BIGNUM *pr, *ps;
-+                ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps);
-+                ssh_print_bignum("r", (BIGNUM *) pr);
-+                ssh_print_bignum("s", (BIGNUM *) ps);
-+            }
- # endif /* DEBUG_CRYPTO */
-             break;
---- a/src/CMakeLists.txt
-+++ b/src/CMakeLists.txt
-@@ -164,6 +164,9 @@ else (WITH_GCRYPT)
-         ${libssh_SRCS}
-         pki_crypto.c
-        )
-+    if(OPENSSL_VERSION VERSION_LESS "1.1.0")
-+        set(libssh_SRCS ${libssh_SRCS} libcrypto-compat.c)
-+    endif()
- endif (WITH_GCRYPT)
- if (WITH_SFTP)
---- /dev/null
-+++ b/src/libcrypto-compat.c
-@@ -0,0 +1,334 @@
-+/*
-+ * 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 "config.h"
-+
-+#include <string.h>
-+#include <openssl/engine.h>
-+#include "libcrypto-compat.h"
-+
-+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;
-+}
-+
-+EVP_MD_CTX *EVP_MD_CTX_new(void)
-+{
-+    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
-+}
-+
-+static void OPENSSL_clear_free(void *str, size_t num)
-+{
-+    if (str == NULL)
-+        return;
-+    if (num)
-+        OPENSSL_cleanse(str, num);
-+    OPENSSL_free(str);
-+}
-+
-+/* This call frees resources associated with the context */
-+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
-+{
-+    if (ctx == NULL)
-+        return 1;
-+
-+    /*
-+     * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
-+     * sometimes only copies of the context are ever finalised.
-+     */
-+    if (ctx->digest && ctx->digest->cleanup
-+        && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
-+        ctx->digest->cleanup(ctx);
-+    if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
-+        && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
-+        OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
-+    }
-+    EVP_PKEY_CTX_free(ctx->pctx);
-+#ifndef OPENSSL_NO_ENGINE
-+    ENGINE_finish(ctx->engine);
-+#endif
-+    OPENSSL_cleanse(ctx, sizeof(*ctx));
-+
-+    return 1;
-+}
-+
-+void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
-+{
-+    EVP_MD_CTX_reset(ctx);
-+    OPENSSL_free(ctx);
-+}
-+
-+HMAC_CTX *HMAC_CTX_new(void)
-+{
-+    HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
-+
-+    if (ctx != NULL) {
-+        if (!HMAC_CTX_reset(ctx)) {
-+            HMAC_CTX_free(ctx);
-+            return NULL;
-+        }
-+    }
-+    return ctx;
-+}
-+
-+static void hmac_ctx_cleanup(HMAC_CTX *ctx)
-+{
-+    EVP_MD_CTX_reset(&ctx->i_ctx);
-+    EVP_MD_CTX_reset(&ctx->o_ctx);
-+    EVP_MD_CTX_reset(&ctx->md_ctx);
-+    ctx->md = NULL;
-+    ctx->key_length = 0;
-+    OPENSSL_cleanse(ctx->key, sizeof(ctx->key));
-+}
-+
-+void HMAC_CTX_free(HMAC_CTX *ctx)
-+{
-+    if (ctx != NULL) {
-+        hmac_ctx_cleanup(ctx);
-+#if OPENSSL_VERSION_NUMBER > 0x10100000L
-+        EVP_MD_CTX_free(&ctx->i_ctx);
-+        EVP_MD_CTX_free(&ctx->o_ctx);
-+        EVP_MD_CTX_free(&ctx->md_ctx);
-+#endif
-+        OPENSSL_free(ctx);
-+    }
-+}
-+
-+int HMAC_CTX_reset(HMAC_CTX *ctx)
-+{
-+    HMAC_CTX_init(ctx);
-+    return 1;
-+}
-+
-+#ifndef HAVE_OPENSSL_EVP_CIPHER_CTX_NEW
-+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
-+{
-+    return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX));
-+}
-+
-+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
-+{
-+    /* EVP_CIPHER_CTX_reset(ctx); alias */
-+    EVP_CIPHER_CTX_init(ctx);
-+    OPENSSL_free(ctx);
-+}
-+#endif
---- /dev/null
-+++ b/src/libcrypto-compat.h
-@@ -0,0 +1,42 @@
-+#ifndef LIBCRYPTO_COMPAT_H
-+#define LIBCRYPTO_COMPAT_H
-+
-+#include <openssl/opensslv.h>
-+#if OPENSSL_VERSION_NUMBER < 0x10100000L
-+
-+#include <openssl/rsa.h>
-+#include <openssl/dsa.h>
-+#include <openssl/ecdsa.h>
-+#include <openssl/dh.h>
-+#include <openssl/evp.h>
-+#include <openssl/hmac.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);
-+
-+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
-+EVP_MD_CTX *EVP_MD_CTX_new(void);
-+void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
-+
-+HMAC_CTX *HMAC_CTX_new(void);
-+int HMAC_CTX_reset(HMAC_CTX *ctx);
-+void HMAC_CTX_free(HMAC_CTX *ctx);
-+
-+#endif /* OPENSSL_VERSION_NUMBER */
-+
-+#endif /* LIBCRYPTO_COMPAT_H */