libssh: added openssl 1.1 compatibility
authorEneas U de Queiroz <redacted>
Wed, 23 May 2018 21:35:16 +0000 (18:35 -0300)
committerEneas U de Queiroz <redacted>
Wed, 23 May 2018 21:35:16 +0000 (18:35 -0300)
This patch was backported from upstream master branch.

Signed-off-by: Eneas U de Queiroz <redacted>
libs/libssh/Makefile
libs/libssh/patches/005-openssl-1.1.patch [new file with mode: 0644]

index 17dd3ba40093688b40afc60403c89dc318c0fc62..cc410c058d39e43766a883dad9b7974d7824e9fd 100644 (file)
@@ -12,7 +12,7 @@ PKG_MAINTAINER:=Mislav Novakovic <mislav.novakovic@sartura.hr>
 
 PKG_NAME:=libssh
 PKG_VERSION:=0.7.5
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
 PKG_SOURCE_URL:=https://red.libssh.org/attachments/download/218/
diff --git a/libs/libssh/patches/005-openssl-1.1.patch b/libs/libssh/patches/005-openssl-1.1.patch
new file mode 100644 (file)
index 0000000..a5916a5
--- /dev/null
@@ -0,0 +1,1159 @@
+--- 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 */
git clone https://git.99rst.org/PROJECT